]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Core/RichManglingContext.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Core / RichManglingContext.cpp
1 //===-- 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
19 using namespace lldb;
20 using namespace lldb_private;
21
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();
32   }
33
34   assert(new_provider != None && "Only reset to a valid provider");
35   m_provider = new_provider;
36 }
37
38 bool 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
57 bool RichManglingContext::FromCxxMethodName(const ConstString &demangled) {
58   ResetProvider(PluginCxxLanguage);
59   m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled);
60   return true;
61 }
62
63 bool 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   }
77   llvm_unreachable("Fully covered switch above!");
78 }
79
80 bool 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   }
90   llvm_unreachable("Fully covered switch above!");
91 }
92
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");
98
99     m_ipd_buf[0] = '\0';
100     m_buffer = llvm::StringRef(m_ipd_buf, 0);
101     return;
102   }
103
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");
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);
120 }
121
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);
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
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);
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
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);
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 }