LLDB mainline
ValueObjectPrinter.cpp
Go to the documentation of this file.
1//===-- ValueObjectPrinter.cpp --------------------------------------------===//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8
10
14#include "lldb/Target/Target.h"
15#include "lldb/Utility/Stream.h"
17#include "llvm/Support/Error.h"
18#include "llvm/Support/MathExtras.h"
19#include <cstdint>
20#include <memory>
21#include <optional>
22
23using namespace lldb;
24using namespace lldb_private;
25
27 : m_orig_valobj(valobj) {
28 DumpValueObjectOptions options(valobj);
29 Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
30}
31
33 const DumpValueObjectOptions &options)
34 : m_orig_valobj(valobj) {
35 Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);
36}
37
39 ValueObject &valobj, Stream *s, const DumpValueObjectOptions &options,
40 const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth,
41 InstancePointersSetSP printed_instance_pointers)
42 : m_orig_valobj(valobj) {
43 Init(valobj, s, options, ptr_depth, curr_depth, printed_instance_pointers);
44}
45
47 ValueObject &valobj, Stream *s, const DumpValueObjectOptions &options,
48 const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth,
49 InstancePointersSetSP printed_instance_pointers) {
50 m_cached_valobj = nullptr;
51 m_stream = s;
52 m_options = options;
53 m_ptr_depth = ptr_depth;
54 m_curr_depth = curr_depth;
55 assert(m_stream && "cannot print to a NULL Stream");
63 m_summary_formatter = {nullptr, false};
64 m_value.assign("");
65 m_summary.assign("");
66 m_error.assign("");
67 m_val_summary_ok = false;
68 m_printed_instance_pointers = printed_instance_pointers
69 ? printed_instance_pointers
70 : std::make_shared<InstancePointersSet>();
72}
73
74static const char *maybeNewline(const std::string &s) {
75 // If the string already ends with a \n don't add another one.
76 if (s.empty() || s.back() != '\n')
77 return "\n";
78 return "";
79}
80
82 return ShouldPrintValueObject() && m_options.m_use_object_desc && !IsNil() &&
83 !IsUninitialized() && !m_options.m_pointer_as_array;
84}
85
87 // If the incoming ValueObject is in an error state, the best we're going to
88 // get out of it is its type. But if we don't even have that, just print
89 // the error and exit early.
90 if (m_orig_valobj.GetError().Fail() &&
91 !m_orig_valobj.GetCompilerType().IsValid())
92 return m_orig_valobj.GetError().ToError();
93
94 std::optional<std::string> object_desc;
96 // The object description is invoked now, but not printed until after
97 // value/summary. Calling GetObjectDescription at the outset of printing
98 // allows for early discovery of errors. In the case of an error, the value
99 // object is printed normally.
100 llvm::Expected<std::string> object_desc_or_err =
102 if (!object_desc_or_err) {
103 auto error_msg = toString(object_desc_or_err.takeError());
104 *m_stream << "error: " << error_msg << maybeNewline(error_msg);
105
106 // Print the value object directly.
107 m_options.DisableObjectDescription();
108 } else {
109 object_desc = *object_desc_or_err;
110 }
111 }
112
115 m_stream->Indent();
116
117 PrintDecl();
118 }
119
120 bool value_printed = false;
121 bool summary_printed = false;
122
124 PrintValueAndSummaryIfNeeded(value_printed, summary_printed);
125
126 if (m_val_summary_ok) {
128 return PrintChildrenIfNeeded(value_printed, summary_printed);
129 }
130 m_stream->EOL();
131
132 return llvm::Error::success();
133}
134
136 assert(m_cached_valobj && "ValueObjectPrinter must have a valid ValueObject");
137 return *m_cached_valobj;
138}
139
141 bool update_success = m_orig_valobj.UpdateValueIfNeeded(true);
142 // If we can't find anything better, we'll fall back on the original
143 // ValueObject.
145 if (update_success) {
146 if (m_orig_valobj.IsDynamic()) {
147 if (m_options.m_use_dynamic == eNoDynamicValues) {
148 ValueObject *static_value = m_orig_valobj.GetStaticValue().get();
149 if (static_value)
150 m_cached_valobj = static_value;
151 }
152 } else {
153 if (m_options.m_use_dynamic != eNoDynamicValues) {
154 ValueObject *dynamic_value =
155 m_orig_valobj.GetDynamicValue(m_options.m_use_dynamic).get();
156 if (dynamic_value)
157 m_cached_valobj = dynamic_value;
158 }
159 }
160
161 if (m_cached_valobj->IsSynthetic()) {
162 if (!m_options.m_use_synthetic) {
163 ValueObject *non_synthetic =
164 m_cached_valobj->GetNonSyntheticValue().get();
165 if (non_synthetic)
166 m_cached_valobj = non_synthetic;
167 }
168 } else {
169 if (m_options.m_use_synthetic) {
170 ValueObject *synthetic = m_cached_valobj->GetSyntheticValue().get();
171 if (synthetic)
172 m_cached_valobj = synthetic;
173 }
174 }
175 }
176 m_compiler_type = m_cached_valobj->GetCompilerType();
177 m_type_flags = m_compiler_type.GetTypeInfo();
178 assert(m_cached_valobj &&
179 "SetupMostSpecialized value must compute a valid ValueObject");
180}
181
183 const char *root_valobj_name =
184 m_options.m_root_valobj_name.empty()
186 : m_options.m_root_valobj_name.c_str();
187 return root_valobj_name ? root_valobj_name : "";
188}
189
193 (!m_options.m_flat_output || m_type_flags.Test(eTypeHasValue))
195 : eLazyBoolNo;
197}
198
205
213
216 m_is_ptr = m_type_flags.Test(eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
217 return m_is_ptr == eLazyBoolYes;
218}
219
222 m_is_ref = m_type_flags.Test(eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
223 return m_is_ref == eLazyBoolYes;
224}
225
232
234 // you need to do this check on the value's clang type
237 m_is_instance_ptr = (valobj.GetValue().GetCompilerType().GetTypeInfo() &
238 eTypeInstanceIsPointer) != 0
240 : eLazyBoolNo;
241 if ((eLazyBoolYes == m_is_instance_ptr) && valobj.IsBaseClass())
244}
245
247 if (m_options.m_show_location) {
248 m_stream->Printf("%s: ", GetMostSpecializedValue().GetLocationAsCString());
249 return true;
250 }
251 return false;
252}
253
255 bool show_type = true;
256 // if we are at the root-level and been asked to hide the root's type, then
257 // hide it
258 if (m_curr_depth == 0 && m_options.m_hide_root_type)
259 show_type = false;
260 else
261 // otherwise decide according to the usual rules (asked to show types -
262 // always at the root level)
263 show_type = m_options.m_show_types ||
264 (m_curr_depth == 0 && !m_options.m_flat_output);
265
266 StreamString typeName;
267 // Figure out which ValueObject we're acting on
269
270 // always show the type at the root level if it is invalid
271 if (show_type) {
272 // Some ValueObjects don't have types (like registers sets). Only print the
273 // type if there is one to print
274 ConstString type_name;
275 if (m_compiler_type.IsValid()) {
276 type_name = m_options.m_use_type_display_name
277 ? valobj.GetDisplayTypeName()
278 : valobj.GetQualifiedTypeName();
279 } else {
280 // only show an invalid type name if the user explicitly triggered
281 // show_type
282 if (m_options.m_show_types)
283 type_name = ConstString("<invalid type>");
284 }
285
286 if (type_name) {
287 std::string type_name_str(type_name.GetCString());
288 if (m_options.m_hide_pointer_value) {
289 for (auto iter = type_name_str.find(" *"); iter != std::string::npos;
290 iter = type_name_str.find(" *")) {
291 type_name_str.erase(iter, 2);
292 }
293 }
294 typeName << type_name_str.c_str();
295 }
296 }
297
298 StreamString varName;
299
300 if (ShouldShowName()) {
301 if (m_options.m_flat_output)
302 valobj.GetExpressionPath(varName);
303 else
304 varName << GetRootNameForDisplay();
305 }
306
307 bool decl_printed = false;
308 if (!m_options.m_decl_printing_helper) {
309 // if the user didn't give us a custom helper, pick one based upon the
310 // language, either the one that this printer is bound to, or the preferred
311 // one for the ValueObject
312 lldb::LanguageType lang_type =
313 (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
315 : m_options.m_varformat_language;
316 if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
317 m_options.m_decl_printing_helper = lang_plugin->GetDeclPrintingHelper();
318 }
319 }
320
321 if (m_options.m_decl_printing_helper) {
322 ConstString type_name_cstr(typeName.GetString());
323 ConstString var_name_cstr(varName.GetString());
324
325 DumpValueObjectOptions decl_print_options = m_options;
326 // Pass printing helpers an option object that indicates whether the name
327 // should be shown or hidden.
328 decl_print_options.SetHideName(!ShouldShowName());
329
330 StreamString dest_stream;
331 if (m_options.m_decl_printing_helper(type_name_cstr, var_name_cstr,
332 decl_print_options, dest_stream)) {
333 decl_printed = true;
334 m_stream->PutCString(dest_stream.GetString());
335 }
336 }
337
338 // if the helper failed, or there is none, do a default thing
339 if (!decl_printed) {
340 if (!typeName.Empty())
341 m_stream->Printf("(%s) ", typeName.GetData());
342 if (!varName.Empty())
343 m_stream->Printf("%s =", varName.GetData());
344 else if (ShouldShowName())
345 m_stream->Printf(" =");
346 }
347}
348
350 if (m_options.m_scope_already_checked)
351 return true;
353}
354
356 if (!m_summary_formatter.second) {
357 TypeSummaryImpl *entry =
358 m_options.m_summary_sp
359 ? m_options.m_summary_sp.get()
361
362 if (m_options.m_omit_summary_depth > 0)
363 entry = nullptr;
364 m_summary_formatter.first = entry;
365 m_summary_formatter.second = true;
366 }
367 if (m_options.m_omit_summary_depth > 0 && null_if_omitted)
368 return nullptr;
369 return m_summary_formatter.first;
370}
371
372static bool IsPointerValue(const CompilerType &type) {
373 Flags type_flags(type.GetTypeInfo());
374 if (type_flags.AnySet(eTypeInstanceIsPointer | eTypeIsPointer))
375 return type_flags.AllClear(eTypeIsBuiltIn);
376 return false;
377}
378
380 std::string &summary,
381 std::string &error) {
382 lldb::Format format = m_options.m_format;
384 // if I am printing synthetized elements, apply the format to those elements
385 // only
386 if (m_options.m_pointer_as_array)
388 else if (format != eFormatDefault && format != valobj.GetFormat())
389 valobj.GetValueAsCString(format, value);
390 else {
391 const char *val_cstr = valobj.GetValueAsCString();
392 if (val_cstr)
393 value.assign(val_cstr);
394 }
395 const char *err_cstr = valobj.GetError().AsCString();
396 if (err_cstr)
397 error.assign(err_cstr);
398
400 return;
401
402 if (IsNil()) {
403 lldb::LanguageType lang_type =
404 (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)
406 : m_options.m_varformat_language;
407 if (Language *lang_plugin = Language::FindPlugin(lang_type)) {
408 summary.assign(lang_plugin->GetNilReferenceSummaryString().str());
409 } else {
410 // We treat C as the fallback language rather than as a separate Language
411 // plugin.
412 summary.assign("NULL");
413 }
414 } else if (IsUninitialized()) {
415 summary.assign("<uninitialized>");
416 } else if (m_options.m_omit_summary_depth == 0) {
418 if (entry) {
419 valobj.GetSummaryAsCString(entry, summary,
420 m_options.m_varformat_language);
421 } else {
422 const char *sum_cstr =
423 valobj.GetSummaryAsCString(m_options.m_varformat_language);
424 if (sum_cstr)
425 summary.assign(sum_cstr);
426 }
427 }
428}
429
431 bool &summary_printed) {
432 bool error_printed = false;
434 if (!CheckScopeIfNeeded())
435 m_error.assign("out of scope");
436 if (m_error.empty()) {
438 }
439 if (m_error.size()) {
440 // we need to support scenarios in which it is actually fine for a value
441 // to have no type but - on the other hand - if we get an error *AND*
442 // have no type, we try to get out gracefully, since most often that
443 // combination means "could not resolve a type" and the default failure
444 // mode is quite ugly
445 if (!m_compiler_type.IsValid()) {
446 m_stream->Printf(" <could not resolve type>");
447 return false;
448 }
449
450 error_printed = true;
451 m_stream->Printf(" <%s>\n", m_error.c_str());
452 } else {
453 // Make sure we have a value and make sure the summary didn't specify
454 // that the value should not be printed - and do not print the value if
455 // this thing is nil (but show the value if the user passes a format
456 // explicitly)
459 const bool has_nil_or_uninitialized_summary =
460 (IsNil() || IsUninitialized()) && !m_summary.empty();
461 if (!has_nil_or_uninitialized_summary && !m_value.empty() &&
462 (entry == nullptr ||
463 (entry->DoesPrintValue(&valobj) ||
464 m_options.m_format != eFormatDefault) ||
465 m_summary.empty()) &&
466 !m_options.m_hide_value) {
467 if (m_options.m_hide_pointer_value &&
469 } else {
470 if (ShouldShowName())
471 m_stream->PutChar(' ');
472 m_stream->PutCString(m_value);
473 value_printed = true;
474 }
475 }
476
477 if (m_summary.size()) {
478 if (ShouldShowName() || value_printed)
479 m_stream->PutChar(' ');
480 m_stream->PutCString(m_summary);
481 summary_printed = true;
482 }
483 }
484 }
485 return !error_printed;
486}
487
489 std::optional<std::string> object_desc) {
490 if (!object_desc)
491 return;
492
493 if (!m_options.m_hide_value || ShouldShowName())
494 *m_stream << ' ';
495 *m_stream << *object_desc << maybeNewline(*object_desc);
496}
497
501
503 DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
504 const bool is_ref = IsRef();
505 const bool is_ptr = IsPtr();
506 const bool is_uninit = IsUninitialized();
507
508 if (is_uninit)
509 return false;
510
511 // If we have reached the maximum depth we shouldn't print any more children.
513 return false;
514
515 // if the user has specified an element count, always print children as it is
516 // explicit user demand being honored
517 if (m_options.m_pointer_as_array)
518 return true;
519
520 if (m_options.m_use_object_desc)
521 return false;
522
523 bool print_children = true;
525 if (TypeSummaryImpl *type_summary = GetSummaryFormatter())
526 print_children = type_summary->DoesPrintChildren(&valobj);
527
528 // We will show children for all concrete types. We won't show pointer
529 // contents unless a pointer depth has been specified. We won't reference
530 // contents unless the reference is the root object (depth of zero).
531
532 // Use a new temporary pointer depth in case we override the current
533 // pointer depth below...
534
535 if (is_ptr || is_ref) {
536 // We have a pointer or reference whose value is an address. Make sure
537 // that address is not NULL
538 if (valobj.GetPointerValue().address == 0)
539 return false;
540
541 const bool is_root_level = m_curr_depth == 0;
542 const bool is_expanded_ptr =
543 is_ptr && m_type_flags.Test(m_options.m_expand_ptr_type_flags);
544
545 if ((is_ref || is_expanded_ptr) && is_root_level && print_children) {
546 // If this is the root object (depth is zero) that we are showing and it
547 // is either a reference or a preferred type of pointer, then print it.
548 // Don't do this at deeper depths otherwise we can end up with infinite
549 // recursion...
550 return true;
551 }
552
553 return curr_ptr_depth.CanAllowExpansion();
554 }
555
556 return print_children || m_summary.empty();
557}
558
561
562 if (!entry)
563 return true;
564
565 return entry->DoesPrintEmptyAggregates();
566}
567
571
573 bool summary_printed) {
574 if (m_options.m_flat_output) {
576 m_stream->EOL();
577 } else {
579 if (IsRef()) {
580 m_stream->PutCString(": ");
581 } else if (value_printed || summary_printed || ShouldShowName()) {
582 m_stream->PutChar(' ');
583 }
584 m_stream->PutCString("{\n");
585 }
586 m_stream->IndentMore();
587 }
588}
589
591 ValueObjectSP child_sp,
592 const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
593 const uint32_t consumed_summary_depth = m_options.m_pointer_as_array ? 0 : 1;
594 const bool does_consume_ptr_depth =
595 ((IsPtr() && !m_options.m_pointer_as_array) || IsRef());
596
597 DumpValueObjectOptions child_options(m_options);
598 child_options.SetFormat(m_options.m_format)
599 .SetSummary()
601 child_options.SetScopeChecked(true)
602 .SetHideName(m_options.m_hide_name)
603 .SetHideValue(m_options.m_hide_value)
605 ? child_options.m_omit_summary_depth -
606 consumed_summary_depth
607 : 0)
608 .SetElementCount(0);
609
610 if (child_sp.get()) {
611 auto ptr_depth = curr_ptr_depth;
612 if (does_consume_ptr_depth)
613 ptr_depth = curr_ptr_depth.Decremented();
614
615 ValueObjectPrinter child_printer(*(child_sp.get()), m_stream, child_options,
616 ptr_depth, m_curr_depth + 1,
618 llvm::Error error = child_printer.PrintValueObject();
619 if (error) {
620 if (m_stream)
621 *m_stream << "error: " << toString(std::move(error));
622 else
623 llvm::consumeError(std::move(error));
624 }
625 }
626}
627
628llvm::Expected<uint32_t>
631
632 if (m_options.m_pointer_as_array)
633 return m_options.m_pointer_as_array.m_element_count;
634
635 const uint32_t max_num_children =
636 m_options.m_ignore_cap ? UINT32_MAX
638 .GetTargetSP()
639 ->GetMaximumNumberOfChildrenToDisplay();
640 // Ask for one more child than the maximum to see if we should print "...".
641 auto num_children_or_err = synth_valobj.GetNumChildren(
642 llvm::SaturatingAdd(max_num_children, uint32_t(1)));
643 if (!num_children_or_err)
644 return num_children_or_err;
645 if (*num_children_or_err > max_num_children) {
646 print_dotdotdot = true;
647 return max_num_children;
648 }
649 return num_children_or_err;
650}
651
653 if (!m_options.m_flat_output) {
654 if (print_dotdotdot) {
656 .GetTargetSP()
657 ->GetDebugger()
658 .GetCommandInterpreter()
659 .ChildrenTruncated();
660 m_stream->Indent("...\n");
661 }
662 m_stream->IndentLess();
663 m_stream->Indent("}\n");
664 }
665}
666
668 bool summary_printed) {
670
671 if (!IsAggregate())
672 return false;
673
674 if (!m_options.m_reveal_empty_aggregates) {
675 if (value_printed || summary_printed)
676 return false;
677 }
678
679 if (synth_valobj.MightHaveChildren())
680 return true;
681
683 return false;
684
685 return true;
686}
687
688static constexpr size_t PhysicalIndexForLogicalIndex(size_t base, size_t stride,
689 size_t logical) {
690 return base + logical * stride;
691}
692
694 size_t idx) {
695 if (m_options.m_pointer_as_array) {
696 // if generating pointer-as-array children, use GetSyntheticArrayMember
697 return synth_valobj.GetSyntheticArrayMember(
699 m_options.m_pointer_as_array.m_base_element,
700 m_options.m_pointer_as_array.m_stride, idx),
701 true);
702 } else {
703 // otherwise, do the usual thing
704 return synth_valobj.GetChildAtIndex(idx);
705 }
706}
707
709 bool value_printed, bool summary_printed,
710 const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {
712
713 bool print_dotdotdot = false;
714 auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot);
715 if (!num_children_or_err) {
716 *m_stream << " <" << llvm::toString(num_children_or_err.takeError()) << '>';
717 return;
718 }
719 uint32_t num_children = *num_children_or_err;
720 if (num_children) {
721 bool any_children_printed = false;
722
723 for (size_t idx = 0; idx < num_children; ++idx) {
724 if (ValueObjectSP child_sp = GenerateChild(synth_valobj, idx)) {
725 if (m_options.m_child_printing_decider &&
726 !m_options.m_child_printing_decider(child_sp->GetName()))
727 continue;
728 if (!any_children_printed) {
729 PrintChildrenPreamble(value_printed, summary_printed);
730 any_children_printed = true;
731 }
732 PrintChild(child_sp, curr_ptr_depth);
733 }
734 }
735
736 if (any_children_printed)
737 PrintChildrenPostamble(print_dotdotdot);
738 else {
739 if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
741 m_stream->PutCString(" {}\n");
742 else
743 m_stream->EOL();
744 } else
745 m_stream->EOL();
746 }
747 } else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {
748 // Aggregate, no children...
750 // if it has a synthetic value, then don't print {}, the synthetic
751 // children are probably only being used to vend a value
752 if (GetMostSpecializedValue().DoesProvideSyntheticValue() ||
754 m_stream->PutCString("\n");
755 else
756 m_stream->PutCString(" {}\n");
757 }
758 } else {
760 m_stream->EOL();
761 }
762}
763
766
767 bool print_dotdotdot = false;
768 auto num_children_or_err = GetMaxNumChildrenToPrint(print_dotdotdot);
769 if (!num_children_or_err) {
770 *m_stream << '<' << llvm::toString(num_children_or_err.takeError()) << '>';
771 return true;
772 }
773 uint32_t num_children = *num_children_or_err;
774
775 if (num_children) {
776 m_stream->PutChar('(');
777
778 bool did_print_children = false;
779 for (uint32_t idx = 0; idx < num_children; ++idx) {
780 lldb::ValueObjectSP child_sp(synth_valobj.GetChildAtIndex(idx));
781 if (child_sp)
782 child_sp = child_sp->GetQualifiedRepresentationIfAvailable(
783 m_options.m_use_dynamic, m_options.m_use_synthetic);
784 if (child_sp) {
785 if (m_options.m_child_printing_decider &&
786 !m_options.m_child_printing_decider(child_sp->GetName()))
787 continue;
788 if (idx && did_print_children)
789 m_stream->PutCString(", ");
790 did_print_children = true;
791 if (!hide_names) {
792 const char *name = child_sp.get()->GetName().AsCString();
793 if (name && *name) {
794 m_stream->PutCString(name);
795 m_stream->PutCString(" = ");
796 }
797 }
798 child_sp->DumpPrintableRepresentation(
800 m_options.m_format,
802 }
803 }
804
805 if (print_dotdotdot)
806 m_stream->PutCString(", ...)");
807 else
808 m_stream->PutChar(')');
809 }
810 return true;
811}
812
813llvm::Error ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,
814 bool summary_printed) {
815
817
819 const bool print_children = ShouldPrintChildren(curr_ptr_depth);
820 const bool print_oneline =
821 (curr_ptr_depth.CanAllowExpansion() || m_options.m_show_types ||
822 !m_options.m_allow_oneliner_mode || m_options.m_flat_output ||
823 (m_options.m_pointer_as_array) || m_options.m_show_location)
824 ? false
826 if (print_children && IsInstancePointer()) {
827 uint64_t instance_ptr_value = valobj.GetValueAsUnsigned(0);
828 if (m_printed_instance_pointers->count(instance_ptr_value)) {
829 // We already printed this instance-is-pointer thing, so don't expand it.
830 m_stream->PutCString(" {...}\n");
831 return llvm::Error::success();
832 } else {
833 // Remember this guy for future reference.
834 m_printed_instance_pointers->emplace(instance_ptr_value);
835 }
836 }
837
838 if (print_children) {
839 if (print_oneline) {
840 m_stream->PutChar(' ');
842 m_stream->EOL();
843 } else
844 PrintChildren(value_printed, summary_printed, curr_ptr_depth);
845 } else if (HasReachedMaximumDepth() && IsAggregate() &&
847 m_stream->PutCString(" {...}\n");
848 // The maximum child depth has been reached. If `m_max_depth` is the default
849 // (i.e. the user has _not_ customized it), then lldb presents a warning to
850 // the user. The warning tells the user that the limit has been reached, but
851 // more importantly tells them how to expand the limit if desired.
852 if (m_options.m_max_depth_is_default)
853 valobj.GetTargetSP()
854 ->GetDebugger()
855 .GetCommandInterpreter()
856 .SetReachedMaximumDepth();
857 } else
858 m_stream->EOL();
859 return llvm::Error::success();
860}
861
865
867 if (m_curr_depth == 0)
868 return !m_options.m_hide_root_name && !m_options.m_hide_name;
869 return !m_options.m_hide_name;
870}
static llvm::raw_ostream & error(Stream &strm)
static bool IsPointerValue(const CompilerType &type)
static constexpr size_t PhysicalIndexForLogicalIndex(size_t base, size_t stride, size_t logical)
static const char * maybeNewline(const std::string &s)
Generic representation of a type in a programming language.
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
A uniqued constant string class.
Definition ConstString.h:40
const char * AsCString(const char *value_if_empty=nullptr) const
Get the string value as a C string.
const char * GetCString() const
Get the string value as a C string.
static bool ShouldPrintAsOneLiner(ValueObject &valobj)
DumpValueObjectOptions & SetHideName(bool hide_name=false)
DumpValueObjectOptions & SetSummary(lldb::TypeSummaryImplSP summary=lldb::TypeSummaryImplSP())
DumpValueObjectOptions & SetOmitSummaryDepth(uint32_t depth=0)
DumpValueObjectOptions & SetRootValueObjectName(const char *name=nullptr)
DumpValueObjectOptions & SetFormat(lldb::Format format=lldb::eFormatDefault)
DumpValueObjectOptions & SetScopeChecked(bool check=true)
DumpValueObjectOptions & SetHideValue(bool hide_value=false)
DumpValueObjectOptions & SetElementCount(uint32_t element_count=0)
A class to manage flags.
Definition Flags.h:22
bool AllClear(ValueType mask) const
Test if all bits in mask are clear.
Definition Flags.h:103
bool AnySet(ValueType mask) const
Test one or more flags.
Definition Flags.h:90
static Language * FindPlugin(lldb::LanguageType language)
Definition Language.cpp:84
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition Status.cpp:195
const char * GetData() const
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition Stream.h:28
virtual bool DoesPrintEmptyAggregates() const
virtual bool DoesPrintValue(ValueObject *valobj) const
void PrintChildrenPreamble(bool value_printed, bool summary_printed)
std::shared_ptr< InstancePointersSet > InstancePointersSetSP
ValueObjectPrinter(ValueObject &valobj, Stream *s)
The ValueObjectPrinter is a one-shot printer for ValueObjects.
std::pair< TypeSummaryImpl *, bool > m_summary_formatter
void PrintChild(lldb::ValueObjectSP child_sp, const DumpValueObjectOptions::PointerDepth &curr_ptr_depth)
TypeSummaryImpl * GetSummaryFormatter(bool null_if_omitted=true)
ValueObject & GetMostSpecializedValue()
Cache the ValueObject we are actually going to print.
bool ShouldPrintChildren(DumpValueObjectOptions::PointerDepth &curr_ptr_depth)
DumpValueObjectOptions::PointerDepth m_ptr_depth
void PrintChildrenPostamble(bool print_dotdotdot)
llvm::Error PrintChildrenIfNeeded(bool value_printed, bool summary_printed)
lldb::ValueObjectSP GenerateChild(ValueObject &synth_valobj, size_t idx)
InstancePointersSetSP m_printed_instance_pointers
void Init(ValueObject &valobj, Stream *s, const DumpValueObjectOptions &options, const DumpValueObjectOptions::PointerDepth &ptr_depth, uint32_t curr_depth, InstancePointersSetSP printed_instance_pointers)
Ee should actually be using delegating constructors here but some versions of GCC still have trouble ...
void PrintChildren(bool value_printed, bool summary_printed, const DumpValueObjectOptions::PointerDepth &curr_ptr_depth)
void PrintObjectDescriptionIfNeeded(std::optional< std::string > object_desc)
bool PrintChildrenOneLiner(bool hide_names)
ValueObject * m_cached_valobj
Cache the current "most specialized" value.
void GetValueSummaryError(std::string &value, std::string &summary, std::string &error)
bool PrintValueAndSummaryIfNeeded(bool &value_printed, bool &summary_printed)
llvm::Expected< uint32_t > GetMaxNumChildrenToPrint(bool &print_dotdotdot)
bool ShouldPrintEmptyBrackets(bool value_printed, bool summary_printed)
lldb::TypeSummaryImplSP GetSummaryFormat()
virtual lldb::ValueObjectSP GetChildAtIndex(uint32_t idx, bool can_create=true)
virtual bool MightHaveChildren()
Find out if a ValueObject might have children.
CompilerType GetCompilerType()
lldb::Format GetFormat() const
virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, bool *success=nullptr)
llvm::Expected< uint32_t > GetNumChildren(uint32_t max=UINT32_MAX)
virtual void GetExpressionPath(Stream &s, GetExpressionPathFormat=eGetExpressionPathFormatDereferencePointers)
virtual ConstString GetDisplayTypeName()
virtual bool IsBaseClass()
const Status & GetError()
lldb::TargetSP GetTargetSP() const
virtual const char * GetValueAsCString()
ConstString GetName() const
virtual ConstString GetQualifiedTypeName()
llvm::Expected< std::string > GetObjectDescription()
const char * GetSummaryAsCString(lldb::LanguageType lang=lldb::eLanguageTypeUnknown)
lldb::ValueObjectSP GetSyntheticArrayMember(size_t index, bool can_create)
const Value & GetValue() const
virtual lldb::LanguageType GetPreferredDisplayLanguage()
#define UINT32_MAX
A class that represents a running process on the host machine.
const char * toString(AppleArm64ExceptionClass EC)
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
Format
Display format definitions.
LanguageType
Programming language type.
@ eLanguageTypeUnknown
Unknown or invalid language value.