|
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