summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2019-01-04 18:48:01 (GMT)
committergennadiycivil <misterg@google.com>2019-01-07 17:09:25 (GMT)
commitb6cd405286ed8635ece71c72f118e659f4ade3fb (patch)
tree5d41d64cb3519951e91a7cedd75328f9e9ffad18
parent3880b13e4c0b04ca88f69b9c93da6058bd836c34 (diff)
downloadgoogletest-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.h27
-rw-r--r--googletest/test/gtest_unittest.cc26
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