brintos

brintos / llvm-project-archived public Read only

0
0
Text · 29.4 KiB · e200511 Raw
871 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/DataFormatters/ValueObjectPrinter.h"10 11#include "lldb/DataFormatters/DataVisualization.h"12#include "lldb/Interpreter/CommandInterpreter.h"13#include "lldb/Target/Language.h"14#include "lldb/Target/Target.h"15#include "lldb/Utility/Stream.h"16#include "lldb/ValueObject/ValueObject.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 26ValueObjectPrinter::ValueObjectPrinter(ValueObject &valobj, Stream *s)27    : m_orig_valobj(valobj) {28  DumpValueObjectOptions options(valobj);29  Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);30}31 32ValueObjectPrinter::ValueObjectPrinter(ValueObject &valobj, Stream *s,33                                       const DumpValueObjectOptions &options)34    : m_orig_valobj(valobj) {35  Init(valobj, s, options, m_options.m_max_ptr_depth, 0, nullptr);36}37 38ValueObjectPrinter::ValueObjectPrinter(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 46void ValueObjectPrinter::Init(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");56  m_should_print = eLazyBoolCalculate;57  m_is_nil = eLazyBoolCalculate;58  m_is_uninit = eLazyBoolCalculate;59  m_is_ptr = eLazyBoolCalculate;60  m_is_ref = eLazyBoolCalculate;61  m_is_aggregate = eLazyBoolCalculate;62  m_is_instance_ptr = eLazyBoolCalculate;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_pointers69                                    ? printed_instance_pointers70                                    : std::make_shared<InstancePointersSet>();71  SetupMostSpecializedValue();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 81bool ValueObjectPrinter::ShouldPrintObjectDescription() {82  return ShouldPrintValueObject() && m_options.m_use_object_desc && !IsNil() &&83         !IsUninitialized() && !m_options.m_pointer_as_array;84}85 86llvm::Error ValueObjectPrinter::PrintValueObject() {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 print89  // 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;95  if (ShouldPrintObjectDescription()) {96    // The object description is invoked now, but not printed until after97    // value/summary. Calling GetObjectDescription at the outset of printing98    // allows for early discovery of errors. In the case of an error, the value99    // object is printed normally.100    llvm::Expected<std::string> object_desc_or_err =101        GetMostSpecializedValue().GetObjectDescription();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 113  if (ShouldPrintValueObject()) {114    PrintLocationIfNeeded();115    m_stream->Indent();116 117    PrintDecl();118  }119 120  bool value_printed = false;121  bool summary_printed = false;122 123  m_val_summary_ok =124      PrintValueAndSummaryIfNeeded(value_printed, summary_printed);125 126  if (m_val_summary_ok) {127    PrintObjectDescriptionIfNeeded(object_desc);128    return PrintChildrenIfNeeded(value_printed, summary_printed);129  }130  m_stream->EOL();131 132  return llvm::Error::success();133}134 135ValueObject &ValueObjectPrinter::GetMostSpecializedValue() {136  assert(m_cached_valobj && "ValueObjectPrinter must have a valid ValueObject");137  return *m_cached_valobj;138}139 140void ValueObjectPrinter::SetupMostSpecializedValue() {141  bool update_success = m_orig_valobj.UpdateValueIfNeeded(true);142  // If we can't find anything better, we'll fall back on the original143  // ValueObject.144  m_cached_valobj = &m_orig_valobj;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 182const char *ValueObjectPrinter::GetRootNameForDisplay() {183  const char *root_valobj_name =184      m_options.m_root_valobj_name.empty()185          ? GetMostSpecializedValue().GetName().AsCString()186          : m_options.m_root_valobj_name.c_str();187  return root_valobj_name ? root_valobj_name : "";188}189 190bool ValueObjectPrinter::ShouldPrintValueObject() {191  if (m_should_print == eLazyBoolCalculate)192    m_should_print =193        (!m_options.m_flat_output || m_type_flags.Test(eTypeHasValue))194            ? eLazyBoolYes195            : eLazyBoolNo;196  return m_should_print == eLazyBoolYes;197}198 199bool ValueObjectPrinter::IsNil() {200  if (m_is_nil == eLazyBoolCalculate)201    m_is_nil =202        GetMostSpecializedValue().IsNilReference() ? eLazyBoolYes : eLazyBoolNo;203  return m_is_nil == eLazyBoolYes;204}205 206bool ValueObjectPrinter::IsUninitialized() {207  if (m_is_uninit == eLazyBoolCalculate)208    m_is_uninit = GetMostSpecializedValue().IsUninitializedReference()209                      ? eLazyBoolYes210                      : eLazyBoolNo;211  return m_is_uninit == eLazyBoolYes;212}213 214bool ValueObjectPrinter::IsPtr() {215  if (m_is_ptr == eLazyBoolCalculate)216    m_is_ptr = m_type_flags.Test(eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;217  return m_is_ptr == eLazyBoolYes;218}219 220bool ValueObjectPrinter::IsRef() {221  if (m_is_ref == eLazyBoolCalculate)222    m_is_ref = m_type_flags.Test(eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;223  return m_is_ref == eLazyBoolYes;224}225 226bool ValueObjectPrinter::IsAggregate() {227  if (m_is_aggregate == eLazyBoolCalculate)228    m_is_aggregate =229        m_type_flags.Test(eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;230  return m_is_aggregate == eLazyBoolYes;231}232 233bool ValueObjectPrinter::IsInstancePointer() {234  // you need to do this check on the value's clang type235  ValueObject &valobj = GetMostSpecializedValue();236  if (m_is_instance_ptr == eLazyBoolCalculate)237    m_is_instance_ptr = (valobj.GetValue().GetCompilerType().GetTypeInfo() &238                         eTypeInstanceIsPointer) != 0239                            ? eLazyBoolYes240                            : eLazyBoolNo;241  if ((eLazyBoolYes == m_is_instance_ptr) && valobj.IsBaseClass())242    m_is_instance_ptr = eLazyBoolNo;243  return m_is_instance_ptr == eLazyBoolYes;244}245 246bool ValueObjectPrinter::PrintLocationIfNeeded() {247  if (m_options.m_show_location) {248    m_stream->Printf("%s: ", GetMostSpecializedValue().GetLocationAsCString());249    return true;250  }251  return false;252}253 254void ValueObjectPrinter::PrintDecl() {255  bool show_type = true;256  // if we are at the root-level and been asked to hide the root's type, then257  // hide it258  if (m_curr_depth == 0 && m_options.m_hide_root_type)259    show_type = false;260  else261    // 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 on268  ValueObject &valobj = GetMostSpecializedValue();269 270  // always show the type at the root level if it is invalid271  if (show_type) {272    // Some ValueObjects don't have types (like registers sets). Only print the273    // type if there is one to print274    ConstString type_name;275    if (m_compiler_type.IsValid()) {276      type_name = m_options.m_use_type_display_name277                      ? valobj.GetDisplayTypeName()278                      : valobj.GetQualifiedTypeName();279    } else {280      // only show an invalid type name if the user explicitly triggered281      // show_type282      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    else304      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 the310    // language, either the one that this printer is bound to, or the preferred311    // one for the ValueObject312    lldb::LanguageType lang_type =313        (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)314            ? valobj.GetPreferredDisplayLanguage()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 name327    // 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 thing339  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 349bool ValueObjectPrinter::CheckScopeIfNeeded() {350  if (m_options.m_scope_already_checked)351    return true;352  return GetMostSpecializedValue().IsInScope();353}354 355TypeSummaryImpl *ValueObjectPrinter::GetSummaryFormatter(bool null_if_omitted) {356  if (!m_summary_formatter.second) {357    TypeSummaryImpl *entry =358        m_options.m_summary_sp359            ? m_options.m_summary_sp.get()360            : GetMostSpecializedValue().GetSummaryFormat().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 379void ValueObjectPrinter::GetValueSummaryError(std::string &value,380                                              std::string &summary,381                                              std::string &error) {382  lldb::Format format = m_options.m_format;383  ValueObject &valobj = GetMostSpecializedValue();384  // if I am printing synthetized elements, apply the format to those elements385  // only386  if (m_options.m_pointer_as_array)387    valobj.GetValueAsCString(lldb::eFormatDefault, value);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 399  if (!ShouldPrintValueObject())400    return;401 402  if (IsNil()) {403    lldb::LanguageType lang_type =404        (m_options.m_varformat_language == lldb::eLanguageTypeUnknown)405            ? valobj.GetPreferredDisplayLanguage()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 Language411      // plugin.412      summary.assign("NULL");413    }414  } else if (IsUninitialized()) {415    summary.assign("<uninitialized>");416  } else if (m_options.m_omit_summary_depth == 0) {417    TypeSummaryImpl *entry = GetSummaryFormatter();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 430bool ValueObjectPrinter::PrintValueAndSummaryIfNeeded(bool &value_printed,431                                                      bool &summary_printed) {432  bool error_printed = false;433  if (ShouldPrintValueObject()) {434    if (!CheckScopeIfNeeded())435      m_error.assign("out of scope");436    if (m_error.empty()) {437      GetValueSummaryError(m_value, m_summary, m_error);438    }439    if (m_error.size()) {440      // we need to support scenarios in which it is actually fine for a value441      // 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 that443      // combination means "could not resolve a type" and the default failure444      // mode is quite ugly445      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 specify454      // that the value should not be printed - and do not print the value if455      // this thing is nil (but show the value if the user passes a format456      // explicitly)457      TypeSummaryImpl *entry = GetSummaryFormatter();458      ValueObject &valobj = GetMostSpecializedValue();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 &&468            IsPointerValue(valobj.GetCompilerType())) {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 488void ValueObjectPrinter::PrintObjectDescriptionIfNeeded(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 498bool DumpValueObjectOptions::PointerDepth::CanAllowExpansion() const {499  return m_count > 0;500}501 502bool ValueObjectPrinter::ShouldPrintChildren(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.512  if (HasReachedMaximumDepth())513    return false;514 515  // if the user has specified an element count, always print children as it is516  // explicit user demand being honored517  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;524  ValueObject &valobj = GetMostSpecializedValue();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 pointer529  // contents unless a pointer depth has been specified. We won't reference530  // contents unless the reference is the root object (depth of zero).531 532  // Use a new temporary pointer depth in case we override the current533  // pointer depth below...534 535  if (is_ptr || is_ref) {536    // We have a pointer or reference whose value is an address. Make sure537    // that address is not NULL538    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 it547      // 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 infinite549      // recursion...550      return true;551    }552 553    return curr_ptr_depth.CanAllowExpansion();554  }555 556  return print_children || m_summary.empty();557}558 559bool ValueObjectPrinter::ShouldExpandEmptyAggregates() {560  TypeSummaryImpl *entry = GetSummaryFormatter();561 562  if (!entry)563    return true;564 565  return entry->DoesPrintEmptyAggregates();566}567 568ValueObject &ValueObjectPrinter::GetValueObjectForChildrenGeneration() {569  return GetMostSpecializedValue();570}571 572void ValueObjectPrinter::PrintChildrenPreamble(bool value_printed,573                                               bool summary_printed) {574  if (m_options.m_flat_output) {575    if (ShouldPrintValueObject())576      m_stream->EOL();577  } else {578    if (ShouldPrintValueObject()) {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 590void ValueObjectPrinter::PrintChild(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()600      .SetRootValueObjectName();601  child_options.SetScopeChecked(true)602      .SetHideName(m_options.m_hide_name)603      .SetHideValue(m_options.m_hide_value)604      .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1605                               ? child_options.m_omit_summary_depth -606                                     consumed_summary_depth607                               : 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,617                                     m_printed_instance_pointers);618    llvm::Error error = child_printer.PrintValueObject();619    if (error) {620      if (m_stream)621        *m_stream << "error: " << toString(std::move(error));622      else623        llvm::consumeError(std::move(error));624    }625  }626}627 628llvm::Expected<uint32_t>629ValueObjectPrinter::GetMaxNumChildrenToPrint(bool &print_dotdotdot) {630  ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();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_MAX637                             : GetMostSpecializedValue()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 652void ValueObjectPrinter::PrintChildrenPostamble(bool print_dotdotdot) {653  if (!m_options.m_flat_output) {654    if (print_dotdotdot) {655      GetMostSpecializedValue()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 667bool ValueObjectPrinter::ShouldPrintEmptyBrackets(bool value_printed,668                                                  bool summary_printed) {669  ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();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 682  if (m_val_summary_ok)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 693ValueObjectSP ValueObjectPrinter::GenerateChild(ValueObject &synth_valobj,694                                                size_t idx) {695  if (m_options.m_pointer_as_array) {696    // if generating pointer-as-array children, use GetSyntheticArrayMember697    return synth_valobj.GetSyntheticArrayMember(698        PhysicalIndexForLogicalIndex(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 thing704    return synth_valobj.GetChildAtIndex(idx);705  }706}707 708void ValueObjectPrinter::PrintChildren(709    bool value_printed, bool summary_printed,710    const DumpValueObjectOptions::PointerDepth &curr_ptr_depth) {711  ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();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)) {740        if (ShouldPrintValueObject())741          m_stream->PutCString(" {}\n");742        else743          m_stream->EOL();744      } else745        m_stream->EOL();746    }747  } else if (ShouldPrintEmptyBrackets(value_printed, summary_printed)) {748    // Aggregate, no children...749    if (ShouldPrintValueObject()) {750      // if it has a synthetic value, then don't print {}, the synthetic751      // children are probably only being used to vend a value752      if (GetMostSpecializedValue().DoesProvideSyntheticValue() ||753          !ShouldExpandEmptyAggregates())754        m_stream->PutCString("\n");755      else756        m_stream->PutCString(" {}\n");757    }758  } else {759    if (ShouldPrintValueObject())760      m_stream->EOL();761  }762}763 764bool ValueObjectPrinter::PrintChildrenOneLiner(bool hide_names) {765  ValueObject &synth_valobj = GetValueObjectForChildrenGeneration();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(799            *m_stream, ValueObject::eValueObjectRepresentationStyleSummary,800            m_options.m_format,801            ValueObject::PrintableRepresentationSpecialCases::eDisable);802      }803    }804 805    if (print_dotdotdot)806      m_stream->PutCString(", ...)");807    else808      m_stream->PutChar(')');809  }810  return true;811}812 813llvm::Error ValueObjectPrinter::PrintChildrenIfNeeded(bool value_printed,814                                                      bool summary_printed) {815 816  ValueObject &valobj = GetMostSpecializedValue();817 818  DumpValueObjectOptions::PointerDepth curr_ptr_depth = m_ptr_depth;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          ? false825          : DataVisualization::ShouldPrintAsOneLiner(valobj);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(' ');841      PrintChildrenOneLiner(false);842      m_stream->EOL();843    } else844      PrintChildren(value_printed, summary_printed, curr_ptr_depth);845  } else if (HasReachedMaximumDepth() && IsAggregate() &&846             ShouldPrintValueObject()) {847    m_stream->PutCString(" {...}\n");848    // The maximum child depth has been reached. If `m_max_depth` is the default849    // (i.e. the user has _not_ customized it), then lldb presents a warning to850    // the user. The warning tells the user that the limit has been reached, but851    // 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  } else858    m_stream->EOL();859  return llvm::Error::success();860}861 862bool ValueObjectPrinter::HasReachedMaximumDepth() {863  return m_curr_depth >= m_options.m_max_depth;864}865 866bool ValueObjectPrinter::ShouldShowName() const {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}871