Index: lldb/include/lldb/DataFormatters/DataVisualization.h =================================================================== --- lldb/include/lldb/DataFormatters/DataVisualization.h +++ lldb/include/lldb/DataFormatters/DataVisualization.h @@ -69,9 +69,9 @@ static void Clear(); - static void - ForEach(std::function - callback); + static void ForEach(std::function + callback); static uint32_t GetCount(); }; Index: lldb/include/lldb/DataFormatters/FormatManager.h =================================================================== --- lldb/include/lldb/DataFormatters/FormatManager.h +++ lldb/include/lldb/DataFormatters/FormatManager.h @@ -34,7 +34,7 @@ // this file's objects directly class FormatManager : public IFormatChangeListener { - typedef FormatMap NamedSummariesMap; + typedef FormatMap NamedSummariesMap; typedef TypeCategoryMap::MapType::iterator CategoryMapIterator; public: @@ -144,13 +144,6 @@ static const char *GetFormatAsCString(lldb::Format format); - // if the user tries to add formatters for, say, "struct Foo" those will not - // match any type because of the way we strip qualifiers from typenames this - // method looks for the case where the user is adding a - // "class","struct","enum" or "union" Foo and strips the unnecessary - // qualifier - static ConstString GetValidTypeName(ConstString type); - // when DataExtractor dumps a vectorOfT, it uses a predefined format for each // item this method returns it, or eFormatInvalid if vector_format is not a // vectorOf Index: lldb/include/lldb/DataFormatters/FormattersContainer.h =================================================================== --- lldb/include/lldb/DataFormatters/FormattersContainer.h +++ lldb/include/lldb/DataFormatters/FormattersContainer.h @@ -37,57 +37,112 @@ virtual uint32_t GetCurrentRevision() = 0; }; -// if the user tries to add formatters for, say, "struct Foo" those will not -// match any type because of the way we strip qualifiers from typenames this -// method looks for the case where the user is adding a "class","struct","enum" -// or "union" Foo and strips the unnecessary qualifier -static inline ConstString GetValidTypeName_Impl(ConstString type) { - if (type.IsEmpty()) - return type; +/// Class for matching type names. +class TypeMatcher { + RegularExpression m_type_name_regex; + ConstString m_type_name; + /// True if this is just matching by the m_type_name string. False if + /// m_type_name_regex should be used for matching. + bool m_is_str; + /// True iff this TypeMatcher is invalid and shouldn't be used for any + /// type matching logic. + bool m_valid = true; + + // if the user tries to add formatters for, say, "struct Foo" those will not + // match any type because of the way we strip qualifiers from typenames this + // method looks for the case where the user is adding a + // "class","struct","enum" or "union" Foo and strips the unnecessary qualifier + static ConstString StripTypeName(ConstString type) { + if (type.IsEmpty()) + return type; + + std::string type_cstr(type.AsCString()); + StringLexer type_lexer(type_cstr); + + type_lexer.AdvanceIf("class "); + type_lexer.AdvanceIf("enum "); + type_lexer.AdvanceIf("struct "); + type_lexer.AdvanceIf("union "); + + while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first) + ; + + return ConstString(type_lexer.GetUnlexed()); + } - std::string type_cstr(type.AsCString()); - StringLexer type_lexer(type_cstr); +public: + /// Creates an invalid matcher that should not be used for any type matching. + TypeMatcher() : m_valid(false) {} + /// Creates a matcher that accepts any type with exactly the given type name. + TypeMatcher(ConstString type_name) : m_type_name(type_name), m_is_str(true) {} + /// Creates a matcher that accepts any type matching the given regex. + TypeMatcher(RegularExpression regex) + : m_type_name_regex(regex), m_is_str(false) {} + + /// True iff this matches the given type name. + bool Matches(ConstString type_name) const { + assert(m_valid && "Using invalid TypeMatcher"); + + if (m_is_str) + return m_type_name == type_name || + StripTypeName(m_type_name) == StripTypeName(type_name); + return m_type_name_regex.Execute(type_name.GetStringRef()); + } - type_lexer.AdvanceIf("class "); - type_lexer.AdvanceIf("enum "); - type_lexer.AdvanceIf("struct "); - type_lexer.AdvanceIf("union "); + /// Returns the underlying match string for this TypeMatcher. + ConstString GetMatchString() const { + assert(m_valid && "Using invalid TypeMatcher"); - while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first) - ; + if (m_is_str) + return StripTypeName(m_type_name); + return ConstString(m_type_name_regex.GetText()); + } - return ConstString(type_lexer.GetUnlexed()); -} + /// Returns true if this TypeMatcher and the given one were most created by + /// the same match string. + /// The main purpose of this function is to find existing TypeMatcher + /// instances by the user input that created them. This is necessary as LLDB + /// allows referencing existing TypeMatchers in commands by the user input + /// that originally created them: + /// (lldb) type summary add --summary-string \"A\" -x TypeName + /// (lldb) type summary delete TypeName + bool CreatedBySameMatchString(TypeMatcher other) const { + assert(m_valid && "Using invalid TypeMatcher"); + + return GetMatchString() == other.GetMatchString(); + } +}; -template class FormattersContainer; +template class FormattersContainer; -template class FormatMap { +template class FormatMap { public: typedef typename ValueType::SharedPointer ValueSP; - typedef std::vector> MapType; + typedef std::vector> MapType; typedef typename MapType::iterator MapIterator; - typedef std::function ForEachCallback; + typedef std::function + ForEachCallback; FormatMap(IFormatChangeListener *lst) : m_map(), m_map_mutex(), listener(lst) {} - void Add(KeyType name, const ValueSP &entry) { + void Add(TypeMatcher matcher, const ValueSP &entry) { if (listener) entry->GetRevision() = listener->GetCurrentRevision(); else entry->GetRevision() = 0; std::lock_guard guard(m_map_mutex); - Delete(name); - m_map.emplace_back(std::move(name), std::move(entry)); + Delete(matcher); + m_map.emplace_back(std::move(matcher), std::move(entry)); if (listener) listener->Changed(); } - bool Delete(const KeyType &name) { + bool Delete(const TypeMatcher &matcher) { std::lock_guard guard(m_map_mutex); for (MapIterator iter = m_map.begin(); iter != m_map.end(); ++iter) - if (iter->first == name) { + if (iter->first.CreatedBySameMatchString(matcher)) { m_map.erase(iter); if (listener) listener->Changed(); @@ -103,10 +158,10 @@ listener->Changed(); } - bool Get(const KeyType &name, ValueSP &entry) { + bool Get(const TypeMatcher &matcher, ValueSP &entry) { std::lock_guard guard(m_map_mutex); for (const auto &pos : m_map) - if (pos.first == name) { + if (pos.first.CreatedBySameMatchString(matcher)) { entry = pos.second; return true; } @@ -117,7 +172,7 @@ if (callback) { std::lock_guard guard(m_map_mutex); for (const auto &pos : m_map) { - const KeyType &type = pos.first; + const TypeMatcher &type = pos.first; if (!callback(type, pos.second)) break; } @@ -134,10 +189,10 @@ } // If caller holds the mutex we could return a reference without copy ctor. - KeyType GetKeyAtIndex(size_t index) { + llvm::Optional GetKeyAtIndex(size_t index) { std::lock_guard guard(m_map_mutex); if (index >= m_map.size()) - return {}; + return llvm::None; return m_map[index].first; } @@ -150,21 +205,18 @@ std::recursive_mutex &mutex() { return m_map_mutex; } - friend class FormattersContainer; + friend class FormattersContainer; friend class FormatManager; }; -template class FormattersContainer { +template class FormattersContainer { protected: - typedef FormatMap BackEndType; + typedef FormatMap BackEndType; public: - typedef typename BackEndType::MapType MapType; - typedef typename MapType::iterator MapIterator; - typedef KeyType MapKeyType; typedef std::shared_ptr MapValueType; typedef typename BackEndType::ForEachCallback ForEachCallback; - typedef typename std::shared_ptr> + typedef typename std::shared_ptr> SharedPointer; friend class TypeCategoryImpl; @@ -172,20 +224,25 @@ FormattersContainer(std::string name, IFormatChangeListener *lst) : m_format_map(lst), m_name(name) {} - void Add(MapKeyType type, const MapValueType &entry) { - Add_Impl(std::move(type), entry, static_cast(nullptr)); + void Add(TypeMatcher type, const MapValueType &entry) { + m_format_map.Add(std::move(type), entry); } - bool Delete(ConstString type) { - return Delete_Impl(type, static_cast(nullptr)); - } + bool Delete(TypeMatcher type) { return m_format_map.Delete(type); } bool Get(ConstString type, MapValueType &entry) { - return Get_Impl(type, entry, static_cast(nullptr)); + std::lock_guard guard(m_format_map.mutex()); + for (auto &formatter : llvm::reverse(m_format_map.map())) { + if (formatter.first.Matches(type)) { + entry = formatter.second; + return true; + } + } + return false; } bool GetExact(ConstString type, MapValueType &entry) { - return GetExact_Impl(type, entry, static_cast(nullptr)); + return m_format_map.Get(type, entry); } MapValueType GetAtIndex(size_t index) { @@ -193,8 +250,12 @@ } lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) { - return GetTypeNameSpecifierAtIndex_Impl(index, - static_cast(nullptr)); + llvm::Optional type_matcher = + m_format_map.GetKeyAtIndex(index); + if (!type_matcher) + return lldb::TypeNameSpecifierImplSP(); + return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl( + type_matcher->GetMatchString().GetStringRef(), true)); } void Clear() { m_format_map.Clear(); } @@ -210,91 +271,6 @@ FormattersContainer(const FormattersContainer &) = delete; const FormattersContainer &operator=(const FormattersContainer &) = delete; - void Add_Impl(MapKeyType type, const MapValueType &entry, - RegularExpression *dummy) { - m_format_map.Add(std::move(type), entry); - } - - void Add_Impl(ConstString type, const MapValueType &entry, - ConstString *dummy) { - m_format_map.Add(GetValidTypeName_Impl(type), entry); - } - - bool Delete_Impl(ConstString type, ConstString *dummy) { - return m_format_map.Delete(type); - } - - bool Delete_Impl(ConstString type, RegularExpression *dummy) { - std::lock_guard guard(m_format_map.mutex()); - MapIterator pos, end = m_format_map.map().end(); - for (pos = m_format_map.map().begin(); pos != end; pos++) { - const RegularExpression ®ex = pos->first; - if (type.GetStringRef() == regex.GetText()) { - m_format_map.map().erase(pos); - if (m_format_map.listener) - m_format_map.listener->Changed(); - return true; - } - } - return false; - } - - bool Get_Impl(ConstString type, MapValueType &entry, 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)); - } - - lldb::TypeNameSpecifierImplSP - GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) { - ConstString key = m_format_map.GetKeyAtIndex(index); - if (key) - return lldb::TypeNameSpecifierImplSP( - new TypeNameSpecifierImpl(key.GetStringRef(), false)); - else - return lldb::TypeNameSpecifierImplSP(); - } - - lldb::TypeNameSpecifierImplSP - GetTypeNameSpecifierAtIndex_Impl(size_t index, RegularExpression *dummy) { - RegularExpression regex = m_format_map.GetKeyAtIndex(index); - if (regex == RegularExpression()) - return lldb::TypeNameSpecifierImplSP(); - return lldb::TypeNameSpecifierImplSP( - new TypeNameSpecifierImpl(regex.GetText().str().c_str(), true)); - } - - bool Get_Impl(ConstString key, MapValueType &value, - RegularExpression *dummy) { - llvm::StringRef key_str = key.GetStringRef(); - std::lock_guard guard(m_format_map.mutex()); - // Patterns are matched in reverse-chronological order. - for (const auto &pos : llvm::reverse(m_format_map.map())) { - const RegularExpression ®ex = pos.first; - if (regex.Execute(key_str)) { - value = pos.second; - return true; - } - } - return false; - } - - bool GetExact_Impl(ConstString key, MapValueType &value, - RegularExpression *dummy) { - std::lock_guard guard(m_format_map.mutex()); - for (const auto &pos : m_format_map.map()) { - const RegularExpression ®ex = pos.first; - if (regex.GetText() == key.GetStringRef()) { - value = pos.second; - return true; - } - } - return false; - } - bool Get(const FormattersMatchVector &candidates, MapValueType &entry) { for (const FormattersMatchCandidate &candidate : candidates) { if (Get(candidate.GetTypeName(), entry)) { Index: lldb/include/lldb/DataFormatters/TypeCategory.h =================================================================== --- lldb/include/lldb/DataFormatters/TypeCategory.h +++ lldb/include/lldb/DataFormatters/TypeCategory.h @@ -25,12 +25,11 @@ template class FormatterContainerPair { public: - typedef FormattersContainer ExactMatchContainer; - typedef FormattersContainer - RegexMatchContainer; + typedef FormattersContainer ExactMatchContainer; + typedef FormattersContainer RegexMatchContainer; - typedef typename ExactMatchContainer::MapType ExactMatchMap; - typedef typename RegexMatchContainer::MapType RegexMatchMap; + typedef TypeMatcher ExactMatchMap; + typedef TypeMatcher RegexMatchMap; typedef typename ExactMatchContainer::MapValueType MapValueType; @@ -349,19 +348,13 @@ friend class LanguageCategory; friend class TypeCategoryMap; - friend class FormattersContainer; - friend class FormattersContainer; + friend class FormattersContainer; - friend class FormattersContainer; - friend class FormattersContainer; + friend class FormattersContainer; - friend class FormattersContainer; - friend class FormattersContainer; - - friend class FormattersContainer; - friend class FormattersContainer; + friend class FormattersContainer; + friend class FormattersContainer; }; } // namespace lldb_private Index: lldb/include/lldb/DataFormatters/TypeCategoryMap.h =================================================================== --- lldb/include/lldb/DataFormatters/TypeCategoryMap.h +++ lldb/include/lldb/DataFormatters/TypeCategoryMap.h @@ -103,7 +103,7 @@ std::recursive_mutex &mutex() { return m_map_mutex; } - friend class FormattersContainer; + friend class FormattersContainer; friend class FormatManager; }; } // namespace lldb_private Index: lldb/source/Commands/CommandObjectType.cpp =================================================================== --- lldb/source/Commands/CommandObjectType.cpp +++ lldb/source/Commands/CommandObjectType.cpp @@ -1066,13 +1066,15 @@ TypeCategoryImpl::ForEachCallbacks foreach; foreach .SetExact([&result, &formatter_regex, &any_printed]( - ConstString name, + const TypeMatcher &type_matcher, const FormatterSharedPointer &format_sp) -> bool { if (formatter_regex) { bool escape = true; - if (name.GetStringRef() == formatter_regex->GetText()) { + if (type_matcher.CreatedBySameMatchString( + ConstString(formatter_regex->GetText()))) { escape = false; - } else if (formatter_regex->Execute(name.GetStringRef())) { + } else if (formatter_regex->Execute( + type_matcher.GetMatchString().GetStringRef())) { escape = false; } @@ -1081,20 +1083,23 @@ } any_printed = true; - result.GetOutputStream().Printf("%s: %s\n", name.AsCString(), - format_sp->GetDescription().c_str()); + result.GetOutputStream().Printf( + "%s: %s\n", type_matcher.GetMatchString().GetCString(), + format_sp->GetDescription().c_str()); return true; }); foreach .SetWithRegex([&result, &formatter_regex, &any_printed]( - const RegularExpression ®ex, + const TypeMatcher &type_matcher, const FormatterSharedPointer &format_sp) -> bool { if (formatter_regex) { bool escape = true; - if (regex.GetText() == formatter_regex->GetText()) { + if (type_matcher.CreatedBySameMatchString( + ConstString(formatter_regex->GetText()))) { escape = false; - } else if (formatter_regex->Execute(regex.GetText())) { + } else if (formatter_regex->Execute( + type_matcher.GetMatchString().GetStringRef())) { escape = false; } @@ -1103,9 +1108,9 @@ } any_printed = true; - result.GetOutputStream().Printf("%s: %s\n", - regex.GetText().str().c_str(), - format_sp->GetDescription().c_str()); + result.GetOutputStream().Printf( + "%s: %s\n", type_matcher.GetMatchString().GetCString(), + format_sp->GetDescription().c_str()); return true; }); @@ -1681,10 +1686,10 @@ if (DataVisualization::NamedSummaryFormats::GetCount() > 0) { result.GetOutputStream().Printf("Named summaries:\n"); DataVisualization::NamedSummaryFormats::ForEach( - [&result](ConstString name, + [&result](const TypeMatcher &type_matcher, const TypeSummaryImplSP &summary_sp) -> bool { result.GetOutputStream().Printf( - "%s: %s\n", name.AsCString(), + "%s: %s\n", type_matcher.GetMatchString().GetCString(), summary_sp->GetDescription().c_str()); return true; }); Index: lldb/source/DataFormatters/DataVisualization.cpp =================================================================== --- lldb/source/DataFormatters/DataVisualization.cpp +++ lldb/source/DataFormatters/DataVisualization.cpp @@ -174,8 +174,7 @@ void DataVisualization::NamedSummaryFormats::Add( ConstString type, const lldb::TypeSummaryImplSP &entry) { - GetFormatManager().GetNamedSummaryContainer().Add( - FormatManager::GetValidTypeName(type), entry); + GetFormatManager().GetNamedSummaryContainer().Add(type, entry); } bool DataVisualization::NamedSummaryFormats::Delete(ConstString type) { @@ -187,7 +186,7 @@ } void DataVisualization::NamedSummaryFormats::ForEach( - std::function + std::function callback) { GetFormatManager().GetNamedSummaryContainer().ForEach(callback); } Index: lldb/source/DataFormatters/FormatManager.cpp =================================================================== --- lldb/source/DataFormatters/FormatManager.cpp +++ lldb/source/DataFormatters/FormatManager.cpp @@ -551,10 +551,6 @@ return true; } -ConstString FormatManager::GetValidTypeName(ConstString type) { - return ::GetValidTypeName_Impl(type); -} - ConstString FormatManager::GetTypeForCache(ValueObject &valobj, lldb::DynamicValueType use_dynamic) { ValueObjectSP valobj_sp = valobj.GetQualifiedRepresentationIfAvailable(