mirror of
https://github.com/ceres-solver/ceres-solver.git
synced 2026-08-30 00:50:37 +08:00
Fix use of va_copy() if compiling with explicit C++ version < C++11.
- va_copy() was defined in the C99 standard, but did not appear in the C++ standard until C++11. If the C++ standard is not specified, both GCC & Clang will define va_copy(), even though strictly speaking they should not. However, if the C++ standard is explicitly specified to something < C++11 (e.g. -std=c++03) then va_copy() will NOT be defined. - Now, if va_copy() is not defined, we either define our own version on non GCC/Clang compilers (as before for MSVC alone), and use the internal __va_copy() version on GCC & Clang, which does exist. Change-Id: I0224f7fa6aae060dee2287782b1cad767c244d3c
This commit is contained in:
@@ -43,14 +43,27 @@ namespace internal {
|
||||
|
||||
using std::string;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
enum { IS_COMPILER_MSVC = 1 };
|
||||
#if _MSC_VER < 1800
|
||||
#define va_copy(d, s) ((d) = (s))
|
||||
#endif
|
||||
// va_copy() was defined in the C99 standard. However, it did not appear in the
|
||||
// C++ standard until C++11. This means that if Ceres is being compiled with a
|
||||
// strict pre-C++11 standard (e.g. -std=c++03), va_copy() will NOT be defined,
|
||||
// as we are using the C++ compiler (it would however be defined if we were
|
||||
// using the C compiler). Note however that both GCC & Clang will in fact
|
||||
// define va_copy() when compiling for C++ if the C++ standard is not explicitly
|
||||
// specified (i.e. no -std=c++<XX> arg), even though it should not strictly be
|
||||
// defined unless -std=c++11 (or greater) was passed.
|
||||
#if !defined(va_copy)
|
||||
#if defined (__GNUC__)
|
||||
// On GCC/Clang, if va_copy() is not defined (C++ standard < C++11 explicitly
|
||||
// specified), use the internal __va_copy() version, which should be present
|
||||
// in even very old GCC versions.
|
||||
#define va_copy(d, s) __va_copy(d, s)
|
||||
#else
|
||||
enum { IS_COMPILER_MSVC = 0 };
|
||||
#endif
|
||||
// Some older versions of MSVC do not have va_copy(), in which case define it.
|
||||
// Although this is required for older MSVC versions, it should also work for
|
||||
// other non-GCC/Clang compilers which also do not defined va_copy().
|
||||
#define va_copy(d, s) ((d) = (s))
|
||||
#endif // defined (__GNUC__)
|
||||
#endif // !defined(va_copy)
|
||||
|
||||
void StringAppendV(string* dst, const char* format, va_list ap) {
|
||||
// First try with a small fixed size buffer
|
||||
@@ -71,13 +84,13 @@ void StringAppendV(string* dst, const char* format, va_list ap) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IS_COMPILER_MSVC) {
|
||||
// Error or MSVC running out of space. MSVC 8.0 and higher
|
||||
// can be asked about space needed with the special idiom below:
|
||||
va_copy(backup_ap, ap);
|
||||
result = vsnprintf(NULL, 0, format, backup_ap);
|
||||
va_end(backup_ap);
|
||||
}
|
||||
#if defined (_MSC_VER)
|
||||
// Error or MSVC running out of space. MSVC 8.0 and higher
|
||||
// can be asked about space needed with the special idiom below:
|
||||
va_copy(backup_ap, ap);
|
||||
result = vsnprintf(NULL, 0, format, backup_ap);
|
||||
va_end(backup_ap);
|
||||
#endif
|
||||
|
||||
if (result < 0) {
|
||||
// Just an error.
|
||||
|
||||
Reference in New Issue
Block a user