//===- TypeName.h -----------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_TYPENAME_H #define LLVM_SUPPORT_TYPENAME_H #include #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 #endif namespace llvm { /// We provide a function which tries to compute 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. /// /// 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. template inline LLVM_GET_TYPE_NAME_CONSTEXPR StringRef getTypeName() { #if defined(__clang__) || defined(__GNUC__) LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Name = __PRETTY_FUNCTION__; LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Key = "DesiredTypeName = "; 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(), "Unable to find the template parameter!"); #else assert(!TemplateParamsStart.empty() && "Unable to find the template parameter!"); #endif LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view SubstitutionKey = TemplateParamsStart.substr(Key.size()); #if LLVM_GET_TYPE_NAME_STATIC_ASSERT // ends_with() is only available in c++20 static_assert(!SubstitutionKey.empty() && SubstitutionKey.back() == ']', "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); #elif defined(_MSC_VER) LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Name = __FUNCSIG__; LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view Key = "getTypeName<"; LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view GetTypeNameStart = Name.substr(Name.find(Key)); static_assert(!GetTypeNameStart.empty(), "Unable to find the template parameter!"); LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view SubstitutionKey = GetTypeNameStart.substr(Key.size()); // starts_with() only available in c++20 LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixClass = SubstitutionKey.find("class ") == 0 ? SubstitutionKey.substr(sizeof("class ") - 1) : SubstitutionKey; LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixStruct = RmPrefixClass.find("struct ") == 0 ? RmPrefixClass.substr(sizeof("struct ") - 1) : RmPrefixClass; LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixUnion = RmPrefixStruct.find("union ") == 0 ? RmPrefixStruct.substr(sizeof("union ") - 1) : RmPrefixStruct; LLVM_GET_TYPE_NAME_CONSTEXPR std::string_view RmPrefixEnum = RmPrefixUnion.find("enum ") == 0 ? RmPrefixUnion.substr(sizeof("enum ") - 1) : RmPrefixUnion; LLVM_GET_TYPE_NAME_CONSTEXPR auto AnglePos = RmPrefixEnum.rfind('>'); static_assert(AnglePos != std::string_view::npos, "Unable to find the closing '>'!"); return RmPrefixEnum.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"; #endif } } // namespace llvm // Don't leak out of this header file #undef LLVM_GET_TYPE_NAME_CONSTEXPR #undef LLVM_GET_TYPE_NAME_STATIC_ASSERT #endif