blob: b5634ec4d2461e44228bed5a003b85f8d5d973b9 [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}"));
Todd Fiala82ffb8e2015-10-22 00:23:38 +0000548
549 lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags,
550 LibStdcppStringSummaryProvider,
551 "libstdc++ c++11 std::string summary provider"));
552 lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags,
553 LibStdcppWStringSummaryProvider,
554 "libstdc++ c++11 std::wstring summary provider"));
555
Enrico Granata33e97e62015-09-04 21:01:18 +0000556 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
557 std_string_summary_sp);
558 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char>"),
559 std_string_summary_sp);
560 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char,std::char_traits<char>,std::allocator<char> >"),
561 std_string_summary_sp);
562 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
563 std_string_summary_sp);
Todd Fiala82ffb8e2015-10-22 00:23:38 +0000564
565 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::string"),
566 cxx11_string_summary_sp);
567 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
568 cxx11_string_summary_sp);
569
Enrico Granata33e97e62015-09-04 21:01:18 +0000570 // making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*)
571 lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags,
572 "${var._M_dataplus._M_p%S}"));
573
574 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::wstring"),
575 std_wstring_summary_sp);
576 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t>"),
577 std_wstring_summary_sp);
578 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >"),
579 std_wstring_summary_sp);
580 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
581 std_wstring_summary_sp);
Todd Fiala82ffb8e2015-10-22 00:23:38 +0000582
583 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::wstring"),
584 cxx11_wstring_summary_sp);
585 cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
586 cxx11_wstring_summary_sp);
587
Enrico Granata33e97e62015-09-04 21:01:18 +0000588#ifndef LLDB_DISABLE_PYTHON
589
590 SyntheticChildren::Flags stl_synth_flags;
591 stl_synth_flags.SetCascades(true).SetSkipPointers(false).SetSkipReferences(false);
592
593 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
594 SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
595 "lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
596 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
597 SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
598 "lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
Todd Fiala82ffb8e2015-10-22 00:23:38 +0000599 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")),
Enrico Granata33e97e62015-09-04 21:01:18 +0000600 SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
601 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
Todd Fiala82ffb8e2015-10-22 00:23:38 +0000602#if 0
603 // With only this, I get std::list showing the content, all children on the same line.
604 // With this and the section below, I see one child element per line.
605 cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::__cxx11::_List_base<.+>(( )?&)?$")),
606 SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
607 "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
608#endif
Enrico Granata33e97e62015-09-04 21:01:18 +0000609
610 stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true);
611 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
612 TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
613 "size=${svar%#}")));
614 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
615 TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
616 "size=${svar%#}")));
Todd Fiala82ffb8e2015-10-22 00:23:38 +0000617 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")),
Enrico Granata33e97e62015-09-04 21:01:18 +0000618 TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
619 "size=${svar%#}")));
Todd Fiala82ffb8e2015-10-22 00:23:38 +0000620#if 0
621 // With this, I get std::list showing one child per line. Requires the change above to get anything, though.
622 cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::__cxx11::_List_base<.+>(( )?&)?$")),
623 TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
624 "size=${svar%#}")));
625#endif
626
Enrico Granata33e97e62015-09-04 21:01:18 +0000627 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
628
629 AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
630#endif
631}
632
633static void
634LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
635{
636 if (!cpp_category_sp)
637 return;
638
639 TypeSummaryImpl::Flags string_flags;
640 string_flags.SetCascades(true)
641 .SetSkipPointers(true)
642 .SetSkipReferences(false)
643 .SetDontShowChildren(true)
644 .SetDontShowValue(false)
645 .SetShowMembersOneLiner(false)
646 .SetHideItemNames(false);
647
648 TypeSummaryImpl::Flags string_array_flags;
649 string_array_flags.SetCascades(true)
650 .SetSkipPointers(true)
651 .SetSkipReferences(false)
652 .SetDontShowChildren(true)
653 .SetDontShowValue(true)
654 .SetShowMembersOneLiner(false)
655 .SetHideItemNames(false);
656
657#ifndef LLDB_DISABLE_PYTHON
658 // FIXME because of a bug in the FormattersContainer we need to add a summary for both X* and const X* (<rdar://problem/12717717>)
659 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "char16_t * summary provider", ConstString("char16_t *"), string_flags);
Dawn Perchik045c8292015-09-25 02:16:52 +0000660 AddCXXSummary(cpp_category_sp,
661 lldb_private::formatters::Char16StringSummaryProvider,
662 "char16_t [] summary provider",
663 ConstString("char16_t \\[[0-9]+\\]"),
664 string_array_flags,
665 true);
Enrico Granata33e97e62015-09-04 21:01:18 +0000666
667 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32StringSummaryProvider, "char32_t * summary provider", ConstString("char32_t *"), string_flags);
Dawn Perchik045c8292015-09-25 02:16:52 +0000668 AddCXXSummary(cpp_category_sp,
669 lldb_private::formatters::Char32StringSummaryProvider,
670 "char32_t [] summary provider",
671 ConstString("char32_t \\[[0-9]+\\]"),
672 string_array_flags,
673 true);
Enrico Granata33e97e62015-09-04 21:01:18 +0000674
675 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t *"), string_flags);
676 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharStringSummaryProvider, "wchar_t * summary provider", ConstString("wchar_t \\[[0-9]+\\]"), string_array_flags, true);
677
678 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16StringSummaryProvider, "unichar * summary provider", ConstString("unichar *"), string_flags);
679
680 TypeSummaryImpl::Flags widechar_flags;
681 widechar_flags.SetDontShowValue(true)
682 .SetSkipPointers(true)
683 .SetSkipReferences(false)
684 .SetCascades(true)
685 .SetDontShowChildren(true)
686 .SetHideItemNames(true)
687 .SetShowMembersOneLiner(false);
688
689 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "char16_t summary provider", ConstString("char16_t"), widechar_flags);
690 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char32SummaryProvider, "char32_t summary provider", ConstString("char32_t"), widechar_flags);
691 AddCXXSummary(cpp_category_sp, lldb_private::formatters::WCharSummaryProvider, "wchar_t summary provider", ConstString("wchar_t"), widechar_flags);
692
693 AddCXXSummary(cpp_category_sp, lldb_private::formatters::Char16SummaryProvider, "unichar summary provider", ConstString("unichar"), widechar_flags);
694#endif
695}
696
697lldb::TypeCategoryImplSP
698CPlusPlusLanguage::GetFormatters ()
699{
700 static std::once_flag g_initialize;
701 static TypeCategoryImplSP g_category;
702
703 std::call_once(g_initialize, [this] () -> void {
704 DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
705 if (g_category)
706 {
707 LoadLibCxxFormatters(g_category);
708 LoadLibStdcppFormatters(g_category);
709 LoadSystemFormatters(g_category);
710 }
711 });
712 return g_category;
713}
714
Enrico Granata7cb59e12015-09-16 18:28:11 +0000715HardcodedFormatters::HardcodedSummaryFinder
716CPlusPlusLanguage::GetHardcodedSummaries ()
717{
718 static std::once_flag g_initialize;
719 static ConstString g_vectortypes("VectorTypes");
720 static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
721
722 std::call_once(g_initialize, [] () -> void {
723 g_formatters.push_back(
724 [](lldb_private::ValueObject& valobj,
725 lldb::DynamicValueType,
726 FormatManager&) -> TypeSummaryImpl::SharedPointer {
727 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags(), lldb_private::formatters::CXXFunctionPointerSummaryProvider, "Function pointer summary provider"));
728 if (valobj.GetCompilerType().IsFunctionPointerType())
729 {
730 return formatter_sp;
731 }
732 return nullptr;
733 });
734 g_formatters.push_back(
735 [](lldb_private::ValueObject& valobj,
736 lldb::DynamicValueType,
737 FormatManager& fmt_mgr) -> TypeSummaryImpl::SharedPointer {
738 static CXXFunctionSummaryFormat::SharedPointer formatter_sp(new CXXFunctionSummaryFormat(TypeSummaryImpl::Flags()
739 .SetCascades(true)
740 .SetDontShowChildren(true)
741 .SetHideItemNames(true)
742 .SetShowMembersOneLiner(true)
743 .SetSkipPointers(true)
744 .SetSkipReferences(false),
745 lldb_private::formatters::VectorTypeSummaryProvider,
746 "vector_type pointer summary provider"));
747 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
748 {
749 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
750 return formatter_sp;
751 }
752 return nullptr;
753 });
754 });
755
756 return g_formatters;
757}
758
759HardcodedFormatters::HardcodedSyntheticFinder
760CPlusPlusLanguage::GetHardcodedSynthetics ()
761{
762 static std::once_flag g_initialize;
763 static ConstString g_vectortypes("VectorTypes");
764 static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
765
766 std::call_once(g_initialize, [] () -> void {
767 g_formatters.push_back(
768 [](lldb_private::ValueObject& valobj,
769 lldb::DynamicValueType,
770 FormatManager& fmt_mgr) -> SyntheticChildren::SharedPointer {
771 static CXXSyntheticChildren::SharedPointer formatter_sp(new CXXSyntheticChildren(SyntheticChildren::Flags().SetCascades(true).SetSkipPointers(true).SetSkipReferences(true).SetNonCacheable(true),
772 "vector_type synthetic children",
773 lldb_private::formatters::VectorTypeSyntheticFrontEndCreator));
774 if (valobj.GetCompilerType().IsVectorType(nullptr, nullptr))
775 {
776 if (fmt_mgr.GetCategory(g_vectortypes)->IsEnabled())
777 return formatter_sp;
778 }
779 return nullptr;
780 });
781 });
782
783 return g_formatters;
784}
785