1303231Sdim//===- TypeName.h -----------------------------------------------*- C++ -*-===//
2303231Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6303231Sdim//
7303231Sdim//===----------------------------------------------------------------------===//
8303231Sdim
9303231Sdim#ifndef LLVM_SUPPORT_TYPENAME_H
10303231Sdim#define LLVM_SUPPORT_TYPENAME_H
11303231Sdim
12303231Sdim#include "llvm/ADT/StringRef.h"
13303231Sdim
14303231Sdimnamespace llvm {
15303231Sdim
16303231Sdim/// We provide a function which tries to compute the (demangled) name of a type
17303231Sdim/// statically.
18303231Sdim///
19303231Sdim/// This routine may fail on some platforms or for particularly unusual types.
20303231Sdim/// Do not use it for anything other than logging and debugging aids. It isn't
21303231Sdim/// portable or dependendable in any real sense.
22303231Sdim///
23303231Sdim/// The returned StringRef will point into a static storage duration string.
24303231Sdim/// However, it may not be null terminated and may be some strangely aligned
25303231Sdim/// inner substring of a larger string.
26303231Sdimtemplate <typename DesiredTypeName>
27303231Sdiminline StringRef getTypeName() {
28303231Sdim#if defined(__clang__) || defined(__GNUC__)
29303231Sdim  StringRef Name = __PRETTY_FUNCTION__;
30303231Sdim
31303231Sdim  StringRef Key = "DesiredTypeName = ";
32303231Sdim  Name = Name.substr(Name.find(Key));
33303231Sdim  assert(!Name.empty() && "Unable to find the template parameter!");
34303231Sdim  Name = Name.drop_front(Key.size());
35303231Sdim
36303231Sdim  assert(Name.endswith("]") && "Name doesn't end in the substitution key!");
37303231Sdim  return Name.drop_back(1);
38303231Sdim#elif defined(_MSC_VER)
39303231Sdim  StringRef Name = __FUNCSIG__;
40303231Sdim
41303231Sdim  StringRef Key = "getTypeName<";
42303231Sdim  Name = Name.substr(Name.find(Key));
43303231Sdim  assert(!Name.empty() && "Unable to find the function name!");
44303231Sdim  Name = Name.drop_front(Key.size());
45303231Sdim
46303231Sdim  for (StringRef Prefix : {"class ", "struct ", "union ", "enum "})
47303231Sdim    if (Name.startswith(Prefix)) {
48303231Sdim      Name = Name.drop_front(Prefix.size());
49303231Sdim      break;
50303231Sdim    }
51303231Sdim
52303231Sdim  auto AnglePos = Name.rfind('>');
53303231Sdim  assert(AnglePos != StringRef::npos && "Unable to find the closing '>'!");
54303231Sdim  return Name.substr(0, AnglePos);
55303231Sdim#else
56303231Sdim  // No known technique for statically extracting a type name on this compiler.
57303231Sdim  // We return a string that is unlikely to look like any type in LLVM.
58303231Sdim  return "UNKNOWN_TYPE";
59303231Sdim#endif
60303231Sdim}
61303231Sdim
62303231Sdim}
63303231Sdim
64303231Sdim#endif
65