diff options
author | Abseil Team <absl-team@google.com> | 2019-01-04 18:48:01 (GMT) |
---|---|---|
committer | gennadiycivil <misterg@google.com> | 2019-01-07 17:09:25 (GMT) |
commit | b6cd405286ed8635ece71c72f118e659f4ade3fb (patch) | |
tree | 5d41d64cb3519951e91a7cedd75328f9e9ffad18 | |
parent | 3880b13e4c0b04ca88f69b9c93da6058bd836c34 (diff) | |
download | googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb.zip googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb.tar.gz googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb.tar.bz2 |
Googletest export
Fix GTEST_IS_NULL_LITERAL_ for types that have magic implicit conversions.
PiperOrigin-RevId: 227879345
-rw-r--r-- | googletest/include/gtest/internal/gtest-internal.h | 27 | ||||
-rw-r--r-- | googletest/test/gtest_unittest.cc | 26 |
2 files changed, 45 insertions, 8 deletions
diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h index 02ef3b3..8ef69c4 100644 --- a/googletest/include/gtest/internal/gtest-internal.h +++ b/googletest/include/gtest/internal/gtest-internal.h @@ -58,6 +58,7 @@ #include <map> #include <set> #include <string> +#include <type_traits> #include <vector> #include "gtest/gtest-message.h" @@ -108,16 +109,29 @@ GTEST_API_ extern const char kStackTraceMarker[]; // An IgnoredValue object can be implicitly constructed from ANY value. class IgnoredValue { + struct Sink {}; public: // This constructor template allows any value to be implicitly // converted to IgnoredValue. The object has no data member and // doesn't try to remember anything about the argument. We // deliberately omit the 'explicit' keyword in order to allow the // conversion to be implicit. - template <typename T> + // Disable the conversion if T already has a magical conversion operator. + // Otherwise we get ambiguity. + template <typename T, + typename std::enable_if<!std::is_convertible<T, Sink>::value, + int>::type = 0> IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit) }; +// The only type that should be convertible to Secret* is nullptr. +// The other null pointer constants are not of a type that is convertible to +// Secret*. Only the literal with the right value is. +template <typename T> +using TypeIsValidNullptrConstant = std::integral_constant< + bool, std::is_same<typename std::decay<T>::type, std::nullptr_t>::value || + !std::is_convertible<T, Secret*>::value>; + // Two overloaded helpers for checking at compile time whether an // expression is a null pointer literal (i.e. NULL or any 0-valued // compile-time integral constant). These helpers have no @@ -130,13 +144,16 @@ class IgnoredValue { // a null pointer literal. Therefore, we know that x is a null // pointer literal if and only if the first version is picked by the // compiler. -std::true_type IsNullLiteralHelper(Secret*); -std::false_type IsNullLiteralHelper(IgnoredValue); +std::true_type IsNullLiteralHelper(Secret*, std::true_type); +std::false_type IsNullLiteralHelper(IgnoredValue, std::false_type); +std::false_type IsNullLiteralHelper(IgnoredValue, std::true_type); // A compile-time bool constant that is true if and only if x is a null pointer // literal (i.e. nullptr, NULL or any 0-valued compile-time integral constant). -#define GTEST_IS_NULL_LITERAL_(x) \ - decltype(::testing::internal::IsNullLiteralHelper(x))::value +#define GTEST_IS_NULL_LITERAL_(x) \ + decltype(::testing::internal::IsNullLiteralHelper( \ + x, \ + ::testing::internal::TypeIsValidNullptrConstant<decltype(x)>()))::value // Appends the user-supplied message to the Google-Test-generated message. GTEST_API_ std::string AppendUserMessage( diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc index 5e0e43a..147f0f5 100644 --- a/googletest/test/gtest_unittest.cc +++ b/googletest/test/gtest_unittest.cc @@ -519,9 +519,9 @@ TEST_F(FormatEpochTimeInMillisAsIso8601Test, PrintsEpochStart) { // Tests that GTEST_IS_NULL_LITERAL_(x) is true when x is a null // pointer literal. TEST(NullLiteralTest, IsTrueForNullLiterals) { - EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(nullptr)); - EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(nullptr)); - EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(nullptr)); + EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(NULL)); // NOLINT + EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(0)); // NOLINT + EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(0u)); // NOLINT EXPECT_TRUE(GTEST_IS_NULL_LITERAL_(nullptr)); } @@ -534,6 +534,26 @@ TEST(NullLiteralTest, IsFalseForNonNullLiterals) { EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(static_cast<void*>(nullptr))); } +struct ConvertToAll { + template <typename T> + operator T() const { // NOLINT + return T(); + } +}; + +struct ConvertToAllButNoPointers { + template <typename T, + typename std::enable_if<!std::is_pointer<T>::value, int>::type = 0> + operator T() const { // NOLINT + return T(); + } +}; + +TEST(NullLiteralTest, ImplicitConversion) { + EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(ConvertToAll{})); + EXPECT_FALSE(GTEST_IS_NULL_LITERAL_(ConvertToAllButNoPointers{})); +} + # ifdef __BORLANDC__ // Restores warnings after previous "#pragma option push" suppressed them. # pragma option pop |