diff options
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/Commands/CommandObjectFrame.cpp | 11 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectType.cpp | 69 | ||||
-rw-r--r-- | lldb/source/Core/Debugger.cpp | 42 | ||||
-rw-r--r-- | lldb/source/Core/FormatManager.cpp | 19 | ||||
-rw-r--r-- | lldb/source/Core/ValueObject.cpp | 615 | ||||
-rw-r--r-- | lldb/source/Interpreter/CommandInterpreter.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Interpreter/OptionGroupVariable.cpp | 13 | ||||
-rw-r--r-- | lldb/source/Symbol/ClangASTContext.cpp | 29 | ||||
-rw-r--r-- | lldb/source/Symbol/SymbolContext.cpp | 2 |
9 files changed, 739 insertions, 63 deletions
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index f82c06bcc15..9d8f429cabc 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -439,6 +439,10 @@ public: const char *name_cstr = NULL; size_t idx; + + SummaryFormatSP summary_format_sp; + if (!m_option_variable.summary.empty()) + Debugger::NamedSummaryFormats::Get(ConstString(m_option_variable.summary.c_str()), summary_format_sp); if (variable_list) { @@ -484,7 +488,8 @@ public: if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module)) s.PutCString (": "); } - + if (summary_format_sp) + valobj_sp->SetCustomSummaryFormat(summary_format_sp); ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), var_sp->GetName().AsCString(), @@ -534,6 +539,8 @@ public: var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); } + if (summary_format_sp) + valobj_sp->SetCustomSummaryFormat(summary_format_sp); ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), valobj_sp->GetParent() ? name_cstr : NULL, @@ -622,6 +629,8 @@ public: var_sp->GetDeclaration ().DumpStopContext (&s, false); s.PutCString (": "); } + if (summary_format_sp) + valobj_sp->SetCustomSummaryFormat(summary_format_sp); ValueObject::DumpValueObject (result.GetOutputStream(), valobj_sp.get(), name_cstr, diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index 2e0aa5c0749..c0ffddb62ae 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -468,6 +468,9 @@ private: case 'x': m_regex = true; break; + case 'n': + m_name = new ConstString(option_arg); + break; default: error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); break; @@ -486,6 +489,7 @@ private: m_skip_references = false; m_skip_pointers = false; m_regex = false; + m_name = NULL; } const OptionDefinition* @@ -508,6 +512,7 @@ private: bool m_skip_pointers; bool m_regex; std::string m_format_string; + ConstString* m_name; }; CommandOptions m_options; @@ -601,7 +606,7 @@ public: { const size_t argc = command.GetArgumentCount(); - if (argc < 1) + if (argc < 1 && !m_options.m_name) { result.AppendErrorWithFormat ("%s takes one or more args.\n", m_cmd_name.c_str()); result.SetStatus(eReturnStatusFailed); @@ -636,14 +641,14 @@ public: for(int i = 0; i < argc; i++) { const char* typeA = command.GetArgumentAtIndex(i); - if(!typeA || typeA[0] == '\0') + if (!typeA || typeA[0] == '\0') { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } ConstString typeCS(typeA); - if(!m_options.m_regex) + if (!m_options.m_regex) { Debugger::SummaryFormats::Add(typeCS, entry); } @@ -660,6 +665,21 @@ public: Debugger::RegexSummaryFormats::Add(typeRX, entry); } } + + if (m_options.m_name) + { + if( (bool)(*(m_options.m_name)) ) + { + Debugger::NamedSummaryFormats::Add(*(m_options.m_name), entry); + } + else + { + result.AppendError("added to types, but not given a name"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } @@ -676,7 +696,8 @@ CommandObjectTypeSummaryAdd::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "regex", 'x', no_argument, NULL, 0, eArgTypeBoolean, "Type names are actually regular expressions."}, { LLDB_OPT_SET_1 , true, "inline-children", 'c', no_argument, NULL, 0, eArgTypeBoolean, "If true, inline all child values into summary string."}, { LLDB_OPT_SET_2 , true, "format-string", 'f', required_argument, NULL, 0, eArgTypeSummaryString, "Format string used to display text and object contents."}, - { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, + { LLDB_OPT_SET_2, false, "expand", 'e', no_argument, NULL, 0, eArgTypeBoolean, "Expand aggregate data types to show children on separate lines."}, + { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeName, "A name for this summary string."}, { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -734,7 +755,9 @@ public: bool delete_summary = Debugger::SummaryFormats::Delete(typeCS); bool delete_regex = Debugger::RegexSummaryFormats::Delete(typeCS); - if (delete_summary || delete_regex) + bool delete_named = Debugger::NamedSummaryFormats::Delete(typeCS); + + if (delete_summary || delete_regex || delete_named) { result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); @@ -774,6 +797,7 @@ public: { Debugger::SummaryFormats::Clear(); Debugger::RegexSummaryFormats::Clear(); + Debugger::NamedSummaryFormats::Clear(); result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } @@ -847,22 +871,33 @@ public: Debugger::SummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); delete param; - if(Debugger::RegexSummaryFormats::GetCount() == 0) + if(Debugger::RegexSummaryFormats::GetCount() > 0) { - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); + result.GetOutputStream().Printf("Regex-based summaries (slower):\n"); + if (argc == 1) { + RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); + regex->Compile(command.GetArgumentAtIndex(0)); + rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result,regex); + } + else + rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result); + Debugger::RegexSummaryFormats::LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, rxparam); + delete rxparam; } - result.GetOutputStream().Printf("Regex-based summaries (slower):\n"); - if (argc == 1) { - RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); - regex->Compile(command.GetArgumentAtIndex(0)); - rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result,regex); + if(Debugger::NamedSummaryFormats::GetCount() > 0) + { + result.GetOutputStream().Printf("Named summaries:\n"); + if (argc == 1) { + RegularExpression* regex = new RegularExpression(command.GetArgumentAtIndex(0)); + regex->Compile(command.GetArgumentAtIndex(0)); + param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result,regex); + } + else + param = new CommandObjectTypeSummaryList_LoopCallbackParam(this,&result); + Debugger::NamedSummaryFormats::LoopThrough(CommandObjectTypeSummaryList_LoopCallback, param); + delete param; } - else - rxparam = new CommandObjectTypeRXSummaryList_LoopCallbackParam(this,&result); - Debugger::RegexSummaryFormats::LoopThrough(CommandObjectTypeRXSummaryList_LoopCallback, rxparam); - delete rxparam; result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index e7b97a59077..9b34331e84f 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1821,6 +1821,48 @@ Debugger::RegexSummaryFormats::GetCount() return GetFormatManager().RegexSummary().GetCount(); } +bool +Debugger::NamedSummaryFormats::Get(const ConstString &type, SummaryFormat::SharedPointer &entry) +{ + return GetFormatManager().NamedSummary().Get(type.AsCString(),entry); +} + +void +Debugger::NamedSummaryFormats::Add(const ConstString &type, const SummaryFormat::SharedPointer &entry) +{ + GetFormatManager().NamedSummary().Add(type.AsCString(),entry); +} + +bool +Debugger::NamedSummaryFormats::Delete(const ConstString &type) +{ + return GetFormatManager().NamedSummary().Delete(type.AsCString()); +} + +void +Debugger::NamedSummaryFormats::Clear() +{ + GetFormatManager().NamedSummary().Clear(); +} + +void +Debugger::NamedSummaryFormats::LoopThrough(SummaryFormat::SummaryCallback callback, void* callback_baton) +{ + GetFormatManager().NamedSummary().LoopThrough(callback, callback_baton); +} + +uint32_t +Debugger::NamedSummaryFormats::GetCurrentRevision() +{ + return GetFormatManager().GetCurrentRevision(); +} + +uint32_t +Debugger::NamedSummaryFormats::GetCount() +{ + return GetFormatManager().NamedSummary().GetCount(); +} + #pragma mark Debugger::SettingsController //-------------------------------------------------- diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index 24b565af996..ece30068e4d 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -154,12 +154,11 @@ FormatManager::GetFormatAsCString (Format format) template<> bool -FormatNavigator<std::map<lldb::RegularExpressionSP, SummaryFormat::SharedPointer>, SummaryFormat::RegexSummaryCallback>::Get(const char* key, - SummaryFormat::SharedPointer& value) +FormatNavigator<lldb::RegularExpressionSP, SummaryFormat>::Get(const char* key, SummaryFormat::SharedPointer& value) { - Mutex::Locker(m_map_mutex); - MapIterator pos, end = m_map.end(); - for (pos = m_map.begin(); pos != end; pos++) + Mutex::Locker(m_format_map.mutex()); + MapIterator pos, end = m_format_map.map().end(); + for (pos = m_format_map.map().begin(); pos != end; pos++) { lldb::RegularExpressionSP regex = pos->first; if (regex->Execute(key)) @@ -173,16 +172,16 @@ FormatNavigator<std::map<lldb::RegularExpressionSP, SummaryFormat::SharedPointer template<> bool -FormatNavigator<std::map<lldb::RegularExpressionSP, SummaryFormat::SharedPointer>, SummaryFormat::RegexSummaryCallback>::Delete(const char* type) +FormatNavigator<lldb::RegularExpressionSP, SummaryFormat>::Delete(const char* type) { - Mutex::Locker(m_map_mutex); - MapIterator pos, end = m_map.end(); - for (pos = m_map.begin(); pos != end; pos++) + Mutex::Locker(m_format_map.mutex()); + MapIterator pos, end = m_format_map.map().end(); + for (pos = m_format_map.map().begin(); pos != end; pos++) { lldb::RegularExpressionSP regex = pos->first; if ( ::strcmp(type,regex->GetText()) == 0) { - m_map.erase(pos); + m_format_map.map().erase(pos); return true; } } 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) { diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 8e499d7de43..bd934c3aa07 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -935,7 +935,7 @@ CommandInterpreter::HandleCommand (const char *command_line, // Make a scoped cleanup object that will clear the crash description string // on exit of this function. - lldb_utility::CleanUp <const char *, void> crash_description_cleanup(NULL, Host::SetCrashDescription); + lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription); if (log) log->Printf ("Processing command: %s", command_line); diff --git a/lldb/source/Interpreter/OptionGroupVariable.cpp b/lldb/source/Interpreter/OptionGroupVariable.cpp index e553e1bea47..9cf8d417610 100644 --- a/lldb/source/Interpreter/OptionGroupVariable.cpp +++ b/lldb/source/Interpreter/OptionGroupVariable.cpp @@ -19,6 +19,7 @@ using namespace lldb; using namespace lldb_private; +// if you add any options here, remember to update the counters in OptionGroupVariable::GetNumDefinitions() static OptionDefinition g_option_table[] = { @@ -28,7 +29,8 @@ g_option_table[] = { LLDB_OPT_SET_1, false, "show-declaration",'c', no_argument, NULL, 0, eArgTypeNone, "Show variable declaration information (source file and line where the variable was declared)."}, { LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, eArgTypeExprFormat, "Specify the format that the variable output should use."}, { LLDB_OPT_SET_1, false, "regex", 'r', no_argument, NULL, 0, eArgTypeRegularExpression, "The <variable-name> argument for name lookups are regular expressions."}, - { LLDB_OPT_SET_1, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."} + { LLDB_OPT_SET_1, false, "scope", 's', no_argument, NULL, 0, eArgTypeNone, "Show variable scope (argument, local, global, static)."}, + { LLDB_OPT_SET_1, false, "summary", 'y', required_argument, NULL, 0, eArgTypeName, "Specify the summary that the variable output should use."}, }; @@ -62,7 +64,9 @@ OptionGroupVariable::SetOptionValue (CommandInterpreter &interpreter, case 's': show_scope = true; break; - + case 'y': + summary = std::string(option_arg); + break; default: error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); break; @@ -81,6 +85,7 @@ OptionGroupVariable::OptionParsingStarting (CommandInterpreter &interpreter) format = lldb::eFormatDefault; use_regex = false; show_scope = false; + summary = ""; } @@ -101,9 +106,9 @@ uint32_t OptionGroupVariable::GetNumDefinitions () { if (include_frame_options) - return 7; + return 8; else - return 4; + return 5; } diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 6e3a83e162c..8ccde5ce1e9 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -2077,7 +2077,30 @@ ClangASTContext::GetTypeInfo if (ast && pointee_or_element_clang_type) *pointee_or_element_clang_type = ast->ObjCBuiltinClassTy.getAsOpaquePtr(); return eTypeIsBuiltIn | eTypeIsPointer | eTypeHasValue; - + break; + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + return eTypeIsBuiltIn | eTypeHasValue | eTypeIsScalar; default: break; } @@ -4645,6 +4668,10 @@ ClangASTContext::GetArraySize (clang_type_t clang_type) case clang::Type::Typedef: return ClangASTContext::GetArraySize(cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr()); + break; + + default: + break; } } return 0; diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp index 1f24f1339bd..0898b812552 100644 --- a/lldb/source/Symbol/SymbolContext.cpp +++ b/lldb/source/Symbol/SymbolContext.cpp @@ -164,7 +164,7 @@ SymbolContext::DumpStopContext dumped_something = true; s->PutCString(" at "); if (line_entry.DumpStopContext(s, show_fullpaths)) - return; + return dumped_something; } } } |