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"
11 #include "lldb/Utility/Log.h"
12 #include "lldb/Utility/Logging.h"
14 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
16 #include "llvm/ADT/StringRef.h"
19 using namespace lldb_private;
21 // RichManglingContext
22 void RichManglingContext::ResetProvider(InfoProvider new_provider) {
23 // If we want to support parsers for other languages some day, we need a
24 // switch here to delete the correct parser type.
25 if (m_cxx_method_parser.hasValue()) {
26 assert(m_provider == PluginCxxLanguage);
27 delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser);
28 m_cxx_method_parser.reset();
31 assert(new_provider != None && "Only reset to a valid provider");
32 m_provider = new_provider;
35 bool RichManglingContext::FromItaniumName(ConstString mangled) {
36 bool err = m_ipd.partialDemangle(mangled.GetCString());
38 ResetProvider(ItaniumPartialDemangler);
41 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
44 LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf);
46 LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle",
51 return !err; // true == success
54 bool RichManglingContext::FromCxxMethodName(ConstString demangled) {
55 ResetProvider(PluginCxxLanguage);
56 m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled);
60 bool RichManglingContext::IsCtorOrDtor() const {
61 assert(m_provider != None && "Initialize a provider first");
63 case ItaniumPartialDemangler:
64 return m_ipd.isCtorOrDtor();
65 case PluginCxxLanguage: {
66 // We can only check for destructors here.
68 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
69 return base_name.startswith("~");
74 llvm_unreachable("Fully covered switch above!");
77 bool RichManglingContext::IsFunction() const {
78 assert(m_provider != None && "Initialize a provider first");
80 case ItaniumPartialDemangler:
81 return m_ipd.isFunction();
82 case PluginCxxLanguage:
83 return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->IsValid();
87 llvm_unreachable("Fully covered switch above!");
90 void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) {
91 // Error case: Clear the buffer.
92 if (LLVM_UNLIKELY(ipd_res == nullptr)) {
93 assert(res_size == m_ipd_buf_size &&
94 "Failed IPD queries keep the original size in the N parameter");
97 m_buffer = llvm::StringRef(m_ipd_buf, 0);
101 // IPD's res_size includes null terminator.
102 assert(ipd_res[res_size - 1] == '\0' &&
103 "IPD returns null-terminated strings and we rely on that");
105 // Update buffer/size on realloc.
106 if (LLVM_UNLIKELY(ipd_res != m_ipd_buf || res_size > m_ipd_buf_size)) {
107 m_ipd_buf = ipd_res; // std::realloc freed or reused the old buffer.
108 m_ipd_buf_size = res_size; // May actually be bigger, but we can't know.
110 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE))
111 LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}",
115 // 99% case: Just remember the string length.
116 m_buffer = llvm::StringRef(m_ipd_buf, res_size - 1);
119 void RichManglingContext::ParseFunctionBaseName() {
120 assert(m_provider != None && "Initialize a provider first");
121 switch (m_provider) {
122 case ItaniumPartialDemangler: {
123 auto n = m_ipd_buf_size;
124 auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n);
125 processIPDStrResult(buf, n);
128 case PluginCxxLanguage:
130 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
137 void RichManglingContext::ParseFunctionDeclContextName() {
138 assert(m_provider != None && "Initialize a provider first");
139 switch (m_provider) {
140 case ItaniumPartialDemangler: {
141 auto n = m_ipd_buf_size;
142 auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);
143 processIPDStrResult(buf, n);
146 case PluginCxxLanguage:
148 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext();
155 void RichManglingContext::ParseFullName() {
156 assert(m_provider != None && "Initialize a provider first");
157 switch (m_provider) {
158 case ItaniumPartialDemangler: {
159 auto n = m_ipd_buf_size;
160 auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);
161 processIPDStrResult(buf, n);
164 case PluginCxxLanguage:
165 m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)