blob: 417b5822aabaf05e35564ef7c64952e212b3d20d [file] [log] [blame]
Enrico Granata4d93b8c2013-09-30 19:11:51 +00001//===-- ValueObjectPrinter.cpp -------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/DataFormatters/ValueObjectPrinter.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Debugger.h"
17#include "lldb/Interpreter/CommandInterpreter.h"
18#include "lldb/Target/Target.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
24 Stream* s,
25 const DumpValueObjectOptions& options) :
26 m_orig_valobj(valobj),
27 m_valobj(nullptr),
28 m_stream(s),
29 options(options),
30 m_ptr_depth(options.m_max_ptr_depth),
31 m_curr_depth(0),
32 m_should_print(eLazyBoolCalculate),
33 m_is_nil(eLazyBoolCalculate),
34 m_is_ptr(eLazyBoolCalculate),
35 m_is_ref(eLazyBoolCalculate),
36 m_is_aggregate(eLazyBoolCalculate),
37 m_summary_formatter({nullptr,false}),
38 m_value(),
39 m_summary(),
40 m_error()
41{
42 assert (m_orig_valobj && "cannot print a NULL ValueObject");
43 assert (m_stream && "cannot print to a NULL Stream");
44}
45
46ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
47 Stream* s,
48 const DumpValueObjectOptions& options,
49 uint32_t ptr_depth,
50 uint32_t curr_depth) :
51 ValueObjectPrinter(valobj,s,options)
52{
53 m_ptr_depth = ptr_depth;
54 m_curr_depth = curr_depth;
55}
56
57bool
58ValueObjectPrinter::PrintValueObject ()
59{
60 if (!GetDynamicValueIfNeeded () || m_valobj == nullptr)
61 return false;
62
63 if (ShouldPrintValueObject())
64 {
65 PrintLocationIfNeeded();
66 m_stream->Indent();
67
68 bool show_type = PrintTypeIfNeeded();
69
70 PrintNameIfNeeded(show_type);
71 }
72
73 bool value_printed = false;
74 bool summary_printed = false;
75
76 bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
77
78 if (val_summary_ok)
79 PrintChildrenIfNeeded (value_printed, summary_printed);
80
81 m_stream->EOL();
82
83 return true;
84}
85
86bool
87ValueObjectPrinter::GetDynamicValueIfNeeded ()
88{
89 bool update_success = m_orig_valobj->UpdateValueIfNeeded (true);
90 if (!update_success)
91 return false;
92 if (options.m_use_dynamic != eNoDynamicValues)
93 {
94 ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get();
95 if (dynamic_value)
96 m_valobj = dynamic_value;
97 else
98 m_valobj = m_orig_valobj;
99 }
100 else
101 m_valobj = m_orig_valobj;
102 m_clang_type = m_valobj->GetClangType();
103 m_type_flags = m_clang_type.GetTypeInfo ();
104 return true;
105}
106
107const char*
108ValueObjectPrinter::GetDescriptionForDisplay ()
109{
110 const char* str = m_valobj->GetObjectDescription();
111 if (!str)
112 str = m_valobj->GetSummaryAsCString();
113 if (!str)
114 str = m_valobj->GetValueAsCString();
115 return str;
116}
117
118const char*
119ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail)
120{
121 const char *root_valobj_name = options.m_root_valobj_name.empty() ?
122 m_valobj->GetName().AsCString() :
123 options.m_root_valobj_name.c_str();
124 return root_valobj_name ? root_valobj_name : if_fail;
125}
126
127bool
128ValueObjectPrinter::ShouldPrintValueObject ()
129{
130 if (m_should_print == eLazyBoolCalculate)
131 m_should_print = (options.m_flat_output == false || m_type_flags.Test (ClangASTType::eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
132 return m_should_print == eLazyBoolYes;
133}
134
135bool
136ValueObjectPrinter::IsNil ()
137{
138 if (m_is_nil == eLazyBoolCalculate)
139 m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo;
140 return m_is_nil == eLazyBoolYes;
141}
142
143bool
144ValueObjectPrinter::IsPtr ()
145{
146 if (m_is_ptr == eLazyBoolCalculate)
147 m_is_ptr = m_type_flags.Test (ClangASTType::eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
148 return m_is_ptr == eLazyBoolYes;
149}
150
151bool
152ValueObjectPrinter::IsRef ()
153{
154 if (m_is_ref == eLazyBoolCalculate)
155 m_is_ref = m_type_flags.Test (ClangASTType::eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
156 return m_is_ref == eLazyBoolYes;
157}
158
159bool
160ValueObjectPrinter::IsAggregate ()
161{
162 if (m_is_aggregate == eLazyBoolCalculate)
163 m_is_aggregate = m_type_flags.Test (ClangASTType::eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
164 return m_is_aggregate == eLazyBoolYes;
165}
166
167bool
168ValueObjectPrinter::PrintLocationIfNeeded ()
169{
170 if (options.m_show_location)
171 {
172 m_stream->Printf("%s: ", m_valobj->GetLocationAsCString());
173 return true;
174 }
175 return false;
176}
177
178bool
179ValueObjectPrinter::PrintTypeIfNeeded ()
180{
181 bool show_type = true;
182 // if we are at the root-level and been asked to hide the root's type, then hide it
183 if (m_curr_depth == 0 && options.m_hide_root_type)
184 show_type = false;
185 else
186 // otherwise decide according to the usual rules (asked to show types - always at the root level)
187 show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output);
188
189 if (show_type)
190 {
191 // Some ValueObjects don't have types (like registers sets). Only print
192 // the type if there is one to print
193 ConstString qualified_type_name(m_valobj->GetQualifiedTypeName());
194 if (qualified_type_name)
195 m_stream->Printf("(%s) ", qualified_type_name.GetCString());
196 else
197 show_type = false;
198 }
199 return show_type;
200}
201
202bool
203ValueObjectPrinter::PrintNameIfNeeded (bool show_type)
204{
205 if (options.m_flat_output)
206 {
207 // If we are showing types, also qualify the C++ base classes
208 const bool qualify_cxx_base_classes = show_type;
209 if (!options.m_hide_name)
210 {
211 m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes);
212 m_stream->PutCString(" =");
213 return true;
214 }
215 }
216 else if (!options.m_hide_name)
217 {
218 const char *name_cstr = GetRootNameForDisplay("");
219 m_stream->Printf ("%s =", name_cstr);
220 return true;
221 }
222 return false;
223}
224
225bool
226ValueObjectPrinter::CheckScopeIfNeeded ()
227{
228 if (options.m_scope_already_checked)
229 return true;
230 return m_valobj->IsInScope();
231}
232
233TypeSummaryImpl*
234ValueObjectPrinter::GetSummaryFormatter ()
235{
236 if (m_summary_formatter.second == false)
237 {
238 TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get();
239
240 if (options.m_omit_summary_depth > 0)
241 entry = NULL;
242 m_summary_formatter.first = entry;
243 m_summary_formatter.second = true;
244 }
245 return m_summary_formatter.first;
246}
247
248void
249ValueObjectPrinter::GetValueSummaryError (std::string& value,
250 std::string& summary,
251 std::string& error)
252{
253 if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat())
254 {
255 m_valobj->GetValueAsCString(options.m_format,
256 value);
257 }
258 else
259 {
260 const char* val_cstr = m_valobj->GetValueAsCString();
261 if (val_cstr)
262 value.assign(val_cstr);
263 }
264 const char* err_cstr = m_valobj->GetError().AsCString();
265 if (err_cstr)
266 error.assign(err_cstr);
267
268 if (ShouldPrintValueObject())
269 {
270 if (IsNil())
271 summary.assign("nil");
272 else if (options.m_omit_summary_depth == 0)
273 {
274 TypeSummaryImpl* entry = GetSummaryFormatter();
275 if (entry)
276 m_valobj->GetSummaryAsCString(entry, summary);
277 else
278 {
279 const char* sum_cstr = m_valobj->GetSummaryAsCString();
280 if (sum_cstr)
281 summary.assign(sum_cstr);
282 }
283 }
284 }
285}
286
287bool
288ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
289 bool& summary_printed)
290{
291 bool error_printed = false;
292 if (ShouldPrintValueObject())
293 {
294 if (!CheckScopeIfNeeded())
295 m_error.assign("out of scope");
296 if (m_error.empty())
297 {
298 GetValueSummaryError(m_value, m_summary, m_error);
299 }
300 if (m_error.size())
301 {
302 error_printed = true;
303 m_stream->Printf (" <%s>\n", m_error.c_str());
304 }
305 else
306 {
307 // Make sure we have a value and make sure the summary didn't
308 // specify that the value should not be printed - and do not print
309 // the value if this thing is nil
310 // (but show the value if the user passes a format explicitly)
311 TypeSummaryImpl* entry = GetSummaryFormatter();
312 if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue() || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value)
313 {
314 m_stream->Printf(" %s", m_value.c_str());
315 value_printed = true;
316 }
317
318 if (m_summary.size())
319 {
320 m_stream->Printf(" %s", m_summary.c_str());
321 summary_printed = true;
322 }
323 }
324 }
325 return !error_printed;
326}
327
328bool
329ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
330 bool summary_printed)
331{
332 if (ShouldPrintValueObject())
333 {
334 // let's avoid the overly verbose no description error for a nil thing
335 if (options.m_use_objc && !IsNil())
336 {
337 if (!options.m_hide_value || !options.m_hide_name)
338 m_stream->Printf(" ");
339 const char *object_desc = nullptr;
340 if (value_printed || summary_printed)
341 object_desc = m_valobj->GetObjectDescription();
342 else
343 object_desc = GetDescriptionForDisplay();
344 if (object_desc && *object_desc)
345 {
346 m_stream->Printf("%s\n", object_desc);
347 return true;
348 }
349 else if (value_printed == false && summary_printed == false)
350 return true;
351 else
352 return false;
353 }
354 }
355 return true;
356}
357
358bool
359ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
360 uint32_t& curr_ptr_depth)
361{
362 const bool is_ref = IsRef ();
363 const bool is_ptr = IsPtr ();
364
365 if (is_failed_description || m_curr_depth < options.m_max_depth)
366 {
367 // We will show children for all concrete types. We won't show
368 // pointer contents unless a pointer depth has been specified.
369 // We won't reference contents unless the reference is the
370 // root object (depth of zero).
371
372 // Use a new temporary pointer depth in case we override the
373 // current pointer depth below...
374 uint32_t curr_ptr_depth = m_ptr_depth;
375
376 if (is_ptr || is_ref)
377 {
378 // We have a pointer or reference whose value is an address.
379 // Make sure that address is not NULL
380 AddressType ptr_address_type;
381 if (m_valobj->GetPointerValue (&ptr_address_type) == 0)
382 return false;
383
384 else if (is_ref && m_curr_depth == 0)
385 {
386 // If this is the root object (depth is zero) that we are showing
387 // and it is a reference, and no pointer depth has been supplied
388 // print out what it references. Don't do this at deeper depths
389 // otherwise we can end up with infinite recursion...
390 curr_ptr_depth = 1;
391 }
392
393 if (curr_ptr_depth == 0)
394 return false;
395 }
396
397 TypeSummaryImpl* entry = GetSummaryFormatter();
398
399 return (!entry || entry->DoesPrintChildren() || m_summary.empty());
400 }
401 return false;
402}
403
404ValueObject*
405ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
406{
407 ValueObjectSP synth_valobj_sp = m_valobj->GetSyntheticValue (options.m_use_synthetic);
408 return (synth_valobj_sp ? synth_valobj_sp.get() : m_valobj);
409}
410
411void
412ValueObjectPrinter::PrintChildrenPreamble ()
413{
414 if (options.m_flat_output)
415 {
416 if (ShouldPrintValueObject())
417 m_stream->EOL();
418 }
419 else
420 {
421 if (ShouldPrintValueObject())
422 m_stream->PutCString(IsRef () ? ": {\n" : " {\n");
423 m_stream->IndentMore();
424 }
425}
426
427void
428ValueObjectPrinter::PrintChild (ValueObjectSP child_sp,
429 uint32_t curr_ptr_depth)
430{
431 DumpValueObjectOptions child_options(options);
432 child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName();
433 child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value)
434 .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0);
435 if (child_sp.get())
436 {
437 ValueObjectPrinter child_printer(child_sp.get(),
438 m_stream,
439 child_options,
440 (IsPtr() || IsRef()) ? curr_ptr_depth - 1 : curr_ptr_depth,
441 m_curr_depth + 1);
442 child_printer.PrintValueObject();
443 }
444
445}
446
447uint32_t
448ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot)
449{
450 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
451
452 size_t num_children = synth_m_valobj->GetNumChildren();
453 print_dotdotdot = false;
454 if (num_children)
455 {
456 const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
457
458 if (num_children > max_num_children && !options.m_ignore_cap)
459 {
460 print_dotdotdot = true;
461 return max_num_children;
462 }
463 }
464 return num_children;
465}
466
467void
468ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
469{
470 if (!options.m_flat_output)
471 {
472 if (print_dotdotdot)
473 {
474 m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated();
475 m_stream->Indent("...\n");
476 }
477 m_stream->IndentLess();
478 m_stream->Indent("}\n");
479 }
480}
481
482void
483ValueObjectPrinter::PrintChildren (uint32_t curr_ptr_depth)
484{
485 ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
486
487 bool print_dotdotdot = false;
488 size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
489 if (num_children)
490 {
491 PrintChildrenPreamble ();
492
493 for (size_t idx=0; idx<num_children; ++idx)
494 {
495 ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
496 PrintChild (child_sp, curr_ptr_depth);
497 }
498
499 PrintChildrenPostamble (print_dotdotdot);
500 }
501 else if (IsAggregate())
502 {
503 // Aggregate, no children...
504 if (ShouldPrintValueObject())
505 m_stream->PutCString(" {}\n");
506 }
507 else
508 {
509 if (ShouldPrintValueObject())
510 m_stream->EOL();
511 }
512}
513
514void
515ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
516 bool summary_printed)
517{
518 // this flag controls whether we tried to display a description for this object and failed
519 // if that happens, we want to display the children, if any
520 bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
521
522 uint32_t curr_ptr_depth = m_ptr_depth;
523 bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth);
524
525 if (print_children)
526 {
527 PrintChildren (curr_ptr_depth);
528 }
529 else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
530 {
531 m_stream->PutCString("{...}\n");
532 }
533}