blob: 889fc9fb947e0a0756192ebdef994d1f04bed937 [file] [log] [blame]
Jim Ingham642036f2010-09-23 02:01:19 +00001//===-- CPPLanguageRuntime.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/Target/CPPLanguageRuntime.h"
Enrico Granatabad97532012-02-03 01:41:25 +000011
Jim Ingham642036f2010-09-23 02:01:19 +000012#include "lldb/Core/PluginManager.h"
Enrico Granatabad97532012-02-03 01:41:25 +000013#include "lldb/Core/UniqueCStringMap.h"
Jim Inghamb66cd072010-09-28 01:25:32 +000014#include "lldb/Target/ExecutionContext.h"
Jim Ingham642036f2010-09-23 02:01:19 +000015
16using namespace lldb;
17using namespace lldb_private;
18
Enrico Granatabad97532012-02-03 01:41:25 +000019class CPPRuntimeEquivalents
20{
21public:
22 CPPRuntimeEquivalents ()
23 {
24
25 m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>"));
26 m_impl.Append(ConstString("class std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >").AsCString(), ConstString("basic_string<char>"));
27
28 // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container
29 m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>"));
30 m_impl.Append(ConstString("class std::basic_string<char, class std::char_traits<char>, class std::allocator<char> >").AsCString(), ConstString("std::asic_string<char>"));
31
32 m_impl.Sort();
33 }
34
35 void
36 Add (ConstString& type_name,
37 ConstString& type_equivalent)
38 {
39 m_impl.Insert(type_name.AsCString(), type_equivalent);
40 }
41
42 uint32_t
43 FindExactMatches (ConstString& type_name,
44 std::vector<ConstString>& equivalents)
45 {
46
47 uint32_t count = 0;
48
49 for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString());
50 match != NULL;
51 match = m_impl.FindNextValueForName(match))
52 {
53 equivalents.push_back(match->value);
54 count++;
55 }
56
57 return count;
58 }
59
60 // partial matches can occur when a name with equivalents is a template argument.
61 // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename
62 // such as "class Templatized<class Foo, Anything>" we want this to be replaced with
63 // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming
64 // once we get a partial match, we add it to the exact matches list for faster retrieval
65 uint32_t
66 FindPartialMatches (ConstString& type_name,
67 std::vector<ConstString>& equivalents)
68 {
69
70 uint32_t count = 0;
71
72 const char* type_name_cstr = type_name.AsCString();
73
74 size_t items_count = m_impl.GetSize();
75
76 for (size_t item = 0; item < items_count; item++)
77 {
78 const char* key_cstr = m_impl.GetCStringAtIndex(item);
79 if ( strstr(type_name_cstr,key_cstr) )
80 {
81 count += AppendReplacements(type_name_cstr,
82 key_cstr,
83 equivalents);
84 }
85 }
86
87 return count;
88
89 }
90
91private:
92
93 std::string& replace (std::string& target,
94 std::string& pattern,
95 std::string& with)
96 {
97 size_t pos;
98 size_t pattern_len = pattern.size();
99
100 while ( (pos = target.find(pattern)) != std::string::npos )
101 target.replace(pos, pattern_len, with);
102
103 return target;
104 }
105
106 uint32_t
107 AppendReplacements (const char* original,
108 const char *matching_key,
109 std::vector<ConstString>& equivalents)
110 {
111
112 std::string matching_key_str(matching_key);
113 ConstString original_const(original);
114
115 uint32_t count = 0;
116
117 for (ImplData match = m_impl.FindFirstValueForName(matching_key);
118 match != NULL;
119 match = m_impl.FindNextValueForName(match))
120 {
121 std::string target(original);
122 std::string equiv_class(match->value.AsCString());
123
124 replace (target, matching_key_str, equiv_class);
125
126 ConstString target_const(target.c_str());
127
128// you will most probably want to leave this off since it might make this map grow indefinitely
129#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW
130 Add(original_const, target_const);
131#endif
132 equivalents.push_back(target_const);
133
134 count++;
135 }
136
137 return count;
138 }
139
140 typedef UniqueCStringMap<ConstString> Impl;
141 typedef const Impl::Entry* ImplData;
142 Impl m_impl;
143};
144
145static CPPRuntimeEquivalents&
146GetEquivalentsMap ()
147{
148 static CPPRuntimeEquivalents g_equivalents_map;
149 return g_equivalents_map;
150}
151
Jim Ingham642036f2010-09-23 02:01:19 +0000152//----------------------------------------------------------------------
153// Destructor
154//----------------------------------------------------------------------
155CPPLanguageRuntime::~CPPLanguageRuntime()
156{
157}
158
159CPPLanguageRuntime::CPPLanguageRuntime (Process *process) :
160 LanguageRuntime (process)
161{
162
Jim Inghamb66cd072010-09-28 01:25:32 +0000163}
164
165bool
Jim Ingham0de37192011-03-31 23:01:21 +0000166CPPLanguageRuntime::GetObjectDescription (Stream &str, ValueObject &object)
Jim Inghamb66cd072010-09-28 01:25:32 +0000167{
168 // C++ has no generic way to do this.
169 return false;
170}
Jim Ingham324067b2010-09-30 00:54:27 +0000171
172bool
173CPPLanguageRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope)
174{
175 // C++ has no generic way to do this.
176 return false;
177}
Jim Ingham8b7b2272011-10-07 22:23:45 +0000178
179bool
180CPPLanguageRuntime::IsCPPMangledName (const char *name)
181{
182 // FIXME, we should really run through all the known C++ Language plugins and ask each one if
183 // this is a C++ mangled name, but we can put that off till there is actually more than one
184 // we care about.
185
186 if (name && name[0] == '_' && name[1] == 'Z')
187 return true;
188 else
189 return false;
190}
191
192bool
193CPPLanguageRuntime::StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end)
194{
195 if (base_name_end == NULL)
196 base_name_end = name + strlen (name);
197
198 const char *last_colon = NULL;
199 for (const char *ptr = base_name_end; ptr != name; ptr--)
200 {
201 if (*ptr == ':')
202 {
203 last_colon = ptr;
204 break;
205 }
206 }
207
208 if (last_colon == NULL)
209 {
210 base_name_start = name;
211 return true;
212 }
213
214 // Can't have a C++ name that begins with a single ':', nor contains an internal single ':'
215 if (last_colon == name)
216 return false;
217 else if (last_colon[-1] != ':')
218 return false;
219 else
220 {
221 // FIXME: should check if there is
222 base_name_start = last_colon + 1;
223 return true;
224 }
225}
226bool
227CPPLanguageRuntime::IsPossibleCPPCall (const char *name, const char *&base_name_start, const char *&base_name_end)
228{
229 if (!name)
230 return false;
231 // For now, I really can't handle taking template names apart, so if you
232 // have < or > I'll say "could be CPP but leave the base_name empty which
233 // means I couldn't figure out what to use for that.
234 // FIXME: Do I need to do more sanity checking here?
235
236 if (strchr(name, '>') != NULL || strchr (name, '>') != NULL)
237 return true;
238
239 size_t name_len = strlen (name);
240
241 if (name[name_len - 1] == ')')
242 {
243 // We've got arguments.
244 base_name_end = strchr (name, '(');
245 if (base_name_end == NULL)
246 return false;
247
248 // FIXME: should check that this parenthesis isn't a template specialized
249 // on a function type or something gross like that...
250 }
251 else
252 base_name_end = name + strlen (name);
253
254 return StripNamespacesFromVariableName (name, base_name_start, base_name_end);
255}
Enrico Granatabad97532012-02-03 01:41:25 +0000256
257uint32_t
258CPPLanguageRuntime::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents)
259{
260 uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents);
261
262 bool might_have_partials=
263 ( count == 0 ) // if we have a full name match just use it
264 && (strchr(type_name.AsCString(), '<') != NULL // we should only have partial matches when templates are involved, check that we have
265 && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches
266
267 if ( might_have_partials )
268 count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents);
269
270 return count;
271}