From eb3953f805d0ed9054dba78b8e842caba0b539c2 Mon Sep 17 00:00:00 2001
From: Krystian Kuzniarek <krystian.kuzniarek@gmail.com>
Date: Sat, 7 Mar 2020 17:25:51 +0100
Subject: [PATCH] make UniversalPrinter<std::any> support RTTI

---
 googletest/include/gtest/gtest-printers.h     | 11 +++++-
 .../include/gtest/internal/gtest-type-util.h  | 38 ++++++++++---------
 googletest/test/googletest-printers-test.cc   | 20 ++++++++--
 3 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h
index 67c87f47..718e6f13 100644
--- a/googletest/include/gtest/gtest-printers.h
+++ b/googletest/include/gtest/gtest-printers.h
@@ -688,13 +688,20 @@ class UniversalPrinter<Any> {
  public:
   static void Print(const Any& value, ::std::ostream* os) {
     if (value.has_value())
-      *os << "'any' type with value of type " << GetTypeName();
+      *os << "'any' type with value of type " << GetTypeName(value);
     else
       *os << "'any' type with no value";
   }
 
  private:
-  static std::string GetTypeName() { return "the element type"; }
+  static std::string GetTypeName(const Any& value) {
+#if GTEST_HAS_RTTI
+    return internal::GetTypeName(value.type());
+#else
+    static_cast<void>(value); // possibly unused
+    return "the element type";
+#endif  // GTEST_HAS_RTTI
+  }
 };
 
 #endif  // GTEST_INTERNAL_HAS_ANY
diff --git a/googletest/include/gtest/internal/gtest-type-util.h b/googletest/include/gtest/internal/gtest-type-util.h
index 082fdad1..c3326f2c 100644
--- a/googletest/include/gtest/internal/gtest-type-util.h
+++ b/googletest/include/gtest/internal/gtest-type-util.h
@@ -64,34 +64,38 @@ inline std::string CanonicalizeForStdLibVersioning(std::string s) {
   return s;
 }
 
-// GetTypeName<T>() returns a human-readable name of type T.
-// NB: This function is also used in Google Mock, so don't move it inside of
-// the typed-test-only section below.
-template <typename T>
-std::string GetTypeName() {
-# if GTEST_HAS_RTTI
-
-  const char* const name = typeid(T).name();
-#  if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
+#if GTEST_HAS_RTTI
+// GetTypeName(const std::type_info&) returns a human-readable name of type T.
+inline std::string GetTypeName(const std::type_info& type) {
+  const char* const name = type.name();
+#if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC)
   int status = 0;
   // gcc's implementation of typeid(T).name() mangles the type name,
   // so we have to demangle it.
-#   if GTEST_HAS_CXXABI_H_
+#if GTEST_HAS_CXXABI_H_
   using abi::__cxa_demangle;
-#   endif  // GTEST_HAS_CXXABI_H_
+#endif  // GTEST_HAS_CXXABI_H_
   char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status);
   const std::string name_str(status == 0 ? readable_name : name);
   free(readable_name);
   return CanonicalizeForStdLibVersioning(name_str);
-#  else
+#else
   return name;
-#  endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
-
-# else
+#endif  // GTEST_HAS_CXXABI_H_ || __HP_aCC
+}
+#endif  // GTEST_HAS_RTTI
 
+// GetTypeName<T>() returns a human-readable name of type T if and only if
+// RTTI is enabled, otherwise it returns a dummy type name.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+std::string GetTypeName() {
+#if GTEST_HAS_RTTI
+  return GetTypeName(typeid(T));
+#else
   return "<type>";
-
-# endif  // GTEST_HAS_RTTI
+#endif  // GTEST_HAS_RTTI
 }
 
 #if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
diff --git a/googletest/test/googletest-printers-test.cc b/googletest/test/googletest-printers-test.cc
index 33050352..1324dd6e 100644
--- a/googletest/test/googletest-printers-test.cc
+++ b/googletest/test/googletest-printers-test.cc
@@ -1532,22 +1532,34 @@ TEST(UniversalTersePrintTupleFieldsToStringsTestWithStd, PrintsTersely) {
 }
 
 #if GTEST_INTERNAL_HAS_ANY
-TEST(PrintAnyTest, Empty) {
+class PrintAnyTest : public ::testing::Test {
+ protected:
+  template <typename T>
+  static std::string ExpectedTypeName() {
+#if GTEST_HAS_RTTI
+    return internal::GetTypeName<T>();
+#else
+    return "the element type";
+#endif  // GTEST_HAS_RTTI
+  }
+};
+
+TEST_F(PrintAnyTest, Empty) {
   internal::Any any;
   EXPECT_EQ("'any' type with no value", PrintToString(any));
 }
 
-TEST(PrintAnyTest, NonEmpty) {
+TEST_F(PrintAnyTest, NonEmpty) {
   internal::Any any;
   constexpr int val1 = 10;
   const std::string val2 = "content";
 
   any = val1;
-  EXPECT_EQ("'any' type with value of type the element type",
+  EXPECT_EQ("'any' type with value of type " + ExpectedTypeName<int>(),
             PrintToString(any));
 
   any = val2;
-  EXPECT_EQ("'any' type with value of type the element type",
+  EXPECT_EQ("'any' type with value of type " + ExpectedTypeName<std::string>(),
             PrintToString(any));
 }
 #endif  // GTEST_INTERNAL_HAS_ANY
-- 
GitLab