Index: lldb/include/lldb/Symbol/SymbolFile.h =================================================================== --- lldb/include/lldb/Symbol/SymbolFile.h +++ lldb/include/lldb/Symbol/SymbolFile.h @@ -189,8 +189,8 @@ bool append, uint32_t max_matches, llvm::DenseSet &searched_symbol_files, TypeMap &types); - virtual size_t FindTypes(const std::vector &context, - bool append, TypeMap &types); + virtual size_t FindTypes(CompilerContextPattern context, bool append, + TypeMap &types); virtual void GetMangledNamesForFunction(const std::string &scope_qualified_name, Index: lldb/include/lldb/Symbol/Type.h =================================================================== --- lldb/include/lldb/Symbol/Type.h +++ lldb/include/lldb/Symbol/Type.h @@ -22,22 +22,32 @@ #include namespace lldb_private { -// CompilerContext allows an array of these items to be passed to perform -// detailed lookups in SymbolVendor and SymbolFile functions. + +/// CompilerContext allows an array of these items to be passed to perform +/// detailed lookups in SymbolVendor and SymbolFile functions. struct CompilerContext { - CompilerContext(CompilerContextKind t, ConstString n) - : type(t), name(n) {} + CompilerContext(CompilerContextKind t, ConstString n) : kind(t), name(n) {} bool operator==(const CompilerContext &rhs) const { - return type == rhs.type && name == rhs.name; + return kind == rhs.kind && name == rhs.name; } + bool operator!=(const CompilerContext &rhs) const { return !(*this == rhs); } void Dump() const; - CompilerContextKind type; + CompilerContextKind kind; ConstString name; }; +/// An array of CompilerContexts. +struct CompilerContextPattern : public llvm::ArrayRef { + CompilerContextPattern(llvm::ArrayRef array); + /// Match this context pattern (which may contain "Any" kinds) + /// against the context chain of a type. Note that \p context_chain + /// should *not* contain any "Any" kinds. + bool matches(CompilerContextPattern context_chain) const; +}; + class SymbolFileType : public std::enable_shared_from_this, public UserID { public: Index: lldb/include/lldb/lldb-private-enumerations.h =================================================================== --- lldb/include/lldb/lldb-private-enumerations.h +++ lldb/include/lldb/lldb-private-enumerations.h @@ -198,18 +198,24 @@ enum class TypeValidatorResult : bool { Success = true, Failure = false }; // Enumerations that can be used to specify scopes types when looking up types. -enum class CompilerContextKind { +enum class CompilerContextKind : uint16_t { Invalid = 0, - TranslationUnit, - Module, - Namespace, - Class, - Structure, - Union, - Function, - Variable, - Enumeration, - Typedef + TranslationUnit = 1, + Module = 1 << 1, + Namespace = 1 << 2, + Class = 1 << 3, + Struct = 1 << 4, + Union = 1 << 5, + Function = 1 << 6, + Variable = 1 << 7, + Enum = 1 << 8, + Typedef = 1 << 9, + + Any = 1 << 15, + /// Match 0..n nested modules. + AnyModule = Any | Module, + /// Match any type. + AnyType = Any | Class | Struct | Union | Enum | Typedef }; // Enumerations that can be used to specify the kind of metric we're looking at Index: lldb/lit/SymbolFile/DWARF/compilercontext.ll =================================================================== --- lldb/lit/SymbolFile/DWARF/compilercontext.ll +++ lldb/lit/SymbolFile/DWARF/compilercontext.ll @@ -1,8 +1,22 @@ ; Test finding types by CompilerContext. ; RUN: llc %s -filetype=obj -o %t.o -; RUN: lldb-test symbols %t.o -find=type -compiler-context="Module:CModule,Module:SubModule,Structure:FromSubmodule" | FileCheck %s -; +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="Module:CModule,Module:SubModule,Struct:FromSubmoduleX" \ +; RUN: | FileCheck %s --check-prefix=NORESULTS +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="Module:CModule,Module:SubModule,Struct:FromSubmodule" \ +; RUN: | FileCheck %s +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="Module:CModule,AnyModule:*,Struct:FromSubmodule" \ +; RUN: | FileCheck %s +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="AnyModule:*,Struct:FromSubmodule" \ +; RUN: | FileCheck %s +; RUN: lldb-test symbols %t.o -find=type \ +; RUN: -compiler-context="Module:CModule,Module:SubModule,AnyType:FromSubmodule" \ +; RUN: | FileCheck %s ; +; NORESULTS: Found 0 types ; CHECK: Found 1 types: ; CHECK: struct FromSubmodule { ; CHECK-NEXT: unsigned int x; Index: lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h =================================================================== --- lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -116,7 +116,7 @@ llvm::DenseSet &searched_symbol_files, TypeMap &types) override; - size_t FindTypes(const std::vector &context, bool append, + size_t FindTypes(CompilerContextPattern context, bool append, TypeMap &types) override; llvm::Expected Index: lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -318,9 +318,8 @@ return types.GetSize(); } -size_t -SymbolFileBreakpad::FindTypes(const std::vector &context, - bool append, TypeMap &types) { +size_t SymbolFileBreakpad::FindTypes(CompilerContextPattern context, + bool append, TypeMap &types) { if (!append) types.Clear(); return types.GetSize(); Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -144,11 +144,11 @@ // If this type comes from a Clang module, look in the DWARF section // of the pcm file in the module cache. Clang generates DWO skeleton // units as breadcrumbs to find them. - std::vector decl_context; + llvm::SmallVector decl_context; die.GetDeclContext(decl_context); TypeMap dwo_types; - if (!dwo_module_sp->GetSymbolFile()->FindTypes(decl_context, true, + if (!dwo_module_sp->GetSymbolFile()->FindTypes({decl_context}, true, dwo_types)) { if (!IsClangModuleFwdDecl(die)) return TypeSP(); @@ -159,7 +159,7 @@ for (const auto &name_module : sym_file.getExternalTypeModules()) { if (!name_module.second) continue; - if (name_module.second->GetSymbolFile()->FindTypes(decl_context, true, + if (name_module.second->GetSymbolFile()->FindTypes({decl_context}, true, dwo_types)) break; } Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -78,8 +78,8 @@ /// Return this DIE's decl context as it is needed to look up types /// in Clang's -gmodules debug info format. - void - GetDeclContext(std::vector &context) const; + void GetDeclContext( + llvm::SmallVectorImpl &context) const; // Getting attribute values from the DIE. // Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -342,7 +342,8 @@ } } -void DWARFDIE::GetDeclContext(std::vector &context) const { +void DWARFDIE::GetDeclContext( + llvm::SmallVectorImpl &context) const { const dw_tag_t tag = Tag(); if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) return; @@ -351,40 +352,33 @@ parent.GetDeclContext(context); switch (tag) { case DW_TAG_module: - context.push_back( - CompilerContext(CompilerContextKind::Module, ConstString(GetName()))); + context.push_back({CompilerContextKind::Module, ConstString(GetName())}); break; case DW_TAG_namespace: - context.push_back(CompilerContext(CompilerContextKind::Namespace, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Namespace, ConstString(GetName())}); break; case DW_TAG_structure_type: - context.push_back(CompilerContext(CompilerContextKind::Structure, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Struct, ConstString(GetName())}); break; case DW_TAG_union_type: - context.push_back( - CompilerContext(CompilerContextKind::Union, ConstString(GetName()))); + context.push_back({CompilerContextKind::Union, ConstString(GetName())}); break; case DW_TAG_class_type: - context.push_back( - CompilerContext(CompilerContextKind::Class, ConstString(GetName()))); + context.push_back({CompilerContextKind::Class, ConstString(GetName())}); break; case DW_TAG_enumeration_type: - context.push_back(CompilerContext(CompilerContextKind::Enumeration, - ConstString(GetName()))); + context.push_back({CompilerContextKind::Enum, ConstString(GetName())}); break; case DW_TAG_subprogram: - context.push_back(CompilerContext(CompilerContextKind::Function, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Function, ConstString(GetPubname())}); break; case DW_TAG_variable: - context.push_back(CompilerContext(CompilerContextKind::Variable, - ConstString(GetPubname()))); + context.push_back( + {CompilerContextKind::Variable, ConstString(GetPubname())}); break; case DW_TAG_typedef: - context.push_back( - CompilerContext(CompilerContextKind::Typedef, ConstString(GetName()))); + context.push_back({CompilerContextKind::Typedef, ConstString(GetName())}); break; default: break; Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -184,8 +184,8 @@ llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector &context, - bool append, lldb_private::TypeMap &types) override; + size_t FindTypes(lldb_private::CompilerContextPattern context, bool append, + lldb_private::TypeMap &types) override; size_t GetTypes(lldb_private::SymbolContextScope *sc_scope, lldb::TypeClass type_mask, Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2484,8 +2484,8 @@ return num_die_matches; } -size_t SymbolFileDWARF::FindTypes(const std::vector &context, - bool append, TypeMap &types) { +size_t SymbolFileDWARF::FindTypes(CompilerContextPattern context, bool append, + TypeMap &types) { std::lock_guard guard(GetModuleMutex()); if (!append) types.Clear(); @@ -2508,9 +2508,9 @@ DWARFDIE die = GetDIE(die_ref); if (die) { - std::vector die_context; + llvm::SmallVector die_context; die.GetDeclContext(die_context); - if (die_context != context) + if (!context.matches({die_context})) continue; Type *matching_type = ResolveType(die, true, true); Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h =================================================================== --- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -134,7 +134,7 @@ llvm::DenseSet &searched_symbol_files, TypeMap &types) override; - size_t FindTypes(const std::vector &context, bool append, + size_t FindTypes(CompilerContextPattern context, bool append, TypeMap &types) override; llvm::Expected Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1269,9 +1269,8 @@ return match_count; } -size_t -SymbolFileNativePDB::FindTypes(const std::vector &context, - bool append, TypeMap &types) { +size_t SymbolFileNativePDB::FindTypes(CompilerContextPattern context, + bool append, TypeMap &types) { return 0; } Index: lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h =================================================================== --- lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -132,8 +132,8 @@ llvm::DenseSet &searched_symbol_files, lldb_private::TypeMap &types) override; - size_t FindTypes(const std::vector &context, - bool append, lldb_private::TypeMap &types) override; + size_t FindTypes(lldb_private::CompilerContextPattern context, bool append, + lldb_private::TypeMap &types) override; void FindTypesByRegex(const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types); Index: lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1584,9 +1584,8 @@ } } -size_t SymbolFilePDB::FindTypes( - const std::vector &contexts, bool append, - lldb_private::TypeMap &types) { +size_t SymbolFilePDB::FindTypes(CompilerContextPattern contexts, bool append, + lldb_private::TypeMap &types) { return 0; } Index: lldb/source/Symbol/SymbolFile.cpp =================================================================== --- lldb/source/Symbol/SymbolFile.cpp +++ lldb/source/Symbol/SymbolFile.cpp @@ -149,8 +149,8 @@ return 0; } -size_t SymbolFile::FindTypes(const std::vector &context, - bool append, TypeMap &types) { +size_t SymbolFile::FindTypes(CompilerContextPattern context, bool append, + TypeMap &types) { if (!append) types.Clear(); return 0; Index: lldb/source/Symbol/Type.cpp =================================================================== --- lldb/source/Symbol/Type.cpp +++ lldb/source/Symbol/Type.cpp @@ -36,9 +36,45 @@ using namespace lldb; using namespace lldb_private; +CompilerContextPattern::CompilerContextPattern( + llvm::ArrayRef array) + : llvm::ArrayRef(array) {} + +bool CompilerContextPattern::matches( + CompilerContextPattern context_chain) const { + auto it = context_chain.begin(); + for (CompilerContext pattern : *this) { + // Early exit if the pattern is too long. + if (it == end()) + return false; + if (*it != pattern) { + // Skip any number of module matches. + if (pattern.kind == CompilerContextKind::AnyModule) { + // Eat any additional module matches. + if (it->kind == CompilerContextKind::Module) + while (std::next(it) != end() && + std::next(it)->kind == CompilerContextKind::Module) + ++it; + else + // Zero module matches, apply the next pattern on this element. + continue; + } + // See if there is a kind mismatch; they should have 1 bit in common. + if (((uint16_t)it->kind & (uint16_t)pattern.kind) == 0) + return false; + // The name is ignored for AnyModule, but not for AnyType. + if (pattern.kind != CompilerContextKind::AnyModule && + it->name != pattern.name) + return false; + } + ++it; + } + return true; +} + void CompilerContext::Dump() const { - switch (type) { - case CompilerContextKind::Invalid: + switch (kind) { + default: printf("Invalid"); break; case CompilerContextKind::TranslationUnit: @@ -53,7 +89,7 @@ case CompilerContextKind::Class: printf("Class"); break; - case CompilerContextKind::Structure: + case CompilerContextKind::Struct: printf("Structure"); break; case CompilerContextKind::Union: @@ -65,12 +101,18 @@ case CompilerContextKind::Variable: printf("Variable"); break; - case CompilerContextKind::Enumeration: + case CompilerContextKind::Enum: printf("Enumeration"); break; case CompilerContextKind::Typedef: printf("Typedef"); break; + case CompilerContextKind::AnyModule: + printf("AnyModule"); + break; + case CompilerContextKind::AnyType: + printf("AnyType"); + break; } printf("(\"%s\")\n", name.GetCString()); } Index: lldb/tools/lldb-test/lldb-test.cpp =================================================================== --- lldb/tools/lldb-test/lldb-test.cpp +++ lldb/tools/lldb-test/lldb-test.cpp @@ -242,12 +242,14 @@ .Case("Module", CompilerContextKind::Module) .Case("Namespace", CompilerContextKind::Namespace) .Case("Class", CompilerContextKind::Class) - .Case("Structure", CompilerContextKind::Structure) + .Case("Struct", CompilerContextKind::Struct) .Case("Union", CompilerContextKind::Union) .Case("Function", CompilerContextKind::Function) .Case("Variable", CompilerContextKind::Variable) - .Case("Enumeration", CompilerContextKind::Enumeration) + .Case("Enum", CompilerContextKind::Enum) .Case("Typedef", CompilerContextKind::Typedef) + .Case("AnyModule", CompilerContextKind::AnyModule) + .Case("AnyType", CompilerContextKind::AnyType) .Default(CompilerContextKind::Invalid); if (value.empty()) { WithColor::error() << "compiler context entry has no \"name\"\n"; @@ -511,7 +513,7 @@ Symfile.FindTypes(ConstString(Name), ContextPtr, true, UINT32_MAX, SearchedFiles, Map); else - Symfile.FindTypes(parseCompilerContext(), true, Map); + Symfile.FindTypes({parseCompilerContext()}, true, Map); outs() << formatv("Found {0} types:\n", Map.GetSize()); StreamString Stream; Index: lldb/unittests/Symbol/TestType.cpp =================================================================== --- lldb/unittests/Symbol/TestType.cpp +++ lldb/unittests/Symbol/TestType.cpp @@ -48,3 +48,47 @@ "std::set>::iterator", true, "std::set>::", "iterator"); } + +TEST(Type, CompilerContextPattern) { + std::vector mms = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Struct, ConstString("S")}}; + EXPECT_TRUE(CompilerContextPattern(mms).matches({mms})); + std::vector mmc = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Class, ConstString("S")}}; + EXPECT_FALSE(CompilerContextPattern(mms).matches({mmc})); + std::vector ms = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Struct, ConstString("S")}}; + std::vector mas = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::AnyModule, ConstString("*")}, + {CompilerContextKind::Struct, ConstString("S")}}; + EXPECT_TRUE(CompilerContextPattern(mas).matches({mms})); + EXPECT_TRUE(CompilerContextPattern(mas).matches({ms})); + EXPECT_FALSE(CompilerContextPattern(ms).matches({mas})); + std::vector mmms = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Module, ConstString("C")}, + {CompilerContextKind::Struct, ConstString("S")}}; + EXPECT_TRUE(CompilerContextPattern(mas).matches({mmms})); + std::vector mme = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Enum, ConstString("S")}}; + std::vector mma = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::AnyType, ConstString("S")}}; + EXPECT_TRUE(CompilerContextPattern(mma).matches({mme})); + EXPECT_TRUE(CompilerContextPattern(mma).matches({mms})); + std::vector mme2 = { + {CompilerContextKind::Module, ConstString("A")}, + {CompilerContextKind::Module, ConstString("B")}, + {CompilerContextKind::Enum, ConstString("S2")}}; + EXPECT_FALSE(CompilerContextPattern(mma).matches({mme2})); +}