1 //===-- 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/DataFormatters/DataVisualization.h"
18 #include "lldb/Interpreter/CommandInterpreter.h"
19 #include "lldb/Target/Target.h"
20 
21 using namespace lldb;
22 using namespace lldb_private;
23 
24 DumpValueObjectOptions::DumpValueObjectOptions (ValueObject& valobj) :
25 DumpValueObjectOptions()
26 {
27     m_use_dynamic = valobj.GetDynamicValueType();
28     m_use_synthetic = valobj.IsSynthetic();
29 }
30 
31 ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
32                                         Stream* s)
33 {
34     if (valobj)
35     {
36         DumpValueObjectOptions options(*valobj);
37         Init (valobj,s,options,options.m_max_ptr_depth,0);
38     }
39     else
40     {
41         DumpValueObjectOptions options;
42         Init (valobj,s,options,options.m_max_ptr_depth,0);
43     }
44 }
45 
46 ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
47                                         Stream* s,
48                                         const DumpValueObjectOptions& options)
49 {
50     Init(valobj,s,options,options.m_max_ptr_depth,0);
51 }
52 
53 ValueObjectPrinter::ValueObjectPrinter (ValueObject* valobj,
54                                         Stream* s,
55                                         const DumpValueObjectOptions& options,
56                                         const DumpValueObjectOptions::PointerDepth& ptr_depth,
57                                         uint32_t curr_depth)
58 {
59     Init(valobj,s,options,ptr_depth,curr_depth);
60 }
61 
62 void
63 ValueObjectPrinter::Init (ValueObject* valobj,
64                           Stream* s,
65                           const DumpValueObjectOptions& options,
66                           const DumpValueObjectOptions::PointerDepth& ptr_depth,
67                           uint32_t curr_depth)
68 {
69     m_orig_valobj = valobj;
70     m_valobj = nullptr;
71     m_stream = s;
72     this->options = options;
73     m_ptr_depth = ptr_depth;
74     m_curr_depth = curr_depth;
75     assert (m_orig_valobj && "cannot print a NULL ValueObject");
76     assert (m_stream && "cannot print to a NULL Stream");
77     m_should_print = eLazyBoolCalculate;
78     m_is_nil = eLazyBoolCalculate;
79     m_is_ptr = eLazyBoolCalculate;
80     m_is_ref = eLazyBoolCalculate;
81     m_is_aggregate = eLazyBoolCalculate;
82     m_summary_formatter = {nullptr,false};
83     m_value.assign("");
84     m_summary.assign("");
85     m_error.assign("");
86 }
87 
88 bool
89 ValueObjectPrinter::PrintValueObject ()
90 {
91     if (!GetMostSpecializedValue () || m_valobj == nullptr)
92         return false;
93 
94     if (ShouldPrintValueObject())
95     {
96         PrintValidationMarkerIfNeeded();
97 
98         PrintLocationIfNeeded();
99         m_stream->Indent();
100 
101         bool show_type = PrintTypeIfNeeded();
102 
103         PrintNameIfNeeded(show_type);
104     }
105 
106     bool value_printed = false;
107     bool summary_printed = false;
108 
109     bool val_summary_ok = PrintValueAndSummaryIfNeeded (value_printed,summary_printed);
110 
111     if (val_summary_ok)
112         PrintChildrenIfNeeded (value_printed, summary_printed);
113     else
114         m_stream->EOL();
115 
116     PrintValidationErrorIfNeeded();
117 
118     return true;
119 }
120 
121 bool
122 ValueObjectPrinter::GetMostSpecializedValue ()
123 {
124     if (m_valobj)
125         return true;
126     bool update_success = m_orig_valobj->UpdateValueIfNeeded (true);
127     if (!update_success)
128     {
129         m_valobj = m_orig_valobj;
130     }
131     else
132     {
133         if (m_orig_valobj->IsDynamic())
134         {
135             if (options.m_use_dynamic == eNoDynamicValues)
136             {
137                 ValueObject *static_value = m_orig_valobj->GetStaticValue().get();
138                 if (static_value)
139                     m_valobj = static_value;
140                 else
141                     m_valobj = m_orig_valobj;
142             }
143             else
144                 m_valobj = m_orig_valobj;
145         }
146         else
147         {
148             if (options.m_use_dynamic != eNoDynamicValues)
149             {
150                 ValueObject *dynamic_value = m_orig_valobj->GetDynamicValue(options.m_use_dynamic).get();
151                 if (dynamic_value)
152                     m_valobj = dynamic_value;
153                 else
154                     m_valobj = m_orig_valobj;
155             }
156             else
157                 m_valobj = m_orig_valobj;
158         }
159 
160         if (m_valobj->IsSynthetic())
161         {
162             if (options.m_use_synthetic == false)
163             {
164                 ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
165                 if (non_synthetic)
166                     m_valobj = non_synthetic;
167             }
168         }
169         else
170         {
171             if (options.m_use_synthetic == true)
172             {
173                 ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
174                 if (synthetic)
175                     m_valobj = synthetic;
176             }
177         }
178     }
179     m_compiler_type = m_valobj->GetCompilerType();
180     m_type_flags = m_compiler_type.GetTypeInfo ();
181     return true;
182 }
183 
184 const char*
185 ValueObjectPrinter::GetDescriptionForDisplay ()
186 {
187     const char* str = m_valobj->GetObjectDescription();
188     if (!str)
189         str = m_valobj->GetSummaryAsCString();
190     if (!str)
191         str = m_valobj->GetValueAsCString();
192     return str;
193 }
194 
195 const char*
196 ValueObjectPrinter::GetRootNameForDisplay (const char* if_fail)
197 {
198     const char *root_valobj_name = options.m_root_valobj_name.empty() ?
199         m_valobj->GetName().AsCString() :
200         options.m_root_valobj_name.c_str();
201     return root_valobj_name ? root_valobj_name : if_fail;
202 }
203 
204 bool
205 ValueObjectPrinter::ShouldPrintValueObject ()
206 {
207     if (m_should_print == eLazyBoolCalculate)
208         m_should_print = (options.m_flat_output == false || m_type_flags.Test (eTypeHasValue)) ? eLazyBoolYes : eLazyBoolNo;
209     return m_should_print == eLazyBoolYes;
210 }
211 
212 bool
213 ValueObjectPrinter::IsNil ()
214 {
215     if (m_is_nil == eLazyBoolCalculate)
216         m_is_nil = m_valobj->IsObjCNil() ? eLazyBoolYes : eLazyBoolNo;
217     return m_is_nil == eLazyBoolYes;
218 }
219 
220 bool
221 ValueObjectPrinter::IsPtr ()
222 {
223     if (m_is_ptr == eLazyBoolCalculate)
224         m_is_ptr = m_type_flags.Test (eTypeIsPointer) ? eLazyBoolYes : eLazyBoolNo;
225     return m_is_ptr == eLazyBoolYes;
226 }
227 
228 bool
229 ValueObjectPrinter::IsRef ()
230 {
231     if (m_is_ref == eLazyBoolCalculate)
232         m_is_ref = m_type_flags.Test (eTypeIsReference) ? eLazyBoolYes : eLazyBoolNo;
233     return m_is_ref == eLazyBoolYes;
234 }
235 
236 bool
237 ValueObjectPrinter::IsAggregate ()
238 {
239     if (m_is_aggregate == eLazyBoolCalculate)
240         m_is_aggregate = m_type_flags.Test (eTypeHasChildren) ? eLazyBoolYes : eLazyBoolNo;
241     return m_is_aggregate == eLazyBoolYes;
242 }
243 
244 bool
245 ValueObjectPrinter::PrintLocationIfNeeded ()
246 {
247     if (options.m_show_location)
248     {
249         m_stream->Printf("%s: ", m_valobj->GetLocationAsCString());
250         return true;
251     }
252     return false;
253 }
254 
255 bool
256 ValueObjectPrinter::PrintTypeIfNeeded ()
257 {
258     bool show_type = true;
259     // if we are at the root-level and been asked to hide the root's type, then hide it
260     if (m_curr_depth == 0 && options.m_hide_root_type)
261         show_type = false;
262     else
263         // otherwise decide according to the usual rules (asked to show types - always at the root level)
264         show_type = options.m_show_types || (m_curr_depth == 0 && !options.m_flat_output);
265 
266     if (show_type)
267     {
268         // Some ValueObjects don't have types (like registers sets). Only print
269         // the type if there is one to print
270         ConstString type_name;
271         if (options.m_use_type_display_name)
272             type_name = m_valobj->GetDisplayTypeName();
273         else
274             type_name = m_valobj->GetQualifiedTypeName();
275         if (type_name)
276             m_stream->Printf("(%s) ", type_name.GetCString());
277         else
278             show_type = false;
279     }
280     return show_type;
281 }
282 
283 bool
284 ValueObjectPrinter::PrintNameIfNeeded (bool show_type)
285 {
286     if (options.m_flat_output)
287     {
288         // If we are showing types, also qualify the C++ base classes
289         const bool qualify_cxx_base_classes = show_type;
290         if (!options.m_hide_name)
291         {
292             m_valobj->GetExpressionPath(*m_stream, qualify_cxx_base_classes);
293             m_stream->PutCString(" =");
294             return true;
295         }
296     }
297     else if (!options.m_hide_name)
298     {
299         const char *name_cstr = GetRootNameForDisplay("");
300         m_stream->Printf ("%s =", name_cstr);
301         return true;
302     }
303     return false;
304 }
305 
306 bool
307 ValueObjectPrinter::CheckScopeIfNeeded ()
308 {
309     if (options.m_scope_already_checked)
310         return true;
311     return m_valobj->IsInScope();
312 }
313 
314 TypeSummaryImpl*
315 ValueObjectPrinter::GetSummaryFormatter ()
316 {
317     if (m_summary_formatter.second == false)
318     {
319         TypeSummaryImpl* entry = options.m_summary_sp ? options.m_summary_sp.get() : m_valobj->GetSummaryFormat().get();
320 
321         if (options.m_omit_summary_depth > 0)
322             entry = NULL;
323         m_summary_formatter.first = entry;
324         m_summary_formatter.second = true;
325     }
326     return m_summary_formatter.first;
327 }
328 
329 void
330 ValueObjectPrinter::GetValueSummaryError (std::string& value,
331                                           std::string& summary,
332                                           std::string& error)
333 {
334     if (options.m_format != eFormatDefault && options.m_format != m_valobj->GetFormat())
335     {
336         m_valobj->GetValueAsCString(options.m_format,
337                                     value);
338     }
339     else
340     {
341         const char* val_cstr = m_valobj->GetValueAsCString();
342         if (val_cstr)
343             value.assign(val_cstr);
344     }
345     const char* err_cstr = m_valobj->GetError().AsCString();
346     if (err_cstr)
347         error.assign(err_cstr);
348 
349     if (ShouldPrintValueObject())
350     {
351         if (IsNil())
352             summary.assign("nil");
353         else if (options.m_omit_summary_depth == 0)
354         {
355             TypeSummaryImpl* entry = GetSummaryFormatter();
356             if (entry)
357                 m_valobj->GetSummaryAsCString(entry, summary);
358             else
359             {
360                 const char* sum_cstr = m_valobj->GetSummaryAsCString();
361                 if (sum_cstr)
362                     summary.assign(sum_cstr);
363             }
364         }
365     }
366 }
367 
368 bool
369 ValueObjectPrinter::PrintValueAndSummaryIfNeeded (bool& value_printed,
370                                                   bool& summary_printed)
371 {
372     bool error_printed = false;
373     if (ShouldPrintValueObject())
374     {
375         if (!CheckScopeIfNeeded())
376             m_error.assign("out of scope");
377         if (m_error.empty())
378         {
379             GetValueSummaryError(m_value, m_summary, m_error);
380         }
381         if (m_error.size())
382         {
383             error_printed = true;
384             m_stream->Printf (" <%s>\n", m_error.c_str());
385         }
386         else
387         {
388             // Make sure we have a value and make sure the summary didn't
389             // specify that the value should not be printed - and do not print
390             // the value if this thing is nil
391             // (but show the value if the user passes a format explicitly)
392             TypeSummaryImpl* entry = GetSummaryFormatter();
393             if (!IsNil() && !m_value.empty() && (entry == NULL || (entry->DoesPrintValue(m_valobj) || options.m_format != eFormatDefault) || m_summary.empty()) && !options.m_hide_value)
394             {
395                 m_stream->Printf(" %s", m_value.c_str());
396                 value_printed = true;
397             }
398 
399             if (m_summary.size())
400             {
401                 m_stream->Printf(" %s", m_summary.c_str());
402                 summary_printed = true;
403             }
404         }
405     }
406     return !error_printed;
407 }
408 
409 bool
410 ValueObjectPrinter::PrintObjectDescriptionIfNeeded (bool value_printed,
411                                                     bool summary_printed)
412 {
413     if (ShouldPrintValueObject())
414     {
415         // let's avoid the overly verbose no description error for a nil thing
416         if (options.m_use_objc && !IsNil())
417         {
418             if (!options.m_hide_value || !options.m_hide_name)
419                 m_stream->Printf(" ");
420             const char *object_desc = nullptr;
421             if (value_printed || summary_printed)
422                 object_desc = m_valobj->GetObjectDescription();
423             else
424                 object_desc = GetDescriptionForDisplay();
425             if (object_desc && *object_desc)
426             {
427                 m_stream->Printf("%s\n", object_desc);
428                 return true;
429             }
430             else if (value_printed == false && summary_printed == false)
431                 return true;
432             else
433                 return false;
434         }
435     }
436     return true;
437 }
438 
439 bool
440 DumpValueObjectOptions::PointerDepth::CanAllowExpansion (bool is_root,
441                                                          TypeSummaryImpl* entry,
442                                                          ValueObject *valobj,
443                                                          const std::string& summary)
444 {
445     switch (m_mode)
446     {
447         case Mode::Always:
448             return (m_count > 0);
449         case Mode::Never:
450             return false;
451         case Mode::Default:
452             if (is_root)
453                 m_count = std::min<decltype(m_count)>(m_count,1);
454             return m_count > 0;
455         case Mode::Formatters:
456             if (!entry || entry->DoesPrintChildren(valobj) || summary.empty())
457                 return m_count > 0;
458             return false;
459     }
460     return false;
461 }
462 
463 bool
464 DumpValueObjectOptions::PointerDepth::CanAllowExpansion () const
465 {
466     switch (m_mode)
467     {
468         case Mode::Always:
469         case Mode::Default:
470         case Mode::Formatters:
471             return (m_count > 0);
472         case Mode::Never:
473             return false;
474     }
475     return false;
476 }
477 
478 bool
479 ValueObjectPrinter::ShouldPrintChildren (bool is_failed_description,
480                                          DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
481 {
482     const bool is_ref = IsRef ();
483     const bool is_ptr = IsPtr ();
484 
485     TypeSummaryImpl* entry = GetSummaryFormatter();
486 
487     if (is_failed_description || m_curr_depth < options.m_max_depth)
488     {
489         // We will show children for all concrete types. We won't show
490         // pointer contents unless a pointer depth has been specified.
491         // We won't reference contents unless the reference is the
492         // root object (depth of zero).
493 
494         // Use a new temporary pointer depth in case we override the
495         // current pointer depth below...
496 
497         if (is_ptr || is_ref)
498         {
499             // We have a pointer or reference whose value is an address.
500             // Make sure that address is not NULL
501             AddressType ptr_address_type;
502             if (m_valobj->GetPointerValue (&ptr_address_type) == 0)
503                 return false;
504 
505             const bool is_root_level = m_curr_depth == 0;
506 
507             if (is_ref &&
508                 is_root_level)
509             {
510                 // If this is the root object (depth is zero) that we are showing
511                 // and it is a reference, and no pointer depth has been supplied
512                 // print out what it references. Don't do this at deeper depths
513                 // otherwise we can end up with infinite recursion...
514                 return true;
515             }
516 
517             return curr_ptr_depth.CanAllowExpansion(false, entry, m_valobj, m_summary);
518         }
519 
520         return (!entry || entry->DoesPrintChildren(m_valobj) || m_summary.empty());
521     }
522     return false;
523 }
524 
525 bool
526 ValueObjectPrinter::ShouldExpandEmptyAggregates ()
527 {
528     TypeSummaryImpl* entry = GetSummaryFormatter();
529 
530     if (!entry)
531         return true;
532 
533     return entry->DoesPrintEmptyAggregates();
534 }
535 
536 ValueObject*
537 ValueObjectPrinter::GetValueObjectForChildrenGeneration ()
538 {
539     return m_valobj;
540 }
541 
542 void
543 ValueObjectPrinter::PrintChildrenPreamble ()
544 {
545     if (options.m_flat_output)
546     {
547         if (ShouldPrintValueObject())
548             m_stream->EOL();
549     }
550     else
551     {
552         if (ShouldPrintValueObject())
553             m_stream->PutCString(IsRef () ? ": {\n" : " {\n");
554         m_stream->IndentMore();
555     }
556 }
557 
558 void
559 ValueObjectPrinter::PrintChild (ValueObjectSP child_sp,
560                                 const DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
561 {
562     DumpValueObjectOptions child_options(options);
563     child_options.SetFormat(options.m_format).SetSummary().SetRootValueObjectName();
564     child_options.SetScopeChecked(true).SetHideName(options.m_hide_name).SetHideValue(options.m_hide_value)
565     .SetOmitSummaryDepth(child_options.m_omit_summary_depth > 1 ? child_options.m_omit_summary_depth - 1 : 0);
566     if (child_sp.get())
567     {
568         ValueObjectPrinter child_printer(child_sp.get(),
569                                          m_stream,
570                                          child_options,
571                                          (IsPtr() || IsRef()) ? --curr_ptr_depth : curr_ptr_depth,
572                                          m_curr_depth + 1);
573         child_printer.PrintValueObject();
574     }
575 }
576 
577 uint32_t
578 ValueObjectPrinter::GetMaxNumChildrenToPrint (bool& print_dotdotdot)
579 {
580     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
581 
582     size_t num_children = synth_m_valobj->GetNumChildren();
583     print_dotdotdot = false;
584     if (num_children)
585     {
586         const size_t max_num_children = m_valobj->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
587 
588         if (num_children > max_num_children && !options.m_ignore_cap)
589         {
590             print_dotdotdot = true;
591             return max_num_children;
592         }
593     }
594     return num_children;
595 }
596 
597 void
598 ValueObjectPrinter::PrintChildrenPostamble (bool print_dotdotdot)
599 {
600     if (!options.m_flat_output)
601     {
602         if (print_dotdotdot)
603         {
604             m_valobj->GetTargetSP()->GetDebugger().GetCommandInterpreter().ChildrenTruncated();
605             m_stream->Indent("...\n");
606         }
607         m_stream->IndentLess();
608         m_stream->Indent("}\n");
609     }
610 }
611 
612 void
613 ValueObjectPrinter::PrintChildren (bool value_printed,
614                                    bool summary_printed,
615                                    const DumpValueObjectOptions::PointerDepth& curr_ptr_depth)
616 {
617     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
618 
619     bool print_dotdotdot = false;
620     size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
621     if (num_children)
622     {
623         PrintChildrenPreamble ();
624 
625         for (size_t idx=0; idx<num_children; ++idx)
626         {
627             ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
628             PrintChild (child_sp, curr_ptr_depth);
629         }
630 
631         PrintChildrenPostamble (print_dotdotdot);
632     }
633     else if (IsAggregate())
634     {
635         // Aggregate, no children...
636         if (ShouldPrintValueObject())
637         {
638             // if it has a synthetic value, then don't print {}, the synthetic children are probably only being used to vend a value
639             if (m_valobj->DoesProvideSyntheticValue() || !ShouldExpandEmptyAggregates())
640                 m_stream->PutCString( "\n");
641             else
642                 m_stream->PutCString(" {}\n");
643         }
644     }
645     else
646     {
647         if (ShouldPrintValueObject())
648             m_stream->EOL();
649     }
650 }
651 
652 bool
653 ValueObjectPrinter::PrintChildrenOneLiner (bool hide_names)
654 {
655     if (!GetMostSpecializedValue () || m_valobj == nullptr)
656         return false;
657 
658     ValueObject* synth_m_valobj = GetValueObjectForChildrenGeneration();
659 
660     bool print_dotdotdot = false;
661     size_t num_children = GetMaxNumChildrenToPrint(print_dotdotdot);
662 
663     if (num_children)
664     {
665         m_stream->PutChar('(');
666 
667         for (uint32_t idx=0; idx<num_children; ++idx)
668         {
669             lldb::ValueObjectSP child_sp(synth_m_valobj->GetChildAtIndex(idx, true));
670             if (child_sp)
671                 child_sp = child_sp->GetQualifiedRepresentationIfAvailable(options.m_use_dynamic, options.m_use_synthetic);
672             if (child_sp)
673             {
674                 if (idx)
675                     m_stream->PutCString(", ");
676                 if (!hide_names)
677                 {
678                     const char* name = child_sp.get()->GetName().AsCString();
679                     if (name && *name)
680                     {
681                         m_stream->PutCString(name);
682                         m_stream->PutCString(" = ");
683                     }
684                 }
685                 child_sp->DumpPrintableRepresentation(*m_stream,
686                                                       ValueObject::eValueObjectRepresentationStyleSummary,
687                                                       lldb::eFormatInvalid,
688                                                       ValueObject::ePrintableRepresentationSpecialCasesDisable);
689             }
690         }
691 
692         if (print_dotdotdot)
693             m_stream->PutCString(", ...)");
694         else
695             m_stream->PutChar(')');
696     }
697     return true;
698 }
699 
700 void
701 ValueObjectPrinter::PrintChildrenIfNeeded (bool value_printed,
702                                            bool summary_printed)
703 {
704     // this flag controls whether we tried to display a description for this object and failed
705     // if that happens, we want to display the children, if any
706     bool is_failed_description = !PrintObjectDescriptionIfNeeded(value_printed, summary_printed);
707 
708     auto curr_ptr_depth = m_ptr_depth;
709     bool print_children = ShouldPrintChildren (is_failed_description,curr_ptr_depth);
710     bool print_oneline = (curr_ptr_depth.CanAllowExpansion() ||
711                           options.m_show_types ||
712                           !options.m_allow_oneliner_mode ||
713                           options.m_flat_output ||
714                           options.m_show_location) ? false : DataVisualization::ShouldPrintAsOneLiner(*m_valobj);
715 
716     if (print_children)
717     {
718         if (print_oneline)
719         {
720             m_stream->PutChar(' ');
721             PrintChildrenOneLiner (false);
722             m_stream->EOL();
723         }
724         else
725             PrintChildren (value_printed, summary_printed, curr_ptr_depth);
726     }
727     else if (m_curr_depth >= options.m_max_depth && IsAggregate() && ShouldPrintValueObject())
728     {
729             m_stream->PutCString("{...}\n");
730     }
731     else
732         m_stream->EOL();
733 }
734 
735 bool
736 ValueObjectPrinter::ShouldPrintValidation ()
737 {
738     return options.m_run_validator;
739 }
740 
741 bool
742 ValueObjectPrinter::PrintValidationMarkerIfNeeded ()
743 {
744     if (!ShouldPrintValidation())
745         return false;
746 
747     m_validation = m_valobj->GetValidationStatus();
748 
749     if (TypeValidatorResult::Failure == m_validation.first)
750     {
751         m_stream->Printf("! ");
752         return true;
753     }
754 
755     return false;
756 }
757 
758 bool
759 ValueObjectPrinter::PrintValidationErrorIfNeeded ()
760 {
761     if (!ShouldPrintValidation())
762         return false;
763 
764     if (TypeValidatorResult::Success == m_validation.first)
765         return false;
766 
767     if (m_validation.second.empty())
768         m_validation.second.assign("unknown error");
769 
770     m_stream->Printf(" ! validation error: %s", m_validation.second.c_str());
771     m_stream->EOL();
772 
773     return true;
774 }
775