diff --git a/llvm/include/llvm/Support/TypeName.h b/llvm/include/llvm/Support/TypeName.h --- a/llvm/include/llvm/Support/TypeName.h +++ b/llvm/include/llvm/Support/TypeName.h @@ -13,50 +13,62 @@ namespace llvm { -/// We provide a function which tries to compute the (demangled) name of a type -/// statically. +/// TypeNameTraits computes the (demangled) name of a type statically. /// -/// This routine may fail on some platforms or for particularly unusual types. -/// Do not use it for anything other than logging and debugging aids. It isn't -/// portable or dependendable in any real sense. +/// This type trait may fail on some platforms or for particularly unusual +/// types. Do not use it for anything other than logging and debugging aids. +/// It isn't portable or dependable in any real sense. /// /// The returned StringRef will point into a static storage duration string. /// However, it may not be null terminated and may be some strangely aligned /// inner substring of a larger string. +/// +/// This type trait serves as a customization point for the +/// llvm::getTypeName() function defined below. template -inline StringRef getTypeName() { +class TypeNameTraits { +public: + static inline StringRef getTypeName() { #if defined(__clang__) || defined(__GNUC__) - StringRef Name = __PRETTY_FUNCTION__; + StringRef Name = __PRETTY_FUNCTION__; - StringRef Key = "DesiredTypeName = "; - Name = Name.substr(Name.find(Key)); - assert(!Name.empty() && "Unable to find the template parameter!"); - Name = Name.drop_front(Key.size()); + StringRef Key = "DesiredTypeName = "; + Name = Name.substr(Name.find(Key)); + assert(!Name.empty() && "Unable to find the template parameter!"); + Name = Name.drop_front(Key.size()); - assert(Name.endswith("]") && "Name doesn't end in the substitution key!"); - return Name.drop_back(1); + assert(Name.endswith("]") && "Name doesn't end in the substitution key!"); + return Name.drop_back(1); #elif defined(_MSC_VER) - StringRef Name = __FUNCSIG__; + StringRef Name = __FUNCSIG__; - StringRef Key = "getTypeName<"; - Name = Name.substr(Name.find(Key)); - assert(!Name.empty() && "Unable to find the function name!"); - Name = Name.drop_front(Key.size()); + StringRef Key = "getTypeName<"; + Name = Name.substr(Name.find(Key)); + assert(!Name.empty() && "Unable to find the function name!"); + Name = Name.drop_front(Key.size()); - for (StringRef Prefix : {"class ", "struct ", "union ", "enum "}) - if (Name.startswith(Prefix)) { - Name = Name.drop_front(Prefix.size()); - break; - } + for (StringRef Prefix : {"class ", "struct ", "union ", "enum "}) + if (Name.startswith(Prefix)) { + Name = Name.drop_front(Prefix.size()); + break; + } - auto AnglePos = Name.rfind('>'); - assert(AnglePos != StringRef::npos && "Unable to find the closing '>'!"); - return Name.substr(0, AnglePos); + auto AnglePos = Name.rfind('>'); + assert(AnglePos != StringRef::npos && "Unable to find the closing '>'!"); + return Name.substr(0, AnglePos); #else - // No known technique for statically extracting a type name on this compiler. - // We return a string that is unlikely to look like any type in LLVM. - return "UNKNOWN_TYPE"; + // No known technique for statically extracting a type name on this + // compiler. We return a string that is unlikely to look like any type in + // LLVM. + return "UNKNOWN_TYPE"; #endif + } +}; + +/// getTypeName computes the (demangled) name of a type statically. +template +inline StringRef getTypeName() { + return TypeNameTraits::getTypeName(); } } diff --git a/llvm/unittests/Support/TypeNameTest.cpp b/llvm/unittests/Support/TypeNameTest.cpp --- a/llvm/unittests/Support/TypeNameTest.cpp +++ b/llvm/unittests/Support/TypeNameTest.cpp @@ -17,7 +17,24 @@ struct S1 {}; class C1 {}; union U1 {}; -} +} // namespace N1 + +template class A {}; +} // anonymous namespace + +namespace llvm { + +template +class TypeNameTraits> { +public: + static inline StringRef getTypeName() { + return "customized_type_name"; + } +}; + +} // namespace llvm + +namespace { TEST(TypeNameTest, Names) { struct S2 {}; @@ -45,4 +62,9 @@ #endif } -} // end anonymous namespace +TEST(TestNameTest, TypeNameTraitsPartialSpecialization) { + StringRef AIntName = getTypeName>(); + EXPECT_EQ("customized_type_name", AIntName); +} + +} // anonymous namespace