diff options
| author | Enrico Granata <granata.enrico@gmail.com> | 2011-07-22 17:03:19 +0000 |
|---|---|---|
| committer | Enrico Granata <granata.enrico@gmail.com> | 2011-07-22 17:03:19 +0000 |
| commit | e992a0899e971d9fcf465b220914bdf18d2e43ed (patch) | |
| tree | 653ffe99cd978c7b07f4c1d57f48517d310fe376 | |
| parent | 4535b9194a17f419227b3e94a10294a05d373714 (diff) | |
| download | bcm5719-llvm-e992a0899e971d9fcf465b220914bdf18d2e43ed.tar.gz bcm5719-llvm-e992a0899e971d9fcf465b220914bdf18d2e43ed.zip | |
some editing of data visualization error messages to make them more meaningful
debugging printfs() for data visualization turned into a meaningful log:
- introduced a new log category `types' in channel `lldb'
llvm-svn: 135773
| -rw-r--r-- | lldb/include/lldb/Core/FormatManager.h | 47 | ||||
| -rw-r--r-- | lldb/include/lldb/lldb-private-log.h | 1 | ||||
| -rw-r--r-- | lldb/source/Core/Debugger.cpp | 145 | ||||
| -rw-r--r-- | lldb/source/Core/ValueObject.cpp | 19 | ||||
| -rw-r--r-- | lldb/source/lldb-log.cpp | 5 | ||||
| -rw-r--r-- | lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py | 5 |
6 files changed, 152 insertions, 70 deletions
diff --git a/lldb/include/lldb/Core/FormatManager.h b/lldb/include/lldb/Core/FormatManager.h index 1dd97b04d26..bad1702db40 100644 --- a/lldb/include/lldb/Core/FormatManager.h +++ b/lldb/include/lldb/Core/FormatManager.h @@ -46,6 +46,7 @@ namespace std #include "lldb/Core/FormatClasses.h" #include "lldb/Core/InputReaderStack.h" #include "lldb/Core/Listener.h" +#include "lldb/Core/Log.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/SourceManager.h" @@ -58,6 +59,8 @@ namespace std #include "lldb/Target/StackFrame.h" #include "lldb/Target/TargetList.h" +using lldb::LogSP; + namespace lldb_private { class IFormatChangeListener @@ -269,13 +272,22 @@ private: MapValueType& entry, uint32_t& reason) { + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); if (type.isNull()) + { + if (log) + log->Printf("type is NULL, returning"); return false; + } // clang::QualType type = q_type.getUnqualifiedType(); type.removeLocalConst(); type.removeLocalVolatile(); type.removeLocalRestrict(); const clang::Type* typePtr = type.getTypePtrOrNull(); if (!typePtr) + { + if (log) + log->Printf("type is NULL, returning"); return false; + } ConstString name(ClangASTType::GetTypeNameForQualType(type).c_str()); if (vobj.GetBitfieldBitSize() > 0) { @@ -283,13 +295,24 @@ private: StreamString sstring; sstring.Printf("%s:%d",name.AsCString(),vobj.GetBitfieldBitSize()); name = ConstString(sstring.GetData()); + if (log) + log->Printf("appended bitfield info, final result is %s", name.GetCString()); } - //printf("trying to get format for VO name %s of type %s\n",vobj.GetName().AsCString(),name.AsCString()); + if (log) + log->Printf("trying to get format for VO name %s of type %s",vobj.GetName().AsCString(),name.AsCString()); if (Get(name.GetCString(), entry)) + { + if (log) + log->Printf("direct match found, returning"); return true; + } + if (log) + log->Printf("no direct match"); // look for a "base type", whatever that means if (typePtr->isReferenceType()) { + if (log) + log->Printf("stripping reference"); if (Get(vobj,type.getNonReferenceType(),entry, reason) && !entry->m_skip_references) { reason |= lldb::eFormatterStrippedPointerReference; @@ -298,6 +321,8 @@ private: } if (typePtr->isPointerType()) { + if (log) + log->Printf("stripping pointer"); if (Get(vobj, typePtr->getPointeeType(), entry, reason) && !entry->m_skip_pointers) { reason |= lldb::eFormatterStrippedPointerReference; @@ -306,6 +331,8 @@ private: } if (typePtr->isObjCObjectPointerType()) { + if (log) + log->Printf("stripping ObjC pointer"); /* for some reason, C++ can quite easily obtain the type hierarchy for a ValueObject even if the VO represent a pointer-to-class, as long as the typePtr is right @@ -325,19 +352,21 @@ private: const clang::ObjCObjectType *objc_class_type = typePtr->getAs<clang::ObjCObjectType>(); if (objc_class_type) { - //printf("working with ObjC\n"); + if (log) + log->Printf("working with ObjC"); clang::ASTContext *ast = vobj.GetClangAST(); if (ClangASTContext::GetCompleteType(ast, vobj.GetClangType()) && !objc_class_type->isObjCId()) { clang::ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface(); if (class_interface_decl) { - //printf("down here\n"); + if (log) + log->Printf("got an ObjCInterfaceDecl"); clang::ObjCInterfaceDecl *superclass_interface_decl = class_interface_decl->getSuperClass(); - //printf("one further step and we're there...\n"); if (superclass_interface_decl) { - //printf("the end is here\n"); + if (log) + log->Printf("got a parent class for this ObjC class"); clang::QualType ivar_qual_type(ast->getObjCInterfaceType(superclass_interface_decl)); if (Get(vobj, ivar_qual_type, entry, reason) && entry->m_cascades) { @@ -351,6 +380,8 @@ private: // for C++ classes, navigate up the hierarchy if (typePtr->isRecordType()) { + if (log) + log->Printf("working with C++"); clang::CXXRecordDecl* record = typePtr->getAsCXXRecordDecl(); if (record) { @@ -361,6 +392,8 @@ private: clang::CXXRecordDecl::base_class_iterator pos,end; if (record->getNumBases() > 0) { + if (log) + log->Printf("look into bases"); end = record->bases_end(); for (pos = record->bases_begin(); pos != end; pos++) { @@ -373,6 +406,8 @@ private: } if (record->getNumVBases() > 0) { + if (log) + log->Printf("look into VBases"); end = record->vbases_end(); for (pos = record->vbases_begin(); pos != end; pos++) { @@ -390,6 +425,8 @@ private: const clang::TypedefType* type_tdef = type->getAs<clang::TypedefType>(); if (type_tdef) { + if (log) + log->Printf("stripping typedef"); if ((Get(vobj, type_tdef->getDecl()->getUnderlyingType(), entry, reason)) && entry->m_cascades) { reason |= lldb::eFormatterNavigatedTypedefs; diff --git a/lldb/include/lldb/lldb-private-log.h b/lldb/include/lldb/lldb-private-log.h index ef45ebf0d48..7017fc56419 100644 --- a/lldb/include/lldb/lldb-private-log.h +++ b/lldb/include/lldb/lldb-private-log.h @@ -38,6 +38,7 @@ #define LIBLLDB_LOG_API (1u << 16) #define LIBLLDB_LOG_SCRIPT (1u << 17) #define LIBLLDB_LOG_COMMANDS (1U << 18) +#define LIBLLDB_LOG_TYPES (1u << 19) #define LIBLLDB_LOG_ALL (UINT32_MAX) #define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\ LIBLLDB_LOG_THREAD |\ diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index 219fbfa8985..d7538f60d42 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -694,18 +694,12 @@ TestPromptFormats (StackFrame *frame) } } -// FIXME this should eventually be replaced by proper use of LLDB logging facilities -//#define VERBOSE_FORMATPROMPT_OUTPUT -#ifdef VERBOSE_FORMATPROMPT_OUTPUT #define IFERROR_PRINT_IT if (error.Fail()) \ { \ - printf("ERROR: %s\n",error.AsCString("unknown")); \ + if (log) \ + log->Printf("ERROR: %s\n", error.AsCString("unknown")); \ break; \ } -#else // IFERROR_PRINT_IT -#define IFERROR_PRINT_IT if (error.Fail()) \ -break; -#endif // IFERROR_PRINT_IT static bool ScanFormatDescriptor(const char* var_name_begin, @@ -715,36 +709,55 @@ ScanFormatDescriptor(const char* var_name_begin, lldb::Format* custom_format, ValueObject::ValueObjectRepresentationStyle* val_obj_display) { + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); *percent_position = ::strchr(var_name_begin,'%'); if (!*percent_position || *percent_position > var_name_end) + { + if (log) + log->Printf("no format descriptor in string, skipping"); *var_name_final = var_name_end; + } else { *var_name_final = *percent_position; char* format_name = new char[var_name_end-*var_name_final]; format_name[var_name_end-*var_name_final-1] = '\0'; memcpy(format_name, *var_name_final+1, var_name_end-*var_name_final-1); + if (log) + log->Printf("parsing %s as a format descriptor", format_name); if ( !FormatManager::GetFormatFromCString(format_name, true, *custom_format) ) { + if (log) + log->Printf("%s is an unknown format", format_name); // if this is an @ sign, print ObjC description if (*format_name == '@') *val_obj_display = ValueObject::eDisplayLanguageSpecific; // if this is a V, print the value using the default format - if (*format_name == 'V') + else if (*format_name == 'V') *val_obj_display = ValueObject::eDisplayValue; // if this is an L, print the location of the value - if (*format_name == 'L') + else if (*format_name == 'L') *val_obj_display = ValueObject::eDisplayLocation; // if this is an S, print the summary after all - if (*format_name == 'S') + else if (*format_name == 'S') *val_obj_display = ValueObject::eDisplaySummary; + else if (log) + log->Printf("%s is an error, leaving the previous value alone", format_name); } // a good custom format tells us to print the value using it else + { + if (log) + log->Printf("will display value for this VO"); *val_obj_display = ValueObject::eDisplayValue; + } delete format_name; } + if (log) + log->Printf("final format description outcome: custom_format = %d, val_obj_display = %d", + *custom_format, + *val_obj_display); return true; } @@ -759,6 +772,7 @@ ScanBracketedRange(const char* var_name_begin, int64_t* index_lower, int64_t* index_higher) { + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); *open_bracket_position = ::strchr(var_name_begin,'['); if (*open_bracket_position && *open_bracket_position < var_name_final) { @@ -769,6 +783,8 @@ ScanBracketedRange(const char* var_name_begin, *var_name_final_if_array_range = *open_bracket_position; if (*close_bracket_position - *open_bracket_position == 1) { + if (log) + log->Printf("[] detected.. going from 0 to end of data"); *index_lower = 0; } else if (*separator_position == NULL || *separator_position > var_name_end) @@ -776,24 +792,34 @@ ScanBracketedRange(const char* var_name_begin, char *end = NULL; *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); *index_higher = *index_lower; - //printf("got to read low=%d high same\n",bitfield_lower); + if (log) + log->Printf("[%d] detected, high index is same",index_lower); } else if (*close_bracket_position && *close_bracket_position < var_name_end) { char *end = NULL; *index_lower = ::strtoul (*open_bracket_position+1, &end, 0); *index_higher = ::strtoul (*separator_position+1, &end, 0); - //printf("got to read low=%d high=%d\n",bitfield_lower,bitfield_higher); + if (log) + log->Printf("[%d-%d] detected",index_lower,index_higher); } else + { + if (log) + log->Printf("expression is erroneous, cannot extract indices out of it"); return false; + } if (*index_lower > *index_higher && *index_higher > 0) { + if (log) + log->Printf("swapping indices"); int temp = *index_lower; *index_lower = *index_higher; *index_higher = temp; } } + else if (log) + log->Printf("no bracketed range, skipping entirely"); return true; } @@ -806,26 +832,30 @@ ExpandExpressionPath(ValueObject* vobj, const char* var_name_final, Error& error) { - + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); StreamString sstring; VariableSP var_sp; if (*do_deref_pointer) + { + if (log) + log->Printf("been told to deref_pointer by caller"); sstring.PutChar('*'); + } else if (vobj->IsDereferenceOfParent() && ClangASTContext::IsPointerType(vobj->GetParent()->GetClangType()) && !vobj->IsArrayItemForPointer()) { + if (log) + log->Printf("decided to deref_pointer myself"); sstring.PutChar('*'); *do_deref_pointer = true; } vobj->GetExpressionPath(sstring, true, ValueObject::eHonorPointers); -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to expand in phase 0: %s\n",sstring.GetData()); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + if (log) + log->Printf("expression path to expand in phase 0: %s",sstring.GetData()); sstring.PutRawBytes(var_name_begin+3, var_name_final-var_name_begin-3); -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to expand in phase 1: %s\n",sstring.GetData()); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + if (log) + log->Printf("expression path to expand in phase 1: %s",sstring.GetData()); std::string name = std::string(sstring.GetData()); ValueObjectSP target = frame->GetValueForVariableExpressionPath (name.c_str(), eNoDynamicValues, @@ -841,12 +871,12 @@ ExpandIndexedExpression(ValueObject* vobj, StackFrame* frame, bool deref_pointer) { + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); const char* ptr_deref_format = "[%d]"; std::auto_ptr<char> ptr_deref_buffer(new char[10]); ::sprintf(ptr_deref_buffer.get(), ptr_deref_format, index); -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("name to deref: %s\n",ptr_deref_buffer.get()); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + if (log) + log->Printf("name to deref: %s",ptr_deref_buffer.get()); const char* first_unparsed; ValueObject::GetValueForExpressionPathOptions options; ValueObject::ExpressionPathEndResultType final_value_type; @@ -860,20 +890,18 @@ ExpandIndexedExpression(ValueObject* vobj, &what_next); if (!item) { -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("ERROR: unparsed portion = %s, why stopping = %d," - " final_value_type %d\n", + if (log) + log->Printf("ERROR: unparsed portion = %s, why stopping = %d," + " final_value_type %d", first_unparsed, reason_to_stop, final_value_type); -#endif //VERBOSE_FORMATPROMPT_OUTPUT } -#ifdef VERBOSE_FORMATPROMPT_OUTPUT else { - printf("ALL RIGHT: unparsed portion = %s, why stopping = %d," - " final_value_type %d\n", + if (log) + log->Printf("ALL RIGHT: unparsed portion = %s, why stopping = %d," + " final_value_type %d", first_unparsed, reason_to_stop, final_value_type); } -#endif //VERBOSE_FORMATPROMPT_OUTPUT return item; } @@ -892,6 +920,7 @@ Debugger::FormatPrompt ValueObject* realvobj = NULL; // makes it super-easy to parse pointers bool success = true; const char *p; + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); for (p = format; *p != '\0'; ++p) { if (realvobj) @@ -967,8 +996,8 @@ Debugger::FormatPrompt const RegisterInfo *reg_info = NULL; RegisterContext *reg_ctx = NULL; bool do_deref_pointer = false; - ValueObject::ExpressionPathScanEndReason reason_to_stop; - ValueObject::ExpressionPathEndResultType final_value_type; + ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eEndOfString; + ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::ePlain; // Each variable must set success to true below... bool var_success = false; @@ -1050,9 +1079,8 @@ Debugger::FormatPrompt ::memset(expr_path.get(), 0, var_name_final-var_name_begin-1); memcpy(expr_path.get(), var_name_begin+3,var_name_final-var_name_begin-3); -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("symbol to expand: %s\n",expr_path.get()); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + if (log) + log->Printf("symbol to expand: %s",expr_path.get()); target = vobj->GetValueForExpressionPath(expr_path.get(), &first_unparsed, @@ -1063,21 +1091,19 @@ Debugger::FormatPrompt if (!target) { -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("ERROR: unparsed portion = %s, why stopping = %d," - " final_value_type %d\n", + if (log) + log->Printf("ERROR: unparsed portion = %s, why stopping = %d," + " final_value_type %d", first_unparsed, reason_to_stop, final_value_type); -#endif //VERBOSE_FORMATPROMPT_OUTPUT break; } -#ifdef VERBOSE_FORMATPROMPT_OUTPUT else { - printf("ALL RIGHT: unparsed portion = %s, why stopping = %d," - " final_value_type %d\n", + if (log) + log->Printf("ALL RIGHT: unparsed portion = %s, why stopping = %d," + " final_value_type %d", first_unparsed, reason_to_stop, final_value_type); } -#endif //VERBOSE_FORMATPROMPT_OUTPUT } else break; @@ -1103,26 +1129,31 @@ Debugger::FormatPrompt if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eDisplayValue) // this should be wrong, but there are some exceptions { -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("I am into array || pointer && !range\n"); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + if (log) + log->Printf("I am into array || pointer && !range"); // try to use the special cases var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); if (!var_success) s << "<invalid, please use [] operator>"; -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("outcome was : %s\n", var_success ? "good" : "bad"); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + if (log) + log->Printf("special cases did%s match", var_success ? "" : "n't"); break; } if (!is_array_range) + { + if (log) + log->Printf("dumping ordinary printable output"); var_success = target->DumpPrintableRepresentation(s,val_obj_display, custom_format); + } else - { + { + if (log) + log->Printf("checking if I can handle as array"); if (!is_array && !is_pointer) break; - + if (log) + log->Printf("handle as array"); const char* special_directions = NULL; StreamString special_directions_writer; if (close_bracket_position && (var_name_end-close_bracket_position > 1)) @@ -1151,16 +1182,14 @@ Debugger::FormatPrompt if (!item) { -#ifdef VERBOSE_FORMATPROMPT_OUTPUT - printf("ERROR\n"); -#endif //VERBOSE_FORMATPROMPT_OUTPUT + if (log) + log->Printf("ERROR in getting child item at index %d", index_lower); } -#ifdef VERBOSE_FORMATPROMPT_OUTPUT else { - printf("special_directions: %s\n",special_directions); + if (log) + log->Printf("special_directions for child item: %s",special_directions); } -#endif //VERBOSE_FORMATPROMPT_OUTPUT if (!special_directions) var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index acc85df556f..76deaf9d288 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -885,6 +885,9 @@ ValueObject::GetValueAsCString () return m_value_str.c_str(); } +// this call should only return pointers to data that needs no special memory management +// (either because they are hardcoded strings, or because they are backed by some other +// object); returning any new()-ed or malloc()-ed data here, will lead to leaks! const char * ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display, lldb::Format custom_format) @@ -921,10 +924,18 @@ ValueObject::GetPrintableRepresentation(ValueObjectRepresentationStyle val_obj_d if (val_obj_display == eDisplayValue) return_value = GetSummaryAsCString(); else if (val_obj_display == eDisplaySummary) - return_value = GetValueAsCString(); + { + if (ClangASTContext::IsAggregateType (GetClangType()) == true) + { + // this thing has no value + return_value = "<no summary defined for this datatype>"; + } + else + return_value = GetValueAsCString(); + } } - return (return_value ? return_value : "<error>"); + return (return_value ? return_value : "<no printable representation>"); } @@ -980,7 +991,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s, ValueObjectSP child = GetChildAtIndex(low,true); if (!child.get()) { - s << "<error>"; + s << "<invalid child>"; continue; } child->DumpPrintableRepresentation(s, ValueObject::eDisplayValue, custom_format); @@ -1018,7 +1029,7 @@ ValueObject::DumpPrintableRepresentation(Stream& s, ValueObjectSP child = GetChildAtIndex(low,true); if (!child.get()) { - s << "<error>"; + s << "<invalid child>"; continue; } child->DumpPrintableRepresentation(s, ValueObject::eDisplayValue, format); diff --git a/lldb/source/lldb-log.cpp b/lldb/source/lldb-log.cpp index 33dd76a0b4e..0ad5f109ecc 100644 --- a/lldb/source/lldb-log.cpp +++ b/lldb/source/lldb-log.cpp @@ -134,6 +134,7 @@ lldb_private::DisableLog (Args &args, Stream *feedback_strm) else if (0 == ::strncasecmp(arg, "conn", 4)) flag_bits &= ~LIBLLDB_LOG_CONNECTION; else if (0 == ::strncasecmp(arg, "host", 4)) flag_bits &= ~LIBLLDB_LOG_HOST; else if (0 == ::strncasecmp(arg, "unwind", 6)) flag_bits &= ~LIBLLDB_LOG_UNWIND; + else if (0 == ::strncasecmp(arg, "types", 5)) flag_bits &= ~LIBLLDB_LOG_TYPES; else { feedback_strm->Printf ("error: unrecognized log category '%s'\n", arg); @@ -200,6 +201,7 @@ lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, Args &ar else if (0 == ::strncasecmp(arg, "conn", 4)) flag_bits |= LIBLLDB_LOG_CONNECTION; else if (0 == ::strncasecmp(arg, "host", 4)) flag_bits |= LIBLLDB_LOG_HOST; else if (0 == ::strncasecmp(arg, "unwind", 6)) flag_bits |= LIBLLDB_LOG_UNWIND; + else if (0 == ::strncasecmp(arg, "types", 5)) flag_bits |= LIBLLDB_LOG_TYPES; else { feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); @@ -238,5 +240,6 @@ lldb_private::ListLogCategories (Stream *strm) "\tstep - log step related activities\n" "\tunwind - log stack unwind activities\n" "\tverbose - enable verbose logging\n" - "\twatch - log watchpoint related activities\n"); + "\twatch - log watchpoint related activities\n" + "\ttypes - log type system related activities\n"); } diff --git a/lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py b/lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py index dceccae4098..d570351fd0a 100644 --- a/lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py +++ b/lldb/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py @@ -57,7 +57,7 @@ class DataFormatterTestCase(TestBase): self.runCmd("type summary add -f \"${var%V}\" SomeData") self.expect("frame variable data", - substrs = ['error']) + substrs = ['no printable representation']) # ${var%s} self.runCmd("type summary add -f \"ptr = ${var%s}\" \"char *\"") @@ -198,12 +198,13 @@ class DataFormatterTestCase(TestBase): '{0x00000009},{0x00000008},{0x00000007},{0x00000006},{0x00000005}']) # printing full array as an array + self.runCmd("log enable lldb types -f dummy.log") self.runCmd("type summary add -f \"arr = ${var%uint32_t[]}\" \"int [5]\"") self.expect("frame variable intarr", substrs = ['intarr = arr =', '0x00000001,0x00000001,0x00000002,0x00000003,0x00000005']) - + self.runCmd("log disable lldb types") self.expect("frame variable other.intarr", substrs = ['intarr = arr =', '0x00000009,0x00000008,0x00000007,0x00000006,0x00000005']) |

