1 //===-- RichManglingContext.cpp -------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Core/RichManglingContext.h"
10 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
11 #include "lldb/Utility/LLDBLog.h"
13 #include "llvm/ADT/StringRef.h"
16 using namespace lldb_private
;
18 // RichManglingContext
19 RichManglingContext::~RichManglingContext() {
21 ResetCxxMethodParser();
24 void RichManglingContext::ResetCxxMethodParser() {
25 // If we want to support parsers for other languages some day, we need a
26 // switch here to delete the correct parser type.
27 if (m_cxx_method_parser
.has_value()) {
28 assert(m_provider
== PluginCxxLanguage
);
29 delete get
<CPlusPlusLanguage::MethodName
>(m_cxx_method_parser
);
30 m_cxx_method_parser
.reset();
34 void RichManglingContext::ResetProvider(InfoProvider new_provider
) {
35 ResetCxxMethodParser();
37 assert(new_provider
!= None
&& "Only reset to a valid provider");
38 m_provider
= new_provider
;
41 bool RichManglingContext::FromItaniumName(ConstString mangled
) {
42 bool err
= m_ipd
.partialDemangle(mangled
.GetCString());
44 ResetProvider(ItaniumPartialDemangler
);
47 if (Log
*log
= GetLog(LLDBLog::Demangle
)) {
50 LLDB_LOG(log
, "demangled itanium: {0} -> \"{1}\"", mangled
, m_ipd_buf
);
52 LLDB_LOG(log
, "demangled itanium: {0} -> error: failed to demangle",
57 return !err
; // true == success
60 bool RichManglingContext::FromCxxMethodName(ConstString demangled
) {
61 ResetProvider(PluginCxxLanguage
);
62 m_cxx_method_parser
= new CPlusPlusLanguage::MethodName(demangled
);
66 bool RichManglingContext::IsCtorOrDtor() const {
67 assert(m_provider
!= None
&& "Initialize a provider first");
69 case ItaniumPartialDemangler
:
70 return m_ipd
.isCtorOrDtor();
71 case PluginCxxLanguage
: {
72 // We can only check for destructors here.
74 get
<CPlusPlusLanguage::MethodName
>(m_cxx_method_parser
)->GetBasename();
75 return base_name
.startswith("~");
80 llvm_unreachable("Fully covered switch above!");
83 llvm::StringRef
RichManglingContext::processIPDStrResult(char *ipd_res
,
85 // Error case: Clear the buffer.
86 if (LLVM_UNLIKELY(ipd_res
== nullptr)) {
87 assert(res_size
== m_ipd_buf_size
&&
88 "Failed IPD queries keep the original size in the N parameter");
91 return llvm::StringRef(m_ipd_buf
, 0);
94 // IPD's res_size includes null terminator.
95 assert(ipd_res
[res_size
- 1] == '\0' &&
96 "IPD returns null-terminated strings and we rely on that");
98 // Update buffer/size on realloc.
99 if (LLVM_UNLIKELY(ipd_res
!= m_ipd_buf
|| res_size
> m_ipd_buf_size
)) {
100 m_ipd_buf
= ipd_res
; // std::realloc freed or reused the old buffer.
101 m_ipd_buf_size
= res_size
; // May actually be bigger, but we can't know.
103 if (Log
*log
= GetLog(LLDBLog::Demangle
))
104 LLDB_LOG(log
, "ItaniumPartialDemangler Realloc: new buffer size is {0}",
108 // 99% case: Just remember the string length.
109 return llvm::StringRef(m_ipd_buf
, res_size
- 1);
112 llvm::StringRef
RichManglingContext::ParseFunctionBaseName() {
113 assert(m_provider
!= None
&& "Initialize a provider first");
114 switch (m_provider
) {
115 case ItaniumPartialDemangler
: {
116 auto n
= m_ipd_buf_size
;
117 auto buf
= m_ipd
.getFunctionBaseName(m_ipd_buf
, &n
);
118 return processIPDStrResult(buf
, n
);
120 case PluginCxxLanguage
:
121 return get
<CPlusPlusLanguage::MethodName
>(m_cxx_method_parser
)
126 llvm_unreachable("Fully covered switch above!");
129 llvm::StringRef
RichManglingContext::ParseFunctionDeclContextName() {
130 assert(m_provider
!= None
&& "Initialize a provider first");
131 switch (m_provider
) {
132 case ItaniumPartialDemangler
: {
133 auto n
= m_ipd_buf_size
;
134 auto buf
= m_ipd
.getFunctionDeclContextName(m_ipd_buf
, &n
);
135 return processIPDStrResult(buf
, n
);
137 case PluginCxxLanguage
:
138 return get
<CPlusPlusLanguage::MethodName
>(m_cxx_method_parser
)
143 llvm_unreachable("Fully covered switch above!");
146 llvm::StringRef
RichManglingContext::ParseFullName() {
147 assert(m_provider
!= None
&& "Initialize a provider first");
148 switch (m_provider
) {
149 case ItaniumPartialDemangler
: {
150 auto n
= m_ipd_buf_size
;
151 auto buf
= m_ipd
.finishDemangle(m_ipd_buf
, &n
);
152 return processIPDStrResult(buf
, n
);
154 case PluginCxxLanguage
:
155 return get
<CPlusPlusLanguage::MethodName
>(m_cxx_method_parser
)
161 llvm_unreachable("Fully covered switch above!");