1 //===- TypeName.h -----------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_SUPPORT_TYPENAME_H 10 #define LLVM_SUPPORT_TYPENAME_H 11 12 #include <string_view> 13 14 #include "llvm/ADT/StringRef.h" 15 16 // Versions of GCC prior to GCC 9 don't declare __PRETTY_FUNCTION__ as constexpr 17 #if defined(__clang__) || defined(_MSC_VER) || \ 18 (defined(__GNUC__) && __GNUC__ >= 9) 19 #define LLVM_GET_TYPE_NAME_CONSTEXPR constexpr 20 #define LLVM_GET_TYPE_NAME_STATIC_ASSERT 1 21 #else 22 #define LLVM_GET_TYPE_NAME_CONSTEXPR 23 #define LLVM_GET_TYPE_NAME_STATIC_ASSERT 0 24 #include <cassert> 25 #endif 26 27 namespace llvm { 28 29 /// We provide a function which tries to compute the (demangled) name of a type 30 /// statically. 31 /// 32 /// This routine may fail on some platforms or for particularly unusual types. 33 /// Do not use it for anything other than logging and debugging aids. It isn't 34 /// portable or dependendable in any real sense. 35 /// 36 /// The returned StringRef will point into a static storage duration string. 37 /// However, it may not be null terminated and may be some strangely aligned 38 /// inner substring of a larger string. 39 template <typename DesiredTypeName> getTypeName()40inline LLVM_GET_TYPE_NAME_CONSTEXPR StringRef getTypeName() { 41 #if defined(__clang__) || defined(__GNUC__) 42 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Name = __PRETTY_FUNCTION__; 43 44 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Key = "DesiredTypeName = "; 45 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view TemplateParamsStart = 46 Name.substr(Name.find(Key)); 47 #if LLVM_GET_TYPE_NAME_STATIC_ASSERT 48 static_assert(!TemplateParamsStart.empty(), 49 "Unable to find the template parameter!"); 50 #else 51 assert(!TemplateParamsStart.empty() && 52 "Unable to find the template parameter!"); 53 #endif 54 55 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view SubstitutionKey = 56 TemplateParamsStart.substr(Key.size()); 57 58 #if LLVM_GET_TYPE_NAME_STATIC_ASSERT 59 // ends_with() is only available in c++20 60 static_assert(!SubstitutionKey.empty() && SubstitutionKey.back() == ']', 61 "Name doesn't end in the substitution key!"); 62 #else 63 assert(!SubstitutionKey.empty() && SubstitutionKey.back() == ']' && 64 "Name doesn't end in the substitution key!"); 65 #endif 66 67 return SubstitutionKey.substr(0, SubstitutionKey.size() - 1); 68 #elif defined(_MSC_VER) 69 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Name = __FUNCSIG__; 70 71 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Key = "getTypeName<"; 72 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view GetTypeNameStart = 73 Name.substr(Name.find(Key)); 74 static_assert(!GetTypeNameStart.empty(), 75 "Unable to find the template parameter!"); 76 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view SubstitutionKey = 77 GetTypeNameStart.substr(Key.size()); 78 79 // starts_with() only available in c++20 80 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixClass = 81 SubstitutionKey.find("class ") == 0 82 ? SubstitutionKey.substr(sizeof("class ") - 1) 83 : SubstitutionKey; 84 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixStruct = 85 RmPrefixClass.find("struct ") == 0 86 ? RmPrefixClass.substr(sizeof("struct ") - 1) 87 : RmPrefixClass; 88 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixUnion = 89 RmPrefixStruct.find("union ") == 0 90 ? RmPrefixStruct.substr(sizeof("union ") - 1) 91 : RmPrefixStruct; 92 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixEnum = 93 RmPrefixUnion.find("enum ") == 0 94 ? RmPrefixUnion.substr(sizeof("enum ") - 1) 95 : RmPrefixUnion; 96 97 LLVM_GET_TYPE_NAME_CONSTEXPR auto AnglePos = RmPrefixEnum.rfind('>'); 98 static_assert(AnglePos != std::string_view::npos, 99 "Unable to find the closing '>'!"); 100 return RmPrefixEnum.substr(0, AnglePos); 101 #else 102 // No known technique for statically extracting a type name on this compiler. 103 // We return a string that is unlikely to look like any type in LLVM. 104 return "UNKNOWN_TYPE"; 105 #endif 106 } 107 108 } // namespace llvm 109 110 // Don't leak out of this header file 111 #undef LLVM_GET_TYPE_NAME_CONSTEXPR 112 #undef LLVM_GET_TYPE_NAME_STATIC_ASSERT 113 114 #endif 115