1 //===-- RichManglingContext.cpp ---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Core/RichManglingContext.h"
12 #include "lldb/Utility/Log.h"
13 #include "lldb/Utility/Logging.h"
15 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
17 #include "llvm/ADT/StringRef.h"
20 using namespace lldb_private;
22 //----------------------------------------------------------------------
23 // RichManglingContext
24 //----------------------------------------------------------------------
25 void RichManglingContext::ResetProvider(InfoProvider new_provider) {
26 // If we want to support parsers for other languages some day, we need a
27 // switch here to delete the correct parser type.
28 if (m_cxx_method_parser.hasValue()) {
29 assert(m_provider == PluginCxxLanguage);
30 delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser);
31 m_cxx_method_parser.reset();
34 assert(new_provider != None && "Only reset to a valid provider");
35 m_provider = new_provider;
38 bool RichManglingContext::FromItaniumName(const ConstString &mangled) {
39 bool err = m_ipd.partialDemangle(mangled.GetCString());
41 ResetProvider(ItaniumPartialDemangler);
44 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
47 LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf);
49 LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle",
54 return !err; // true == success
57 bool RichManglingContext::FromCxxMethodName(const ConstString &demangled) {
58 ResetProvider(PluginCxxLanguage);
59 m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled);
63 bool RichManglingContext::IsCtorOrDtor() const {
64 assert(m_provider != None && "Initialize a provider first");
66 case ItaniumPartialDemangler:
67 return m_ipd.isCtorOrDtor();
68 case PluginCxxLanguage: {
69 // We can only check for destructors here.
71 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
72 return base_name.startswith("~");
77 llvm_unreachable("Fully covered switch above!");
80 bool RichManglingContext::IsFunction() const {
81 assert(m_provider != None && "Initialize a provider first");
83 case ItaniumPartialDemangler:
84 return m_ipd.isFunction();
85 case PluginCxxLanguage:
86 return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->IsValid();
90 llvm_unreachable("Fully covered switch above!");
93 void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) {
94 // Error case: Clear the buffer.
95 if (LLVM_UNLIKELY(ipd_res == nullptr)) {
96 assert(res_size == m_ipd_buf_size &&
97 "Failed IPD queries keep the original size in the N parameter");
100 m_buffer = llvm::StringRef(m_ipd_buf, 0);
104 // IPD's res_size includes null terminator.
105 assert(ipd_res[res_size - 1] == '\0' &&
106 "IPD returns null-terminated strings and we rely on that");
108 // Update buffer/size on realloc.
109 if (LLVM_UNLIKELY(ipd_res != m_ipd_buf || res_size > m_ipd_buf_size)) {
110 m_ipd_buf = ipd_res; // std::realloc freed or reused the old buffer.
111 m_ipd_buf_size = res_size; // May actually be bigger, but we can't know.
113 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE))
114 LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}",
118 // 99% case: Just remember the string length.
119 m_buffer = llvm::StringRef(m_ipd_buf, res_size - 1);
122 void RichManglingContext::ParseFunctionBaseName() {
123 assert(m_provider != None && "Initialize a provider first");
124 switch (m_provider) {
125 case ItaniumPartialDemangler: {
126 auto n = m_ipd_buf_size;
127 auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n);
128 processIPDStrResult(buf, n);
131 case PluginCxxLanguage:
133 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
140 void RichManglingContext::ParseFunctionDeclContextName() {
141 assert(m_provider != None && "Initialize a provider first");
142 switch (m_provider) {
143 case ItaniumPartialDemangler: {
144 auto n = m_ipd_buf_size;
145 auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);
146 processIPDStrResult(buf, n);
149 case PluginCxxLanguage:
151 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext();
158 void RichManglingContext::ParseFullName() {
159 assert(m_provider != None && "Initialize a provider first");
160 switch (m_provider) {
161 case ItaniumPartialDemangler: {
162 auto n = m_ipd_buf_size;
163 auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);
164 processIPDStrResult(buf, n);
167 case PluginCxxLanguage:
168 m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)