1 // Copyright 2008 Google Inc. 2 // All Rights Reserved. 3 // 4 // Redistribution and use in source and binary forms, with or without 5 // modification, are permitted provided that the following conditions are 6 // met: 7 // 8 // * Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // * Redistributions in binary form must reproduce the above 11 // copyright notice, this list of conditions and the following disclaimer 12 // in the documentation and/or other materials provided with the 13 // distribution. 14 // * Neither the name of Google Inc. nor the names of its 15 // contributors may be used to endorse or promote products derived from 16 // this software without specific prior written permission. 17 // 18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 // Type utilities needed for implementing typed and type-parameterized 31 // tests. 32 33 // IWYU pragma: private, include "gtest/gtest.h" 34 // IWYU pragma: friend gtest/.* 35 // IWYU pragma: friend gmock/.* 36 37 #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 38 #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 39 40 #include <string> 41 #include <type_traits> 42 #include <typeinfo> 43 44 #include "gtest/internal/gtest-port.h" 45 46 // #ifdef __GNUC__ is too general here. It is possible to use gcc without using 47 // libstdc++ (which is where cxxabi.h comes from). 48 #if GTEST_HAS_CXXABI_H_ 49 #include <cxxabi.h> 50 #elif defined(__HP_aCC) 51 #include <acxx_demangle.h> 52 #endif // GTEST_HASH_CXXABI_H_ 53 54 namespace testing { 55 namespace internal { 56 57 // Canonicalizes a given name with respect to the Standard C++ Library. 58 // This handles removing the inline namespace within `std` that is 59 // used by various standard libraries (e.g., `std::__1`). Names outside 60 // of namespace std are returned unmodified. 61 inline std::string CanonicalizeForStdLibVersioning(std::string s) { 62 static const char prefix[] = "std::__"; 63 if (s.compare(0, strlen(prefix), prefix) == 0) { 64 std::string::size_type end = s.find("::", strlen(prefix)); 65 if (end != s.npos) { 66 // Erase everything between the initial `std` and the second `::`. 67 s.erase(strlen("std"), end - strlen("std")); 68 } 69 } 70 71 // Strip redundant spaces in typename to match MSVC 72 // For example, std::pair<int, bool> -> std::pair<int,bool> 73 static const char to_search[] = ", "; 74 static const char replace_str[] = ","; 75 size_t pos = 0; 76 while (true) { 77 // Get the next occurrence from the current position 78 pos = s.find(to_search, pos); 79 if (pos == std::string::npos) { 80 break; 81 } 82 // Replace this occurrence of substring 83 s.replace(pos, strlen(to_search), replace_str); 84 pos += strlen(replace_str); 85 } 86 return s; 87 } 88 89 #if GTEST_HAS_RTTI 90 // GetTypeName(const std::type_info&) returns a human-readable name of type T. 91 inline std::string GetTypeName(const std::type_info& type) { 92 const char* const name = type.name(); 93 #if GTEST_HAS_CXXABI_H_ || defined(__HP_aCC) 94 int status = 0; 95 // gcc's implementation of typeid(T).name() mangles the type name, 96 // so we have to demangle it. 97 #if GTEST_HAS_CXXABI_H_ 98 using abi::__cxa_demangle; 99 #endif // GTEST_HAS_CXXABI_H_ 100 char* const readable_name = __cxa_demangle(name, nullptr, nullptr, &status); 101 const std::string name_str(status == 0 ? readable_name : name); 102 free(readable_name); 103 return CanonicalizeForStdLibVersioning(name_str); 104 #elif defined(_MSC_VER) 105 // Strip struct and class due to differences between 106 // MSVC and other compilers. std::pair<int,bool> is printed as 107 // "struct std::pair<int,bool>" when using MSVC vs "std::pair<int, bool>" with 108 // other compilers. 109 std::string s = name; 110 // Only strip the leading "struct " and "class ", so uses rfind == 0 to 111 // ensure that 112 if (s.rfind("struct ", 0) == 0) { 113 s = s.substr(strlen("struct ")); 114 } else if (s.rfind("class ", 0) == 0) { 115 s = s.substr(strlen("class ")); 116 } 117 return s; 118 #else 119 return name; 120 #endif // GTEST_HAS_CXXABI_H_ || __HP_aCC 121 } 122 #endif // GTEST_HAS_RTTI 123 124 // GetTypeName<T>() returns a human-readable name of type T if and only if 125 // RTTI is enabled, otherwise it returns a dummy type name. 126 // NB: This function is also used in Google Mock, so don't move it inside of 127 // the typed-test-only section below. 128 template <typename T> 129 std::string GetTypeName() { 130 #if GTEST_HAS_RTTI 131 return GetTypeName(typeid(T)); 132 #else 133 return "<type>"; 134 #endif // GTEST_HAS_RTTI 135 } 136 137 // A unique type indicating an empty node 138 struct None {}; 139 140 #define GTEST_TEMPLATE_ \ 141 template <typename T> \ 142 class 143 144 // The template "selector" struct TemplateSel<Tmpl> is used to 145 // represent Tmpl, which must be a class template with one type 146 // parameter, as a type. TemplateSel<Tmpl>::Bind<T>::type is defined 147 // as the type Tmpl<T>. This allows us to actually instantiate the 148 // template "selected" by TemplateSel<Tmpl>. 149 // 150 // This trick is necessary for simulating typedef for class templates, 151 // which C++ doesn't support directly. 152 template <GTEST_TEMPLATE_ Tmpl> 153 struct TemplateSel { 154 template <typename T> 155 struct Bind { 156 typedef Tmpl<T> type; 157 }; 158 }; 159 160 #define GTEST_BIND_(TmplSel, T) TmplSel::template Bind<T>::type 161 162 template <GTEST_TEMPLATE_ Head_, GTEST_TEMPLATE_... Tail_> 163 struct Templates { 164 using Head = TemplateSel<Head_>; 165 using Tail = Templates<Tail_...>; 166 }; 167 168 template <GTEST_TEMPLATE_ Head_> 169 struct Templates<Head_> { 170 using Head = TemplateSel<Head_>; 171 using Tail = None; 172 }; 173 174 // Tuple-like type lists 175 template <typename Head_, typename... Tail_> 176 struct Types { 177 using Head = Head_; 178 using Tail = Types<Tail_...>; 179 }; 180 181 template <typename Head_> 182 struct Types<Head_> { 183 using Head = Head_; 184 using Tail = None; 185 }; 186 187 // Helper metafunctions to tell apart a single type from types 188 // generated by ::testing::Types 189 template <typename... Ts> 190 struct ProxyTypeList { 191 using type = Types<Ts...>; 192 }; 193 194 template <typename> 195 struct is_proxy_type_list : std::false_type {}; 196 197 template <typename... Ts> 198 struct is_proxy_type_list<ProxyTypeList<Ts...>> : std::true_type {}; 199 200 // Generator which conditionally creates type lists. 201 // It recognizes if a requested type list should be created 202 // and prevents creating a new type list nested within another one. 203 template <typename T> 204 struct GenerateTypeList { 205 private: 206 using proxy = typename std::conditional<is_proxy_type_list<T>::value, T, 207 ProxyTypeList<T>>::type; 208 209 public: 210 using type = typename proxy::type; 211 }; 212 213 } // namespace internal 214 215 template <typename... Ts> 216 using Types = internal::ProxyTypeList<Ts...>; 217 218 } // namespace testing 219 220 #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_ 221