1//===-- RichManglingContext.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 liblldb_RichManglingContext_h_
10#define liblldb_RichManglingContext_h_
11
12#include "lldb/lldb-forward.h"
13#include "lldb/lldb-private.h"
14
15#include "lldb/Utility/ConstString.h"
16
17#include "llvm/ADT/Any.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/Demangle/Demangle.h"
20
21namespace lldb_private {
22
23/// Uniform wrapper for access to rich mangling information from different
24/// providers. See Mangled::DemangleWithRichManglingInfo()
25class RichManglingContext {
26public:
27  RichManglingContext() : m_provider(None), m_ipd_buf_size(2048) {
28    m_ipd_buf = static_cast<char *>(std::malloc(m_ipd_buf_size));
29    m_ipd_buf[0] = '\0';
30  }
31
32  ~RichManglingContext() { std::free(m_ipd_buf); }
33
34  /// Use the ItaniumPartialDemangler to obtain rich mangling information from
35  /// the given mangled name.
36  bool FromItaniumName(ConstString mangled);
37
38  /// Use the legacy language parser implementation to obtain rich mangling
39  /// information from the given demangled name.
40  bool FromCxxMethodName(ConstString demangled);
41
42  /// If this symbol describes a constructor or destructor.
43  bool IsCtorOrDtor() const;
44
45  /// If this symbol describes a function.
46  bool IsFunction() const;
47
48  /// Get the base name of a function. This doesn't include trailing template
49  /// arguments, ie "a::b<int>" gives "b". The result will overwrite the
50  /// internal buffer. It can be obtained via GetBufferRef().
51  void ParseFunctionBaseName();
52
53  /// Get the context name for a function. For "a::b::c", this function returns
54  /// "a::b". The result will overwrite the internal buffer. It can be obtained
55  /// via GetBufferRef().
56  void ParseFunctionDeclContextName();
57
58  /// Get the entire demangled name. The result will overwrite the internal
59  /// buffer. It can be obtained via GetBufferRef().
60  void ParseFullName();
61
62  /// Obtain a StringRef to the internal buffer that holds the result of the
63  /// most recent ParseXy() operation. The next ParseXy() call invalidates it.
64  llvm::StringRef GetBufferRef() const {
65    assert(m_provider != None && "Initialize a provider first");
66    return m_buffer;
67  }
68
69private:
70  enum InfoProvider { None, ItaniumPartialDemangler, PluginCxxLanguage };
71
72  /// Selects the rich mangling info provider.
73  InfoProvider m_provider;
74
75  /// Reference to the buffer used for results of ParseXy() operations.
76  llvm::StringRef m_buffer;
77
78  /// Members for ItaniumPartialDemangler
79  llvm::ItaniumPartialDemangler m_ipd;
80  char *m_ipd_buf;
81  size_t m_ipd_buf_size;
82
83  /// Members for PluginCxxLanguage
84  /// Cannot forward declare inner class CPlusPlusLanguage::MethodName. The
85  /// respective header is in Plugins and including it from here causes cyclic
86  /// dependency. Instead keep a llvm::Any and cast it on-access in the cpp.
87  llvm::Any m_cxx_method_parser;
88
89  /// Clean up memory and set a new info provider for this instance.
90  void ResetProvider(InfoProvider new_provider);
91
92  /// Uniform handling of string buffers for ItaniumPartialDemangler.
93  void processIPDStrResult(char *ipd_res, size_t res_len);
94
95  /// Cast the given parser to the given type. Ideally we would have a type
96  /// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we
97  /// can't access CPlusPlusLanguage::MethodName from within the header.
98  template <class ParserT> static ParserT *get(llvm::Any parser) {
99    assert(parser.hasValue());
100    assert(llvm::any_isa<ParserT *>(parser));
101    return llvm::any_cast<ParserT *>(parser);
102  }
103};
104
105} // namespace lldb_private
106
107#endif
108