diff options
Diffstat (limited to 'lldb/source/Core/ValueObject.cpp')
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 615 |
1 files changed, 587 insertions, 28 deletions
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp index 5c548dfbb97..d39b836f021 100644 --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -77,7 +77,8 @@ ValueObject::ValueObject (ValueObject &parent) : m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), m_last_summary_format(), - m_last_value_format() + m_last_value_format(), + m_forced_summary_format() { m_manager->ManageObject(this); } @@ -114,7 +115,8 @@ ValueObject::ValueObject (ExecutionContextScope *exe_scope) : m_is_bitfield_for_scalar(false), m_last_format_mgr_revision(0), m_last_summary_format(), - m_last_value_format() + m_last_value_format(), + m_forced_summary_format() { m_manager = new ValueObjectManager(); m_manager->ManageObject (this); @@ -189,6 +191,11 @@ ValueObject::UpdateFormatsIfNeeded() /*printf("CHECKING FOR UPDATES. I am at revision %d, while the format manager is at revision %d\n", m_last_format_mgr_revision, Debugger::ValueFormats::GetCurrentRevision());*/ + if (HasCustomSummaryFormat() && m_update_point.GetUpdateID() != m_user_id_of_forced_summary) + { + ClearCustomSummaryFormat(); + m_summary_str.clear(); + } if (m_last_format_mgr_revision != Debugger::ValueFormats::GetCurrentRevision()) { if (m_last_summary_format.get()) @@ -495,7 +502,9 @@ ValueObject::GetSummaryAsCString () { if (m_summary_str.empty()) { - if (m_last_summary_format.get()) + SummaryFormat* summary_format = GetSummaryFormat().get(); + + if (summary_format) { StreamString s; ExecutionContext exe_ctx; @@ -504,7 +513,7 @@ ValueObject::GetSummaryAsCString () if (exe_ctx.frame) sc = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything); - if (m_last_summary_format->m_show_members_oneliner) + if (summary_format->m_show_members_oneliner) { const uint32_t num_children = GetNumChildren(); if (num_children) @@ -536,7 +545,7 @@ ValueObject::GetSummaryAsCString () } else { - if (Debugger::FormatPrompt(m_last_summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this)) + if (Debugger::FormatPrompt(summary_format->m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, this)) { m_summary_str.swap(s.GetString()); return m_summary_str.c_str(); @@ -719,6 +728,157 @@ ValueObject::GetSummaryAsCString () return m_summary_str.c_str(); } +bool +ValueObject::IsCStringContainer(bool check_pointer) +{ + clang_type_t elem_or_pointee_clang_type; + const Flags type_flags (ClangASTContext::GetTypeInfo (GetClangType(), + GetClangAST(), + &elem_or_pointee_clang_type)); + bool is_char_arr_ptr (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && + ClangASTContext::IsCharType (elem_or_pointee_clang_type)); + if (!is_char_arr_ptr) + return false; + if (!check_pointer) + return true; + if (type_flags.Test(ClangASTContext::eTypeIsArray)) + return true; + lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; + AddressType cstr_address_type = eAddressTypeInvalid; + cstr_address = GetAddressOf (cstr_address_type, true); + return (cstr_address != LLDB_INVALID_ADDRESS); +} + +void +ValueObject::ReadPointedString(Stream& s, + Error& error, + uint32_t max_length) +{ + + if (max_length == 0) + max_length = 128; // this should be a setting, or a formatting parameter + + clang_type_t clang_type = GetClangType(); + clang_type_t elem_or_pointee_clang_type; + const Flags type_flags (ClangASTContext::GetTypeInfo (clang_type, + GetClangAST(), + &elem_or_pointee_clang_type)); + if (type_flags.AnySet (ClangASTContext::eTypeIsArray | ClangASTContext::eTypeIsPointer) && + ClangASTContext::IsCharType (elem_or_pointee_clang_type)) + { + ExecutionContextScope *exe_scope = GetExecutionContextScope(); + if (exe_scope) + { + Target *target = exe_scope->CalculateTarget(); + if (target != NULL) + { + lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; + AddressType cstr_address_type = eAddressTypeInvalid; + + size_t cstr_len = 0; + bool capped_data = false; + if (type_flags.Test (ClangASTContext::eTypeIsArray)) + { + // We have an array + cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > max_length) // TODO: make cap a setting + { + cstr_len = ClangASTContext::GetArraySize (clang_type); + if (cstr_len > max_length) // TODO: make cap a setting + { + capped_data = true; + cstr_len = max_length; + } + } + cstr_address = GetAddressOf (cstr_address_type, true); + } + else + { + // We have a pointer + cstr_address = GetPointerValue (cstr_address_type, true); + } + if (cstr_address != LLDB_INVALID_ADDRESS) + { + Address cstr_so_addr (NULL, cstr_address); + DataExtractor data; + size_t bytes_read = 0; + std::vector<char> data_buffer; + Error error; + bool prefer_file_cache = false; + if (cstr_len > 0) + { + data_buffer.resize(cstr_len); + data.SetData (&data_buffer.front(), data_buffer.size(), lldb::endian::InlHostByteOrder()); + bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + cstr_len, + error); + if (bytes_read > 0) + { + s << '"'; + data.Dump (&s, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + bytes_read, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + if (capped_data) + s << "..."; + s << '"'; + } + } + else + { + const size_t k_max_buf_size = 256; + data_buffer.resize (k_max_buf_size + 1); + // NULL terminate in case we don't get the entire C string + data_buffer.back() = '\0'; + + s << '"'; + + data.SetData (&data_buffer.front(), data_buffer.size(), endian::InlHostByteOrder()); + while ((bytes_read = target->ReadMemory (cstr_so_addr, + prefer_file_cache, + &data_buffer.front(), + k_max_buf_size, + error)) > 0) + { + size_t len = strlen(&data_buffer.front()); + if (len == 0) + break; + if (len > bytes_read) + len = bytes_read; + + data.Dump (&s, + 0, // Start offset in "data" + eFormatCharArray, // Print as characters + 1, // Size of item (1 byte for a char!) + len, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS,// base address + 0, // bitfield bit size + 0); // bitfield bit offset + + if (len < k_max_buf_size) + break; + cstr_so_addr.Slide (k_max_buf_size); + } + s << '"'; + } + } + } + } + } + else + { + error.SetErrorString("impossible to read a string from this object"); + } +} + const char * ValueObject::GetObjectDescription () { @@ -894,13 +1054,25 @@ ValueObject::DumpPrintableRepresentation(Stream& s, ValueObjectRepresentationStyle val_obj_display, lldb::Format custom_format) { - const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format); - if(targetvalue) - s.PutCString(targetvalue); - bool var_success = (targetvalue != NULL); - if(custom_format != eFormatInvalid) - SetFormat(eFormatDefault); - return var_success; + + if (IsCStringContainer(true) && + val_obj_display == ValueObject::eDisplayValue && + custom_format == lldb::eFormatCString) + { + Error error; + ReadPointedString(s, error); + return error.Success(); + } + else + { + const char *targetvalue = GetPrintableRepresentation(val_obj_display, custom_format); + if(targetvalue) + s.PutCString(targetvalue); + bool var_success = (targetvalue != NULL); + if(custom_format != eFormatInvalid) + SetFormat(eFormatDefault); + return var_success; + } } addr_t @@ -1503,6 +1675,92 @@ ValueObject::GetValueForExpressionPath(const char* expression, return ret_val; // final_task_on_target will still have its original value, so you know I did not do it } +int +ValueObject::GetValuesForExpressionPath(const char* expression, + lldb::ValueObjectListSP& list, + const char** first_unparsed, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_value_type, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* final_task_on_target) +{ + const char* dummy_first_unparsed; + ExpressionPathScanEndReason dummy_reason_to_stop; + ExpressionPathEndResultType dummy_final_value_type; + ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eNothing; + + ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression, + first_unparsed ? first_unparsed : &dummy_first_unparsed, + reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, + final_value_type ? final_value_type : &dummy_final_value_type, + options, + final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); + + if (!ret_val.get()) // if there are errors, I add nothing to the list + return 0; + + if (*reason_to_stop != eArrayRangeOperatorMet) + { + // I need not expand a range, just post-process the final value and return + if (!final_task_on_target || *final_task_on_target == ValueObject::eNothing) + { + list->Append(ret_val); + return 1; + } + if (ret_val.get() && *final_value_type == ePlain) // I can only deref and takeaddress of plain objects + { + if (*final_task_on_target == ValueObject::eDereference) + { + Error error; + ValueObjectSP final_value = ret_val->Dereference(error); + if (error.Fail() || !final_value.get()) + { + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_value_type = ValueObject::eInvalid; + return 0; + } + else + { + *final_task_on_target = ValueObject::eNothing; + list->Append(final_value); + return 1; + } + } + if (*final_task_on_target == ValueObject::eTakeAddress) + { + Error error; + ValueObjectSP final_value = ret_val->AddressOf(error); + if (error.Fail() || !final_value.get()) + { + *reason_to_stop = ValueObject::eTakingAddressFailed; + *final_value_type = ValueObject::eInvalid; + return 0; + } + else + { + *final_task_on_target = ValueObject::eNothing; + list->Append(final_value); + return 1; + } + } + } + } + else + { + return ExpandArraySliceExpression(first_unparsed ? *first_unparsed : dummy_first_unparsed, + first_unparsed ? first_unparsed : &dummy_first_unparsed, + ret_val, + list, + reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, + final_value_type ? final_value_type : &dummy_final_value_type, + options, + final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); + } + // in any non-covered case, just do the obviously right thing + list->Append(ret_val); + return 1; +} + lldb::ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, const char** first_unparsed, @@ -1524,6 +1782,12 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr lldb::clang_type_t root_clang_type = root->GetClangType(); + lldb::clang_type_t pointee_clang_type; + Flags root_clang_type_info,pointee_clang_type_info; + + root_clang_type_info = Flags(ClangASTContext::GetTypeInfo(root_clang_type, GetClangAST(), &pointee_clang_type)); + if (pointee_clang_type) + pointee_clang_type_info = Flags(ClangASTContext::GetTypeInfo(pointee_clang_type, GetClangAST(), NULL)); if (!expression_cstr || *expression_cstr == '\0') { @@ -1536,16 +1800,15 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, case '-': { if (options.m_check_dot_vs_arrow_syntax && - !ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use -> on a non-pointer and I must catch the error + root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eArrowInsteadOfDot; *final_result = ValueObject::eInvalid; return ValueObjectSP(); } - const uint32_t pointer_type_flags = ClangASTContext::GetTypeInfo (root_clang_type, NULL, NULL); - if ((pointer_type_flags & ClangASTContext::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden - (pointer_type_flags & ClangASTContext::eTypeIsPointer) && + if (root_clang_type_info.Test(ClangASTContext::eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden + root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) && options.m_no_fragile_ivar) { *first_unparsed = expression_cstr; @@ -1565,7 +1828,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, case '.': // or fallthrough from -> { if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' && - ClangASTContext::IsPointerType(root_clang_type)) // if you are trying to use . on a pointer and I must catch the error + root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eDotInsteadOfArrow; @@ -1616,9 +1879,9 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } case '[': { - if (!ClangASTContext::IsArrayType(root_clang_type) && !ClangASTContext::IsPointerType(root_clang_type)) // if this is not a T[] nor a T* + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray) && !root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if this is not a T[] nor a T* { - if (!ClangASTContext::IsScalarType(root_clang_type)) // if this is not even a scalar, this syntax is just plain wrong! + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eRangeOperatorInvalid; @@ -1635,7 +1898,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays { - if (!ClangASTContext::IsArrayType(root_clang_type)) + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { *first_unparsed = expression_cstr; *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; @@ -1672,7 +1935,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays { - if (ClangASTContext::IsArrayType(root_clang_type)) + if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { *first_unparsed = expression_cstr+2; *reason_to_stop = ValueObject::eArrayRangeOperatorMet; @@ -1688,7 +1951,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } } // from here on we do have a valid index - if (ClangASTContext::IsArrayType(root_clang_type)) + if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) { ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); if (!child_valobj_sp) @@ -1708,10 +1971,10 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return ValueObjectSP(); } } - else if (ClangASTContext::IsPointerType(root_clang_type)) + else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) { if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr())) + pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -1790,7 +2053,7 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, index_lower = index_higher; index_higher = temp; } - if (ClangASTContext::IsScalarType(root_clang_type)) // expansion only works for scalars + if (root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // expansion only works for scalars { root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); if (!root.get()) @@ -1808,9 +2071,9 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, return root; } } - else if (ClangASTContext::IsPointerType(root_clang_type) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield *what_next == ValueObject::eDereference && - ClangASTContext::IsScalarType(clang::QualType::getFromOpaquePtr(root_clang_type).getTypePtr()->getPointeeType().getAsOpaquePtr())) + pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) { Error error; root = root->Dereference(error); @@ -1849,6 +2112,302 @@ ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, } } +int +ValueObject::ExpandArraySliceExpression(const char* expression_cstr, + const char** first_unparsed, + lldb::ValueObjectSP root, + lldb::ValueObjectListSP& list, + ExpressionPathScanEndReason* reason_to_stop, + ExpressionPathEndResultType* final_result, + const GetValueForExpressionPathOptions& options, + ExpressionPathAftermath* what_next) +{ + if (!root.get()) + return 0; + + *first_unparsed = expression_cstr; + + while (true) + { + + const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr + + lldb::clang_type_t root_clang_type = root->GetClangType(); + lldb::clang_type_t pointee_clang_type; + Flags root_clang_type_info,pointee_clang_type_info; + + root_clang_type_info = Flags(ClangASTContext::GetTypeInfo(root_clang_type, GetClangAST(), &pointee_clang_type)); + if (pointee_clang_type) + pointee_clang_type_info = Flags(ClangASTContext::GetTypeInfo(pointee_clang_type, GetClangAST(), NULL)); + + if (!expression_cstr || *expression_cstr == '\0') + { + *reason_to_stop = ValueObject::eEndOfString; + list->Append(root); + return 1; + } + + switch (*expression_cstr) + { + case '[': + { + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray) && !root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) // if this is not a T[] nor a T* + { + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eRangeOperatorInvalid; + *final_result = ValueObject::eInvalid; + return 0; + } + else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eRangeOperatorNotAllowed; + *final_result = ValueObject::eInvalid; + return 0; + } + } + if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays + { + if (!root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; + *final_result = ValueObject::eInvalid; + return 0; + } + else // expand this into list + { + int max_index = root->GetNumChildren() - 1; + for (int index = 0; index < max_index; index++) + { + ValueObjectSP child = + root->GetChildAtIndex(index, true); + list->Append(child); + } + *first_unparsed = expression_cstr+2; + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return max_index; // tell me number of items I added to the VOList + } + } + const char *separator_position = ::strchr(expression_cstr+1,'-'); + const char *close_bracket_position = ::strchr(expression_cstr+1,']'); + if (!close_bracket_position) // if there is no ], this is a syntax error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + } + if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N] + { + char *end = NULL; + unsigned long index = ::strtoul (expression_cstr+1, &end, 0); + if (!end || end != close_bracket_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + } + if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays + { + if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) + { + int max_index = root->GetNumChildren() - 1; + for (int index = 0; index < max_index; index++) + { + ValueObjectSP child = + root->GetChildAtIndex(index, true); + list->Append(child); + } + *first_unparsed = expression_cstr+2; + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return max_index; // tell me number of items I added to the VOList + } + else + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eEmptyRangeNotAllowed; + *final_result = ValueObject::eInvalid; + return 0; + } + } + // from here on we do have a valid index + if (root_clang_type_info.Test(ClangASTContext::eTypeIsArray)) + { + root = root->GetChildAtIndex(index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + list->Append(root); + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return 1; + } + } + else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer)) + { + if (*what_next == ValueObject::eDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) + { + Error error; + root = root->Dereference(error); + if (error.Fail() || !root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + *what_next = eNothing; + continue; + } + } + else + { + root = root->GetSyntheticArrayMemberFromPointer(index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + list->Append(root); + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return 1; + } + } + } + else /*if (ClangASTContext::IsScalarType(root_clang_type))*/ + { + root = root->GetSyntheticBitFieldChild(index, index, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return 0; + } + else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing + { + list->Append(root); + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return 1; + } + } + } + else // we have a low and a high index + { + char *end = NULL; + unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0); + if (!end || end != separator_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + } + unsigned long index_higher = ::strtoul (separator_position+1, &end, 0); + if (!end || end != close_bracket_position) // if something weird is in our way return an error + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + } + if (index_lower > index_higher) // swap indices if required + { + unsigned long temp = index_lower; + index_lower = index_higher; + index_higher = temp; + } + if (root_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) // expansion only works for scalars + { + root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); + if (!root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eNoSuchChild; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + list->Append(root); + *first_unparsed = end+1; // skip ] + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return 1; + } + } + else if (root_clang_type_info.Test(ClangASTContext::eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield + *what_next == ValueObject::eDereference && + pointee_clang_type_info.Test(ClangASTContext::eTypeIsScalar)) + { + Error error; + root = root->Dereference(error); + if (error.Fail() || !root.get()) + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eDereferencingFailed; + *final_result = ValueObject::eInvalid; + return 0; + } + else + { + *what_next = ValueObject::eNothing; + continue; + } + } + else + { + for (int index = index_lower; + index <= index_higher; index++) + { + ValueObjectSP child = + root->GetChildAtIndex(index, true); + list->Append(child); + } + *first_unparsed = end+1; + *reason_to_stop = ValueObject::eRangeOperatorExpanded; + *final_result = ValueObject::eValueObjectList; + return index_higher-index_lower+1; // tell me number of items I added to the VOList + } + } + break; + } + default: // some non-[ separator, or something entirely wrong, is in the way + { + *first_unparsed = expression_cstr; + *reason_to_stop = ValueObject::eUnexpectedSymbol; + *final_result = ValueObject::eInvalid; + return 0; + break; + } + } + } +} + void ValueObject::DumpValueObject ( @@ -1921,7 +2480,7 @@ ValueObject::DumpValueObject const char *val_cstr = NULL; const char *sum_cstr = NULL; - SummaryFormat* entry = valobj->m_last_summary_format.get(); + SummaryFormat* entry = valobj->GetSummaryFormat().get(); if (err_cstr == NULL) { |