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