blob: b06656aa3fb77b94845cd29091632b6152f1651d [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Mangled.cpp ---------------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Chris Lattner30fdc8d2010-06-08 16:52:24 +00006//
7//===----------------------------------------------------------------------===//
8
Zachary Turner2f3df612017-04-06 21:28:29 +00009#include "lldb/Core/Mangled.h"
10
Stefan Granitzf1a98df2018-08-08 21:57:37 +000011#include "lldb/Core/RichManglingContext.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000012#include "lldb/Utility/ConstString.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000013#include "lldb/Utility/Log.h"
14#include "lldb/Utility/Logging.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000015#include "lldb/Utility/RegularExpression.h"
16#include "lldb/Utility/Stream.h"
Pavel Labath38d06322017-06-29 14:32:17 +000017#include "lldb/Utility/Timer.h"
Stefan Granitz2f842d62018-07-25 15:19:04 +000018#include "lldb/lldb-enumerations.h"
Zachary Turner2f3df612017-04-06 21:28:29 +000019
20#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
21#include "Plugins/Language/ObjC/ObjCLanguage.h"
22
Stefan Granitz2f842d62018-07-25 15:19:04 +000023#include "llvm/ADT/StringRef.h"
24#include "llvm/Demangle/Demangle.h"
25#include "llvm/Support/Compiler.h"
Zachary Turner2f3df612017-04-06 21:28:29 +000026
Stefan Granitz2f842d62018-07-25 15:19:04 +000027#include <mutex>
28#include <string>
29#include <utility>
Zachary Turner2f3df612017-04-06 21:28:29 +000030
Daniel Maleac91e4ab2013-05-31 20:21:38 +000031#include <stdlib.h>
Kate Stoneb9c1b512016-09-06 20:57:50 +000032#include <string.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033using namespace lldb_private;
34
Kate Stoneb9c1b512016-09-06 20:57:50 +000035static inline Mangled::ManglingScheme cstring_mangling_scheme(const char *s) {
36 if (s) {
37 if (s[0] == '?')
38 return Mangled::eManglingSchemeMSVC;
39 if (s[0] == '_' && s[1] == 'Z')
40 return Mangled::eManglingSchemeItanium;
41 }
42 return Mangled::eManglingSchemeNone;
Chaoren Lin7f951142015-05-28 21:19:31 +000043}
44
Kate Stoneb9c1b512016-09-06 20:57:50 +000045static inline bool cstring_is_mangled(const char *s) {
46 return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone;
Greg Clayton5e0c5e82012-07-18 20:47:40 +000047}
48
Adrian Prantl0e4c4822019-03-06 21:22:25 +000049static ConstString
Kate Stoneb9c1b512016-09-06 20:57:50 +000050get_demangled_name_without_arguments(ConstString mangled,
51 ConstString demangled) {
52 // This pair is <mangled name, demangled name without function arguments>
53 static std::pair<ConstString, ConstString>
54 g_most_recent_mangled_to_name_sans_args;
Jason Molendaaff1b352014-10-10 23:07:36 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 // Need to have the mangled & demangled names we're currently examining as
Adrian Prantl05097242018-04-30 16:49:04 +000057 // statics so we can return a const ref to them at the end of the func if we
58 // don't have anything better.
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 static ConstString g_last_mangled;
60 static ConstString g_last_demangled;
Jason Molendaaff1b352014-10-10 23:07:36 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) {
63 return g_most_recent_mangled_to_name_sans_args.second;
64 }
65
66 g_last_demangled = demangled;
67 g_last_mangled = mangled;
68
69 const char *mangled_name_cstr = mangled.GetCString();
70
71 if (demangled && mangled_name_cstr && mangled_name_cstr[0]) {
72 if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' &&
73 (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure,
74 // typeinfo structure, and typeinfo
75 // mangled_name
76 mangled_name_cstr[2] != 'G' && // avoid guard variables
77 mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually
78 // handle eSymbolTypeData, we will want
79 // this back)
Jason Molendaaff1b352014-10-10 23:07:36 +000080 {
Kate Stoneb9c1b512016-09-06 20:57:50 +000081 CPlusPlusLanguage::MethodName cxx_method(demangled);
82 if (!cxx_method.GetBasename().empty()) {
83 std::string shortname;
84 if (!cxx_method.GetContext().empty())
85 shortname = cxx_method.GetContext().str() + "::";
86 shortname += cxx_method.GetBasename().str();
87 ConstString result(shortname.c_str());
88 g_most_recent_mangled_to_name_sans_args.first = mangled;
89 g_most_recent_mangled_to_name_sans_args.second = result;
Jason Molendaaff1b352014-10-10 23:07:36 +000090 return g_most_recent_mangled_to_name_sans_args.second;
Kate Stoneb9c1b512016-09-06 20:57:50 +000091 }
Jason Molendaaff1b352014-10-10 23:07:36 +000092 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000093 }
Jason Molendaaff1b352014-10-10 23:07:36 +000094
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 if (demangled)
96 return g_last_demangled;
97 return g_last_mangled;
Jason Molendaaff1b352014-10-10 23:07:36 +000098}
99
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000100#pragma mark Mangled
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000101
Adrian Prantl0e4c4822019-03-06 21:22:25 +0000102Mangled::Mangled(ConstString s) : m_mangled(), m_demangled() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000103 if (s)
104 SetValue(s);
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000105}
106
Zachary Turner97d2c402016-10-05 23:40:23 +0000107Mangled::Mangled(llvm::StringRef name) {
108 if (!name.empty())
109 SetValue(ConstString(name));
110}
111
Adrian Prantl05097242018-04-30 16:49:04 +0000112// Convert to pointer operator. This allows code to check any Mangled objects
113// to see if they contain anything valid using code such as:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114//
115// Mangled mangled(...);
116// if (mangled)
117// { ...
Kate Stoneb9c1b512016-09-06 20:57:50 +0000118Mangled::operator void *() const {
Konrad Kleine248a1302019-05-23 11:14:47 +0000119 return (m_mangled) ? const_cast<Mangled *>(this) : nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120}
121
Adrian Prantl05097242018-04-30 16:49:04 +0000122// Logical NOT operator. This allows code to check any Mangled objects to see
123// if they are invalid using code such as:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000124//
125// Mangled mangled(...);
126// if (!file_spec)
127// { ...
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128bool Mangled::operator!() const { return !m_mangled; }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000130// Clear the mangled and demangled values.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000131void Mangled::Clear() {
132 m_mangled.Clear();
133 m_demangled.Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000134}
135
Bruce Mitchener58ef3912015-06-18 05:27:05 +0000136// Compare the string values.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000137int Mangled::Compare(const Mangled &a, const Mangled &b) {
138 return ConstString::Compare(
139 a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled),
Stefan Granitzc238ca22018-08-06 14:15:21 +0000140 b.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000141}
142
Adrian Prantl05097242018-04-30 16:49:04 +0000143// Set the string value in this objects. If "mangled" is true, then the mangled
144// named is set with the new value in "s", else the demangled name is set.
Adrian Prantl0e4c4822019-03-06 21:22:25 +0000145void Mangled::SetValue(ConstString s, bool mangled) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 if (s) {
147 if (mangled) {
148 m_demangled.Clear();
149 m_mangled = s;
150 } else {
151 m_demangled = s;
152 m_mangled.Clear();
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000153 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 } else {
155 m_demangled.Clear();
156 m_mangled.Clear();
157 }
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000158}
159
Adrian Prantl0e4c4822019-03-06 21:22:25 +0000160void Mangled::SetValue(ConstString name) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000161 if (name) {
162 if (cstring_is_mangled(name.GetCString())) {
163 m_demangled.Clear();
164 m_mangled = name;
165 } else {
166 m_demangled = name;
167 m_mangled.Clear();
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000168 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000169 } else {
170 m_demangled.Clear();
171 m_mangled.Clear();
172 }
Greg Clayton5e0c5e82012-07-18 20:47:40 +0000173}
174
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000175// Local helpers for different demangling implementations.
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000176static char *GetMSVCDemangledStr(const char *M) {
Martin Storsjo13993a62019-10-16 19:39:56 +0000177 char *demangled_cstr = llvm::microsoftDemangle(
178 M, nullptr, nullptr, nullptr,
179 llvm::MSDemangleFlags(llvm::MSDF_NoAccessSpecifier |
180 llvm::MSDF_NoCallingConvention |
181 llvm::MSDF_NoMemberType));
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000182
183 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
184 if (demangled_cstr && demangled_cstr[0])
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000185 LLDB_LOGF(log, "demangled msvc: %s -> \"%s\"", M, demangled_cstr);
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000186 else
Martin Storsjo13993a62019-10-16 19:39:56 +0000187 LLDB_LOGF(log, "demangled msvc: %s -> error", M);
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000188 }
189
Martin Storsjo13993a62019-10-16 19:39:56 +0000190 return demangled_cstr;
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000191}
192
Stefan Granitzd0514162018-08-10 15:21:33 +0000193static char *GetItaniumDemangledStr(const char *M) {
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000194 char *demangled_cstr = nullptr;
Stefan Granitzd0514162018-08-10 15:21:33 +0000195
196 llvm::ItaniumPartialDemangler ipd;
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000197 bool err = ipd.partialDemangle(M);
198 if (!err) {
199 // Default buffer and size (will realloc in case it's too small).
200 size_t demangled_size = 80;
201 demangled_cstr = static_cast<char *>(std::malloc(demangled_size));
202 demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size);
203
204 assert(demangled_cstr &&
205 "finishDemangle must always succeed if partialDemangle did");
206 assert(demangled_cstr[demangled_size - 1] == '\0' &&
207 "Expected demangled_size to return length including trailing null");
208 }
209
210 if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
211 if (demangled_cstr)
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000212 LLDB_LOGF(log, "demangled itanium: %s -> \"%s\"", M, demangled_cstr);
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000213 else
Jonas Devlieghere63e5fb72019-07-24 17:56:10 +0000214 LLDB_LOGF(log, "demangled itanium: %s -> error: failed to demangle", M);
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000215 }
216
217 return demangled_cstr;
218}
219
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000220// Explicit demangling for scheduled requests during batch processing. This
221// makes use of ItaniumPartialDemangler's rich demangle info
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000222bool Mangled::DemangleWithRichManglingInfo(
223 RichManglingContext &context, SkipMangledNameFn *skip_mangled_name) {
224 // We need to generate and cache the demangled name.
225 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
226 Timer scoped_timer(func_cat,
227 "Mangled::DemangleWithRichNameIndexInfo (m_mangled = %s)",
228 m_mangled.GetCString());
229
230 // Others are not meant to arrive here. ObjC names or C's main() for example
231 // have their names stored in m_demangled, while m_mangled is empty.
232 assert(m_mangled);
233
234 // Check whether or not we are interested in this name at all.
235 ManglingScheme scheme = cstring_mangling_scheme(m_mangled.GetCString());
236 if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme))
237 return false;
238
239 switch (scheme) {
240 case eManglingSchemeNone:
241 // The current mangled_name_filter would allow llvm_unreachable here.
242 return false;
243
244 case eManglingSchemeItanium:
245 // We want the rich mangling info here, so we don't care whether or not
246 // there is a demangled string in the pool already.
247 if (context.FromItaniumName(m_mangled)) {
248 // If we got an info, we have a name. Copy to string pool and connect the
249 // counterparts to accelerate later access in GetDemangledName().
250 context.ParseFullName();
251 m_demangled.SetStringWithMangledCounterpart(context.GetBufferRef(),
252 m_mangled);
253 return true;
254 } else {
255 m_demangled.SetCString("");
256 return false;
257 }
258
259 case eManglingSchemeMSVC: {
260 // We have no rich mangling for MSVC-mangled names yet, so first try to
261 // demangle it if necessary.
262 if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) {
263 if (char *d = GetMSVCDemangledStr(m_mangled.GetCString())) {
264 // If we got an info, we have a name. Copy to string pool and connect
265 // the counterparts to accelerate later access in GetDemangledName().
266 m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d),
267 m_mangled);
268 ::free(d);
269 } else {
270 m_demangled.SetCString("");
271 }
272 }
273
274 if (m_demangled.IsEmpty()) {
275 // Cannot demangle it, so don't try parsing.
276 return false;
277 } else {
278 // Demangled successfully, we can try and parse it with
279 // CPlusPlusLanguage::MethodName.
280 return context.FromCxxMethodName(m_demangled);
281 }
282 }
283 }
Pavel Labathd5fa57e2018-08-31 05:18:11 +0000284 llvm_unreachable("Fully covered switch above!");
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000285}
286
Adrian Prantl05097242018-04-30 16:49:04 +0000287// Generate the demangled name on demand using this accessor. Code in this
288// class will need to use this accessor if it wishes to decode the demangled
289// name. The result is cached and will be kept until a new string value is
290// supplied to this object, or until the end of the object's lifetime.
Adrian Prantl0e4c4822019-03-06 21:22:25 +0000291ConstString
Kate Stoneb9c1b512016-09-06 20:57:50 +0000292Mangled::GetDemangledName(lldb::LanguageType language) const {
Adrian Prantl05097242018-04-30 16:49:04 +0000293 // Check to make sure we have a valid mangled name and that we haven't
294 // already decoded our mangled name.
Stefan Granitz4af5a832018-08-06 14:15:17 +0000295 if (m_mangled && m_demangled.IsNull()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 // We need to generate and cache the demangled name.
Pavel Labathf9d16472017-05-15 13:02:37 +0000297 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
298 Timer scoped_timer(func_cat, "Mangled::GetDemangledName (m_mangled = %s)",
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299 m_mangled.GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300
Kate Stoneb9c1b512016-09-06 20:57:50 +0000301 // Don't bother running anything that isn't mangled
302 const char *mangled_name = m_mangled.GetCString();
303 ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
304 if (mangling_scheme != eManglingSchemeNone &&
305 !m_mangled.GetMangledCounterpart(m_demangled)) {
306 // We didn't already mangle this name, demangle it and if all goes well
307 // add it to our map.
308 char *demangled_name = nullptr;
309 switch (mangling_scheme) {
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000310 case eManglingSchemeMSVC:
311 demangled_name = GetMSVCDemangledStr(mangled_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000313 case eManglingSchemeItanium: {
Stefan Granitzd0514162018-08-10 15:21:33 +0000314 demangled_name = GetItaniumDemangledStr(mangled_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000315 break;
316 }
317 case eManglingSchemeNone:
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000318 llvm_unreachable("eManglingSchemeNone was handled already");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000319 }
320 if (demangled_name) {
Stefan Granitzf1a98df2018-08-08 21:57:37 +0000321 m_demangled.SetStringWithMangledCounterpart(
322 llvm::StringRef(demangled_name), m_mangled);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000323 free(demangled_name);
324 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325 }
Stefan Granitz4af5a832018-08-06 14:15:17 +0000326 if (m_demangled.IsNull()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000327 // Set the demangled string to the empty string to indicate we tried to
328 // parse it once and failed.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000329 m_demangled.SetCString("");
330 }
331 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000332
Kate Stoneb9c1b512016-09-06 20:57:50 +0000333 return m_demangled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000334}
335
Enrico Granatac1f705c2015-07-06 18:28:46 +0000336ConstString
Kate Stoneb9c1b512016-09-06 20:57:50 +0000337Mangled::GetDisplayDemangledName(lldb::LanguageType language) const {
338 return GetDemangledName(language);
Enrico Granatac1f705c2015-07-06 18:28:46 +0000339}
340
Kate Stoneb9c1b512016-09-06 20:57:50 +0000341bool Mangled::NameMatches(const RegularExpression &regex,
342 lldb::LanguageType language) const {
343 if (m_mangled && regex.Execute(m_mangled.AsCString()))
344 return true;
Greg Claytonddaf6a72015-07-08 22:32:23 +0000345
Kate Stoneb9c1b512016-09-06 20:57:50 +0000346 ConstString demangled = GetDemangledName(language);
Jonas Devliegherea6682a42018-12-15 00:15:33 +0000347 return demangled && regex.Execute(demangled.AsCString());
Greg Clayton83c5cd92010-11-14 22:13:40 +0000348}
349
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000350// Get the demangled name if there is one, else return the mangled name.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000351ConstString Mangled::GetName(lldb::LanguageType language,
352 Mangled::NamePreference preference) const {
353 if (preference == ePreferMangled && m_mangled)
354 return m_mangled;
Greg Clayton3feddff2015-12-17 01:00:50 +0000355
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356 ConstString demangled = GetDemangledName(language);
Greg Claytonddaf6a72015-07-08 22:32:23 +0000357
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358 if (preference == ePreferDemangledWithoutArguments) {
359 return get_demangled_name_without_arguments(m_mangled, demangled);
360 }
361 if (preference == ePreferDemangled) {
Adrian Prantl05097242018-04-30 16:49:04 +0000362 // Call the accessor to make sure we get a demangled name in case it hasn't
363 // been demangled yet...
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364 if (demangled)
365 return demangled;
366 return m_mangled;
367 }
368 return demangled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000369}
370
Adrian Prantl05097242018-04-30 16:49:04 +0000371// Dump a Mangled object to stream "s". We don't force our demangled name to be
372// computed currently (we don't use the accessor).
Kate Stoneb9c1b512016-09-06 20:57:50 +0000373void Mangled::Dump(Stream *s) const {
374 if (m_mangled) {
375 *s << ", mangled = " << m_mangled;
376 }
377 if (m_demangled) {
378 const char *demangled = m_demangled.AsCString();
379 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
380 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000381}
382
Adrian Prantl05097242018-04-30 16:49:04 +0000383// Dumps a debug version of this string with extra object and state information
384// to stream "s".
Kate Stoneb9c1b512016-09-06 20:57:50 +0000385void Mangled::DumpDebug(Stream *s) const {
386 s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2),
387 static_cast<const void *>(this));
388 m_mangled.DumpDebug(s);
389 s->Printf(", demangled = ");
390 m_demangled.DumpDebug(s);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000391}
392
Adrian Prantl05097242018-04-30 16:49:04 +0000393// Return the size in byte that this object takes in memory. The size includes
394// the size of the objects it owns, and not the strings that it references
395// because they are shared strings.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396size_t Mangled::MemorySize() const {
397 return m_mangled.MemorySize() + m_demangled.MemorySize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000398}
399
Adrian Prantl05097242018-04-30 16:49:04 +0000400// We "guess" the language because we can't determine a symbol's language from
401// it's name. For example, a Pascal symbol can be mangled using the C++
402// Itanium scheme, and defined in a compilation unit within the same module as
403// other C++ units. In addition, different targets could have different ways
404// of mangling names from a given language, likewise the compilation units
405// within those targets.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000406lldb::LanguageType Mangled::GuessLanguage() const {
407 ConstString mangled = GetMangledName();
408 if (mangled) {
Adrian Prantl7feefe82019-02-27 22:54:47 +0000409 const char *mangled_name = mangled.GetCString();
410 if (CPlusPlusLanguage::IsCPPMangledName(mangled_name))
411 return lldb::eLanguageTypeC_plus_plus;
412 else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name))
413 return lldb::eLanguageTypeObjC;
Jim Inghambdbdd222017-04-12 00:19:54 +0000414 } else {
Adrian Prantl05097242018-04-30 16:49:04 +0000415 // ObjC names aren't really mangled, so they won't necessarily be in the
Jim Inghambdbdd222017-04-12 00:19:54 +0000416 // mangled name slot.
417 ConstString demangled_name = GetDemangledName(lldb::eLanguageTypeUnknown);
418 if (demangled_name
419 && ObjCLanguage::IsPossibleObjCMethodName(demangled_name.GetCString()))
420 return lldb::eLanguageTypeObjC;
421
Kate Stoneb9c1b512016-09-06 20:57:50 +0000422 }
423 return lldb::eLanguageTypeUnknown;
Greg Clayton94976f72015-01-23 23:18:53 +0000424}
425
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000426// Dump OBJ to the supplied stream S.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427Stream &operator<<(Stream &s, const Mangled &obj) {
428 if (obj.GetMangledName())
429 s << "mangled = '" << obj.GetMangledName() << "'";
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000430
Adrian Prantl0e4c4822019-03-06 21:22:25 +0000431 ConstString demangled =
Kate Stoneb9c1b512016-09-06 20:57:50 +0000432 obj.GetDemangledName(lldb::eLanguageTypeUnknown);
433 if (demangled)
434 s << ", demangled = '" << demangled << '\'';
435 else
436 s << ", demangled = <error>";
437 return s;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000438}