Index: lldb/include/lldb/Core/ValueObject.h =================================================================== --- lldb/include/lldb/Core/ValueObject.h +++ lldb/include/lldb/Core/ValueObject.h @@ -456,6 +456,8 @@ // The functions below should NOT be modified by subclasses const Status &GetError(); + void SetError(Status &&error) { m_error = std::move(error); } + ConstString GetName() const; virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create); Index: lldb/include/lldb/DataFormatters/FormattersContainer.h =================================================================== --- lldb/include/lldb/DataFormatters/FormattersContainer.h +++ lldb/include/lldb/DataFormatters/FormattersContainer.h @@ -204,8 +204,8 @@ return ret; } - bool Get(ConstString type, MapValueType &entry) { - return Get_Impl(type, entry, static_cast(nullptr)); + bool Get(ConstString type, MapValueType &entry, ValueObject *valobj) { + return Get_Impl(type, entry, valobj, static_cast(nullptr)); } bool GetExact(ConstString type, MapValueType &entry) { @@ -262,13 +262,15 @@ return false; } - bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) { + bool Get_Impl(ConstString type, MapValueType &entry, ValueObject *valobj, + ConstString *dummy) { return m_format_map.Get(type, entry); } bool GetExact_Impl(ConstString type, MapValueType &entry, ConstString *dummy) { - return Get_Impl(type, entry, static_cast(nullptr)); + return Get_Impl(type, entry, nullptr /*valobj*/, + static_cast(nullptr)); } lldb::TypeNameSpecifierImplSP @@ -291,19 +293,31 @@ new TypeNameSpecifierImpl(regex->GetText().str().c_str(), true)); } - bool Get_Impl(ConstString key, MapValueType &value, + bool Get_Impl(ConstString key, MapValueType &value, ValueObject *valobj, lldb::RegularExpressionSP *dummy) { llvm::StringRef key_str = key.GetStringRef(); std::lock_guard guard(m_format_map.mutex()); MapIterator pos, end = m_format_map.map().end(); + MapIterator found = end; for (pos = m_format_map.map().begin(); pos != end; pos++) { lldb::RegularExpressionSP regex = pos->first; if (regex->Execute(key_str)) { - value = pos->second; - return true; + if (found != end) { + if (valobj) + valobj->SetError(Status("Two regexes (\"%s\" and \"%s\") " + "ambiguously match the same string \"%s\".", + found->first->GetText().str().c_str(), + regex->GetText().str().c_str(), + key.GetCString())); + return false; + } + found = pos; } } - return false; + if (found == end) + return false; + value = found->second; + return true; } bool GetExact_Impl(ConstString key, MapValueType &value, @@ -321,9 +335,9 @@ } bool Get(const FormattersMatchVector &candidates, MapValueType &entry, - uint32_t *reason) { + uint32_t *reason, ValueObject *valobj) { for (const FormattersMatchCandidate &candidate : candidates) { - if (Get(candidate.GetTypeName(), entry)) { + if (Get(candidate.GetTypeName(), entry, valobj)) { if (candidate.IsMatch(entry) == false) { entry.reset(); continue; Index: lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py =================================================================== --- lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py +++ lldb/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py @@ -130,6 +130,10 @@ self.expect("frame variable int_array", substrs=['1,2']) + # "int []" gets converted by FixArrayTypeNameWithRegex into "int \[[0-9]+\]" + # which becomes ambiguous for some string against "int \[[0-9]\]". + self.runCmd("type summary clear") + self.runCmd( 'type summary add --summary-string \"${var[0-1]}\" "int []"') Index: lldb/source/DataFormatters/TypeCategory.cpp =================================================================== --- lldb/source/DataFormatters/TypeCategory.cpp +++ lldb/source/DataFormatters/TypeCategory.cpp @@ -101,9 +101,10 @@ lldb::TypeFormatImplSP &entry, uint32_t *reason) { if (!IsEnabled() || !IsApplicable(valobj)) return false; - if (GetTypeFormatsContainer()->Get(candidates, entry, reason)) + if (GetTypeFormatsContainer()->Get(candidates, entry, reason, &valobj)) return true; - bool regex = GetRegexTypeFormatsContainer()->Get(candidates, entry, reason); + bool regex = + GetRegexTypeFormatsContainer()->Get(candidates, entry, reason, &valobj); if (regex && reason) *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary; return regex; @@ -114,9 +115,10 @@ lldb::TypeSummaryImplSP &entry, uint32_t *reason) { if (!IsEnabled() || !IsApplicable(valobj)) return false; - if (GetTypeSummariesContainer()->Get(candidates, entry, reason)) + if (GetTypeSummariesContainer()->Get(candidates, entry, reason, &valobj)) return true; - bool regex = GetRegexTypeSummariesContainer()->Get(candidates, entry, reason); + bool regex = + GetRegexTypeSummariesContainer()->Get(candidates, entry, reason, &valobj); if (regex && reason) *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary; return regex; @@ -132,17 +134,19 @@ bool regex_filter = false; // first find both Filter and Synth, and then check which is most recent - if (!GetTypeFiltersContainer()->Get(candidates, filter_sp, &reason_filter)) + if (!GetTypeFiltersContainer()->Get(candidates, filter_sp, &reason_filter, + &valobj)) regex_filter = GetRegexTypeFiltersContainer()->Get(candidates, filter_sp, - &reason_filter); + &reason_filter, &valobj); bool regex_synth = false; uint32_t reason_synth = 0; bool pick_synth = false; ScriptedSyntheticChildren::SharedPointer synth; - if (!GetTypeSyntheticsContainer()->Get(candidates, synth, &reason_synth)) - regex_synth = GetRegexTypeSyntheticsContainer()->Get(candidates, synth, - &reason_synth); + if (!GetTypeSyntheticsContainer()->Get(candidates, synth, &reason_synth, + &valobj)) + regex_synth = GetRegexTypeSyntheticsContainer()->Get( + candidates, synth, &reason_synth, &valobj); if (!filter_sp.get() && !synth.get()) return false; else if (!filter_sp.get() && synth.get()) @@ -174,10 +178,10 @@ lldb::TypeValidatorImplSP &entry, uint32_t *reason) { if (!IsEnabled()) return false; - if (GetTypeValidatorsContainer()->Get(candidates, entry, reason)) + if (GetTypeValidatorsContainer()->Get(candidates, entry, reason, &valobj)) return true; - bool regex = - GetRegexTypeValidatorsContainer()->Get(candidates, entry, reason); + bool regex = GetRegexTypeValidatorsContainer()->Get(candidates, entry, reason, + &valobj); if (regex && reason) *reason |= lldb_private::eFormatterChoiceCriterionRegularExpressionSummary; return regex; @@ -295,7 +299,8 @@ TypeValidatorImpl::SharedPointer validator_sp; if ((items & eFormatCategoryItemValue) == eFormatCategoryItemValue) { - if (GetTypeFormatsContainer()->Get(type_name, format_sp)) { + if (GetTypeFormatsContainer()->Get(type_name, format_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -305,7 +310,8 @@ } if ((items & eFormatCategoryItemRegexValue) == eFormatCategoryItemRegexValue) { - if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp)) { + if (GetRegexTypeFormatsContainer()->Get(type_name, format_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -315,7 +321,8 @@ } if ((items & eFormatCategoryItemSummary) == eFormatCategoryItemSummary) { - if (GetTypeSummariesContainer()->Get(type_name, summary_sp)) { + if (GetTypeSummariesContainer()->Get(type_name, summary_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -325,7 +332,8 @@ } if ((items & eFormatCategoryItemRegexSummary) == eFormatCategoryItemRegexSummary) { - if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp)) { + if (GetRegexTypeSummariesContainer()->Get(type_name, summary_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -335,7 +343,8 @@ } if ((items & eFormatCategoryItemFilter) == eFormatCategoryItemFilter) { - if (GetTypeFiltersContainer()->Get(type_name, filter_sp)) { + if (GetTypeFiltersContainer()->Get(type_name, filter_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -345,7 +354,8 @@ } if ((items & eFormatCategoryItemRegexFilter) == eFormatCategoryItemRegexFilter) { - if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp)) { + if (GetRegexTypeFiltersContainer()->Get(type_name, filter_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -355,7 +365,8 @@ } if ((items & eFormatCategoryItemSynth) == eFormatCategoryItemSynth) { - if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp)) { + if (GetTypeSyntheticsContainer()->Get(type_name, synth_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -365,7 +376,8 @@ } if ((items & eFormatCategoryItemRegexSynth) == eFormatCategoryItemRegexSynth) { - if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp)) { + if (GetRegexTypeSyntheticsContainer()->Get(type_name, synth_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -375,7 +387,8 @@ } if ((items & eFormatCategoryItemValidator) == eFormatCategoryItemValidator) { - if (GetTypeValidatorsContainer()->Get(type_name, validator_sp)) { + if (GetTypeValidatorsContainer()->Get(type_name, validator_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type) @@ -385,7 +398,8 @@ } if ((items & eFormatCategoryItemRegexValidator) == eFormatCategoryItemRegexValidator) { - if (GetRegexTypeValidatorsContainer()->Get(type_name, validator_sp)) { + if (GetRegexTypeValidatorsContainer()->Get(type_name, validator_sp, + nullptr /*valobj*/)) { if (matching_category) *matching_category = m_name.GetCString(); if (matching_type)