Fix -Wmicrosoft-cast warnings when using gtest with clang on Windows.
This upstreams a Google-internal change. Original CL description: The C++ standard says that function pointers are not implicitly convertible to object pointers. Visual Studio disregards that and allows implicit conversion between function pointers and object points, and enough code relies on this that clang follows suit in Microsoft-compatibility mode. However, clang emits a -Wmicrosoft-cast warning when such a conversion is done: E:\b\c\b\win_clang\src\sandbox\win\src\sync_dispatcher.cc(42,7): warning: implicit conversion between pointer-to-function and pointer-to-object is a Microsoft extension [-Wmicrosoft-cast] This change fixes this warning in gtest, while hopefully not changing any behavior. The change does two things: 1. It replaces the if in DefaultPrintTo with SFINAE 2. In C++11 mode, it uses enable_if<is_function<>> instead of ImplicitlyConvertible<T*, const void*> to check if the explicit cast is needed. With this change, functions will use the branch with the reintpret_casts with Visual Studio and clang/win, and clang no longer needs to warn that it implicitly converts a function pointer to a void pointer.
This commit is contained in:
parent
294f72bc77
commit
b2cbbec04c
|
@ -364,11 +364,18 @@ class UniversalPrinter;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void UniversalPrint(const T& value, ::std::ostream* os);
|
void UniversalPrint(const T& value, ::std::ostream* os);
|
||||||
|
|
||||||
|
enum DefaultPrinterType {
|
||||||
|
kPrintContainer,
|
||||||
|
kPrintPointer,
|
||||||
|
kPrintFunctionPointer,
|
||||||
|
kPrintOther,
|
||||||
|
};
|
||||||
|
template <DefaultPrinterType type> struct WrapPrinterType {};
|
||||||
|
|
||||||
// Used to print an STL-style container when the user doesn't define
|
// Used to print an STL-style container when the user doesn't define
|
||||||
// a PrintTo() for it.
|
// a PrintTo() for it.
|
||||||
template <typename C>
|
template <typename C>
|
||||||
void DefaultPrintTo(IsContainer /* dummy */,
|
void DefaultPrintTo(WrapPrinterType<kPrintContainer> /* dummy */,
|
||||||
false_type /* is not a pointer */,
|
|
||||||
const C& container, ::std::ostream* os) {
|
const C& container, ::std::ostream* os) {
|
||||||
const size_t kMaxCount = 32; // The maximum number of elements to print.
|
const size_t kMaxCount = 32; // The maximum number of elements to print.
|
||||||
*os << '{';
|
*os << '{';
|
||||||
|
@ -401,40 +408,38 @@ void DefaultPrintTo(IsContainer /* dummy */,
|
||||||
// implementation-defined. Therefore they will be printed as raw
|
// implementation-defined. Therefore they will be printed as raw
|
||||||
// bytes.)
|
// bytes.)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DefaultPrintTo(IsNotContainer /* dummy */,
|
void DefaultPrintTo(WrapPrinterType<kPrintPointer> /* dummy */,
|
||||||
true_type /* is a pointer */,
|
|
||||||
T* p, ::std::ostream* os) {
|
T* p, ::std::ostream* os) {
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
*os << "NULL";
|
*os << "NULL";
|
||||||
} else {
|
} else {
|
||||||
// C++ doesn't allow casting from a function pointer to any object
|
// T is not a function type. We just call << to print p,
|
||||||
// pointer.
|
// relying on ADL to pick up user-defined << for their pointer
|
||||||
//
|
// types, if any.
|
||||||
// IsTrue() silences warnings: "Condition is always true",
|
*os << p;
|
||||||
// "unreachable code".
|
}
|
||||||
if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
|
}
|
||||||
// T is not a function type. We just call << to print p,
|
template <typename T>
|
||||||
// relying on ADL to pick up user-defined << for their pointer
|
void DefaultPrintTo(WrapPrinterType<kPrintFunctionPointer> /* dummy */,
|
||||||
// types, if any.
|
T* p, ::std::ostream* os) {
|
||||||
*os << p;
|
if (p == NULL) {
|
||||||
} else {
|
*os << "NULL";
|
||||||
// T is a function type, so '*os << p' doesn't do what we want
|
} else {
|
||||||
// (it just prints p as bool). We want to print p as a const
|
// T is a function type, so '*os << p' doesn't do what we want
|
||||||
// void*. However, we cannot cast it to const void* directly,
|
// (it just prints p as bool). We want to print p as a const
|
||||||
// even using reinterpret_cast, as earlier versions of gcc
|
// void*. However, we cannot cast it to const void* directly,
|
||||||
// (e.g. 3.4.5) cannot compile the cast when p is a function
|
// even using reinterpret_cast, as earlier versions of gcc
|
||||||
// pointer. Casting to UInt64 first solves the problem.
|
// (e.g. 3.4.5) cannot compile the cast when p is a function
|
||||||
*os << reinterpret_cast<const void*>(
|
// pointer. Casting to UInt64 first solves the problem.
|
||||||
reinterpret_cast<internal::UInt64>(p));
|
*os << reinterpret_cast<const void*>(
|
||||||
}
|
reinterpret_cast<internal::UInt64>(p));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to print a non-container, non-pointer value when the user
|
// Used to print a non-container, non-pointer value when the user
|
||||||
// doesn't define PrintTo() for it.
|
// doesn't define PrintTo() for it.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void DefaultPrintTo(IsNotContainer /* dummy */,
|
void DefaultPrintTo(WrapPrinterType<kPrintOther> /* dummy */,
|
||||||
false_type /* is not a pointer */,
|
|
||||||
const T& value, ::std::ostream* os) {
|
const T& value, ::std::ostream* os) {
|
||||||
::testing_internal::DefaultPrintNonContainerTo(value, os);
|
::testing_internal::DefaultPrintNonContainerTo(value, os);
|
||||||
}
|
}
|
||||||
|
@ -452,11 +457,8 @@ void DefaultPrintTo(IsNotContainer /* dummy */,
|
||||||
// wants).
|
// wants).
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void PrintTo(const T& value, ::std::ostream* os) {
|
void PrintTo(const T& value, ::std::ostream* os) {
|
||||||
// DefaultPrintTo() is overloaded. The type of its first two
|
// DefaultPrintTo() is overloaded. The type of its first argument
|
||||||
// arguments determine which version will be picked. If T is an
|
// determines which version will be picked.
|
||||||
// STL-style container, the version for container will be called; if
|
|
||||||
// T is a pointer, the pointer version will be called; otherwise the
|
|
||||||
// generic version will be called.
|
|
||||||
//
|
//
|
||||||
// Note that we check for container types here, prior to we check
|
// Note that we check for container types here, prior to we check
|
||||||
// for protocol message types in our operator<<. The rationale is:
|
// for protocol message types in our operator<<. The rationale is:
|
||||||
|
@ -468,13 +470,24 @@ void PrintTo(const T& value, ::std::ostream* os) {
|
||||||
// elements; therefore we check for container types here to ensure
|
// elements; therefore we check for container types here to ensure
|
||||||
// that our format is used.
|
// that our format is used.
|
||||||
//
|
//
|
||||||
// The second argument of DefaultPrintTo() is needed to bypass a bug
|
// Note that MSVC and clang-cl do allow an implicit conversion from
|
||||||
// in Symbian's C++ compiler that prevents it from picking the right
|
// pointer-to-function to pointer-to-object, but clang-cl warns on it.
|
||||||
// overload between:
|
// So don't use ImplicitlyConvertible if it can be helped since it will
|
||||||
//
|
// cause this warning, and use a separate overload of DefaultPrintTo for
|
||||||
// PrintTo(const T& x, ...);
|
// function pointers so that the `*os << p` in the object pointer overload
|
||||||
// PrintTo(T* x, ...);
|
// doesn't cause that warning either.
|
||||||
DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
|
DefaultPrintTo(
|
||||||
|
WrapPrinterType<sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)
|
||||||
|
? kPrintContainer : !is_pointer<T>::value
|
||||||
|
? kPrintOther
|
||||||
|
#if GTEST_LANG_CXX11
|
||||||
|
: std::is_function<typename std::remove_pointer<T>::type>::value
|
||||||
|
#else
|
||||||
|
: !internal::ImplicitlyConvertible<T, const void*>::value
|
||||||
|
#endif
|
||||||
|
? kPrintFunctionPointer
|
||||||
|
: kPrintPointer>(),
|
||||||
|
value, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following list of PrintTo() overloads tells
|
// The following list of PrintTo() overloads tells
|
||||||
|
|
Loading…
Reference in New Issue
Block a user