LLVM/project 45ca39dllvm/include/llvm/Support TypeName.h

[Support] Fix for non-constexpr `__PRETTY_FUNCTION__` on older gcc (#128212)

Prior to gcc version 9, the `__PRETTY_FUNCTION__` macro was not declared
constexpr. In that case, don't declare this as constexpr, and switch the
static asserts to runtime asserts.

Verified this should work on all supported compilers:
https://godbolt.org/z/T77rvPW5z

Followup to #127893 / 8a39214b7e6e79e65135b7dbcc98b427a032d5fb
DeltaFile
+44-14llvm/include/llvm/Support/TypeName.h
+44-141 files

UnifiedSplitRaw

llvm/include/llvm/Support/TypeName.h
@@ -13,6 +13,17 @@
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
+// Versions of GCC prior to GCC 9 don't declare __PRETTY_FUNCTION__ as constexpr
+#if defined(__clang__) || defined(_MSC_VER) || \
+ (defined(__GNUC__) && __GNUC__ >= 9)
+#define LLVM_GET_TYPE_NAME_CONSTEXPR constexpr
+#define LLVM_GET_TYPE_NAME_STATIC_ASSERT 1
+#else
+#define LLVM_GET_TYPE_NAME_CONSTEXPR
+#define LLVM_GET_TYPE_NAME_STATIC_ASSERT 0
+#include <cassert>
+#endif
+
namespace llvm { namespace llvm {
/// We provide a function which tries to compute the (demangled) name of a type /// We provide a function which tries to compute the (demangled) name of a type
@@ -25,50 +36,65 @@ namespace llvm {
/// The returned StringRef will point into a static storage duration string. /// The returned StringRef will point into a static storage duration string.
/// However, it may not be null terminated and may be some strangely aligned /// However, it may not be null terminated and may be some strangely aligned
/// inner substring of a larger string. /// inner substring of a larger string.
-template <typename DesiredTypeName> inline constexpr StringRef getTypeName() {+template <typename DesiredTypeName>
+inline LLVM_GET_TYPE_NAME_CONSTEXPR StringRef getTypeName() {
#if defined(__clang__) || defined(__GNUC__) #if defined(__clang__) || defined(__GNUC__)
- constexpr std::string_view Name = __PRETTY_FUNCTION__;+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Name = __PRETTY_FUNCTION__;
- constexpr std::string_view Key = "DesiredTypeName = ";+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Key = "DesiredTypeName = ";
- constexpr std::string_view TemplateParamsStart = Name.substr(Name.find(Key));+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view TemplateParamsStart =
+ Name.substr(Name.find(Key));
+#if LLVM_GET_TYPE_NAME_STATIC_ASSERT
static_assert(!TemplateParamsStart.empty(), static_assert(!TemplateParamsStart.empty(),
"Unable to find the template parameter!"); "Unable to find the template parameter!");
- constexpr std::string_view SubstitutionKey =+#else
+ assert(!TemplateParamsStart.empty() &&
+ "Unable to find the template parameter!");
+#endif
+
+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view SubstitutionKey =
TemplateParamsStart.substr(Key.size()); TemplateParamsStart.substr(Key.size());
+#if LLVM_GET_TYPE_NAME_STATIC_ASSERT
// ends_with() is only available in c++20 // ends_with() is only available in c++20
static_assert(!SubstitutionKey.empty() && SubstitutionKey.back() == ']', static_assert(!SubstitutionKey.empty() && SubstitutionKey.back() == ']',
"Name doesn't end in the substitution key!"); "Name doesn't end in the substitution key!");
+#else
+ assert(!SubstitutionKey.empty() && SubstitutionKey.back() == ']' &&
+ "Name doesn't end in the substitution key!");
+#endif
+
return SubstitutionKey.substr(0, SubstitutionKey.size() - 1); return SubstitutionKey.substr(0, SubstitutionKey.size() - 1);
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
- constexpr std::string_view Name = __FUNCSIG__;+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Name = __FUNCSIG__;
- constexpr std::string_view Key = "getTypeName<";+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Key = "getTypeName<";
- constexpr std::string_view GetTypeNameStart = Name.substr(Name.find(Key));+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view GetTypeNameStart =
+ Name.substr(Name.find(Key));
static_assert(!GetTypeNameStart.empty(), static_assert(!GetTypeNameStart.empty(),
"Unable to find the template parameter!"); "Unable to find the template parameter!");
- constexpr std::string_view SubstitutionKey =+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view SubstitutionKey =
GetTypeNameStart.substr(Key.size()); GetTypeNameStart.substr(Key.size());
// starts_with() only available in c++20 // starts_with() only available in c++20
- constexpr std::string_view RmPrefixClass =+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixClass =
SubstitutionKey.find("class ") == 0 SubstitutionKey.find("class ") == 0
? SubstitutionKey.substr(sizeof("class ") - 1) ? SubstitutionKey.substr(sizeof("class ") - 1)
: SubstitutionKey; : SubstitutionKey;
- constexpr std::string_view RmPrefixStruct =+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixStruct =
RmPrefixClass.find("struct ") == 0 RmPrefixClass.find("struct ") == 0
? RmPrefixClass.substr(sizeof("struct ") - 1) ? RmPrefixClass.substr(sizeof("struct ") - 1)
: RmPrefixClass; : RmPrefixClass;
- constexpr std::string_view RmPrefixUnion =+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixUnion =
RmPrefixStruct.find("union ") == 0 RmPrefixStruct.find("union ") == 0
? RmPrefixStruct.substr(sizeof("union ") - 1) ? RmPrefixStruct.substr(sizeof("union ") - 1)
: RmPrefixStruct; : RmPrefixStruct;
- constexpr std::string_view RmPrefixEnum =+ LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixEnum =
RmPrefixUnion.find("enum ") == 0 RmPrefixUnion.find("enum ") == 0
? RmPrefixUnion.substr(sizeof("enum ") - 1) ? RmPrefixUnion.substr(sizeof("enum ") - 1)
: RmPrefixUnion; : RmPrefixUnion;
- constexpr auto AnglePos = RmPrefixEnum.rfind('>');+ LLVM_GET_TYPE_NAME_CONSTEXPR auto AnglePos = RmPrefixEnum.rfind('>');
static_assert(AnglePos != std::string_view::npos, static_assert(AnglePos != std::string_view::npos,
"Unable to find the closing '>'!"); "Unable to find the closing '>'!");
return RmPrefixEnum.substr(0, AnglePos); return RmPrefixEnum.substr(0, AnglePos);
@@ -81,4 +107,8 @@ template <typename DesiredTypeName> inline constexpr StringRef getTypeName() {
} // namespace llvm } // namespace llvm
+// Don't leak out of this header file
+#undef LLVM_GET_TYPE_NAME_CONSTEXPR
+#undef LLVM_GET_TYPE_NAME_STATIC_ASSERT
+
#endif #endif