blob: f5fbe38a49fb4eeb4ac538371e4eadca56938d59 [file] [log] [blame]
Stefan Granitzf1a98df2018-08-08 21:57:37 +00001//===-- RichManglingContext.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/RichManglingContext.h"
11
12#include "lldb/Utility/Log.h"
13#include "lldb/Utility/Logging.h"
14
15#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
16
17#include "llvm/ADT/StringRef.h"
18
19using namespace lldb;
20using namespace lldb_private;
21
22//----------------------------------------------------------------------
23// RichManglingContext
24//----------------------------------------------------------------------
25void 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();
32 }
33
34 assert(new_provider != None && "Only reset to a valid provider");
35 m_provider = new_provider;
36}
37
38bool RichManglingContext::FromItaniumName(const ConstString &mangled) {
39 bool err = m_ipd.partialDemangle(mangled.GetCString());
40 if (!err) {
41 ResetProvider(ItaniumPartialDemangler);
42 }
43
44 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
45 if (!err) {
46 ParseFullName();
47 LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf);
48 } else {
49 LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle",
50 mangled);
51 }
52 }
53
54 return !err; // true == success
55}
56
57bool RichManglingContext::FromCxxMethodName(const ConstString &demangled) {
58 ResetProvider(PluginCxxLanguage);
59 m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled);
60 return true;
61}
62
63bool RichManglingContext::IsCtorOrDtor() const {
64 assert(m_provider != None && "Initialize a provider first");
65 switch (m_provider) {
66 case ItaniumPartialDemangler:
67 return m_ipd.isCtorOrDtor();
68 case PluginCxxLanguage: {
69 // We can only check for destructors here.
70 auto base_name =
71 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
72 return base_name.startswith("~");
73 }
74 case None:
75 return false;
76 }
Pavel Labathd5fa57e2018-08-31 05:18:11 +000077 llvm_unreachable("Fully covered switch above!");
Stefan Granitzf1a98df2018-08-08 21:57:37 +000078}
79
80bool RichManglingContext::IsFunction() const {
81 assert(m_provider != None && "Initialize a provider first");
82 switch (m_provider) {
83 case ItaniumPartialDemangler:
84 return m_ipd.isFunction();
85 case PluginCxxLanguage:
86 return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->IsValid();
87 case None:
88 return false;
89 }
Pavel Labathd5fa57e2018-08-31 05:18:11 +000090 llvm_unreachable("Fully covered switch above!");
Stefan Granitzf1a98df2018-08-08 21:57:37 +000091}
92
93void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) {
Stefan Granitzd0514162018-08-10 15:21:33 +000094 // Error case: Clear the buffer.
Stefan Granitzf1a98df2018-08-08 21:57:37 +000095 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");
98
Stefan Granitzd0514162018-08-10 15:21:33 +000099 m_ipd_buf[0] = '\0';
100 m_buffer = llvm::StringRef(m_ipd_buf, 0);
101 return;
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000102 }
103
Stefan Granitzd0514162018-08-10 15:21:33 +0000104 // 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");
107
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.
112
113 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE))
114 LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}",
115 m_ipd_buf_size);
116 }
117
118 // 99% case: Just remember the string length.
119 m_buffer = llvm::StringRef(m_ipd_buf, res_size - 1);
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000120}
121
122void 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);
129 return;
130 }
131 case PluginCxxLanguage:
132 m_buffer =
133 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
134 return;
135 case None:
136 return;
137 }
138}
139
140void 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);
147 return;
148 }
149 case PluginCxxLanguage:
150 m_buffer =
151 get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext();
152 return;
153 case None:
154 return;
155 }
156}
157
158void 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);
165 return;
166 }
167 case PluginCxxLanguage:
168 m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
169 ->GetFullName()
170 .GetStringRef();
171 return;
172 case None:
173 return;
174 }
175}