//===-- 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 #include "lldb/Symbol/ClangASTImporter.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Target/Target.h" #include "clang/Basic/IdentifierTable.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 IsKindWeWant, llvm::SmallVectorImpl &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 &FieldOffsets, llvm::DenseMap &BaseOffsets, llvm::DenseMap &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 IsKindWeWant, llvm::SmallVectorImpl &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 &FieldOffsets, llvm::DenseMap &BaseOffsets, llvm::DenseMap &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. //------------------------------------------------------------------ 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 m_active_lexical_decls; std::set 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 &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 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; bool local_vars_nsp : 1; bool type : 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 &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_