aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/Module.h77
-rw-r--r--lldb/include/lldb/Core/ModuleList.h24
-rw-r--r--lldb/include/lldb/Symbol/CompilerDecl.h7
-rw-r--r--lldb/include/lldb/Symbol/CompilerDeclContext.h8
-rw-r--r--lldb/include/lldb/Symbol/SymbolFile.h29
-rw-r--r--lldb/include/lldb/Symbol/SymbolFileOnDemand.h13
-rw-r--r--lldb/include/lldb/Symbol/Type.h305
-rw-r--r--lldb/include/lldb/Symbol/TypeMap.h6
-rw-r--r--lldb/include/lldb/Symbol/TypeSystem.h24
-rw-r--r--lldb/include/lldb/lldb-forward.h2
-rw-r--r--lldb/include/lldb/lldb-private-enumerations.h5
-rw-r--r--lldb/source/API/SBModule.cpp54
-rw-r--r--lldb/source/API/SBTarget.cpp38
-rw-r--r--lldb/source/Commands/CommandObjectMemory.cpp23
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp51
-rw-r--r--lldb/source/Core/Module.cpp94
-rw-r--r--lldb/source/Core/ModuleList.cpp37
-rw-r--r--lldb/source/DataFormatters/TypeFormat.cpp11
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp97
-rw-r--r--lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp30
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp15
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp9
-rw-r--r--lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h9
-rw-r--r--lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp23
-rw-r--r--lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h8
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp32
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp48
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h15
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp270
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h10
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp23
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h9
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp37
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h10
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp59
-rw-r--r--lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h15
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp151
-rw-r--r--lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h8
-rw-r--r--lldb/source/Symbol/CompilerDecl.cpp5
-rw-r--r--lldb/source/Symbol/CompilerDeclContext.cpp7
-rw-r--r--lldb/source/Symbol/SymbolFile.cpp11
-rw-r--r--lldb/source/Symbol/SymbolFileOnDemand.cpp23
-rw-r--r--lldb/source/Symbol/Type.cpp146
-rw-r--r--lldb/source/Symbol/TypeMap.cpp14
-rw-r--r--lldb/source/Symbol/TypeSystem.cpp10
-rw-r--r--lldb/source/Target/Language.cpp10
-rw-r--r--lldb/test/API/functionalities/type_find_first/Makefile2
-rw-r--r--lldb/test/API/functionalities/type_find_first/TestFindFirstType.py38
-rw-r--r--lldb/test/API/functionalities/type_find_first/main.cpp17
-rw-r--r--lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py21
-rw-r--r--lldb/test/API/lang/cpp/unique-types4/main.cpp4
-rw-r--r--lldb/tools/lldb-test/lldb-test.cpp48
52 files changed, 1135 insertions, 907 deletions
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index 2973ee0..f4973cd 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -415,70 +415,19 @@ public:
void FindGlobalVariables(const RegularExpression &regex, size_t max_matches,
VariableList &variable_list);
- /// Find types by name.
- ///
- /// Type lookups in modules go through the SymbolFile. The SymbolFile needs to
- /// be able to lookup types by basename and not the fully qualified typename.
- /// This allows the type accelerator tables to stay small, even with heavily
- /// templatized C++. The type search will then narrow down the search
- /// results. If "exact_match" is true, then the type search will only match
- /// exact type name matches. If "exact_match" is false, the type will match
- /// as long as the base typename matches and as long as any immediate
- /// containing namespaces/class scopes that are specified match. So to
- /// search for a type "d" in "b::c", the name "b::c::d" can be specified and
- /// it will match any class/namespace "b" which contains a class/namespace
- /// "c" which contains type "d". We do this to allow users to not always
- /// have to specify complete scoping on all expressions, but it also allows
- /// for exact matching when required.
- ///
- /// \param[in] type_name
- /// The name of the type we are looking for that is a fully
- /// or partially qualified type name.
- ///
- /// \param[in] exact_match
- /// If \b true, \a type_name is fully qualified and must match
- /// exactly. If \b false, \a type_name is a partially qualified
- /// name where the leading namespaces or classes can be
- /// omitted to make finding types that a user may type
- /// easier.
- ///
- /// \param[out] types
- /// A type list gets populated with any matches.
+ /// Find types using a type-matching object that contains all search
+ /// parameters.
///
- void
- FindTypes(ConstString type_name, bool exact_match, size_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeList &types);
-
- /// Find types by name.
- ///
- /// This behaves like the other FindTypes method but allows to
- /// specify a DeclContext and a language for the type being searched
- /// for.
- ///
- /// \param searched_symbol_files
- /// Prevents one file from being visited multiple times.
- void
- FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types);
-
- lldb::TypeSP FindFirstType(const SymbolContext &sc, ConstString type_name,
- bool exact_match);
-
- /// Find types by name that are in a namespace. This function is used by the
- /// expression parser when searches need to happen in an exact namespace
- /// scope.
+ /// \see lldb_private::TypeQuery
///
- /// \param[in] type_name
- /// The name of a type within a namespace that should not include
- /// any qualifying namespaces (just a type basename).
+ /// \param[in] query
+ /// A type matching object that contains all of the details of the type
+ /// search.
///
- /// \param[out] type_list
- /// A type list gets populated with any matches.
- void FindTypesInNamespace(ConstString type_name,
- const CompilerDeclContext &parent_decl_ctx,
- size_t max_matches, TypeList &type_list);
+ /// \param[in] results
+ /// Any matching types will be populated into the \a results object using
+ /// TypeMap::InsertUnique(...).
+ void FindTypes(const TypeQuery &query, TypeResults &results);
/// Get const accessor for the module architecture.
///
@@ -1122,12 +1071,6 @@ protected:
private:
Module(); // Only used internally by CreateJITModule ()
- void FindTypes_Impl(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- size_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types);
-
Module(const Module &) = delete;
const Module &operator=(const Module &) = delete;
diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h
index 9826dd0..d78f7c5 100644
--- a/lldb/include/lldb/Core/ModuleList.h
+++ b/lldb/include/lldb/Core/ModuleList.h
@@ -340,26 +340,22 @@ public:
lldb::SymbolType symbol_type,
SymbolContextList &sc_list) const;
- /// Find types by name.
+ /// Find types using a type-matching object that contains all search
+ /// parameters.
///
/// \param[in] search_first
/// If non-null, this module will be searched before any other
/// modules.
///
- /// \param[in] name
- /// The name of the type we are looking for.
- ///
- /// \param[in] max_matches
- /// Allow the number of matches to be limited to \a
- /// max_matches. Specify UINT32_MAX to get all possible matches.
- ///
- /// \param[out] types
- /// A type list gets populated with any matches.
+ /// \param[in] query
+ /// A type matching object that contains all of the details of the type
+ /// search.
///
- void FindTypes(Module *search_first, ConstString name,
- bool name_is_fully_qualified, size_t max_matches,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeList &types) const;
+ /// \param[in] results
+ /// Any matching types will be populated into the \a results object using
+ /// TypeMap::InsertUnique(...).
+ void FindTypes(Module *search_first, const TypeQuery &query,
+ lldb_private::TypeResults &results) const;
bool FindSourceFile(const FileSpec &orig_spec, FileSpec &new_spec) const;
diff --git a/lldb/include/lldb/Symbol/CompilerDecl.h b/lldb/include/lldb/Symbol/CompilerDecl.h
index 67290b9..825a4f1 100644
--- a/lldb/include/lldb/Symbol/CompilerDecl.h
+++ b/lldb/include/lldb/Symbol/CompilerDecl.h
@@ -84,6 +84,13 @@ public:
// based argument index
CompilerType GetFunctionArgumentType(size_t arg_idx) const;
+ /// Populate a valid compiler context from the current declaration.
+ ///
+ /// \returns A valid vector of CompilerContext entries that describes
+ /// this declaration. The first entry in the vector is the parent of
+ /// the subsequent entry, so the topmost entry is the global namespace.
+ std::vector<lldb_private::CompilerContext> GetCompilerContext() const;
+
private:
TypeSystem *m_type_system = nullptr;
void *m_opaque_decl = nullptr;
diff --git a/lldb/include/lldb/Symbol/CompilerDeclContext.h b/lldb/include/lldb/Symbol/CompilerDeclContext.h
index 61a9c9c..89b4a97 100644
--- a/lldb/include/lldb/Symbol/CompilerDeclContext.h
+++ b/lldb/include/lldb/Symbol/CompilerDeclContext.h
@@ -11,6 +11,7 @@
#include <vector>
+#include "lldb/Symbol/Type.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
@@ -56,6 +57,13 @@ public:
return m_type_system != nullptr && m_opaque_decl_ctx != nullptr;
}
+ /// Populate a valid compiler context from the current decl context.
+ ///
+ /// \returns A valid vector of CompilerContext entries that describes
+ /// this declaration context. The first entry in the vector is the parent of
+ /// the subsequent entry, so the topmost entry is the global namespace.
+ std::vector<lldb_private::CompilerContext> GetCompilerContext() const;
+
std::vector<CompilerDecl> FindDeclByName(ConstString name,
const bool ignore_using_decls);
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h
index a546b05..c9a2a64 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -301,21 +301,20 @@ public:
bool include_inlines, SymbolContextList &sc_list);
virtual void FindFunctions(const RegularExpression &regex,
bool include_inlines, SymbolContextList &sc_list);
- virtual void
- FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types);
-
- /// Find types specified by a CompilerContextPattern.
- /// \param languages
- /// Only return results in these languages.
- /// \param searched_symbol_files
- /// Prevents one file from being visited multiple times.
- virtual void
- FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types);
+
+ /// Find types using a type-matching object that contains all search
+ /// parameters.
+ ///
+ /// \see lldb_private::TypeQuery
+ ///
+ /// \param[in] query
+ /// A type matching object that contains all of the details of the type
+ /// search.
+ ///
+ /// \param[in] results
+ /// Any matching types will be populated into the \a results object using
+ /// TypeMap::InsertUnique(...).
+ virtual void FindTypes(const TypeQuery &query, TypeResults &results) {}
virtual void
GetMangledNamesForFunction(const std::string &scope_qualified_name,
diff --git a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h
index 9cbcef2..cde9f3c 100644
--- a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h
+++ b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h
@@ -152,17 +152,8 @@ public:
const std::string &scope_qualified_name,
std::vector<lldb_private::ConstString> &mangled_names) override;
- void
- FindTypes(lldb_private::ConstString name,
- const lldb_private::CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- lldb_private::TypeMap &types) override;
-
- void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
- lldb_private::LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- lldb_private::TypeMap &types) override;
+ void FindTypes(const lldb_private::TypeQuery &query,
+ lldb_private::TypeResults &results) override;
void GetTypes(lldb_private::SymbolContextScope *sc_scope,
lldb::TypeClass type_mask,
diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h
index 15edbea..307be6c 100644
--- a/lldb/include/lldb/Symbol/Type.h
+++ b/lldb/include/lldb/Symbol/Type.h
@@ -12,11 +12,15 @@
#include "lldb/Core/Declaration.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/DenseSet.h"
#include <optional>
#include <set>
@@ -24,6 +28,23 @@
namespace lldb_private {
class SymbolFileCommon;
+/// A SmallBitVector that represents a set of source languages (\p
+/// lldb::LanguageType). Each lldb::LanguageType is represented by
+/// the bit with the position of its enumerator. The largest
+/// LanguageType is < 64, so this is space-efficient and on 64-bit
+/// architectures a LanguageSet can be completely stack-allocated.
+struct LanguageSet {
+ llvm::SmallBitVector bitvector;
+ LanguageSet();
+
+ /// If the set contains a single language only, return it.
+ std::optional<lldb::LanguageType> GetSingularLanguage();
+ void Insert(lldb::LanguageType language);
+ bool Empty() const;
+ size_t Size() const;
+ bool operator[](unsigned i) const;
+};
+
/// CompilerContext allows an array of these items to be passed to perform
/// detailed lookups in SymbolVendor and SymbolFile functions.
struct CompilerContext {
@@ -45,6 +66,290 @@ struct CompilerContext {
bool contextMatches(llvm::ArrayRef<CompilerContext> context_chain,
llvm::ArrayRef<CompilerContext> pattern);
+FLAGS_ENUM(TypeQueryOptions){
+ e_none = 0u,
+ /// If set, TypeQuery::m_context contains an exact context that must match
+ /// the full context. If not set, TypeQuery::m_context can contain a partial
+ /// type match where the full context isn't fully specified.
+ e_exact_match = (1u << 0),
+ /// If set, TypeQuery::m_context is a clang module compiler context. If not
+ /// set TypeQuery::m_context is normal type lookup context.
+ e_module_search = (1u << 1),
+ /// When true, the find types call should stop the query as soon as a single
+ /// matching type is found. When false, the type query should find all
+ /// matching types.
+ e_find_one = (1u << 2),
+};
+LLDB_MARK_AS_BITMASK_ENUM(TypeQueryOptions)
+
+/// A class that contains all state required for type lookups.
+///
+/// Using a TypeQuery class for matching types simplifies the internal APIs we
+/// need to implement type lookups in LLDB. Type lookups can fully specify the
+/// exact typename by filling out a complete or partial CompilerContext array.
+/// This technique allows for powerful searches and also allows the SymbolFile
+/// classes to use the m_context array to lookup types by basename, then
+/// eliminate potential matches without having to resolve types into each
+/// TypeSystem. This makes type lookups vastly more efficient and allows the
+/// SymbolFile objects to stop looking up types when the type matching is
+/// complete, like if we are looking for only a single type in our search.
+class TypeQuery {
+public:
+ TypeQuery() = delete;
+
+ /// Construct a type match object using a fully- or partially-qualified name.
+ ///
+ /// The specified \a type_name will be chopped up and the m_context will be
+ /// populated by separating the string by looking for "::". We do this because
+ /// symbol files have indexes that contain only the type's basename. This also
+ /// allows symbol files to efficiently not realize types that don't match the
+ /// specified context. Example of \a type_name values that can be specified
+ /// include:
+ /// "foo": Look for any type whose basename matches "foo".
+ /// If \a exact_match is true, then the type can't be contained in any
+ /// declaration context like a namespace, class, or other containing
+ /// scope.
+ /// If \a exact match is false, then we will find all matches including
+ /// ones that are contained in other declaration contexts, including top
+ /// level types.
+ /// "foo::bar": Look for any type whose basename matches "bar" but make sure
+ /// its parent declaration context is any named declaration context
+ /// (namespace, class, struct, etc) whose name matches "foo".
+ /// If \a exact_match is true, then the "foo" declaration context must
+ /// appear at the source file level or inside of a function.
+ /// If \a exact match is false, then the "foo" declaration context can
+ /// be contained in any other declaration contexts.
+ /// "class foo": Only match types that are classes whose basename matches
+ /// "foo".
+ /// "struct foo": Only match types that are structures whose basename
+ /// matches "foo".
+ /// "class foo::bar": Only match types that are classes whose basename
+ /// matches "bar" and that are contained in any named declaration context
+ /// named "foo".
+ ///
+ /// \param[in] type_name
+ /// A fully- or partially-qualified type name. This name will be parsed and
+ /// broken up and the m_context will be populated with the various parts of
+ /// the name. This typename can be prefixed with "struct ", "class ",
+ /// "union", "enum " or "typedef " before the actual type name to limit the
+ /// results of the types that match. The declaration context can be
+ /// specified with the "::" string. For example, "a::b::my_type".
+ ///
+ /// \param[in] options A set of boolean enumeration flags from the
+ /// TypeQueryOptions enumerations. \see TypeQueryOptions.
+ TypeQuery(llvm::StringRef name, TypeQueryOptions options = e_none);
+
+ /// Construct a type-match object that matches a type basename that exists
+ /// in the specified declaration context.
+ ///
+ /// This allows the m_context to be first populated using a declaration
+ /// context to exactly identify the containing declaration context of a type.
+ /// This can be used when you have a forward declaration to a type and you
+ /// need to search for its complete type.
+ ///
+ /// \param[in] decl_ctx
+ /// A declaration context object that comes from a TypeSystem plug-in. This
+ /// object will be asked to populate the array of CompilerContext objects
+ /// by adding the top most declaration context first into the array and then
+ /// adding any containing declaration contexts.
+ ///
+ /// \param[in] type_basename
+ /// The basename of the type to lookup in the specified declaration context.
+ ///
+ /// \param[in] options A set of boolean enumeration flags from the
+ /// TypeQueryOptions enumerations. \see TypeQueryOptions.
+ TypeQuery(const CompilerDeclContext &decl_ctx, ConstString type_basename,
+ TypeQueryOptions options = e_none);
+ /// Construct a type-match object using a compiler declaration that specifies
+ /// a typename and a declaration context to use when doing exact type lookups.
+ ///
+ /// This allows the m_context to be first populated using a type declaration.
+ /// The type declaration might have a declaration context and each TypeSystem
+ /// plug-in can populate the declaration context needed to perform an exact
+ /// lookup for a type.
+ /// This can be used when you have a forward declaration to a type and you
+ /// need to search for its complete type.
+ ///
+ /// \param[in] decl
+ /// A type declaration context object that comes from a TypeSystem plug-in.
+ /// This object will be asked to full the array of CompilerContext objects
+ /// by adding the top most declaration context first into the array and then
+ /// adding any containing declaration contexts, and ending with the exact
+ /// typename and the kind of type it is (class, struct, union, enum, etc).
+ ///
+ /// \param[in] options A set of boolean enumeration flags from the
+ /// TypeQueryOptions enumerations. \see TypeQueryOptions.
+ TypeQuery(const CompilerDecl &decl, TypeQueryOptions options = e_none);
+
+ /// Construct a type-match object using a CompilerContext array.
+ ///
+ /// Clients can manually create compiler contexts and use these to find
+ /// matches when searching for types. There are two types of contexts that
+ /// are supported when doing type searchs: type contexts and clang module
+ /// contexts. Type contexts have contexts that specify the type and its
+ /// containing declaration context like namespaces and classes. Clang module
+ /// contexts specify contexts more completely to find exact matches within
+ /// clang module debug information. They will include the modules that the
+ /// type is included in and any functions that the type might be defined in.
+ /// This allows very fine-grained type resolution.
+ ///
+ /// \param[in] context The compiler context to use when doing the search.
+ ///
+ /// \param[in] options A set of boolean enumeration flags from the
+ /// TypeQueryOptions enumerations. \see TypeQueryOptions.
+ TypeQuery(const llvm::ArrayRef<lldb_private::CompilerContext> &context,
+ TypeQueryOptions options = e_none);
+
+ /// Construct a type-match object that duplicates all matching criterea,
+ /// but not any searched symbol files or the type map for matches. This allows
+ /// the m_context to be modified prior to performing another search.
+ TypeQuery(const TypeQuery &rhs) = default;
+ /// Assign a type-match object that duplicates all matching criterea,
+ /// but not any searched symbol files or the type map for matches. This allows
+ /// the m_context to be modified prior to performing another search.
+ TypeQuery &operator=(const TypeQuery &rhs) = default;
+
+ /// Check of a CompilerContext array from matching type from a symbol file
+ /// matches the \a m_context.
+ ///
+ /// \param[in] context
+ /// A fully qualified CompilerContext array for a potential match that is
+ /// created by the symbol file prior to trying to actually resolve a type.
+ ///
+ /// \returns
+ /// True if the context matches, false if it doesn't. If e_exact_match
+ /// is set in m_options, then \a context must exactly match \a m_context. If
+ /// e_exact_match is not set, then the bottom m_context.size() objects in
+ /// \a context must match. This allows SymbolFile objects the fill in a
+ /// potential type basename match from the index into \a context, and see if
+ /// it matches prior to having to resolve a lldb_private::Type object for
+ /// the type from the index. This allows type parsing to be as efficient as
+ /// possible and only realize the types that match the query.
+ bool
+ ContextMatches(llvm::ArrayRef<lldb_private::CompilerContext> context) const;
+
+ /// Get the type basename to use when searching the type indexes in each
+ /// SymbolFile object.
+ ///
+ /// Debug information indexes often contain indexes that track the basename
+ /// of types only, not a fully qualified path. This allows the indexes to be
+ /// smaller and allows for efficient lookups.
+ ///
+ /// \returns
+ /// The type basename to use when doing lookups as a constant string.
+ ConstString GetTypeBasename() const;
+
+ /// Returns true if any matching languages have been specified in this type
+ /// matching object.
+ bool HasLanguage() const { return m_languages.has_value(); }
+
+ /// Add a language family to the list of languages that should produce a
+ /// match.
+ void AddLanguage(lldb::LanguageType language);
+
+ /// Check if the language matches any languages that have been added to this
+ /// match object.
+ ///
+ /// \returns
+ /// True if no language have been specified, or if some language have been
+ /// added using AddLanguage(...) and they match. False otherwise.
+ bool LanguageMatches(lldb::LanguageType language) const;
+
+ bool GetExactMatch() const { return (m_options & e_exact_match) != 0; }
+ /// The \a m_context can be used in two ways: normal types searching with
+ /// the context containing a stanadard declaration context for a type, or
+ /// with the context being more complete for exact matches in clang modules.
+ /// Set this to true if you wish to search for a type in clang module.
+ bool GetModuleSearch() const { return (m_options & e_module_search) != 0; }
+
+ /// Returns true if the type query is supposed to find only a single matching
+ /// type. Returns false if the type query should find all matches.
+ bool GetFindOne() const { return (m_options & e_find_one) != 0; }
+ void SetFindOne(bool b) {
+ if (b)
+ m_options |= e_find_one;
+ else
+ m_options &= (e_exact_match | e_find_one);
+ }
+
+ /// Access the internal compiler context array.
+ ///
+ /// Clients can use this to populate the context manually.
+ std::vector<lldb_private::CompilerContext> &GetContextRef() {
+ return m_context;
+ }
+
+protected:
+ /// A full or partial compiler context array where the parent declaration
+ /// contexts appear at the top of the array starting at index zero and the
+ /// last entry contains the type and name of the type we are looking for.
+ std::vector<lldb_private::CompilerContext> m_context;
+ /// An options bitmask that contains enabled options for the type query.
+ /// \see TypeQueryOptions.
+ TypeQueryOptions m_options;
+ /// If this variable has a value, then the language family must match at least
+ /// one of the specified languages. If this variable has no value, then the
+ /// language of the type doesn't need to match any types that are searched.
+ std::optional<LanguageSet> m_languages;
+};
+
+/// This class tracks the state and results of a \ref TypeQuery.
+///
+/// Any mutable state required for type lookups and the results are tracked in
+/// this object.
+class TypeResults {
+public:
+ /// Construct a type results object
+ TypeResults() = default;
+
+ /// When types that match a TypeQuery are found, this API is used to insert
+ /// the matching types.
+ ///
+ /// \return
+ /// True if the type was added, false if the \a type_sp was already in the
+ /// results.
+ bool InsertUnique(const lldb::TypeSP &type_sp);
+
+ /// Check if the type matching has found all of the matches that it needs.
+ bool Done(const TypeQuery &query) const;
+
+ /// Check if a SymbolFile object has already been searched by this type match
+ /// object.
+ ///
+ /// This function will add \a sym_file to the set of SymbolFile objects if it
+ /// isn't already in the set and return \a false. Returns true if \a sym_file
+ /// was already in the set and doesn't need to be searched.
+ ///
+ /// Any clients that search for types should first check that the symbol file
+ /// has not already been searched. If this function returns true, the type
+ /// search function should early return to avoid duplicating type searchihng
+ /// efforts.
+ ///
+ /// \param[in] sym_file
+ /// A SymbolFile pointer that will be used to track which symbol files have
+ /// already been searched.
+ ///
+ /// \returns
+ /// True if the symbol file has been search already, false otherwise.
+ bool AlreadySearched(lldb_private::SymbolFile *sym_file);
+
+ /// Access the set of searched symbol files.
+ llvm::DenseSet<lldb_private::SymbolFile *> &GetSearchedSymbolFiles() {
+ return m_searched_symbol_files;
+ }
+
+ lldb::TypeSP GetFirstType() const { return m_type_map.FirstType(); }
+ TypeMap &GetTypeMap() { return m_type_map; }
+ const TypeMap &GetTypeMap() const { return m_type_map; }
+
+private:
+ /// Matching types get added to this map as type search continues.
+ TypeMap m_type_map;
+ /// This set is used to track and make sure we only perform lookups in a
+ /// symbol file one time.
+ llvm::DenseSet<lldb_private::SymbolFile *> m_searched_symbol_files;
+};
+
class SymbolFileType : public std::enable_shared_from_this<SymbolFileType>,
public UserID {
public:
diff --git a/lldb/include/lldb/Symbol/TypeMap.h b/lldb/include/lldb/Symbol/TypeMap.h
index c200ccb..4337118 100644
--- a/lldb/include/lldb/Symbol/TypeMap.h
+++ b/lldb/include/lldb/Symbol/TypeMap.h
@@ -27,7 +27,7 @@ public:
void Clear();
void Dump(Stream *s, bool show_context,
- lldb::DescriptionLevel level = lldb::eDescriptionLevelFull);
+ lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) const;
TypeMap FindTypes(ConstString name);
@@ -41,10 +41,12 @@ public:
lldb::TypeSP GetTypeAtIndex(uint32_t idx);
+ lldb::TypeSP FirstType() const;
+
typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection;
typedef AdaptedIterable<collection, lldb::TypeSP, map_adapter> TypeIterable;
- TypeIterable Types() { return TypeIterable(m_types); }
+ TypeIterable Types() const { return TypeIterable(m_types); }
void ForEach(
std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const;
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index cd5004a..6382913 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -26,6 +26,7 @@
#include "lldb/Expression/Expression.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
+#include "lldb/Symbol/Type.h"
#include "lldb/lldb-private.h"
class PDBASTParser;
@@ -43,23 +44,6 @@ namespace npdb {
class PdbAstBuilder;
} // namespace npdb
-/// A SmallBitVector that represents a set of source languages (\p
-/// lldb::LanguageType). Each lldb::LanguageType is represented by
-/// the bit with the position of its enumerator. The largest
-/// LanguageType is < 64, so this is space-efficient and on 64-bit
-/// architectures a LanguageSet can be completely stack-allocated.
-struct LanguageSet {
- llvm::SmallBitVector bitvector;
- LanguageSet();
-
- /// If the set contains a single language only, return it.
- std::optional<lldb::LanguageType> GetSingularLanguage();
- void Insert(lldb::LanguageType language);
- bool Empty() const;
- size_t Size() const;
- bool operator[](unsigned i) const;
-};
-
/// Interface for representing a type system.
///
/// Implemented by language plugins to define the type system for a given
@@ -122,6 +106,9 @@ public:
virtual CompilerType DeclGetFunctionArgumentType(void *opaque_decl,
size_t arg_idx);
+ virtual std::vector<lldb_private::CompilerContext>
+ DeclGetCompilerContext(void *opaque_decl);
+
virtual CompilerType GetTypeForDecl(void *opaque_decl) = 0;
// CompilerDeclContext functions
@@ -146,6 +133,9 @@ public:
virtual CompilerDeclContext
GetCompilerDeclContextForType(const CompilerType &type);
+ virtual std::vector<lldb_private::CompilerContext>
+ DeclContextGetCompilerContext(void *opaque_decl_ctx);
+
// Tests
#ifndef NDEBUG
/// Verify the integrity of the type to catch CompilerTypes that mix
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 068fce4..4e0c62f 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -258,9 +258,11 @@ class TypeImpl;
class TypeList;
class TypeListImpl;
class TypeMap;
+class TypeQuery;
class TypeMemberFunctionImpl;
class TypeMemberImpl;
class TypeNameSpecifierImpl;
+class TypeResults;
class TypeSummaryImpl;
class TypeSummaryOptions;
class TypeSystem;
diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h
index 7f98220..5f15972 100644
--- a/lldb/include/lldb/lldb-private-enumerations.h
+++ b/lldb/include/lldb/lldb-private-enumerations.h
@@ -198,12 +198,15 @@ enum class CompilerContextKind : uint16_t {
Variable = 1 << 7,
Enum = 1 << 8,
Typedef = 1 << 9,
+ Builtin = 1 << 10,
Any = 1 << 15,
/// Match 0..n nested modules.
AnyModule = Any | Module,
/// Match any type.
- AnyType = Any | Class | Struct | Union | Enum | Typedef
+ AnyType = Any | Class | Struct | Union | Enum | Typedef | Builtin,
+ /// Math any declaration context.
+ AnyDeclContext = Any | Namespace | Class | Struct | Union | Enum | Function
};
// Enumerations that can be used to specify the kind of metric we're looking at
diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp
index b865502..262e26c 100644
--- a/lldb/source/API/SBModule.cpp
+++ b/lldb/source/API/SBModule.cpp
@@ -437,26 +437,25 @@ lldb::SBType SBModule::FindFirstType(const char *name_cstr) {
LLDB_INSTRUMENT_VA(this, name_cstr);
ModuleSP module_sp(GetSP());
- if (!name_cstr || !module_sp)
- return {};
- SymbolContext sc;
- const bool exact_match = false;
- ConstString name(name_cstr);
+ if (name_cstr && module_sp) {
+ ConstString name(name_cstr);
+ TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_find_one);
+ TypeResults results;
+ module_sp->FindTypes(query, results);
+ TypeSP type_sp = results.GetFirstType();
+ if (type_sp)
+ return SBType(type_sp);
- SBType sb_type = SBType(module_sp->FindFirstType(sc, name, exact_match));
-
- if (sb_type.IsValid())
- return sb_type;
+ auto type_system_or_err =
+ module_sp->GetTypeSystemForLanguage(eLanguageTypeC);
+ if (auto err = type_system_or_err.takeError()) {
+ llvm::consumeError(std::move(err));
+ return {};
+ }
- auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC);
- if (auto err = type_system_or_err.takeError()) {
- llvm::consumeError(std::move(err));
- return {};
+ if (auto ts = *type_system_or_err)
+ return SBType(ts->GetBuiltinTypeByName(name));
}
-
- if (auto ts = *type_system_or_err)
- return SBType(ts->GetBuiltinTypeByName(name));
-
return {};
}
@@ -471,7 +470,7 @@ lldb::SBType SBModule::GetBasicType(lldb::BasicType type) {
llvm::consumeError(std::move(err));
} else {
if (auto ts = *type_system_or_err)
- return SBType(ts->GetBasicTypeFromAST(type));
+ return SBType(ts->GetBasicTypeFromAST(type));
}
}
return SBType();
@@ -485,13 +484,11 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) {
ModuleSP module_sp(GetSP());
if (type && module_sp) {
TypeList type_list;
- const bool exact_match = false;
- ConstString name(type);
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- module_sp->FindTypes(name, exact_match, UINT32_MAX, searched_symbol_files,
- type_list);
-
- if (type_list.Empty()) {
+ TypeQuery query(type);
+ TypeResults results;
+ module_sp->FindTypes(query, results);
+ if (results.GetTypeMap().Empty()) {
+ ConstString name(type);
auto type_system_or_err =
module_sp->GetTypeSystemForLanguage(eLanguageTypeC);
if (auto err = type_system_or_err.takeError()) {
@@ -502,11 +499,8 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) {
retval.Append(SBType(compiler_type));
}
} else {
- for (size_t idx = 0; idx < type_list.GetSize(); idx++) {
- TypeSP type_sp(type_list.GetTypeAtIndex(idx));
- if (type_sp)
- retval.Append(SBType(type_sp));
- }
+ for (const TypeSP &type_sp : results.GetTypeMap().Types())
+ retval.Append(SBType(type_sp));
}
}
return retval;
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 2d02955..8e616af 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -1804,21 +1804,13 @@ lldb::SBType SBTarget::FindFirstType(const char *typename_cstr) {
TargetSP target_sp(GetSP());
if (typename_cstr && typename_cstr[0] && target_sp) {
ConstString const_typename(typename_cstr);
- SymbolContext sc;
- const bool exact_match = false;
-
- const ModuleList &module_list = target_sp->GetImages();
- size_t count = module_list.GetSize();
- for (size_t idx = 0; idx < count; idx++) {
- ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
- if (module_sp) {
- TypeSP type_sp(
- module_sp->FindFirstType(sc, const_typename, exact_match));
- if (type_sp)
- return SBType(type_sp);
- }
- }
-
+ TypeQuery query(const_typename.GetStringRef(),
+ TypeQueryOptions::e_find_one);
+ TypeResults results;
+ target_sp->GetImages().FindTypes(/*search_first=*/nullptr, query, results);
+ TypeSP type_sp = results.GetFirstType();
+ if (type_sp)
+ return SBType(type_sp);
// Didn't find the type in the symbols; Try the loaded language runtimes.
if (auto process_sp = target_sp->GetProcessSP()) {
for (auto *runtime : process_sp->GetLanguageRuntimes()) {
@@ -1859,17 +1851,11 @@ lldb::SBTypeList SBTarget::FindTypes(const char *typename_cstr) {
if (typename_cstr && typename_cstr[0] && target_sp) {
ModuleList &images = target_sp->GetImages();
ConstString const_typename(typename_cstr);
- bool exact_match = false;
- TypeList type_list;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- images.FindTypes(nullptr, const_typename, exact_match, UINT32_MAX,
- searched_symbol_files, type_list);
-
- for (size_t idx = 0; idx < type_list.GetSize(); idx++) {
- TypeSP type_sp(type_list.GetTypeAtIndex(idx));
- if (type_sp)
- sb_type_list.Append(SBType(type_sp));
- }
+ TypeQuery query(typename_cstr);
+ TypeResults results;
+ images.FindTypes(nullptr, query, results);
+ for (const TypeSP &type_sp : results.GetTypeMap().Types())
+ sb_type_list.Append(SBType(type_sp));
// Try the loaded language runtimes
if (auto process_sp = target_sp->GetProcessSP()) {
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index b02b7de..4ecac73 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -372,8 +372,6 @@ protected:
if (view_as_type_cstr && view_as_type_cstr[0]) {
// We are viewing memory as a type
- const bool exact_match = false;
- TypeList type_list;
uint32_t reference_count = 0;
uint32_t pointer_count = 0;
size_t idx;
@@ -452,18 +450,18 @@ protected:
}
}
- llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
ConstString lookup_type_name(type_str.c_str());
StackFrame *frame = m_exe_ctx.GetFramePtr();
ModuleSP search_first;
- if (frame) {
+ if (frame)
search_first = frame->GetSymbolContext(eSymbolContextModule).module_sp;
- }
- target->GetImages().FindTypes(search_first.get(), lookup_type_name,
- exact_match, 1, searched_symbol_files,
- type_list);
+ TypeQuery query(lookup_type_name.GetStringRef(),
+ TypeQueryOptions::e_find_one);
+ TypeResults results;
+ target->GetImages().FindTypes(search_first.get(), query, results);
+ TypeSP type_sp = results.GetFirstType();
- if (type_list.GetSize() == 0 && lookup_type_name.GetCString()) {
+ if (!type_sp && lookup_type_name.GetCString()) {
LanguageType language_for_type =
m_memory_options.m_language_for_type.GetCurrentValue();
std::set<LanguageType> languages_to_check;
@@ -499,15 +497,14 @@ protected:
}
if (!compiler_type.IsValid()) {
- if (type_list.GetSize() == 0) {
+ if (type_sp) {
+ compiler_type = type_sp->GetFullCompilerType();
+ } else {
result.AppendErrorWithFormat("unable to find any types that match "
"the raw type '%s' for full type '%s'\n",
lookup_type_name.GetCString(),
view_as_type_cstr);
return;
- } else {
- TypeSP type_sp(type_list.GetTypeAtIndex(0));
- compiler_type = type_sp->GetFullCompilerType();
}
}
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 63232c2..bc8bc51 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -1706,16 +1706,18 @@ static size_t LookupTypeInModule(Target *target,
CommandInterpreter &interpreter, Stream &strm,
Module *module, const char *name_cstr,
bool name_is_regex) {
- TypeList type_list;
if (module && name_cstr && name_cstr[0]) {
- const uint32_t max_num_matches = UINT32_MAX;
- bool name_is_fully_qualified = false;
-
- ConstString name(name_cstr);
- llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
- module->FindTypes(name, name_is_fully_qualified, max_num_matches,
- searched_symbol_files, type_list);
+ TypeQuery query(name_cstr);
+ TypeResults results;
+ module->FindTypes(query, results);
+ TypeList type_list;
+ SymbolContext sc;
+ if (module)
+ sc.module_sp = module->shared_from_this();
+ // Sort the type results and put the results that matched in \a module
+ // first if \a module was specified.
+ sc.SortTypeList(results.GetTypeMap(), type_list);
if (type_list.Empty())
return 0;
@@ -1748,22 +1750,21 @@ static size_t LookupTypeInModule(Target *target,
}
strm.EOL();
}
+ return type_list.GetSize();
}
- return type_list.GetSize();
+ return 0;
}
static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter,
Stream &strm, Module &module,
const char *name_cstr, bool name_is_regex) {
+ TypeQuery query(name_cstr);
+ TypeResults results;
+ module.FindTypes(query, results);
TypeList type_list;
- const uint32_t max_num_matches = UINT32_MAX;
- bool name_is_fully_qualified = false;
-
- ConstString name(name_cstr);
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- module.FindTypes(name, name_is_fully_qualified, max_num_matches,
- searched_symbol_files, type_list);
-
+ SymbolContext sc;
+ sc.module_sp = module.shared_from_this();
+ sc.SortTypeList(results.GetTypeMap(), type_list);
if (type_list.Empty())
return 0;
@@ -2082,7 +2083,7 @@ protected:
result.GetOutputStream().EOL();
result.GetOutputStream().EOL();
}
- if (INTERRUPT_REQUESTED(GetDebugger(),
+ if (INTERRUPT_REQUESTED(GetDebugger(),
"Interrupted in dump all symtabs with {0} "
"of {1} dumped.", num_dumped, num_modules))
break;
@@ -2112,8 +2113,8 @@ protected:
result.GetOutputStream().EOL();
result.GetOutputStream().EOL();
}
- if (INTERRUPT_REQUESTED(GetDebugger(),
- "Interrupted in dump symtab list with {0} of {1} dumped.",
+ if (INTERRUPT_REQUESTED(GetDebugger(),
+ "Interrupted in dump symtab list with {0} of {1} dumped.",
num_dumped, num_matches))
break;
@@ -2175,7 +2176,7 @@ protected:
result.GetOutputStream().Format("Dumping sections for {0} modules.\n",
num_modules);
for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
- if (INTERRUPT_REQUESTED(GetDebugger(),
+ if (INTERRUPT_REQUESTED(GetDebugger(),
"Interrupted in dump all sections with {0} of {1} dumped",
image_idx, num_modules))
break;
@@ -2196,7 +2197,7 @@ protected:
FindModulesByName(target, arg_cstr, module_list, true);
if (num_matches > 0) {
for (size_t i = 0; i < num_matches; ++i) {
- if (INTERRUPT_REQUESTED(GetDebugger(),
+ if (INTERRUPT_REQUESTED(GetDebugger(),
"Interrupted in dump section list with {0} of {1} dumped.",
i, num_matches))
break;
@@ -2338,7 +2339,7 @@ protected:
}
for (size_t i = 0; i < num_matches; ++i) {
- if (INTERRUPT_REQUESTED(GetDebugger(),
+ if (INTERRUPT_REQUESTED(GetDebugger(),
"Interrupted in dump clang ast list with {0} of {1} dumped.",
i, num_matches))
break;
@@ -2477,9 +2478,9 @@ protected:
if (num_modules > 0) {
uint32_t num_dumped = 0;
for (ModuleSP module_sp : target_modules.ModulesNoLocking()) {
- if (INTERRUPT_REQUESTED(GetDebugger(),
+ if (INTERRUPT_REQUESTED(GetDebugger(),
"Interrupted in dump all line tables with "
- "{0} of {1} dumped", num_dumped,
+ "{0} of {1} dumped", num_dumped,
num_modules))
break;
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index e6279a0..65a65c4 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -949,99 +949,9 @@ void Module::FindAddressesForLine(const lldb::TargetSP target_sp,
}
}
-void Module::FindTypes_Impl(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- size_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types) {
+void Module::FindTypes(const TypeQuery &query, TypeResults &results) {
if (SymbolFile *symbols = GetSymbolFile())
- symbols->FindTypes(name, parent_decl_ctx, max_matches,
- searched_symbol_files, types);
-}
-
-void Module::FindTypesInNamespace(ConstString type_name,
- const CompilerDeclContext &parent_decl_ctx,
- size_t max_matches, TypeList &type_list) {
- TypeMap types_map;
- llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
- FindTypes_Impl(type_name, parent_decl_ctx, max_matches, searched_symbol_files,
- types_map);
- if (types_map.GetSize()) {
- SymbolContext sc;
- sc.module_sp = shared_from_this();
- sc.SortTypeList(types_map, type_list);
- }
-}
-
-lldb::TypeSP Module::FindFirstType(const SymbolContext &sc, ConstString name,
- bool exact_match) {
- TypeList type_list;
- llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
- FindTypes(name, exact_match, 1, searched_symbol_files, type_list);
- if (type_list.GetSize())
- return type_list.GetTypeAtIndex(0);
- return TypeSP();
-}
-
-void Module::FindTypes(
- ConstString name, bool exact_match, size_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeList &types) {
- const char *type_name_cstr = name.GetCString();
- llvm::StringRef type_scope;
- llvm::StringRef type_basename;
- TypeClass type_class = eTypeClassAny;
- TypeMap typesmap;
-
- if (Type::GetTypeScopeAndBasename(type_name_cstr, type_scope, type_basename,
- type_class)) {
- // Check if "name" starts with "::" which means the qualified type starts
- // from the root namespace and implies and exact match. The typenames we
- // get back from clang do not start with "::" so we need to strip this off
- // in order to get the qualified names to match
- exact_match = type_scope.consume_front("::");
-
- ConstString type_basename_const_str(type_basename);
- FindTypes_Impl(type_basename_const_str, CompilerDeclContext(), max_matches,
- searched_symbol_files, typesmap);
- if (typesmap.GetSize())
- typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,
- exact_match);
- } else {
- // The type is not in a namespace/class scope, just search for it by
- // basename
- if (type_class != eTypeClassAny && !type_basename.empty()) {
- // The "type_name_cstr" will have been modified if we have a valid type
- // class prefix (like "struct", "class", "union", "typedef" etc).
- FindTypes_Impl(ConstString(type_basename), CompilerDeclContext(),
- UINT_MAX, searched_symbol_files, typesmap);
- typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,
- exact_match);
- } else {
- FindTypes_Impl(name, CompilerDeclContext(), UINT_MAX,
- searched_symbol_files, typesmap);
- if (exact_match) {
- typesmap.RemoveMismatchedTypes(type_scope, name, type_class,
- exact_match);
- }
- }
- }
- if (typesmap.GetSize()) {
- SymbolContext sc;
- sc.module_sp = shared_from_this();
- sc.SortTypeList(typesmap, types);
- }
-}
-
-void Module::FindTypes(
- llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types) {
- // If a scoped timer is needed, place it in a SymbolFile::FindTypes override.
- // A timer here is too high volume for some cases, for example when calling
- // FindTypes on each object file.
- if (SymbolFile *symbols = GetSymbolFile())
- symbols->FindTypes(pattern, languages, searched_symbol_files, types);
+ symbols->FindTypes(query, results);
}
static Debugger::DebuggerList
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index 04a9df7d..aa89c93 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -557,36 +557,21 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const {
return module_sp;
}
-void ModuleList::FindTypes(Module *search_first, ConstString name,
- bool name_is_fully_qualified, size_t max_matches,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeList &types) const {
+void ModuleList::FindTypes(Module *search_first, const TypeQuery &query,
+ TypeResults &results) const {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
-
- collection::const_iterator pos, end = m_modules.end();
if (search_first) {
- for (pos = m_modules.begin(); pos != end; ++pos) {
- if (search_first == pos->get()) {
- search_first->FindTypes(name, name_is_fully_qualified, max_matches,
- searched_symbol_files, types);
-
- if (types.GetSize() >= max_matches)
- return;
- }
- }
- }
-
- for (pos = m_modules.begin(); pos != end; ++pos) {
- // Search the module if the module is not equal to the one in the symbol
- // context "sc". If "sc" contains a empty module shared pointer, then the
- // comparison will always be true (valid_module_ptr != nullptr).
- if (search_first != pos->get())
- (*pos)->FindTypes(name, name_is_fully_qualified, max_matches,
- searched_symbol_files, types);
-
- if (types.GetSize() >= max_matches)
+ search_first->FindTypes(query, results);
+ if (results.Done(query))
return;
}
+ for (const auto &module_sp : m_modules) {
+ if (search_first != module_sp.get()) {
+ module_sp->FindTypes(query, results);
+ if (results.Done(query))
+ return;
+ }
+ }
}
bool ModuleList::FindSourceFile(const FileSpec &orig_spec,
diff --git a/lldb/source/DataFormatters/TypeFormat.cpp b/lldb/source/DataFormatters/TypeFormat.cpp
index 126240a..409c452 100644
--- a/lldb/source/DataFormatters/TypeFormat.cpp
+++ b/lldb/source/DataFormatters/TypeFormat.cpp
@@ -161,13 +161,12 @@ bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj,
if (!target_sp)
return false;
const ModuleList &images(target_sp->GetImages());
- TypeList types;
- llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
- images.FindTypes(nullptr, m_enum_type, false, UINT32_MAX,
- searched_symbol_files, types);
- if (types.Empty())
+ TypeQuery query(m_enum_type.GetStringRef());
+ TypeResults results;
+ images.FindTypes(nullptr, query, results);
+ if (results.GetTypeMap().Empty())
return false;
- for (lldb::TypeSP type_sp : types.Types()) {
+ for (lldb::TypeSP type_sp : results.GetTypeMap().Types()) {
if (!type_sp)
continue;
if ((type_sp->GetForwardCompilerType().GetTypeInfo() &
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 5d7e125..00ab6a0 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -201,19 +201,17 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) {
LLDB_LOG(log, " CTD Searching namespace {0} in module {1}",
item.second.GetName(), item.first->GetFileSpec().GetFilename());
- TypeList types;
-
ConstString name(decl->getName());
- item.first->FindTypesInNamespace(name, item.second, UINT32_MAX, types);
-
- for (uint32_t ti = 0, te = types.GetSize(); ti != te; ++ti) {
- lldb::TypeSP type = types.GetTypeAtIndex(ti);
-
- if (!type)
- continue;
+ // Create a type matcher using the CompilerDeclContext for the namespace
+ // as the context (item.second) and search for the name inside of this
+ // context.
+ TypeQuery query(item.second, name);
+ TypeResults results;
+ item.first->FindTypes(query, results);
- CompilerType clang_type(type->GetFullCompilerType());
+ for (const lldb::TypeSP &type_sp : results.GetTypeMap().Types()) {
+ CompilerType clang_type(type_sp->GetFullCompilerType());
if (!ClangUtil::IsClangType(clang_type))
continue;
@@ -233,24 +231,15 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) {
}
}
} else {
- TypeList types;
-
- ConstString name(decl->getName());
-
const ModuleList &module_list = m_target->GetImages();
+ // Create a type matcher using a CompilerDecl. Each TypeSystem class knows
+ // how to fill out a CompilerContext array using a CompilerDecl.
+ TypeQuery query(CompilerDecl(m_clang_ast_context, (void *)decl));
+ TypeResults results;
+ module_list.FindTypes(nullptr, query, results);
+ for (const lldb::TypeSP &type_sp : results.GetTypeMap().Types()) {
- bool exact_match = false;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- module_list.FindTypes(nullptr, name, exact_match, UINT32_MAX,
- searched_symbol_files, types);
-
- for (uint32_t ti = 0, te = types.GetSize(); ti != te; ++ti) {
- lldb::TypeSP type = types.GetTypeAtIndex(ti);
-
- if (!type)
- continue;
-
- CompilerType clang_type(type->GetFullCompilerType());
+ CompilerType clang_type(type_sp->GetFullCompilerType());
if (!ClangUtil::IsClangType(clang_type))
continue;
@@ -263,13 +252,6 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) {
TagDecl *candidate_tag_decl = const_cast<TagDecl *>(tag_type->getDecl());
- // We have found a type by basename and we need to make sure the decl
- // contexts are the same before we can try to complete this type with
- // another
- if (!TypeSystemClang::DeclsAreEquivalent(const_cast<TagDecl *>(decl),
- candidate_tag_decl))
- continue;
-
if (TypeSystemClang::GetCompleteDecl(&candidate_tag_decl->getASTContext(),
candidate_tag_decl))
return candidate_tag_decl;
@@ -614,41 +596,40 @@ void ClangASTSource::FindExternalVisibleDecls(
if (context.m_found_type)
return;
- TypeList types;
- const bool exact_match = true;
- llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
- if (module_sp && namespace_decl)
- module_sp->FindTypesInNamespace(name, namespace_decl, 1, types);
- else {
- m_target->GetImages().FindTypes(module_sp.get(), name, exact_match, 1,
- searched_symbol_files, types);
+ lldb::TypeSP type_sp;
+ TypeResults results;
+ if (module_sp && namespace_decl) {
+ // Match the name in the specified decl context.
+ TypeQuery query(namespace_decl, name, TypeQueryOptions::e_find_one);
+ module_sp->FindTypes(query, results);
+ type_sp = results.GetFirstType();
+ } else {
+ // Match the exact name of the type at the root level.
+ TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match |
+ TypeQueryOptions::e_find_one);
+ m_target->GetImages().FindTypes(nullptr, query, results);
+ type_sp = results.GetFirstType();
}
- if (size_t num_types = types.GetSize()) {
- for (size_t ti = 0; ti < num_types; ++ti) {
- lldb::TypeSP type_sp = types.GetTypeAtIndex(ti);
-
- if (log) {
- const char *name_string = type_sp->GetName().GetCString();
-
- LLDB_LOG(log, " CAS::FEVD Matching type found for \"{0}\": {1}", name,
- (name_string ? name_string : "<anonymous>"));
- }
+ if (type_sp) {
+ if (log) {
+ const char *name_string = type_sp->GetName().GetCString();
- CompilerType full_type = type_sp->GetFullCompilerType();
+ LLDB_LOG(log, " CAS::FEVD Matching type found for \"{0}\": {1}", name,
+ (name_string ? name_string : "<anonymous>"));
+ }
- CompilerType copied_clang_type(GuardedCopyType(full_type));
+ CompilerType full_type = type_sp->GetFullCompilerType();
- if (!copied_clang_type) {
- LLDB_LOG(log, " CAS::FEVD - Couldn't export a type");
+ CompilerType copied_clang_type(GuardedCopyType(full_type));
- continue;
- }
+ if (!copied_clang_type) {
+ LLDB_LOG(log, " CAS::FEVD - Couldn't export a type");
+ } else {
context.AddTypeDecl(copied_clang_type);
context.m_found_type = true;
- break;
}
}
diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index a5c9ead..0ea9201 100644
--- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -82,24 +82,30 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo(
lookup_name.append(class_name.data(), class_name.size());
type_info.SetName(class_name);
- const bool exact_match = true;
+ ConstString const_lookup_name(lookup_name);
TypeList class_types;
-
+ ModuleSP module_sp = vtable_info.symbol->CalculateSymbolContextModule();
// First look in the module that the vtable symbol came from and
// look for a single exact match.
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- ModuleSP module_sp = vtable_info.symbol->CalculateSymbolContextModule();
- if (module_sp)
- module_sp->FindTypes(ConstString(lookup_name), exact_match, 1,
- searched_symbol_files, class_types);
+ TypeResults results;
+ TypeQuery query(const_lookup_name.GetStringRef(),
+ TypeQueryOptions::e_exact_match |
+ TypeQueryOptions::e_find_one);
+ if (module_sp) {
+ module_sp->FindTypes(query, results);
+ TypeSP type_sp = results.GetFirstType();
+ if (type_sp)
+ class_types.Insert(type_sp);
+ }
// If we didn't find a symbol, then move on to the entire module
// list in the target and get as many unique matches as possible
- Target &target = m_process->GetTarget();
- if (class_types.Empty())
- target.GetImages().FindTypes(nullptr, ConstString(lookup_name),
- exact_match, UINT32_MAX,
- searched_symbol_files, class_types);
+ if (class_types.Empty()) {
+ query.SetFindOne(false);
+ m_process->GetTarget().GetImages().FindTypes(nullptr, query, results);
+ for (const auto &type_sp : results.GetTypeMap().Types())
+ class_types.Insert(type_sp);
+ }
lldb::TypeSP type_sp;
if (class_types.Empty()) {
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
index 289288a..ba52444 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp
@@ -139,17 +139,10 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) {
if (!module_sp)
return TypeSP();
- const bool exact_match = true;
- const uint32_t max_matches = UINT32_MAX;
- TypeList types;
-
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- module_sp->FindTypes(name, exact_match, max_matches, searched_symbol_files,
- types);
-
- for (uint32_t i = 0; i < types.GetSize(); ++i) {
- TypeSP type_sp(types.GetTypeAtIndex(i));
-
+ TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match);
+ TypeResults results;
+ module_sp->FindTypes(query, results);
+ for (const TypeSP &type_sp : results.GetTypeMap().Types()) {
if (TypeSystemClang::IsObjCObjectOrInterfaceType(
type_sp->GetForwardCompilerType())) {
if (TypePayloadClang(type_sp->GetPayload()).IsCompleteObjCClass()) {
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
index cd52233..729d6af0 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -448,15 +448,6 @@ void SymbolFileBreakpad::FindFunctions(const RegularExpression &regex,
// TODO
}
-void SymbolFileBreakpad::FindTypes(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) {}
-
-void SymbolFileBreakpad::FindTypes(
- llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
-
void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
Log *log = GetLog(LLDBLog::Symbols);
Module &module = *m_objfile_sp->GetModule();
diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
index 4a01a64..214fbdd 100644
--- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -118,15 +118,6 @@ public:
void FindFunctions(const RegularExpression &regex, bool include_inlines,
SymbolContextList &sc_list) override;
- void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) override;
-
- void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) override;
-
llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language) override {
return llvm::make_error<llvm::StringError>(
diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
index 7a2b4c0..d192944 100644
--- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
+++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp
@@ -1020,23 +1020,18 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) {
return type_sp.get();
}
-void SymbolFileCTF::FindTypes(
- lldb_private::ConstString name,
- const lldb_private::CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- lldb_private::TypeMap &types) {
-
- searched_symbol_files.clear();
- searched_symbol_files.insert(this);
+void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match,
+ lldb_private::TypeResults &results) {
+ // Make sure we haven't already searched this SymbolFile before.
+ if (results.AlreadySearched(this))
+ return;
- size_t matches = 0;
+ ConstString name = match.GetTypeBasename();
for (TypeSP type_sp : GetTypeList().Types()) {
- if (matches == max_matches)
- break;
if (type_sp && type_sp->GetName() == name) {
- types.Insert(type_sp);
- matches++;
+ results.InsertUnique(type_sp);
+ if (results.Done(match))
+ return;
}
}
}
diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
index 787dc18..f111937 100644
--- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
+++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h
@@ -105,12 +105,8 @@ public:
lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) override {}
- void
- FindTypes(lldb_private::ConstString name,
- const lldb_private::CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- lldb_private::TypeMap &types) override;
+ void FindTypes(const lldb_private::TypeQuery &match,
+ lldb_private::TypeResults &results) override;
void FindTypesByRegex(const lldb_private::RegularExpression &regex,
uint32_t max_matches, lldb_private::TypeMap &types);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index e3c6464..3348766 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -152,16 +152,16 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
// If this type comes from a Clang module, recursively 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<CompilerContext> decl_context = die.GetDeclContext();
- TypeMap pcm_types;
+ std::vector<lldb_private::CompilerContext> die_context = die.GetDeclContext();
+ TypeQuery query(die_context, TypeQueryOptions::e_module_search |
+ TypeQueryOptions::e_find_one);
+ TypeResults results;
// The type in the Clang module must have the same language as the current CU.
- LanguageSet languages;
- languages.Insert(SymbolFileDWARF::GetLanguageFamily(*die.GetCU()));
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages,
- searched_symbol_files, pcm_types);
- if (pcm_types.Empty()) {
+ query.AddLanguage(SymbolFileDWARF::GetLanguageFamily(*die.GetCU()));
+ clang_module_sp->FindTypes(query, results);
+ TypeSP pcm_type_sp = results.GetTypeMap().FirstType();
+ if (!pcm_type_sp) {
// Since this type is defined in one of the Clang modules imported
// by this symbol file, search all of them. Instead of calling
// sym_file->FindTypes(), which would return this again, go straight
@@ -170,24 +170,20 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
// Well-formed clang modules never form cycles; guard against corrupted
// ones by inserting the current file.
- searched_symbol_files.insert(&sym_file);
+ results.AlreadySearched(&sym_file);
sym_file.ForEachExternalModule(
- *sc.comp_unit, searched_symbol_files, [&](Module &module) {
- module.GetSymbolFile()->FindTypes(decl_context, languages,
- searched_symbol_files, pcm_types);
- return pcm_types.GetSize();
+ *sc.comp_unit, results.GetSearchedSymbolFiles(), [&](Module &module) {
+ module.FindTypes(query, results);
+ pcm_type_sp = results.GetTypeMap().FirstType();
+ return !pcm_type_sp;
});
}
- if (!pcm_types.GetSize())
+ if (!pcm_type_sp)
return TypeSP();
// We found a real definition for this type in the Clang module, so lets use
// it and cache the fact that we found a complete type for this die.
- TypeSP pcm_type_sp = pcm_types.GetTypeAtIndex(0);
- if (!pcm_type_sp)
- return TypeSP();
-
lldb_private::CompilerType pcm_type = pcm_type_sp->GetForwardCompilerType();
lldb_private::CompilerType type =
GetClangASTImporter().CopyType(m_ast, pcm_type);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 1f9524f..bed68f4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -418,6 +418,54 @@ std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const {
return context;
}
+std::vector<lldb_private::CompilerContext>
+DWARFDIE::GetTypeLookupContext() const {
+ std::vector<lldb_private::CompilerContext> context;
+ // If there is no name, then there is no need to look anything up for this
+ // DIE.
+ const char *name = GetName();
+ if (!name || !name[0])
+ return context;
+ const dw_tag_t tag = Tag();
+ if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
+ return context;
+ DWARFDIE parent = GetParent();
+ if (parent)
+ context = parent.GetTypeLookupContext();
+ auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) {
+ context.push_back({kind, ConstString(name)});
+ };
+ switch (tag) {
+ case DW_TAG_namespace:
+ push_ctx(CompilerContextKind::Namespace, name);
+ break;
+ case DW_TAG_structure_type:
+ push_ctx(CompilerContextKind::Struct, name);
+ break;
+ case DW_TAG_union_type:
+ push_ctx(CompilerContextKind::Union, name);
+ break;
+ case DW_TAG_class_type:
+ push_ctx(CompilerContextKind::Class, name);
+ break;
+ case DW_TAG_enumeration_type:
+ push_ctx(CompilerContextKind::Enum, name);
+ break;
+ case DW_TAG_variable:
+ push_ctx(CompilerContextKind::Variable, GetPubname());
+ break;
+ case DW_TAG_typedef:
+ push_ctx(CompilerContextKind::Typedef, name);
+ break;
+ case DW_TAG_base_type:
+ push_ctx(CompilerContextKind::Builtin, name);
+ break;
+ default:
+ break;
+ }
+ return context;
+}
+
DWARFDIE
DWARFDIE::GetParentDeclContextDIE() const {
if (IsValid())
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index a68af62c..511ca62 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -73,9 +73,22 @@ public:
std::vector<DWARFDIE> GetDeclContextDIEs() const;
/// Return this DIE's decl context as it is needed to look up types
- /// in Clang's -gmodules debug info format.
+ /// in Clang modules. This context will include any modules or functions that
+ /// the type is declared in so an exact module match can be efficiently made.
std::vector<CompilerContext> GetDeclContext() const;
+ /// Get a context to a type so it can be looked up.
+ ///
+ /// This function uses the current DIE to fill in a CompilerContext array
+ /// that is suitable for type lookup for comparison to a TypeQuery's compiler
+ /// context (TypeQuery::GetContextRef()). If this DIE represents a named type,
+ /// it should fill out the compiler context with the type itself as the last
+ /// entry. The declaration context should be above the type and stop at an
+ /// appropriate time, like either the translation unit or at a function
+ /// context. This is designed to allow users to efficiently look for types
+ /// using a full or partial CompilerContext array.
+ std::vector<CompilerContext> GetTypeLookupContext() const;
+
// Getting attribute values from the DIE.
//
// GetAttributeValueAsXXX() functions should only be used if you are
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index d4c573e..7eddc50 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2596,177 +2596,157 @@ void SymbolFileDWARF::GetMangledNamesForFunction(
}
}
-void SymbolFileDWARF::FindTypes(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types) {
- std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- // Make sure we haven't already searched this SymbolFile before.
- if (!searched_symbol_files.insert(this).second)
- return;
-
- Log *log = GetLog(DWARFLog::Lookups);
+/// Split a name up into a basename and template parameters.
+static bool SplitTemplateParams(llvm::StringRef fullname,
+ llvm::StringRef &basename,
+ llvm::StringRef &template_params) {
+ auto it = fullname.find('<');
+ if (it == llvm::StringRef::npos) {
+ basename = fullname;
+ template_params = llvm::StringRef();
+ return false;
+ }
+ basename = fullname.slice(0, it);
+ template_params = fullname.slice(it, fullname.size());
+ return true;
+}
- if (log) {
- if (parent_decl_ctx)
- GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = "
- "{1:p} (\"{2}\"), max_matches={3}, type_list)",
- name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
- parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches);
- else
- GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = "
- "NULL, max_matches={1}, type_list)",
- name.GetCString(), max_matches);
+static bool UpdateCompilerContextForSimpleTemplateNames(TypeQuery &match) {
+ // We need to find any names in the context that have template parameters
+ // and strip them so the context can be matched when -gsimple-template-names
+ // is being used. Returns true if any of the context items were updated.
+ bool any_context_updated = false;
+ for (auto &context : match.GetContextRef()) {
+ llvm::StringRef basename, params;
+ if (SplitTemplateParams(context.name.GetStringRef(), basename, params)) {
+ context.name = ConstString(basename);
+ any_context_updated = true;
+ }
}
+ return any_context_updated;
+}
+void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) {
- if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
+ // Make sure we haven't already searched this SymbolFile before.
+ if (results.AlreadySearched(this))
return;
- // Unlike FindFunctions(), FindTypes() following cannot produce false
- // positives.
-
- const llvm::StringRef name_ref = name.GetStringRef();
- auto name_bracket_index = name_ref.find('<');
- m_index->GetTypes(name, [&](DWARFDIE die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
- return true; // The containing decl contexts don't match
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- Type *matching_type = ResolveType(die, true, true);
- if (!matching_type)
- return true;
+ bool have_index_match = false;
+ m_index->GetTypes(query.GetTypeBasename(), [&](DWARFDIE die) {
+ // Check the language, but only if we have a language filter.
+ if (query.HasLanguage()) {
+ if (!query.LanguageMatches(GetLanguageFamily(*die.GetCU())))
+ return true; // Keep iterating over index types, language mismatch.
+ }
- // With -gsimple-template-names, a templated type's DW_AT_name will not
- // contain the template parameters. Make sure that if the original query
- // didn't contain a '<', we filter out entries with template parameters.
- if (name_bracket_index == llvm::StringRef::npos &&
- matching_type->IsTemplateType())
- return true;
+ // Check the context matches
+ std::vector<lldb_private::CompilerContext> die_context;
+ if (query.GetModuleSearch())
+ die_context = die.GetDeclContext();
+ else
+ die_context = die.GetTypeLookupContext();
+ assert(!die_context.empty());
+ if (!query.ContextMatches(die_context))
+ return true; // Keep iterating over index types, context mismatch.
- // We found a type pointer, now find the shared pointer form our type
- // list
- types.InsertUnique(matching_type->shared_from_this());
- return types.GetSize() < max_matches;
+ // Try to resolve the type.
+ if (Type *matching_type = ResolveType(die, true, true)) {
+ if (matching_type->IsTemplateType()) {
+ // We have to watch out for case where we lookup a type by basename and
+ // it matches a template with simple template names. Like looking up
+ // "Foo" and if we have simple template names then we will match
+ // "Foo<int>" and "Foo<double>" because all the DWARF has is "Foo" in
+ // the accelerator tables. The main case we see this in is when the
+ // expression parser is trying to parse "Foo<int>" and it will first do
+ // a lookup on just "Foo". We verify the type basename matches before
+ // inserting the type in the results.
+ auto CompilerTypeBasename =
+ matching_type->GetForwardCompilerType().GetTypeName(true);
+ if (CompilerTypeBasename != query.GetTypeBasename())
+ return true; // Keep iterating over index types, basename mismatch.
+ }
+ have_index_match = true;
+ results.InsertUnique(matching_type->shared_from_this());
+ }
+ return !results.Done(query); // Keep iterating if we aren't done.
});
+ if (results.Done(query))
+ return;
+
// With -gsimple-template-names, a templated type's DW_AT_name will not
// contain the template parameters. Try again stripping '<' and anything
// after, filtering out entries with template parameters that don't match.
- if (types.GetSize() < max_matches) {
- if (name_bracket_index != llvm::StringRef::npos) {
- const llvm::StringRef name_no_template_params =
- name_ref.slice(0, name_bracket_index);
- const llvm::StringRef template_params =
- name_ref.slice(name_bracket_index, name_ref.size());
- m_index->GetTypes(ConstString(name_no_template_params), [&](DWARFDIE die) {
- if (!DIEInDeclContext(parent_decl_ctx, die))
- return true; // The containing decl contexts don't match
-
- const llvm::StringRef base_name = GetTypeForDIE(die)->GetBaseName().AsCString();
- auto it = base_name.find('<');
- // If the candidate qualified name doesn't have '<', it doesn't have
- // template params to compare.
- if (it == llvm::StringRef::npos)
- return true;
-
- // Filter out non-matching instantiations by comparing template params.
- const llvm::StringRef base_name_template_params =
- base_name.slice(it, base_name.size());
-
- if (template_params != base_name_template_params)
- return true;
-
- Type *matching_type = ResolveType(die, true, true);
- if (!matching_type)
- return true;
+ if (!have_index_match) {
+ // Create a type matcher with a compiler context that is tuned for
+ // -gsimple-template-names. We will use this for the index lookup and the
+ // context matching, but will use the original "match" to insert matches
+ // into if things match. The "match_simple" has a compiler context with
+ // all template parameters removed to allow the names and context to match.
+ // The UpdateCompilerContextForSimpleTemplateNames(...) will return true if
+ // it trims any context items down by removing template parameter names.
+ TypeQuery query_simple(query);
+ if (UpdateCompilerContextForSimpleTemplateNames(query_simple)) {
+
+ // Copy our match's context and update the basename we are looking for
+ // so we can use this only to compare the context correctly.
+ m_index->GetTypes(query_simple.GetTypeBasename(), [&](DWARFDIE die) {
+ // Check the language, but only if we have a language filter.
+ if (query.HasLanguage()) {
+ if (!query.LanguageMatches(GetLanguageFamily(*die.GetCU())))
+ return true; // Keep iterating over index types, language mismatch.
+ }
- // We found a type pointer, now find the shared pointer form our type
- // list.
- types.InsertUnique(matching_type->shared_from_this());
- return types.GetSize() < max_matches;
+ // Check the context matches
+ std::vector<lldb_private::CompilerContext> die_context;
+ if (query.GetModuleSearch())
+ die_context = die.GetDeclContext();
+ else
+ die_context = die.GetTypeLookupContext();
+ assert(!die_context.empty());
+ if (!query_simple.ContextMatches(die_context))
+ return true; // Keep iterating over index types, context mismatch.
+
+ // Try to resolve the type.
+ if (Type *matching_type = ResolveType(die, true, true)) {
+ ConstString name = matching_type->GetQualifiedName();
+ // We have found a type that still might not match due to template
+ // parameters. If we create a new TypeQuery that uses the new type's
+ // fully qualified name, we can find out if this type matches at all
+ // context levels. We can't use just the "match_simple" context
+ // because all template parameters were stripped off. The fully
+ // qualified name of the type will have the template parameters and
+ // will allow us to make sure it matches correctly.
+ TypeQuery die_query(name.GetStringRef(),
+ TypeQueryOptions::e_exact_match);
+ if (!query.ContextMatches(die_query.GetContextRef()))
+ return true; // Keep iterating over index types, context mismatch.
+
+ results.InsertUnique(matching_type->shared_from_this());
+ }
+ return !results.Done(query); // Keep iterating if we aren't done.
});
+ if (results.Done(query))
+ return;
}
}
// Next search through the reachable Clang modules. This only applies for
// DWARF objects compiled with -gmodules that haven't been processed by
// dsymutil.
- if (types.GetSize() < max_matches) {
- UpdateExternalModuleListIfNeeded();
-
- for (const auto &pair : m_external_type_modules)
- if (ModuleSP external_module_sp = pair.second)
- if (SymbolFile *sym_file = external_module_sp->GetSymbolFile())
- sym_file->FindTypes(name, parent_decl_ctx, max_matches,
- searched_symbol_files, types);
- }
+ UpdateExternalModuleListIfNeeded();
- if (log && types.GetSize()) {
- if (parent_decl_ctx) {
- GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx "
- "= {1:p} (\"{2}\"), max_matches={3}, type_list) => {4}",
- name.GetCString(), static_cast<const void *>(&parent_decl_ctx),
- parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches,
- types.GetSize());
- } else {
- GetObjectFile()->GetModule()->LogMessage(
- log,
- "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx "
- "= NULL, max_matches={1}, type_list) => {2}",
- name.GetCString(), max_matches, types.GetSize());
+ for (const auto &pair : m_external_type_modules) {
+ if (ModuleSP external_module_sp = pair.second) {
+ external_module_sp->FindTypes(query, results);
+ if (results.Done(query))
+ return;
}
}
}
-void SymbolFileDWARF::FindTypes(
- llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
- // Make sure we haven't already searched this SymbolFile before.
- if (!searched_symbol_files.insert(this).second)
- return;
-
- std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- if (pattern.empty())
- return;
-
- ConstString name = pattern.back().name;
-
- if (!name)
- return;
-
- m_index->GetTypes(name, [&](DWARFDIE die) {
- if (!languages[GetLanguageFamily(*die.GetCU())])
- return true;
-
- std::vector<CompilerContext> die_context = die.GetDeclContext();
- if (!contextMatches(die_context, pattern))
- return true;
-
- if (Type *matching_type = ResolveType(die, true, true)) {
- // We found a type pointer, now find the shared pointer form our type
- // list.
- types.InsertUnique(matching_type->shared_from_this());
- }
- return true;
- });
-
- // Next search through the reachable Clang modules. This only applies for
- // DWARF objects compiled with -gmodules that haven't been processed by
- // dsymutil.
- UpdateExternalModuleListIfNeeded();
-
- for (const auto &pair : m_external_type_modules)
- if (ModuleSP external_module_sp = pair.second)
- external_module_sp->FindTypes(pattern, languages, searched_symbol_files,
- types);
-}
-
CompilerDeclContext
SymbolFileDWARF::FindNamespace(ConstString name,
const CompilerDeclContext &parent_decl_ctx,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index e6efbba..78819ed 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -186,14 +186,8 @@ public:
GetMangledNamesForFunction(const std::string &scope_qualified_name,
std::vector<ConstString> &mangled_names) override;
- void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) override;
-
- void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) override;
+ void FindTypes(const lldb_private::TypeQuery &match,
+ lldb_private::TypeResults &results) override;
void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
TypeList &type_list) override;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 263ada9..e5b59460 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -1227,27 +1227,12 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
return TypeSP();
}
-void SymbolFileDWARFDebugMap::FindTypes(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types) {
+void SymbolFileDWARFDebugMap::FindTypes(const TypeQuery &query,
+ TypeResults &results) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches,
- searched_symbol_files, types);
- return types.GetSize() >= max_matches;
- });
-}
-
-void SymbolFileDWARFDebugMap::FindTypes(
- llvm::ArrayRef<CompilerContext> context, LanguageSet languages,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types) {
- LLDB_SCOPED_TIMER();
- ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- oso_dwarf->FindTypes(context, languages, searched_symbol_files, types);
- return false;
+ oso_dwarf->FindTypes(query, results);
+ return !results.Done(query); // Keep iterating if we aren't done.
});
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 13f94f6..cd0a4bb 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -118,13 +118,8 @@ public:
bool include_inlines, SymbolContextList &sc_list) override;
void FindFunctions(const RegularExpression &regex, bool include_inlines,
SymbolContextList &sc_list) override;
- void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) override;
- void FindTypes(llvm::ArrayRef<CompilerContext> context, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) override;
+ void FindTypes(const lldb_private::TypeQuery &match,
+ lldb_private::TypeResults &results) override;
CompilerDeclContext FindNamespace(ConstString name,
const CompilerDeclContext &parent_decl_ctx,
bool only_root_namespaces) override;
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index eaca476..35c2575 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1717,24 +1717,33 @@ void SymbolFileNativePDB::FindFunctions(const RegularExpression &regex,
bool include_inlines,
SymbolContextList &sc_list) {}
-void SymbolFileNativePDB::FindTypes(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) {
- std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- if (!name)
+void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query,
+ lldb_private::TypeResults &results) {
+
+ // Make sure we haven't already searched this SymbolFile before.
+ if (results.AlreadySearched(this))
return;
- searched_symbol_files.clear();
- searched_symbol_files.insert(this);
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- // There is an assumption 'name' is not a regex
- FindTypesByName(name.GetStringRef(), max_matches, types);
-}
+ std::vector<TypeIndex> matches =
+ m_index->tpi().findRecordsByName(query.GetTypeBasename().GetStringRef());
-void SymbolFileNativePDB::FindTypes(
- llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {}
+ for (TypeIndex type_idx : matches) {
+ TypeSP type_sp = GetOrCreateType(type_idx);
+ if (!type_sp)
+ continue;
+
+ // We resolved a type. Get the fully qualified name to ensure it matches.
+ ConstString name = type_sp->GetQualifiedName();
+ TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match);
+ if (query.ContextMatches(type_match.GetContextRef())) {
+ results.InsertUnique(type_sp);
+ if (results.Done(query))
+ return;
+ }
+ }
+}
void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
uint32_t max_matches,
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index bf64cd33..9d0458c 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -140,14 +140,8 @@ public:
std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id);
- void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) override;
-
- void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) override;
+ void FindTypes(const lldb_private::TypeQuery &match,
+ lldb_private::TypeResults &results) override;
llvm::Expected<lldb::TypeSystemSP>
GetTypeSystemForLanguage(lldb::LanguageType language) override;
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index 78eabc3..96036de 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -1446,24 +1446,6 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) {
symtab.Finalize();
}
-void SymbolFilePDB::FindTypes(
- lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- lldb_private::TypeMap &types) {
- std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
- if (!name)
- return;
- if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx))
- return;
-
- searched_symbol_files.clear();
- searched_symbol_files.insert(this);
-
- // There is an assumption 'name' is not a regex
- FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types);
-}
-
void SymbolFilePDB::DumpClangAST(Stream &s) {
auto type_system_or_err =
GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
@@ -1536,25 +1518,27 @@ void SymbolFilePDB::FindTypesByRegex(
}
}
-void SymbolFilePDB::FindTypesByName(
- llvm::StringRef name,
- const lldb_private::CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches, lldb_private::TypeMap &types) {
+void SymbolFilePDB::FindTypes(const lldb_private::TypeQuery &query,
+ lldb_private::TypeResults &type_results) {
+
+ // Make sure we haven't already searched this SymbolFile before.
+ if (type_results.AlreadySearched(this))
+ return;
+
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+
std::unique_ptr<IPDBEnumSymbols> results;
- if (name.empty())
+ llvm::StringRef basename = query.GetTypeBasename().GetStringRef();
+ if (basename.empty())
return;
results = m_global_scope_up->findAllChildren(PDB_SymType::None);
if (!results)
return;
- uint32_t matches = 0;
-
while (auto result = results->getNext()) {
- if (max_matches > 0 && matches >= max_matches)
- break;
if (MSVCUndecoratedNameParser::DropScope(
- result->getRawSymbol().getName()) != name)
+ result->getRawSymbol().getName()) != basename)
continue;
switch (result->getSymTag()) {
@@ -1573,23 +1557,20 @@ void SymbolFilePDB::FindTypesByName(
if (!ResolveTypeUID(result->getSymIndexId()))
continue;
- if (parent_decl_ctx.IsValid() &&
- GetDeclContextContainingUID(result->getSymIndexId()) != parent_decl_ctx)
- continue;
-
auto iter = m_types.find(result->getSymIndexId());
if (iter == m_types.end())
continue;
- types.Insert(iter->second);
- ++matches;
+ // We resolved a type. Get the fully qualified name to ensure it matches.
+ ConstString name = iter->second->GetQualifiedName();
+ TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match);
+ if (query.ContextMatches(type_match.GetContextRef())) {
+ type_results.InsertUnique(iter->second);
+ if (type_results.Done(query))
+ return;
+ }
}
}
-void SymbolFilePDB::FindTypes(
- llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- lldb_private::TypeMap &types) {}
-
void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
uint32_t type_mask,
TypeCollection &type_collection) {
diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index 5b98c6e..01851f1 100644
--- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -134,19 +134,8 @@ public:
std::vector<lldb_private::ConstString> &mangled_names) override;
void AddSymbols(lldb_private::Symtab &symtab) override;
-
- void
- FindTypes(lldb_private::ConstString name,
- const lldb_private::CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- lldb_private::TypeMap &types) override;
-
- void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern,
- lldb_private::LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- lldb_private::TypeMap &types) override;
-
+ void FindTypes(const lldb_private::TypeQuery &match,
+ lldb_private::TypeResults &results) override;
void FindTypesByRegex(const lldb_private::RegularExpression &regex,
uint32_t max_matches, lldb_private::TypeMap &types);
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 7c28935..47024cd 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -2461,89 +2461,6 @@ void TypeSystemClang::DumpDeclHiearchy(clang::Decl *decl) {
}
}
-bool TypeSystemClang::DeclsAreEquivalent(clang::Decl *lhs_decl,
- clang::Decl *rhs_decl) {
- if (lhs_decl && rhs_decl) {
- // Make sure the decl kinds match first
- const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind();
- const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind();
-
- if (lhs_decl_kind == rhs_decl_kind) {
- // Now check that the decl contexts kinds are all equivalent before we
- // have to check any names of the decl contexts...
- clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext();
- clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext();
- if (lhs_decl_ctx && rhs_decl_ctx) {
- while (true) {
- if (lhs_decl_ctx && rhs_decl_ctx) {
- const clang::Decl::Kind lhs_decl_ctx_kind =
- lhs_decl_ctx->getDeclKind();
- const clang::Decl::Kind rhs_decl_ctx_kind =
- rhs_decl_ctx->getDeclKind();
- if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) {
- lhs_decl_ctx = lhs_decl_ctx->getParent();
- rhs_decl_ctx = rhs_decl_ctx->getParent();
-
- if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr)
- break;
- } else
- return false;
- } else
- return false;
- }
-
- // Now make sure the name of the decls match
- clang::NamedDecl *lhs_named_decl =
- llvm::dyn_cast<clang::NamedDecl>(lhs_decl);
- clang::NamedDecl *rhs_named_decl =
- llvm::dyn_cast<clang::NamedDecl>(rhs_decl);
- if (lhs_named_decl && rhs_named_decl) {
- clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName();
- clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName();
- if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) {
- if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
- return false;
- } else
- return false;
- } else
- return false;
-
- // We know that the decl context kinds all match, so now we need to
- // make sure the names match as well
- lhs_decl_ctx = lhs_decl->getDeclContext();
- rhs_decl_ctx = rhs_decl->getDeclContext();
- while (true) {
- switch (lhs_decl_ctx->getDeclKind()) {
- case clang::Decl::TranslationUnit:
- // We don't care about the translation unit names
- return true;
- default: {
- clang::NamedDecl *lhs_named_decl =
- llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx);
- clang::NamedDecl *rhs_named_decl =
- llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx);
- if (lhs_named_decl && rhs_named_decl) {
- clang::DeclarationName lhs_decl_name =
- lhs_named_decl->getDeclName();
- clang::DeclarationName rhs_decl_name =
- rhs_named_decl->getDeclName();
- if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) {
- if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString())
- return false;
- } else
- return false;
- } else
- return false;
- } break;
- }
- lhs_decl_ctx = lhs_decl_ctx->getParent();
- rhs_decl_ctx = rhs_decl_ctx->getParent();
- }
- }
- }
- }
- return false;
-}
bool TypeSystemClang::GetCompleteDecl(clang::ASTContext *ast,
clang::Decl *decl) {
if (!decl)
@@ -9070,6 +8987,66 @@ size_t TypeSystemClang::DeclGetFunctionNumArguments(void *opaque_decl) {
return 0;
}
+static CompilerContextKind GetCompilerKind(clang::Decl::Kind clang_kind,
+ clang::DeclContext const *decl_ctx) {
+ switch (clang_kind) {
+ case Decl::TranslationUnit:
+ return CompilerContextKind::TranslationUnit;
+ case Decl::Namespace:
+ return CompilerContextKind::Namespace;
+ case Decl::Var:
+ return CompilerContextKind::Variable;
+ case Decl::Enum:
+ return CompilerContextKind::Enum;
+ case Decl::Typedef:
+ return CompilerContextKind::Typedef;
+ default:
+ // Many other kinds have multiple values
+ if (decl_ctx) {
+ if (decl_ctx->isFunctionOrMethod())
+ return CompilerContextKind::Function;
+ else if (decl_ctx->isRecord())
+ return (CompilerContextKind)((uint16_t)CompilerContextKind::Class |
+ (uint16_t)CompilerContextKind::Struct |
+ (uint16_t)CompilerContextKind::Union);
+ }
+ break;
+ }
+ return CompilerContextKind::Any;
+}
+
+static void
+InsertCompilerContext(TypeSystemClang *ts, clang::DeclContext *decl_ctx,
+ std::vector<lldb_private::CompilerContext> &context) {
+ if (decl_ctx == nullptr)
+ return;
+ InsertCompilerContext(ts, decl_ctx->getParent(), context);
+ clang::Decl::Kind clang_kind = decl_ctx->getDeclKind();
+ if (clang_kind == Decl::TranslationUnit)
+ return; // Stop at the translation unit.
+ const CompilerContextKind compiler_kind =
+ GetCompilerKind(clang_kind, decl_ctx);
+ ConstString decl_ctx_name = ts->DeclContextGetName(decl_ctx);
+ context.push_back({compiler_kind, decl_ctx_name});
+}
+
+std::vector<lldb_private::CompilerContext>
+TypeSystemClang::DeclGetCompilerContext(void *opaque_decl) {
+ std::vector<lldb_private::CompilerContext> context;
+ ConstString decl_name = DeclGetName(opaque_decl);
+ if (decl_name) {
+ clang::Decl *decl = (clang::Decl *)opaque_decl;
+ // Add the entire decl context first
+ clang::DeclContext *decl_ctx = decl->getDeclContext();
+ InsertCompilerContext(this, decl_ctx, context);
+ // Now add the decl information
+ auto compiler_kind =
+ GetCompilerKind(decl->getKind(), dyn_cast<DeclContext>(decl));
+ context.push_back({compiler_kind, decl_name});
+ }
+ return context;
+}
+
CompilerType TypeSystemClang::DeclGetFunctionArgumentType(void *opaque_decl,
size_t idx) {
if (clang::FunctionDecl *func_decl =
@@ -9308,6 +9285,14 @@ bool TypeSystemClang::DeclContextIsClassMethod(void *opaque_decl_ctx) {
return false;
}
+std::vector<lldb_private::CompilerContext>
+TypeSystemClang::DeclContextGetCompilerContext(void *opaque_decl_ctx) {
+ auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
+ std::vector<lldb_private::CompilerContext> context;
+ InsertCompilerContext(this, decl_ctx, context);
+ return context;
+}
+
bool TypeSystemClang::DeclContextIsContainedInLookup(
void *opaque_decl_ctx, void *other_opaque_decl_ctx) {
auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 19f2673..a731648 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -183,8 +183,6 @@ public:
static void DumpDeclContextHiearchy(clang::DeclContext *decl_ctx);
- static bool DeclsAreEquivalent(clang::Decl *lhs_decl, clang::Decl *rhs_decl);
-
static bool GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl);
void SetMetadataAsUserID(const clang::Decl *decl, lldb::user_id_t user_id);
@@ -558,6 +556,9 @@ public:
CompilerType DeclGetFunctionArgumentType(void *opaque_decl,
size_t arg_idx) override;
+ std::vector<lldb_private::CompilerContext>
+ DeclGetCompilerContext(void *opaque_decl) override;
+
CompilerType GetTypeForDecl(void *opaque_decl) override;
// CompilerDeclContext override functions
@@ -587,6 +588,9 @@ public:
lldb::LanguageType DeclContextGetLanguage(void *opaque_decl_ctx) override;
+ std::vector<lldb_private::CompilerContext>
+ DeclContextGetCompilerContext(void *opaque_decl_ctx) override;
+
// Clang specific clang::DeclContext functions
static clang::DeclContext *
diff --git a/lldb/source/Symbol/CompilerDecl.cpp b/lldb/source/Symbol/CompilerDecl.cpp
index 3cafa95..0eb630e 100644
--- a/lldb/source/Symbol/CompilerDecl.cpp
+++ b/lldb/source/Symbol/CompilerDecl.cpp
@@ -47,3 +47,8 @@ bool lldb_private::operator!=(const lldb_private::CompilerDecl &lhs,
return lhs.GetTypeSystem() != rhs.GetTypeSystem() ||
lhs.GetOpaqueDecl() != rhs.GetOpaqueDecl();
}
+
+std::vector<lldb_private::CompilerContext>
+CompilerDecl::GetCompilerContext() const {
+ return m_type_system->DeclGetCompilerContext(m_opaque_decl);
+}
diff --git a/lldb/source/Symbol/CompilerDeclContext.cpp b/lldb/source/Symbol/CompilerDeclContext.cpp
index a188e60..b40a08e 100644
--- a/lldb/source/Symbol/CompilerDeclContext.cpp
+++ b/lldb/source/Symbol/CompilerDeclContext.cpp
@@ -59,6 +59,13 @@ bool CompilerDeclContext::IsContainedInLookup(CompilerDeclContext other) const {
other.m_opaque_decl_ctx);
}
+std::vector<lldb_private::CompilerContext>
+CompilerDeclContext::GetCompilerContext() const {
+ if (IsValid())
+ return m_type_system->DeclContextGetCompilerContext(m_opaque_decl_ctx);
+ return {};
+}
+
bool lldb_private::operator==(const lldb_private::CompilerDeclContext &lhs,
const lldb_private::CompilerDeclContext &rhs) {
return lhs.GetTypeSystem() == rhs.GetTypeSystem() &&
diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp
index 4b9c386..e318e2be 100644
--- a/lldb/source/Symbol/SymbolFile.cpp
+++ b/lldb/source/Symbol/SymbolFile.cpp
@@ -134,17 +134,6 @@ void SymbolFile::GetMangledNamesForFunction(
const std::string &scope_qualified_name,
std::vector<ConstString> &mangled_names) {}
-void SymbolFile::FindTypes(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types) {}
-
-void SymbolFile::FindTypes(llvm::ArrayRef<CompilerContext> pattern,
- LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files,
- TypeMap &types) {}
-
void SymbolFile::AssertModuleLock() {
// The code below is too expensive to leave enabled in release builds. It's
// enabled in debug builds or when the correct macro is set.
diff --git a/lldb/source/Symbol/SymbolFileOnDemand.cpp b/lldb/source/Symbol/SymbolFileOnDemand.cpp
index 19b519c..3399525 100644
--- a/lldb/source/Symbol/SymbolFileOnDemand.cpp
+++ b/lldb/source/Symbol/SymbolFileOnDemand.cpp
@@ -431,31 +431,14 @@ void SymbolFileOnDemand::GetMangledNamesForFunction(
mangled_names);
}
-void SymbolFileOnDemand::FindTypes(
- ConstString name, const CompilerDeclContext &parent_decl_ctx,
- uint32_t max_matches,
- llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
- TypeMap &types) {
- if (!m_debug_info_enabled) {
- Log *log = GetLog();
- LLDB_LOG(log, "[{0}] {1}({2}) is skipped", GetSymbolFileName(),
- __FUNCTION__, name);
- return;
- }
- return m_sym_file_impl->FindTypes(name, parent_decl_ctx, max_matches,
- searched_symbol_files, types);
-}
-
-void SymbolFileOnDemand::FindTypes(
- llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages,
- llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
+void SymbolFileOnDemand::FindTypes(const TypeQuery &match,
+ TypeResults &results) {
if (!m_debug_info_enabled) {
LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(),
__FUNCTION__);
return;
}
- return m_sym_file_impl->FindTypes(pattern, languages, searched_symbol_files,
- types);
+ return m_sym_file_impl->FindTypes(match, results);
}
void SymbolFileOnDemand::GetTypes(SymbolContextScope *sc_scope,
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 54eeace..293fe1b 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -64,6 +64,127 @@ bool lldb_private::contextMatches(llvm::ArrayRef<CompilerContext> context_chain,
return true;
}
+static CompilerContextKind ConvertTypeClass(lldb::TypeClass type_class) {
+ if (type_class == eTypeClassAny)
+ return CompilerContextKind::AnyType;
+ uint16_t result = 0;
+ if (type_class & lldb::eTypeClassClass)
+ result |= (uint16_t)CompilerContextKind::Class;
+ if (type_class & lldb::eTypeClassStruct)
+ result |= (uint16_t)CompilerContextKind::Struct;
+ if (type_class & lldb::eTypeClassUnion)
+ result |= (uint16_t)CompilerContextKind::Union;
+ if (type_class & lldb::eTypeClassEnumeration)
+ result |= (uint16_t)CompilerContextKind::Enum;
+ if (type_class & lldb::eTypeClassFunction)
+ result |= (uint16_t)CompilerContextKind::Function;
+ if (type_class & lldb::eTypeClassTypedef)
+ result |= (uint16_t)CompilerContextKind::Typedef;
+ return (CompilerContextKind)result;
+}
+
+TypeQuery::TypeQuery(llvm::StringRef name, TypeQueryOptions options)
+ : m_options(options) {
+ llvm::StringRef scope, basename;
+ lldb::TypeClass type_class = lldb::eTypeClassAny;
+ if (Type::GetTypeScopeAndBasename(name, scope, basename, type_class)) {
+ if (scope.consume_front("::"))
+ m_options |= e_exact_match;
+ if (!scope.empty()) {
+ std::pair<llvm::StringRef, llvm::StringRef> scope_pair =
+ scope.split("::");
+ while (!scope_pair.second.empty()) {
+ m_context.push_back({CompilerContextKind::AnyDeclContext,
+ ConstString(scope_pair.first.str())});
+ scope_pair = scope_pair.second.split("::");
+ }
+ m_context.push_back({CompilerContextKind::AnyDeclContext,
+ ConstString(scope_pair.first.str())});
+ }
+ m_context.push_back(
+ {ConvertTypeClass(type_class), ConstString(basename.str())});
+ } else {
+ m_context.push_back(
+ {CompilerContextKind::AnyType, ConstString(name.str())});
+ }
+}
+
+TypeQuery::TypeQuery(const CompilerDeclContext &decl_ctx,
+ ConstString type_basename, TypeQueryOptions options)
+ : m_options(options) {
+ // Always use an exact match if we are looking for a type in compiler context.
+ m_options |= e_exact_match;
+ m_context = decl_ctx.GetCompilerContext();
+ m_context.push_back({CompilerContextKind::AnyType, type_basename});
+}
+
+TypeQuery::TypeQuery(
+ const llvm::ArrayRef<lldb_private::CompilerContext> &context,
+ TypeQueryOptions options)
+ : m_context(context), m_options(options) {
+ // Always use an exact match if we are looking for a type in compiler context.
+ m_options |= e_exact_match;
+}
+
+TypeQuery::TypeQuery(const CompilerDecl &decl, TypeQueryOptions options)
+ : m_options(options) {
+ // Always for an exact match if we are looking for a type using a declaration.
+ m_options |= e_exact_match;
+ m_context = decl.GetCompilerContext();
+}
+
+ConstString TypeQuery::GetTypeBasename() const {
+ if (m_context.empty())
+ return ConstString();
+ return m_context.back().name;
+}
+
+void TypeQuery::AddLanguage(LanguageType language) {
+ if (!m_languages)
+ m_languages = LanguageSet();
+ m_languages->Insert(language);
+}
+
+bool TypeQuery::ContextMatches(
+ llvm::ArrayRef<CompilerContext> context_chain) const {
+ if (GetExactMatch() || context_chain.size() == m_context.size())
+ return ::contextMatches(context_chain, m_context);
+
+ // We don't have an exact match, we need to bottom m_context.size() items to
+ // match for a successful lookup.
+ if (context_chain.size() < m_context.size())
+ return false; // Not enough items in context_chain to allow for a match.
+
+ size_t compare_count = context_chain.size() - m_context.size();
+ return ::contextMatches(
+ llvm::ArrayRef<CompilerContext>(context_chain.data() + compare_count,
+ m_context.size()),
+ m_context);
+}
+
+bool TypeQuery::LanguageMatches(lldb::LanguageType language) const {
+ // If we have no language filterm language always matches.
+ if (!m_languages.has_value())
+ return true;
+ return (*m_languages)[language];
+}
+
+bool TypeResults::AlreadySearched(lldb_private::SymbolFile *sym_file) {
+ return !m_searched_symbol_files.insert(sym_file).second;
+}
+
+bool TypeResults::InsertUnique(const lldb::TypeSP &type_sp) {
+ if (type_sp)
+ return m_type_map.InsertUnique(type_sp);
+ return false;
+}
+
+bool TypeResults::Done(const TypeQuery &query) const {
+ if (query.GetFindOne())
+ return !m_type_map.Empty();
+ return false;
+}
+
void CompilerContext::Dump(Stream &s) const {
switch (kind) {
default:
@@ -641,6 +762,8 @@ bool Type::GetTypeScopeAndBasename(llvm::StringRef name,
if (name.empty())
return false;
+ // Clear the scope in case we have just a type class and a basename.
+ scope = llvm::StringRef();
basename = name;
if (basename.consume_front("struct "))
type_class = eTypeClassStruct;
@@ -654,8 +777,10 @@ bool Type::GetTypeScopeAndBasename(llvm::StringRef name,
type_class = eTypeClassTypedef;
size_t namespace_separator = basename.find("::");
- if (namespace_separator == llvm::StringRef::npos)
- return false;
+ if (namespace_separator == llvm::StringRef::npos) {
+ // If "name" started a type class we need to return true with no scope.
+ return type_class != eTypeClassAny;
+ }
size_t template_begin = basename.find('<');
while (namespace_separator != llvm::StringRef::npos) {
@@ -1049,16 +1174,19 @@ CompilerType TypeImpl::FindDirectNestedType(llvm::StringRef name) {
return CompilerType();
auto type_system = GetTypeSystem(/*prefer_dynamic*/ false);
auto *symbol_file = type_system->GetSymbolFile();
+ if (!symbol_file)
+ return CompilerType();
auto decl_context = type_system->GetCompilerDeclContextForType(m_static_type);
if (!decl_context.IsValid())
return CompilerType();
- llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
- TypeMap search_result;
- symbol_file->FindTypes(ConstString(name), decl_context, /*max_matches*/ 1,
- searched_symbol_files, search_result);
- if (search_result.Empty())
- return CompilerType();
- return search_result.GetTypeAtIndex(0)->GetFullCompilerType();
+ TypeQuery query(decl_context, ConstString(name),
+ TypeQueryOptions::e_find_one);
+ TypeResults results;
+ symbol_file->FindTypes(query, results);
+ TypeSP type_sp = results.GetFirstType();
+ if (type_sp)
+ return type_sp->GetFullCompilerType();
+ return CompilerType();
}
bool TypeMemberFunctionImpl::IsValid() {
diff --git a/lldb/source/Symbol/TypeMap.cpp b/lldb/source/Symbol/TypeMap.cpp
index 0d5f6d5..8933de5 100644
--- a/lldb/source/Symbol/TypeMap.cpp
+++ b/lldb/source/Symbol/TypeMap.cpp
@@ -91,6 +91,12 @@ TypeSP TypeMap::GetTypeAtIndex(uint32_t idx) {
return TypeSP();
}
+lldb::TypeSP TypeMap::FirstType() const {
+ if (m_types.empty())
+ return TypeSP();
+ return m_types.begin()->second;
+}
+
void TypeMap::ForEach(
std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const {
for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) {
@@ -121,10 +127,10 @@ bool TypeMap::Remove(const lldb::TypeSP &type_sp) {
return false;
}
-void TypeMap::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) {
- for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) {
- pos->second->Dump(s, show_context, level);
- }
+void TypeMap::Dump(Stream *s, bool show_context,
+ lldb::DescriptionLevel level) const {
+ for (const auto &pair : m_types)
+ pair.second->Dump(s, show_context, level);
}
void TypeMap::RemoveMismatchedTypes(llvm::StringRef type_scope,
diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp
index 874f125..59b1b39 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -171,6 +171,16 @@ CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,
return CompilerType();
}
+std::vector<lldb_private::CompilerContext>
+TypeSystem::DeclGetCompilerContext(void *opaque_decl) {
+ return {};
+}
+
+std::vector<lldb_private::CompilerContext>
+TypeSystem::DeclContextGetCompilerContext(void *opaque_decl_ctx) {
+ return {};
+}
+
std::vector<CompilerDecl>
TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
bool ignore_imported_decls) {
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index 42c3350..caf3e66 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -434,12 +434,10 @@ bool Language::ImageListTypeScavenger::Find_Impl(
Target *target = exe_scope->CalculateTarget().get();
if (target) {
const auto &images(target->GetImages());
- ConstString cs_key(key);
- llvm::DenseSet<SymbolFile *> searched_sym_files;
- TypeList matches;
- images.FindTypes(nullptr, cs_key, false, UINT32_MAX, searched_sym_files,
- matches);
- for (const auto &match : matches.Types()) {
+ TypeQuery query(key);
+ TypeResults type_results;
+ images.FindTypes(nullptr, query, type_results);
+ for (const auto &match : type_results.GetTypeMap().Types()) {
if (match) {
CompilerType compiler_type(match->GetFullCompilerType());
compiler_type = AdjustForInclusion(compiler_type);
diff --git a/lldb/test/API/functionalities/type_find_first/Makefile b/lldb/test/API/functionalities/type_find_first/Makefile
new file mode 100644
index 0000000..3d0b98f
--- /dev/null
+++ b/lldb/test/API/functionalities/type_find_first/Makefile
@@ -0,0 +1,2 @@
+CXX_SOURCES := main.cpp
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py b/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py
new file mode 100644
index 0000000..432708d
--- /dev/null
+++ b/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py
@@ -0,0 +1,38 @@
+"""
+Test the SBModule and SBTarget type lookup APIs.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TypeFindFirstTestCase(TestBase):
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_find_first_type(self):
+ """
+ Test SBTarget::FindFirstType() and SBModule::FindFirstType() APIs.
+
+ This function had regressed after some past modification of the type
+ lookup internal code where if we had multiple types with the same
+ basename, FindFirstType() could end up failing depending on which
+ type was found first in the debug info indexes. This test will
+ ensure this doesn't regress in the future.
+ """
+ self.build()
+ target = self.createTestTarget()
+ # Test the SBTarget APIs for FindFirstType
+ integer_type = target.FindFirstType("Integer::Point")
+ self.assertTrue(integer_type.IsValid())
+ float_type = target.FindFirstType("Float::Point")
+ self.assertTrue(float_type.IsValid())
+
+ # Test the SBModule APIs for FindFirstType
+ exe_module = target.GetModuleAtIndex(0)
+ self.assertTrue(exe_module.IsValid())
+ integer_type = exe_module.FindFirstType("Integer::Point")
+ self.assertTrue(integer_type.IsValid())
+ float_type = exe_module.FindFirstType("Float::Point")
+ self.assertTrue(float_type.IsValid())
diff --git a/lldb/test/API/functionalities/type_find_first/main.cpp b/lldb/test/API/functionalities/type_find_first/main.cpp
new file mode 100644
index 0000000..f4e4672
--- /dev/null
+++ b/lldb/test/API/functionalities/type_find_first/main.cpp
@@ -0,0 +1,17 @@
+namespace Integer {
+struct Point {
+ int x, y;
+};
+} // namespace Integer
+
+namespace Float {
+struct Point {
+ float x, y;
+};
+} // namespace Float
+
+int main(int argc, char const *argv[]) {
+ Integer::Point ip = {2, 3};
+ Float::Point fp = {2.0, 3.0};
+ return 0;
+}
diff --git a/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py b/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py
index d9ac07f..3fa694fa1 100644
--- a/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py
+++ b/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py
@@ -17,27 +17,20 @@ class UniqueTypesTestCase4(TestBase):
)
# FIXME: these should successfully print the values
self.expect(
- "expression ns::Foo<double>::value", substrs=["no member named"], error=True
+ "expression ns::Foo<double>::value", substrs=["'Foo' in namespace 'ns'"], error=True
)
self.expect(
- "expression ns::Foo<int>::value", substrs=["no member named"], error=True
+ "expression ns::Foo<int>::value", substrs=["'Foo' in namespace 'ns'"], error=True
)
self.expect(
- "expression ns::Bar<double>::value", substrs=["no member named"], error=True
+ "expression ns::Bar<double>::value", substrs=["'Bar' in namespace 'ns'"], error=True
)
self.expect(
- "expression ns::Bar<int>::value", substrs=["no member named"], error=True
- )
- self.expect(
- "expression ns::FooDouble::value",
- substrs=["Couldn't look up symbols"],
- error=True,
- )
- self.expect(
- "expression ns::FooInt::value",
- substrs=["Couldn't look up symbols"],
- error=True,
+ "expression ns::Bar<int>::value", substrs=["'Bar' in namespace 'ns'"], error=True
)
+ self.expect_expr("ns::FooDouble::value", result_type="double", result_value="0")
+ self.expect_expr("ns::FooInt::value", result_type="int", result_value="0")
+
@skipIf(compiler=no_match("clang"))
@skipIf(compiler_version=["<", "15.0"])
diff --git a/lldb/test/API/lang/cpp/unique-types4/main.cpp b/lldb/test/API/lang/cpp/unique-types4/main.cpp
index 8306352..815b4f9 100644
--- a/lldb/test/API/lang/cpp/unique-types4/main.cpp
+++ b/lldb/test/API/lang/cpp/unique-types4/main.cpp
@@ -4,6 +4,8 @@ template <typename T> struct Foo {
static T value;
};
+template <class T> T Foo<T>::value = 0;
+
template <typename T> using Bar = Foo<T>;
using FooInt = Foo<int>;
@@ -20,4 +22,6 @@ ns::FooDouble f;
int main() {
// Set breakpoint here
+ return (int)a.value + b.value + (int)c.value + d.value + e.value +
+ (int)f.value;
}
diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp
index 45911b9..e326a84 100644
--- a/lldb/tools/lldb-test/lldb-test.cpp
+++ b/lldb/tools/lldb-test/lldb-test.cpp
@@ -290,8 +290,8 @@ int lldb_assert(Debugger &Dbg);
} // namespace assert
} // namespace opts
-std::vector<CompilerContext> parseCompilerContext() {
- std::vector<CompilerContext> result;
+llvm::SmallVector<CompilerContext, 4> parseCompilerContext() {
+ llvm::SmallVector<CompilerContext, 4> result;
if (opts::symbols::CompilerContext.empty())
return result;
@@ -577,29 +577,33 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) {
Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile);
if (!ContextOr)
return ContextOr.takeError();
- const CompilerDeclContext &ContextPtr =
- ContextOr->IsValid() ? *ContextOr : CompilerDeclContext();
-
- LanguageSet languages;
- if (!Language.empty())
- languages.Insert(Language::GetLanguageTypeFromString(Language));
-
- DenseSet<SymbolFile *> SearchedFiles;
- TypeMap Map;
- if (!Name.empty())
- Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles,
- Map);
- else
- Module.FindTypes(parseCompilerContext(), languages, SearchedFiles, Map);
- outs() << formatv("Found {0} types:\n", Map.GetSize());
+ TypeResults results;
+ if (!Name.empty()) {
+ if (ContextOr->IsValid()) {
+ TypeQuery query(*ContextOr, ConstString(Name),
+ TypeQueryOptions::e_module_search);
+ if (!Language.empty())
+ query.AddLanguage(Language::GetLanguageTypeFromString(Language));
+ Symfile.FindTypes(query, results);
+ } else {
+ TypeQuery query(Name);
+ if (!Language.empty())
+ query.AddLanguage(Language::GetLanguageTypeFromString(Language));
+ Symfile.FindTypes(query, results);
+ }
+ } else {
+ TypeQuery query(parseCompilerContext(), TypeQueryOptions::e_module_search);
+ if (!Language.empty())
+ query.AddLanguage(Language::GetLanguageTypeFromString(Language));
+ Symfile.FindTypes(query, results);
+ }
+ outs() << formatv("Found {0} types:\n", results.GetTypeMap().GetSize());
StreamString Stream;
// Resolve types to force-materialize typedef types.
- Map.ForEach([&](TypeSP &type) {
- type->GetFullCompilerType();
- return false;
- });
- Map.Dump(&Stream, false, GetDescriptionLevel());
+ for (const auto &type_sp : results.GetTypeMap().Types())
+ type_sp->GetFullCompilerType();
+ results.GetTypeMap().Dump(&Stream, false, GetDescriptionLevel());
outs() << Stream.GetData() << "\n";
return Error::success();
}