xref: /llvm-project/llvm/include/llvm/Support/TypeName.h (revision 5cac0eb4b4156ed7e2dae2a73af04484cf330ddb)
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 "llvm/ADT/StringRef.h"
13 
14 namespace llvm {
15 
16 namespace detail {
17 template <typename DesiredTypeName> inline StringRef getTypeNameImpl() {
18 #if defined(__clang__) || defined(__GNUC__)
19   StringRef Name = __PRETTY_FUNCTION__;
20 
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());
25 
26   assert(Name.ends_with("]") && "Name doesn't end in the substitution key!");
27   return Name.drop_back(1);
28 #elif defined(_MSC_VER)
29   StringRef Name = __FUNCSIG__;
30 
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());
35 
36   for (StringRef Prefix : {"class ", "struct ", "union ", "enum "})
37     if (Name.starts_with(Prefix)) {
38       Name = Name.drop_front(Prefix.size());
39       break;
40     }
41 
42   auto AnglePos = Name.rfind('>');
43   assert(AnglePos != StringRef::npos && "Unable to find the closing '>'!");
44   return Name.substr(0, AnglePos);
45 #else
46   // No known technique for statically extracting a type name on this compiler.
47   // We return a string that is unlikely to look like any type in LLVM.
48   return "UNKNOWN_TYPE";
49 #endif
50 }
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 
68 } // namespace llvm
69 
70 #endif
71