|
9 | 9 | #ifndef LLVM_SUPPORT_TYPENAME_H |
10 | 10 | #define LLVM_SUPPORT_TYPENAME_H |
11 | 11 |
|
| 12 | +#include <string_view> |
| 13 | + |
12 | 14 | #include "llvm/ADT/StringRef.h" |
13 | 15 |
|
14 | 16 | namespace llvm { |
15 | 17 |
|
16 | | -namespace detail { |
17 | | -template <typename DesiredTypeName> inline StringRef getTypeNameImpl() { |
| 18 | +/// We provide a function which tries to compute the (demangled) name of a type |
| 19 | +/// statically. |
| 20 | +/// |
| 21 | +/// This routine may fail on some platforms or for particularly unusual types. |
| 22 | +/// Do not use it for anything other than logging and debugging aids. It isn't |
| 23 | +/// portable or dependendable in any real sense. |
| 24 | +/// |
| 25 | +/// The returned StringRef will point into a static storage duration string. |
| 26 | +/// However, it may not be null terminated and may be some strangely aligned |
| 27 | +/// inner substring of a larger string. |
| 28 | +template <typename DesiredTypeName> inline constexpr StringRef getTypeName() { |
18 | 29 | #if defined(__clang__) || defined(__GNUC__) |
19 | | - StringRef Name = __PRETTY_FUNCTION__; |
| 30 | + constexpr std::string_view Name = __PRETTY_FUNCTION__; |
20 | 31 |
|
21 | | - StringRef Key = "DesiredTypeName = "; |
22 | | - Name = Name.substr(Name.find(Key)); |
23 | | - assert(!Name.empty() && "Unable to find the template parameter!"); |
24 | | - Name = Name.drop_front(Key.size()); |
| 32 | + constexpr std::string_view Key = "DesiredTypeName = "; |
| 33 | + constexpr std::string_view TemplateParamsStart = Name.substr(Name.find(Key)); |
| 34 | + static_assert(!TemplateParamsStart.empty(), |
| 35 | + "Unable to find the template parameter!"); |
| 36 | + constexpr std::string_view SubstitutionKey = |
| 37 | + TemplateParamsStart.substr(Key.size()); |
25 | 38 |
|
26 | | - assert(Name.ends_with("]") && "Name doesn't end in the substitution key!"); |
27 | | - return Name.drop_back(1); |
| 39 | + // ends_with() is only available in c++20 |
| 40 | + static_assert(!SubstitutionKey.empty() && SubstitutionKey.back() == ']', |
| 41 | + "Name doesn't end in the substitution key!"); |
| 42 | + return SubstitutionKey.substr(0, SubstitutionKey.size() - 1); |
28 | 43 | #elif defined(_MSC_VER) |
29 | | - StringRef Name = __FUNCSIG__; |
| 44 | + constexpr std::string_view Name = __FUNCSIG__; |
30 | 45 |
|
31 | | - StringRef Key = "getTypeNameImpl<"; |
32 | | - Name = Name.substr(Name.find(Key)); |
33 | | - assert(!Name.empty() && "Unable to find the function name!"); |
34 | | - Name = Name.drop_front(Key.size()); |
| 46 | + constexpr std::string_view Key = "getTypeName<"; |
| 47 | + constexpr std::string_view GetTypeNameStart = Name.substr(Name.find(Key)); |
| 48 | + static_assert(!GetTypeNameStart.empty(), |
| 49 | + "Unable to find the template parameter!"); |
| 50 | + constexpr std::string_view SubstitutionKey = |
| 51 | + GetTypeNameStart.substr(Key.size()); |
35 | 52 |
|
36 | | - for (StringRef Prefix : {"class ", "struct ", "union ", "enum "}) |
37 | | - if (Name.starts_with(Prefix)) { |
38 | | - Name = Name.drop_front(Prefix.size()); |
39 | | - break; |
40 | | - } |
| 53 | + // starts_with() only available in c++20 |
| 54 | + constexpr std::string_view RmPrefixClass = |
| 55 | + SubstitutionKey.find("class ") == 0 |
| 56 | + ? SubstitutionKey.substr(sizeof("class ") - 1) |
| 57 | + : SubstitutionKey; |
| 58 | + constexpr std::string_view RmPrefixStruct = |
| 59 | + RmPrefixClass.find("struct ") == 0 |
| 60 | + ? RmPrefixClass.substr(sizeof("struct ") - 1) |
| 61 | + : RmPrefixClass; |
| 62 | + constexpr std::string_view RmPrefixUnion = |
| 63 | + RmPrefixStruct.find("union ") == 0 |
| 64 | + ? RmPrefixStruct.substr(sizeof("union ") - 1) |
| 65 | + : RmPrefixStruct; |
| 66 | + constexpr std::string_view RmPrefixEnum = |
| 67 | + RmPrefixUnion.find("enum ") == 0 |
| 68 | + ? RmPrefixUnion.substr(sizeof("enum ") - 1) |
| 69 | + : RmPrefixUnion; |
41 | 70 |
|
42 | | - auto AnglePos = Name.rfind('>'); |
43 | | - assert(AnglePos != StringRef::npos && "Unable to find the closing '>'!"); |
44 | | - return Name.substr(0, AnglePos); |
| 71 | + constexpr auto AnglePos = RmPrefixEnum.rfind('>'); |
| 72 | + static_assert(AnglePos != std::string_view::npos, |
| 73 | + "Unable to find the closing '>'!"); |
| 74 | + return RmPrefixEnum.substr(0, AnglePos); |
45 | 75 | #else |
46 | 76 | // No known technique for statically extracting a type name on this compiler. |
47 | 77 | // We return a string that is unlikely to look like any type in LLVM. |
48 | 78 | return "UNKNOWN_TYPE"; |
49 | 79 | #endif |
50 | 80 | } |
51 | | -} // namespace detail |
52 | | - |
53 | | -/// We provide a function which tries to compute the (demangled) name of a type |
54 | | -/// statically. |
55 | | -/// |
56 | | -/// This routine may fail on some platforms or for particularly unusual types. |
57 | | -/// Do not use it for anything other than logging and debugging aids. It isn't |
58 | | -/// portable or dependendable in any real sense. |
59 | | -/// |
60 | | -/// The returned StringRef will point into a static storage duration string. |
61 | | -/// However, it may not be null terminated and may be some strangely aligned |
62 | | -/// inner substring of a larger string. |
63 | | -template <typename DesiredTypeName> inline StringRef getTypeName() { |
64 | | - static StringRef Name = detail::getTypeNameImpl<DesiredTypeName>(); |
65 | | - return Name; |
66 | | -} |
67 | 81 |
|
68 | 82 | } // namespace llvm |
69 | 83 |
|
|
0 commit comments