diff options
Diffstat (limited to 'source/Plugins/ExpressionParser/Clang/ClangASTSource.h')
-rw-r--r-- | source/Plugins/ExpressionParser/Clang/ClangASTSource.h | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h new file mode 100644 index 0000000..bb63847 --- /dev/null +++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -0,0 +1,526 @@ +//===-- ClangASTSource.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangASTSource_h_ +#define liblldb_ClangASTSource_h_ + +#include <set> + +#include "clang/Basic/IdentifierTable.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" +#include "lldb/Symbol/ClangASTImporter.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Target/Target.h" + +#include "llvm/ADT/SmallSet.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Provider for named objects defined in the debug info for Clang +/// +/// As Clang parses an expression, it may encounter names that are not +/// defined inside the expression, including variables, functions, and +/// types. Clang knows the name it is looking for, but nothing else. +/// The ExternalSemaSource class provides Decls (VarDecl, FunDecl, TypeDecl) +/// to Clang for these names, consulting the ClangExpressionDeclMap to do +/// the actual lookups. +//---------------------------------------------------------------------- +class ClangASTSource : + public ClangExternalASTSourceCommon, + public ClangASTImporter::MapCompleter +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] declMap + /// A reference to the LLDB object that handles entity lookup. + //------------------------------------------------------------------ + ClangASTSource (const lldb::TargetSP &target) : + m_import_in_progress (false), + m_lookups_enabled (false), + m_target (target), + m_ast_context (NULL), + m_active_lexical_decls (), + m_active_lookups () + { + m_ast_importer_sp = m_target->GetClangASTImporter(); + } + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangASTSource() override; + + //------------------------------------------------------------------ + /// Interface stubs. + //------------------------------------------------------------------ + clang::Decl *GetExternalDecl (uint32_t) override { return NULL; } + clang::Stmt *GetExternalDeclStmt (uint64_t) override { return NULL; } + clang::Selector GetExternalSelector (uint32_t) override { return clang::Selector(); } + uint32_t GetNumExternalSelectors () override { return 0; } + clang::CXXBaseSpecifier *GetExternalCXXBaseSpecifiers (uint64_t Offset) override + { return NULL; } + void MaterializeVisibleDecls (const clang::DeclContext *DC) + { return; } + + void InstallASTContext (clang::ASTContext *ast_context) + { + m_ast_context = ast_context; + m_ast_importer_sp->InstallMapCompleter(ast_context, *this); + } + + // + // APIs for ExternalASTSource + // + + //------------------------------------------------------------------ + /// Look up all Decls that match a particular name. Only handles + /// Identifiers and DeclContexts that are either NamespaceDecls or + /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with + /// the result. + /// + /// The work for this function is done by + /// void FindExternalVisibleDecls (NameSearchContext &); + /// + /// @param[in] DC + /// The DeclContext to register the found Decls in. + /// + /// @param[in] Name + /// The name to find entries for. + /// + /// @return + /// Whatever SetExternalVisibleDeclsForName returns. + //------------------------------------------------------------------ + bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override; + + //------------------------------------------------------------------ + /// Enumerate all Decls in a given lexical context. + /// + /// @param[in] DC + /// The DeclContext being searched. + /// + /// @param[in] isKindWeWant + /// A callback function that returns true given the + /// DeclKinds of desired Decls, and false otherwise. + /// + /// @param[in] Decls + /// A vector that is filled in with matching Decls. + //------------------------------------------------------------------ + void FindExternalLexicalDecls( + const clang::DeclContext *DC, llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, + llvm::SmallVectorImpl<clang::Decl *> &Decls) override; + + //------------------------------------------------------------------ + /// Specify the layout of the contents of a RecordDecl. + /// + /// @param[in] Record + /// The record (in the parser's AST context) that needs to be + /// laid out. + /// + /// @param[out] Size + /// The total size of the record in bits. + /// + /// @param[out] Alignment + /// The alignment of the record in bits. + /// + /// @param[in] FieldOffsets + /// A map that must be populated with pairs of the record's + /// fields (in the parser's AST context) and their offsets + /// (measured in bits). + /// + /// @param[in] BaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ concrete base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @param[in] VirtualBaseOffsets + /// A map that must be populated with pairs of the record's + /// C++ virtual base classes (in the parser's AST context, + /// and only if the record is a CXXRecordDecl and has base + /// classes) and their offsets (measured in bytes). + /// + /// @return + /// True <=> the layout is valid. + //----------------------------------------------------------------- + bool layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override; + + //------------------------------------------------------------------ + /// Complete a TagDecl. + /// + /// @param[in] Tag + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::TagDecl *Tag) override; + + //------------------------------------------------------------------ + /// Complete an ObjCInterfaceDecl. + /// + /// @param[in] Class + /// The Decl to be completed in place. + //------------------------------------------------------------------ + void CompleteType(clang::ObjCInterfaceDecl *Class) override; + + //------------------------------------------------------------------ + /// Called on entering a translation unit. Tells Clang by calling + /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() + /// that this object has something to say about undefined names. + /// + /// @param[in] ASTConsumer + /// Unused. + //------------------------------------------------------------------ + void StartTranslationUnit(clang::ASTConsumer *Consumer) override; + + // + // APIs for NamespaceMapCompleter + // + + //------------------------------------------------------------------ + /// Look up the modules containing a given namespace and put the + /// appropriate entries in the namespace map. + /// + /// @param[in] namespace_map + /// The map to be completed. + /// + /// @param[in] name + /// The name of the namespace to be found. + /// + /// @param[in] parent_map + /// The map for the namespace's parent namespace, if there is + /// one. + //------------------------------------------------------------------ + void CompleteNamespaceMap(ClangASTImporter::NamespaceMapSP &namespace_map, const ConstString &name, + ClangASTImporter::NamespaceMapSP &parent_map) const override; + + // + // Helper APIs + // + + clang::NamespaceDecl * + AddNamespace (NameSearchContext &context, + ClangASTImporter::NamespaceMapSP &namespace_decls); + + //------------------------------------------------------------------ + /// The worker function for FindExternalVisibleDeclsByName. + /// + /// @param[in] context + /// The NameSearchContext to use when filing results. + //------------------------------------------------------------------ + virtual void FindExternalVisibleDecls (NameSearchContext &context); + + void SetImportInProgress (bool import_in_progress) { m_import_in_progress = import_in_progress; } + bool GetImportInProgress () { return m_import_in_progress; } + + void SetLookupsEnabled (bool lookups_enabled) { m_lookups_enabled = lookups_enabled; } + bool GetLookupsEnabled () { return m_lookups_enabled; } + + //---------------------------------------------------------------------- + /// @class ClangASTSourceProxy ClangASTSource.h "lldb/Expression/ClangASTSource.h" + /// @brief Proxy for ClangASTSource + /// + /// Clang AST contexts like to own their AST sources, so this is a + /// state-free proxy object. + //---------------------------------------------------------------------- + class ClangASTSourceProxy : public ClangExternalASTSourceCommon + { + public: + ClangASTSourceProxy (ClangASTSource &original) : + m_original(original) + { + } + + bool + FindExternalVisibleDeclsByName(const clang::DeclContext *DC, clang::DeclarationName Name) override + { + return m_original.FindExternalVisibleDeclsByName(DC, Name); + } + + void + FindExternalLexicalDecls(const clang::DeclContext *DC, + llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, + llvm::SmallVectorImpl<clang::Decl *> &Decls) override + { + return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls); + } + + void + CompleteType(clang::TagDecl *Tag) override + { + return m_original.CompleteType(Tag); + } + + void + CompleteType(clang::ObjCInterfaceDecl *Class) override + { + return m_original.CompleteType(Class); + } + + bool + layoutRecordType(const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, + llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets) override + { + return m_original.layoutRecordType(Record, + Size, + Alignment, + FieldOffsets, + BaseOffsets, + VirtualBaseOffsets); + } + + void + StartTranslationUnit(clang::ASTConsumer *Consumer) override + { + return m_original.StartTranslationUnit(Consumer); + } + + ClangASTMetadata * + GetMetadata(const void * object) + { + return m_original.GetMetadata(object); + } + + void + SetMetadata(const void * object, ClangASTMetadata &metadata) + { + return m_original.SetMetadata(object, metadata); + } + + bool + HasMetadata(const void * object) + { + return m_original.HasMetadata(object); + } + private: + ClangASTSource &m_original; + }; + + clang::ExternalASTSource *CreateProxy() + { + return new ClangASTSourceProxy(*this); + } + +protected: + //------------------------------------------------------------------ + /// Look for the complete version of an Objective-C interface, and + /// return it if found. + /// + /// @param[in] interface_decl + /// An ObjCInterfaceDecl that may not be the complete one. + /// + /// @return + /// NULL if the complete interface couldn't be found; + /// the complete interface otherwise. + //------------------------------------------------------------------ + clang::ObjCInterfaceDecl * + GetCompleteObjCInterface (clang::ObjCInterfaceDecl *interface_decl); + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + CompilerDeclContext &namespace_decl, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Find all Objective-C methods matching a given selector. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the selector and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCMethodDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// Find all Objective-C properties and ivars with a given name. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// Its m_decl_name contains the name and its m_decl_context + /// is the containing object. + //------------------------------------------------------------------ + void + FindObjCPropertyAndIvarDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// A wrapper for ClangASTContext::CopyType that sets a flag that + /// indicates that we should not respond to queries during import. + /// + /// @param[in] dest_context + /// The target AST context, typically the parser's AST context. + /// + /// @param[in] source_context + /// The source AST context, typically the AST context of whatever + /// symbol file the type was found in. + /// + /// @param[in] src_type + /// The source type. + /// + /// @return + /// The imported type. + //------------------------------------------------------------------ + CompilerType + GuardedCopyType (const CompilerType &src_type); + + friend struct NameSearchContext; + + bool m_import_in_progress; + bool m_lookups_enabled; + + const lldb::TargetSP m_target; ///< The target to use in finding variables and types. + clang::ASTContext *m_ast_context; ///< The AST context requests are coming in for. + lldb::ClangASTImporterSP m_ast_importer_sp; ///< The target's AST importer. + std::set<const clang::Decl *> m_active_lexical_decls; + std::set<const char *> m_active_lookups; +}; + +//---------------------------------------------------------------------- +/// @class NameSearchContext ClangASTSource.h "lldb/Expression/ClangASTSource.h" +/// @brief Container for all objects relevant to a single name lookup +/// +/// LLDB needs to create Decls for entities it finds. This class communicates +/// what name is being searched for and provides helper functions to construct +/// Decls given appropriate type information. +//---------------------------------------------------------------------- +struct NameSearchContext { + ClangASTSource &m_ast_source; ///< The AST source making the request + llvm::SmallVectorImpl<clang::NamedDecl*> &m_decls; ///< The list of declarations already constructed + ClangASTImporter::NamespaceMapSP m_namespace_map; ///< The mapping of all namespaces found for this request back to their modules + const clang::DeclarationName &m_decl_name; ///< The name being looked for + const clang::DeclContext *m_decl_context; ///< The DeclContext to put declarations into + llvm::SmallSet <CompilerType, 5> m_function_types; ///< All the types of functions that have been reported, so we don't report conflicts + + struct { + bool variable : 1; + bool function_with_type_info : 1; + bool function : 1; + } m_found; + + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] astSource + /// A reference to the AST source making a request. + /// + /// @param[in] decls + /// A reference to a list into which new Decls will be placed. This + /// list is typically empty when the function is called. + /// + /// @param[in] name + /// The name being searched for (always an Identifier). + /// + /// @param[in] dc + /// The DeclContext to register Decls in. + //------------------------------------------------------------------ + NameSearchContext (ClangASTSource &astSource, + llvm::SmallVectorImpl<clang::NamedDecl*> &decls, + clang::DeclarationName &name, + const clang::DeclContext *dc) : + m_ast_source(astSource), + m_decls(decls), + m_decl_name(name), + m_decl_context(dc) + { + memset(&m_found, 0, sizeof(m_found)); + } + + //------------------------------------------------------------------ + /// Create a VarDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the VarDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddVarDecl(const CompilerType &type); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] type + /// The opaque QualType for the FunDecl being registered. + /// + /// @param[in] extern_c + /// If true, build an extern "C" linkage specification for this. + //------------------------------------------------------------------ + clang::NamedDecl *AddFunDecl(const CompilerType &type, + bool extern_c = false); + + //------------------------------------------------------------------ + /// Create a FunDecl with the name being searched for and generic + /// type (i.e. intptr_t NAME_GOES_HERE(...)) and register it in the + /// right places. + //------------------------------------------------------------------ + clang::NamedDecl *AddGenericFunDecl(); + + //------------------------------------------------------------------ + /// Create a TypeDecl with the name being searched for and the provided + /// type and register it in the right places. + /// + /// @param[in] compiler_type + /// The opaque QualType for the TypeDecl being registered. + //------------------------------------------------------------------ + clang::NamedDecl *AddTypeDecl(const CompilerType &compiler_type); + + + //------------------------------------------------------------------ + /// Add Decls from the provided DeclContextLookupResult to the list + /// of results. + /// + /// @param[in] result + /// The DeclContextLookupResult, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddLookupResult (clang::DeclContextLookupResult result); + + //------------------------------------------------------------------ + /// Add a NamedDecl to the list of results. + /// + /// @param[in] decl + /// The NamedDecl, usually returned as the result + /// of querying a DeclContext. + //------------------------------------------------------------------ + void AddNamedDecl (clang::NamedDecl *decl); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangASTSource_h_ |