blob: f09e40378903a391cc24cad885db8adf878cd046 [file] [log] [blame]
Enrico Granata5f9d3102015-08-27 21:33:50 +00001//===-- CPlusPlusLanguage.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 "CPlusPlusLanguage.h"
11
Jim Inghamaa816b82015-09-02 01:59:14 +000012#include <string.h>
13
14#include "llvm/ADT/StringRef.h"
15
Enrico Granata5f9d3102015-08-27 21:33:50 +000016#include "lldb/Core/ConstString.h"
17#include "lldb/Core/PluginManager.h"
Jim Inghamaa816b82015-09-02 01:59:14 +000018#include "lldb/Core/RegularExpression.h"
19#include "lldb/Core/UniqueCStringMap.h"
Enrico Granata7cb59e12015-09-16 18:28:11 +000020#include "lldb/DataFormatters/CXXFunctionPointer.h"
Enrico Granata33e97e62015-09-04 21:01:18 +000021#include "lldb/DataFormatters/DataVisualization.h"
22#include "lldb/DataFormatters/FormattersHelpers.h"
Enrico Granata7cb59e12015-09-16 18:28:11 +000023#include "lldb/DataFormatters/VectorType.h"
Enrico Granata33e97e62015-09-04 21:01:18 +000024
Enrico Granata33e97e62015-09-04 21:01:18 +000025#include "CxxStringTypes.h"
26#include "LibCxx.h"
27#include "LibStdcpp.h"
28
29#include <functional>
30#include <mutex>
Enrico Granata5f9d3102015-08-27 21:33:50 +000031
32using namespace lldb;
33using namespace lldb_private;
Enrico Granata33e97e62015-09-04 21:01:18 +000034using namespace lldb_private::formatters;
Enrico Granata5f9d3102015-08-27 21:33:50 +000035
36void
37CPlusPlusLanguage::Initialize()
38{
39 PluginManager::RegisterPlugin (GetPluginNameStatic(),
40 "C++ Language",
41 CreateInstance);
42}
43
44void
45CPlusPlusLanguage::Terminate()
46{
47 PluginManager::UnregisterPlugin (CreateInstance);
48}
49
50lldb_private::ConstString
51CPlusPlusLanguage::GetPluginNameStatic()
52{
53 static ConstString g_name("cplusplus");
54 return g_name;
55}
56
57
58//------------------------------------------------------------------
59// PluginInterface protocol
60//------------------------------------------------------------------
61lldb_private::ConstString
62CPlusPlusLanguage::GetPluginName()
63{
64 return GetPluginNameStatic();
65}
66
67uint32_t
68CPlusPlusLanguage::GetPluginVersion()
69{
70 return 1;
71}
72
73//------------------------------------------------------------------
74// Static Functions
75//------------------------------------------------------------------
76Language *
77CPlusPlusLanguage::CreateInstance (lldb::LanguageType language)
78{
Enrico Granata578c8a72015-09-02 01:28:24 +000079 if (Language::LanguageIsCPlusPlus(language))
80 return new CPlusPlusLanguage();
81 return nullptr;
Enrico Granata5f9d3102015-08-27 21:33:50 +000082}
Jim Inghamaa816b82015-09-02 01:59:14 +000083
84void
85CPlusPlusLanguage::MethodName::Clear()
86{
87 m_full.Clear();
88 m_basename = llvm::StringRef();
89 m_context = llvm::StringRef();
90 m_arguments = llvm::StringRef();
91 m_qualifiers = llvm::StringRef();
92 m_type = eTypeInvalid;
93 m_parsed = false;
94 m_parse_error = false;
95}
96
97bool
98ReverseFindMatchingChars (const llvm::StringRef &s,
99 const llvm::StringRef &left_right_chars,
100 size_t &left_pos,
101 size_t &right_pos,
102 size_t pos = llvm::StringRef::npos)
103{
104 assert (left_right_chars.size() == 2);
105 left_pos = llvm::StringRef::npos;
106 const char left_char = left_right_chars[0];
107 const char right_char = left_right_chars[1];
108 pos = s.find_last_of(left_right_chars, pos);
109 if (pos == llvm::StringRef::npos || s[pos] == left_char)
110 return false;
111 right_pos = pos;
112 uint32_t depth = 1;
113 while (pos > 0 && depth > 0)
114 {
115 pos = s.find_last_of(left_right_chars, pos);
116 if (pos == llvm::StringRef::npos)
117 return false;
118 if (s[pos] == left_char)
119 {
120 if (--depth == 0)
121 {
122 left_pos = pos;
123 return left_pos < right_pos;
124 }
125 }
126 else if (s[pos] == right_char)
127 {
128 ++depth;
129 }
130 }
131 return false;
132}
133
134
135void
136CPlusPlusLanguage::MethodName::Parse()
137{
138 if (!m_parsed && m_full)
139 {
140// ConstString mangled;
141// m_full.GetMangledCounterpart(mangled);
142// printf ("\n parsing = '%s'\n", m_full.GetCString());
143// if (mangled)
144// printf (" mangled = '%s'\n", mangled.GetCString());
145 m_parse_error = false;
146 m_parsed = true;
147 llvm::StringRef full (m_full.GetCString());
148
149 size_t arg_start, arg_end;
150 llvm::StringRef parens("()", 2);
151 if (ReverseFindMatchingChars (full, parens, arg_start, arg_end))
152 {
153 m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
154 if (arg_end + 1 < full.size())
155 m_qualifiers = full.substr(arg_end + 1);
156 if (arg_start > 0)
157 {
158 size_t basename_end = arg_start;
159 size_t context_start = 0;
160 size_t context_end = llvm::StringRef::npos;
161 if (basename_end > 0 && full[basename_end-1] == '>')
162 {
163 // TODO: handle template junk...
164 // Templated function
165 size_t template_start, template_end;
166 llvm::StringRef lt_gt("<>", 2);
167 if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end))
168 {
169 // Check for templated functions that include return type like: 'void foo<Int>()'
170 context_start = full.rfind(' ', template_start);
171 if (context_start == llvm::StringRef::npos)
172 context_start = 0;
173
174 context_end = full.rfind(':', template_start);
175 if (context_end == llvm::StringRef::npos || context_end < context_start)
176 context_end = context_start;
177 }
178 else
179 {
180 context_end = full.rfind(':', basename_end);
181 }
182 }
183 else if (context_end == llvm::StringRef::npos)
184 {
185 context_end = full.rfind(':', basename_end);
186 }
187
188 if (context_end == llvm::StringRef::npos)
189 m_basename = full.substr(0, basename_end);
190 else
191 {
192 if (context_start < context_end)
193 m_context = full.substr(context_start, context_end - 1);
194 const size_t basename_begin = context_end + 1;
195 m_basename = full.substr(basename_begin, basename_end - basename_begin);
196 }
197 m_type = eTypeUnknownMethod;
198 }
199 else
200 {
201 m_parse_error = true;
202 return;
203 }
204
205// if (!m_context.empty())
206// printf (" context = '%s'\n", m_context.str().c_str());
207// if (m_basename)
208// printf (" basename = '%s'\n", m_basename.GetCString());
209// if (!m_arguments.empty())
210// printf (" arguments = '%s'\n", m_arguments.str().c_str());
211// if (!m_qualifiers.empty())
212// printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str());
213
214 // Make sure we have a valid C++ basename with optional template args
215 static RegularExpression g_identifier_regex("^~?([A-Za-z_][A-Za-z_0-9]*)(<.*>)?$");
216 std::string basename_str(m_basename.str());
217 bool basename_is_valid = g_identifier_regex.Execute (basename_str.c_str(), NULL);
218 if (!basename_is_valid)
219 {
220 // Check for C++ operators
221 if (m_basename.startswith("operator"))
222 {
223 static RegularExpression g_operator_regex("^(operator)( ?)([A-Za-z_][A-Za-z_0-9]*|\\(\\)|\\[\\]|[\\^<>=!\\/*+-]+)(<.*>)?(\\[\\])?$");
224 basename_is_valid = g_operator_regex.Execute(basename_str.c_str(), NULL);
225 }
226 }
227 if (!basename_is_valid)
228 {
229 // The C++ basename doesn't match our regular expressions so this can't
230 // be a valid C++ method, clear everything out and indicate an error
231 m_context = llvm::StringRef();
232 m_basename = llvm::StringRef();
233 m_arguments = llvm::StringRef();
234 m_qualifiers = llvm::StringRef();
235 m_parse_error = true;
236 }
237 }
238 else
239 {
240 m_parse_error = true;
241// printf ("error: didn't find matching parens for arguments\n");
242 }
243 }
244}
245
246llvm::StringRef
247CPlusPlusLanguage::MethodName::GetBasename ()
248{
249 if (!m_parsed)
250 Parse();
251 return m_basename;
252}
253
254llvm::StringRef
255CPlusPlusLanguage::MethodName::GetContext ()
256{
257 if (!m_parsed)
258 Parse();
259 return m_context;
260}
261
262llvm::StringRef
263CPlusPlusLanguage::MethodName::GetArguments ()
264{
265 if (!m_parsed)
266 Parse();
267 return m_arguments;
268}
269
270llvm::StringRef
271CPlusPlusLanguage::MethodName::GetQualifiers ()
272{
273 if (!m_parsed)
274 Parse();
275 return m_qualifiers;
276}
277
278bool
279CPlusPlusLanguage::IsCPPMangledName (const char *name)
280{
281 // FIXME, we should really run through all the known C++ Language plugins and ask each one if
282 // this is a C++ mangled name, but we can put that off till there is actually more than one
283 // we care about.
284
285 if (name && name[0] == '_' && name[1] == 'Z')
286 return true;
287 else
288 return false;
289}
290
291bool
292CPlusPlusLanguage::ExtractContextAndIdentifier (const char *name, llvm::StringRef &context, llvm::StringRef &identifier)
293{
294 static RegularExpression g_basename_regex("^(([A-Za-z_][A-Za-z_0-9]*::)*)([A-Za-z_][A-Za-z_0-9]*)$");
295 RegularExpression::Match match(4);
296 if (g_basename_regex.Execute (name, &match))
297 {
298 match.GetMatchAtIndex(name, 1, context);
299 match.GetMatchAtIndex(name, 3, identifier);
300 return true;
301 }
302 return false;
303}
304
305class CPPRuntimeEquivalents
306{
307public:
308 CPPRuntimeEquivalents ()
309 {
310
311 m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>"));
312
313 // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container
314 m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>"));
315
316 m_impl.Sort();
317 }
318
319 void
320 Add (ConstString& type_name,
321 ConstString& type_equivalent)
322 {
323 m_impl.Insert(type_name.AsCString(), type_equivalent);
324 }
325
326 uint32_t
327 FindExactMatches (ConstString& type_name,
328 std::vector<ConstString>& equivalents)
329 {
330
331 uint32_t count = 0;
332
333 for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString());
334 match != NULL;
335 match = m_impl.FindNextValueForName(match))
336 {
337 equivalents.push_back(match->value);
338 count++;
339 }
340
341 return count;
342 }
343
344 // partial matches can occur when a name with equivalents is a template argument.
345 // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename
346 // such as "class Templatized<class Foo, Anything>" we want this to be replaced with
347 // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming
348 // once we get a partial match, we add it to the exact matches list for faster retrieval
349 uint32_t
350 FindPartialMatches (ConstString& type_name,
351 std::vector<ConstString>& equivalents)
352 {
353
354 uint32_t count = 0;
355
356 const char* type_name_cstr = type_name.AsCString();
357
358 size_t items_count = m_impl.GetSize();
359
360 for (size_t item = 0; item < items_count; item++)
361 {
362 const char* key_cstr = m_impl.GetCStringAtIndex(item);
363 if ( strstr(type_name_cstr,key_cstr) )
364 {
365 count += AppendReplacements(type_name_cstr,
366 key_cstr,
367 equivalents);
368 }
369 }
370
371 return count;
372
373 }
374
375private:
376
377 std::string& replace (std::string& target,
378 std::string& pattern,
379 std::string& with)
380 {
381 size_t pos;
382 size_t pattern_len = pattern.size();
383
384 while ( (pos = target.find(pattern)) != std::string::npos )
385 target.replace(pos, pattern_len, with);
386
387 return target;
388 }
389
390 uint32_t
391 AppendReplacements (const char* original,
392 const char *matching_key,
393 std::vector<ConstString>& equivalents)
394 {
395
396 std::string matching_key_str(matching_key);
397 ConstString original_const(original);
398
399 uint32_t count = 0;
400
401 for (ImplData match = m_impl.FindFirstValueForName(matching_key);
402 match != NULL;
403 match = m_impl.FindNextValueForName(match))
404 {
405 std::string target(original);
406 std::string equiv_class(match->value.AsCString());
407
408 replace (target, matching_key_str, equiv_class);
409
410 ConstString target_const(target.c_str());
411
412// you will most probably want to leave this off since it might make this map grow indefinitely
413#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW
414 Add(original_const, target_const);
415#endif
416 equivalents.push_back(target_const);
417
418 count++;
419 }
420
421 return count;
422 }
423
424 typedef UniqueCStringMap<ConstString> Impl;
425 typedef const Impl::Entry* ImplData;
426 Impl m_impl;
427};
428
429static CPPRuntimeEquivalents&
430GetEquivalentsMap ()
431{
432 static CPPRuntimeEquivalents g_equivalents_map;
433 return g_equivalents_map;
434}
435
436
437uint32_t
438CPlusPlusLanguage::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents)
439{
440 uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents);
441
442 bool might_have_partials=
443 ( count == 0 ) // if we have a full name match just use it
444 && (strchr(type_name.AsCString(), '<') != NULL // we should only have partial matches when templates are involved, check that we have
445 && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches
446
447 if ( might_have_partials )
448 count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents);
449
450 return count;
451}
452
Enrico Granata33e97e62015-09-04 21:01:18 +0000453static void
454LoadLibCxxFormatters (lldb::TypeCategoryImplSP cpp_category_sp)
455{
456 if (!cpp_category_sp)
457 return;
458
459 TypeSummaryImpl::Flags stl_summary_flags;
460 stl_summary_flags.SetCascades(true)
461 .SetSkipPointers(false)
462 .SetSkipReferences(false)
463 .SetDontShowChildren(true)
464 .SetDontShowValue(true)
465 .SetShowMembersOneLiner(false)
466 .SetHideItemNames(false);
467
468#ifndef LLDB_DISABLE_PYTHON
469 lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider, "std::string summary provider"));
470 lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider, "std::wstring summary provider"));
471
472 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::string"),
473 std_string_summary_sp);
474 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >"),
475 std_string_summary_sp);
476
477 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::wstring"),
478 std_wstring_summary_sp);
479 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> >"),
480 std_wstring_summary_sp);
481
482 SyntheticChildren::Flags stl_synth_flags;
483 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
484
485 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator, "libc++ std::vector synthetic children", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_synth_flags, true);
486 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true);
487 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true);
488 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_synth_flags);
489 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
490 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true);
491 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
492 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
493 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator, "libc++ std::unordered containers synthetic children", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_synth_flags, true);
494 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxInitializerListSyntheticFrontEndCreator, "libc++ std::initializer_list synthetic children", ConstString("^std::initializer_list<.+>(( )?&)?$"), stl_synth_flags, true);
495
496 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
497 SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
498 "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
499
500 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "shared_ptr synthetic children", ConstString("^(std::__1::)shared_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
501 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxSharedPtrSyntheticFrontEndCreator, "weak_ptr synthetic children", ConstString("^(std::__1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags, true);
502
503 stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(false);
504 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_synth_flags);
505
506 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector summary provider", ConstString("^std::__1::vector<.+>(( )?&)?$"), stl_summary_flags, true);
507 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::list summary provider", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_summary_flags, true);
508 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true);
509 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true);
510 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_summary_flags);
511 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
512 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true);
513 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true);
514 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true);
515 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::unordered containers summary provider", ConstString("^(std::__1::)unordered_(multi)?(map|set)<.+> >$"), stl_summary_flags, true);
516
517 stl_summary_flags.SetSkipPointers(true);
518
519 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::shared_ptr summary provider", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
520 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxSmartPointerSummaryProvider, "libc++ std::weak_ptr summary provider", ConstString("^std::__1::weak_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
521
522 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^std::__1::__wrap_iter<.+>$"), stl_synth_flags, true);
523
524 AddCXXSummary(cpp_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<bool, std::__1::allocator<bool> >"), stl_summary_flags);
525 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::__1::__map_iterator<.+>$"), stl_synth_flags, true);
526
527 AddFilter(cpp_category_sp, {"__a_"}, "libc++ std::atomic filter", ConstString("^std::__1::atomic<.*>$"), stl_synth_flags, true);
528#endif
529}
530
531static void
532LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
533{
534 if (!cpp_category_sp)
535 return;
536
537 TypeSummaryImpl::Flags stl_summary_flags;
538 stl_summary_flags.SetCascades(true)
539 .SetSkipPointers(false)
540 .SetSkipReferences(false)
541 .SetDontShowChildren(true)
542 .SetDontShowValue(true)
543 .SetShowMembersOneLiner(false)
544 .SetHideItemNames(false);
545
546 lldb::TypeSummaryImplSP std_string_summary_sp(new StringSummaryFormat(stl_summary_flags,
547 "${var._M_dataplus._M_p}"));
548
549 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
550 std_string_summary_sp);
551 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char>"),
552 std_string_summary_sp);
553 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"),
554 std_string_summary_sp);
555 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
556 std_string_summary_sp);
557
558 // making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*)
559 lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags,
560 "${var._M_dataplus._M_p%S}"));
561
562 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
563 std_wstring_summary_sp);
564 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t>"),
565 std_wstring_summary_sp);
566 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >"),
567 std_wstring_summary_sp);
568 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
569 std_wstring_summary_sp);
570
571
572#ifndef LLDB_DISABLE_PYTHON
573
574 SyntheticChildren::Flags stl_synth_flags;
575 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
576
577 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
578 SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
579 "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
580 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
581 SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
582 "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
583 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
584 SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
585 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
586
587 stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true);
588 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
589 TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
590 "size=${svar%#}")));
591 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
592 TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
593 "size=${svar%#}")));
594 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
595 TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
596 "size=${svar%#}")));
597
598 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
599
600 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
601#endif
602}
603
604static void
605LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
606{
607 if (!cpp_category_sp)
608 return;
609
610 TypeSummaryImpl::Flags string_flags;
611 string_flags.SetCascades(true)
612 .SetSkipPointers(true)
613 .SetSkipReferences(false)
614 .SetDontShowChildren(true)
615 .SetDontShowValue(false)
616 .SetShowMembersOneLiner(false)
617 .SetHideItemNames(false);
618
619 TypeSummaryImpl::Flags string_array_flags;
620 string_array_flags.SetCascades(true)
621 .SetSkipPointers(true)
622 .SetSkipReferences(false)
623 .SetDontShowChildren(true)
624 .SetDontShowValue(true)
625 .SetShowMembersOneLiner(false)
626 .SetHideItemNames(false);
627
628#ifndef LLDB_DISABLE_PYTHON
629 // FIXME because of a bug in the FormattersContainer we need to add a summary for both X* and const X* (<rdar://problem/12717717>)
630 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags);
Dawn Perchik045c8292015-09-25 02:16:52 +0000631 AddCXXSummary(cpp_category_sp,
632 lldb_private::formatters::Char16StringSummaryProvider,
633 "char16_t [] summary provider",
634 ConstString("char16_t \\[[0-9]+\\]"),
635 string_array_flags,
636 true);
Enrico Granata33e97e62015-09-04 21:01:18 +0000637
638 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider, "char32_t * summary provider", ConstString("char32_t *"), string_flags);
Dawn Perchik045c8292015-09-25 02:16:52 +0000639 AddCXXSummary(cpp_category_sp,
640 lldb_private::formatters::Char32StringSummaryProvider,
641 "char32_t [] summary provider",
642 ConstString("char32_t \\[[0-9]+\\]"),
643 string_array_flags,
644 true);
Enrico Granata33e97e62015-09-04 21:01:18 +0000645
646 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
647 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
648
649 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags);
650
651 TypeSummaryImpl::Flags widechar_flags;
652 widechar_flags.SetDontShowValue(true)
653 .SetSkipPointers(true)
654 .SetSkipReferences(false)
655 .SetCascades(true)
656 .SetDontShowChildren(true)
657 .SetHideItemNames(true)
658 .SetShowMembersOneLiner(false);
659
660 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags);
661 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags);
662 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags);
663
664 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags);
665#endif
666}
667
668lldb::TypeCategoryImplSP
669CPlusPlusLanguage::GetFormatters ()
670{
671 static std::once_flag g_initialize;
672 static TypeCategoryImplSP g_category;
673
674 std::call_once(g_initialize, [this] () -> void {
675 DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
676 if (g_category)
677 {
678 LoadLibCxxFormatters(g_category);
679 LoadLibStdcppFormatters(g_category);
680 LoadSystemFormatters(g_category);
681 }
682 });
683 return g_category;
684}
685
Enrico Granata7cb59e12015-09-16 18:28:11 +0000686HardcodedFormatters::HardcodedSummaryFinder
687CPlusPlusLanguage::GetHardcodedSummaries ()
688{
689 static std::once_flag g_initialize;
690 static ConstString g_vectortypes("VectorTypes");
691 static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
692
693 std::call_once(g_initialize, [] () -> void {
694 g_formatters.push_back(
695 [](lldb_private::ValueObject& valobj,
696 lldb::DynamicValueType,
697 FormatManager&) -> TypeSummaryImpl::SharedPointer {
698 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::CXXFunctionPointerSummaryProvider, "Function pointer summary provider"));
699 if (valobj.GetCompilerType().IsFunctionPointerType())
700 {
701 return formatter_sp;
702 }
703 return nullptr;
704 });
705 g_formatters.push_back(
706 [](lldb_private::ValueObject& valobj,
707 lldb::DynamicValueType,
708 FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
709 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
710 .SetCascades(true)
711 .SetDontShowChildren(true)
712 .SetHideItemNames(true)
713 .SetShowMembersOneLiner(true)
714 .SetSkipPointers(true)
715 .SetSkipReferences(false),
716 lldb_private::formatters::VectorTypeSummaryProvider,
717 "vector_type pointer summary provider"));
718 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
719 {
720 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
721 return formatter_sp;
722 }
723 return nullptr;
724 });
725 });
726
727 return g_formatters;
728}
729
730HardcodedFormatters::HardcodedSyntheticFinder
731CPlusPlusLanguage::GetHardcodedSynthetics ()
732{
733 static std::once_flag g_initialize;
734 static ConstString g_vectortypes("VectorTypes");
735 static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
736
737 std::call_once(g_initialize, [] () -> void {
738 g_formatters.push_back(
739 [](lldb_private::ValueObject& valobj,
740 lldb::DynamicValueType,
741 FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer {
742 static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true),
743 "vector_type synthetic children",
744 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
745 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
746 {
747 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
748 return formatter_sp;
749 }
750 return nullptr;
751 });
752 });
753
754 return g_formatters;
755}
756