diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h index fc0913ff..1d8fa48b 100644 --- a/googletest/include/gtest/gtest-printers.h +++ b/googletest/include/gtest/gtest-printers.h @@ -676,18 +676,13 @@ inline void PrintTo(char32_t* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } -// MSVC can be configured to define wchar_t as a typedef of unsigned -// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native -// type. When wchar_t is a typedef, defining an overload for const -// wchar_t* would cause unsigned short* be printed as a wide string, -// possibly causing invalid memory accesses. -#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +#if GTEST_HAS_WCHAR // Overloads for wide C strings GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os); inline void PrintTo(wchar_t* s, ::std::ostream* os) { PrintTo(ImplicitCast_(s), os); } -#endif +#endif // GTEST_HAS_WCHAR // Overload for C arrays. Multi-dimensional arrays are printed // properly. diff --git a/googletest/include/gtest/internal/gtest-port.h b/googletest/include/gtest/internal/gtest-port.h index 31654b09..6afceeb2 100644 --- a/googletest/include/gtest/internal/gtest-port.h +++ b/googletest/include/gtest/internal/gtest-port.h @@ -80,6 +80,11 @@ // is/isn't available. // GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't // enabled. +// GTEST_HAS_WCHAR - Define it to 1/0 to indicate that wide +// characters are/aren't supported. (Google Test +// can be used where std::char_traits and +// libc wchar_t functions (putwc, getwc, etc.) are +// unavailable.) // GTEST_HAS_STD_WSTRING - Define it to 1/0 to indicate that // std::wstring does/doesn't work (Google Test can // be used where std::wstring is unavailable). @@ -499,22 +504,89 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION; #endif // defined(_MSC_VER) || defined(__BORLANDC__) #endif // GTEST_HAS_EXCEPTIONS -#ifndef GTEST_HAS_STD_WSTRING -// The user didn't tell us whether ::std::wstring is available, so we need -// to figure it out. +// 1. Calculate default GTEST_HAS_WCHAR and GTEST_HAS_STD_WSTRING values based +// on compiler / STL capabilities. +#if defined(_MSC_VER) +// MSVC always supports ::std::wstring. +#define GTEST_HAS_STD_WSTRING_DEFAULT 1 +// MSVC either defines wchar_t as a typedef of unsigned short, or as a native +// type (in which case, it defines _NATIVE_WCHAR_T_DEFINED). When wchar_t is a +// typedef, defining an overload for const wchar_t* would cause unsigned short* +// be printed as a wide string, possibly causing invalid memory accesses, so we +// omit wchar_t overloads in that case. +#if defined(_NATIVE_WCHAR_T_DEFINED) +#define GTEST_HAS_WCHAR_DEFAULT 1 +#else +#define GTEST_HAS_WCHAR_DEFAULT 0 +#endif + +#elif defined(_LIBCPP_VERSION) +#if _LIBCPP_HAS_WIDE_CHARACTERS +#define GTEST_HAS_WCHAR_DEFAULT 1 +#define GTEST_HAS_STD_WSTRING_DEFAULT 1 +#else +#define GTEST_HAS_WCHAR_DEFAULT 0 +#define GTEST_HAS_STD_WSTRING_DEFAULT 0 +#endif + +#elif defined(__GLIBCXX__) +#if _GLIBCXX_USE_WCHAR_T +#define GTEST_HAS_WCHAR_DEFAULT 1 +#define GTEST_HAS_STD_WSTRING_DEFAULT 1 +#else +#define GTEST_HAS_WCHAR_DEFAULT 0 +#define GTEST_HAS_STD_WSTRING_DEFAULT 0 +#endif + +#else +// Unknown standard library implementation; fall back to a list of OSes known to +// not support wide characters. +// // Cygwin 1.7 and below doesn't support ::std::wstring. // Solaris' libc++ doesn't support it either. Android has // no support for it at least as recent as Froyo (2.2). +// +// Always let the user override the defaults in this case; they might have more +// information about what's supported than we do. #if (!(defined(GTEST_OS_LINUX_ANDROID) || defined(GTEST_OS_CYGWIN) || \ defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_HAIKU) || \ defined(GTEST_OS_ESP32) || defined(GTEST_OS_ESP8266) || \ defined(GTEST_OS_XTENSA) || defined(GTEST_OS_QURT) || \ defined(GTEST_OS_NXP_QN9090) || defined(GTEST_OS_NRF52))) -#define GTEST_HAS_STD_WSTRING 1 +#define GTEST_HAS_WCHAR_DEFAULT 1 +#define GTEST_HAS_STD_WSTRING_DEFAULT 1 #else -#define GTEST_HAS_STD_WSTRING 0 +#define GTEST_HAS_WCHAR_DEFAULT 0 +#define GTEST_HAS_STD_WSTRING_DEFAULT 0 +#endif +#endif + +// 2. Validate explicit user overrides (if user passed -DGTEST_HAS_*=1) +#if defined(GTEST_HAS_WCHAR) && GTEST_HAS_WCHAR +#if defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED) +#error Cannot explicitly enable GTEST_HAS_WCHAR when wchar_t is a typedef. +#elif defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_WIDE_CHARACTERS +#error Cannot explicitly enable GTEST_HAS_WCHAR without libc++ wide character support. +#elif defined(__GLIBCXX__) && !_GLIBCXX_USE_WCHAR_T +#error Cannot explicitly enable GTEST_HAS_WCHAR without libstdc++ wide character support. +#endif +#endif + +#if defined(GTEST_HAS_STD_WSTRING) && GTEST_HAS_STD_WSTRING +#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_WIDE_CHARACTERS +#error Cannot explicitly enable GTEST_HAS_STD_WSTRING without libc++ wide character support. +#elif defined(__GLIBCXX__) && !_GLIBCXX_USE_WCHAR_T +#error Cannot explicitly enable GTEST_HAS_STD_WSTRING without libstdc++ wide character support. +#endif +#endif + +// 3. Set final values if not explicitly overridden by user +#if !defined(GTEST_HAS_WCHAR) +#define GTEST_HAS_WCHAR GTEST_HAS_WCHAR_DEFAULT +#endif +#if !defined(GTEST_HAS_STD_WSTRING) +#define GTEST_HAS_STD_WSTRING GTEST_HAS_STD_WSTRING_DEFAULT #endif -#endif // GTEST_HAS_STD_WSTRING #ifndef GTEST_HAS_FILE_SYSTEM // Most platforms support a file system. diff --git a/googletest/src/gtest-printers.cc b/googletest/src/gtest-printers.cc index 6d1de6d9..0fb2de59 100644 --- a/googletest/src/gtest-printers.cc +++ b/googletest/src/gtest-printers.cc @@ -445,16 +445,10 @@ void PrintTo(const char16_t* s, ostream* os) { PrintCStringTo(s, os); } void PrintTo(const char32_t* s, ostream* os) { PrintCStringTo(s, os); } -// MSVC compiler can be configured to define whar_t as a typedef -// of unsigned short. Defining an overload for const wchar_t* in that case -// would cause pointers to unsigned shorts be printed as wide strings, -// possibly accessing more memory than intended and causing invalid -// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when -// wchar_t is implemented as a native type. -#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +#if GTEST_HAS_WCHAR // Prints the given wide C string to the ostream. void PrintTo(const wchar_t* s, ostream* os) { PrintCStringTo(s, os); } -#endif // wchar_t is native +#endif // GTEST_HAS_WCHAR namespace { diff --git a/googletest/test/googletest-printers-test.cc b/googletest/test/googletest-printers-test.cc index aa1ddaeb..8e0a6e75 100644 --- a/googletest/test/googletest-printers-test.cc +++ b/googletest/test/googletest-printers-test.cc @@ -648,13 +648,7 @@ TEST(PrintU32StringTest, EscapesProperly) { Print(p)); } -// MSVC compiler can be configured to define whar_t as a typedef -// of unsigned short. Defining an overload for const wchar_t* in that case -// would cause pointers to unsigned shorts be printed as wide strings, -// possibly accessing more memory than intended and causing invalid -// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when -// wchar_t is implemented as a native type. -#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) +#if GTEST_HAS_WCHAR // const wchar_t*. TEST(PrintWideCStringTest, Const) { @@ -685,7 +679,7 @@ TEST(PrintWideCStringTest, EscapesProperly) { "\\n\\r\\t\\v\\xD3\\x576\\x8D3\\xC74D a\"", Print(static_cast(s))); } -#endif // native wchar_t +#endif // GTEST_HAS_WCHAR // Tests printing pointers to other char types.