You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
14 KiB
393 lines
14 KiB
4 months ago
|
//===-- ClangASTSource.h ----------------------------------------*- C++ -*-===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
|
||
|
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
|
||
|
|
||
|
#include <set>
|
||
|
|
||
|
#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
|
||
|
#include "Plugins/ExpressionParser/Clang/NameSearchContext.h"
|
||
|
#include "lldb/Symbol/CompilerType.h"
|
||
|
#include "lldb/Target/Target.h"
|
||
|
#include "clang/AST/ExternalASTSource.h"
|
||
|
#include "clang/Basic/IdentifierTable.h"
|
||
|
|
||
|
#include "llvm/ADT/SmallSet.h"
|
||
|
|
||
|
namespace lldb_private {
|
||
|
|
||
|
/// \class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h"
|
||
|
/// 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 clang::ExternalASTSource,
|
||
|
public ClangASTImporter::MapCompleter {
|
||
|
public:
|
||
|
/// Constructor
|
||
|
///
|
||
|
/// Initializes class variables.
|
||
|
///
|
||
|
/// \param[in] target
|
||
|
/// A reference to the target containing debug information to use.
|
||
|
///
|
||
|
/// \param[in] importer
|
||
|
/// The ClangASTImporter to use.
|
||
|
ClangASTSource(const lldb::TargetSP &target,
|
||
|
const std::shared_ptr<ClangASTImporter> &importer);
|
||
|
|
||
|
/// Destructor
|
||
|
~ClangASTSource() override;
|
||
|
|
||
|
/// Interface stubs.
|
||
|
clang::Decl *GetExternalDecl(uint32_t) override { return nullptr; }
|
||
|
clang::Stmt *GetExternalDeclStmt(uint64_t) override { return nullptr; }
|
||
|
clang::Selector GetExternalSelector(uint32_t) override {
|
||
|
return clang::Selector();
|
||
|
}
|
||
|
uint32_t GetNumExternalSelectors() override { return 0; }
|
||
|
clang::CXXBaseSpecifier *
|
||
|
GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
|
||
|
return nullptr;
|
||
|
}
|
||
|
void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; }
|
||
|
|
||
|
void InstallASTContext(TypeSystemClang &ast_context);
|
||
|
|
||
|
//
|
||
|
// 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] Consumer
|
||
|
/// 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, 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);
|
||
|
|
||
|
clang::Sema *getSema();
|
||
|
|
||
|
void SetLookupsEnabled(bool lookups_enabled) {
|
||
|
m_lookups_enabled = lookups_enabled;
|
||
|
}
|
||
|
bool GetLookupsEnabled() { return m_lookups_enabled; }
|
||
|
|
||
|
/// \class ClangASTSourceProxy ClangASTSource.h
|
||
|
/// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource
|
||
|
///
|
||
|
/// Clang AST contexts like to own their AST sources, so this is a state-
|
||
|
/// free proxy object.
|
||
|
class ClangASTSourceProxy : public clang::ExternalASTSource {
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
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(const 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.
|
||
|
void FindExternalVisibleDecls(NameSearchContext &context,
|
||
|
lldb::ModuleSP module,
|
||
|
CompilerDeclContext &namespace_decl);
|
||
|
|
||
|
/// 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);
|
||
|
|
||
|
/// Performs lookup into a namespace.
|
||
|
///
|
||
|
/// \param context
|
||
|
/// The NameSearchContext for a lookup inside a namespace.
|
||
|
void LookupInNamespace(NameSearchContext &context);
|
||
|
|
||
|
/// A wrapper for TypeSystemClang::CopyType that sets a flag that
|
||
|
/// indicates that we should not respond to queries during import.
|
||
|
///
|
||
|
/// \param[in] src_type
|
||
|
/// The source type.
|
||
|
///
|
||
|
/// \return
|
||
|
/// The imported type.
|
||
|
CompilerType GuardedCopyType(const CompilerType &src_type);
|
||
|
|
||
|
public:
|
||
|
/// Returns true if a name should be ignored by name lookup.
|
||
|
///
|
||
|
/// \param[in] name
|
||
|
/// The name to be considered.
|
||
|
///
|
||
|
/// \param[in] ignore_all_dollar_names
|
||
|
/// True if $-names of all sorts should be ignored.
|
||
|
///
|
||
|
/// \return
|
||
|
/// True if the name is one of a class of names that are ignored by
|
||
|
/// global lookup for performance reasons.
|
||
|
bool IgnoreName(const ConstString name, bool ignore_all_dollar_names);
|
||
|
|
||
|
/// Copies a single Decl into the parser's AST context.
|
||
|
///
|
||
|
/// \param[in] src_decl
|
||
|
/// The Decl to copy.
|
||
|
///
|
||
|
/// \return
|
||
|
/// A copy of the Decl in m_ast_context, or NULL if the copy failed.
|
||
|
clang::Decl *CopyDecl(clang::Decl *src_decl);
|
||
|
|
||
|
/// Determined the origin of a single Decl, if it can be found.
|
||
|
///
|
||
|
/// \param[in] decl
|
||
|
/// The Decl whose origin is to be found.
|
||
|
///
|
||
|
/// \return
|
||
|
/// True if lookup succeeded; false otherwise.
|
||
|
ClangASTImporter::DeclOrigin GetDeclOrigin(const clang::Decl *decl);
|
||
|
|
||
|
/// Returns the TypeSystem that uses this ClangASTSource instance as it's
|
||
|
/// ExternalASTSource.
|
||
|
TypeSystemClang *GetTypeSystem() const { return m_clang_ast_context; }
|
||
|
|
||
|
protected:
|
||
|
bool FindObjCMethodDeclsWithOrigin(
|
||
|
NameSearchContext &context,
|
||
|
clang::ObjCInterfaceDecl *original_interface_decl, const char *log_info);
|
||
|
|
||
|
void FindDeclInModules(NameSearchContext &context, ConstString name);
|
||
|
void FindDeclInObjCRuntime(NameSearchContext &context, ConstString name);
|
||
|
|
||
|
/// Fills the namespace map of the given NameSearchContext.
|
||
|
///
|
||
|
/// \param context The NameSearchContext with the namespace map to fill.
|
||
|
/// \param module_sp The module to search for namespaces or a nullptr if
|
||
|
/// the current target should be searched.
|
||
|
/// \param namespace_decl The DeclContext in which to search for namespaces.
|
||
|
void FillNamespaceMap(NameSearchContext &context, lldb::ModuleSP module_sp,
|
||
|
const CompilerDeclContext &namespace_decl);
|
||
|
|
||
|
clang::TagDecl *FindCompleteType(const clang::TagDecl *decl);
|
||
|
|
||
|
friend struct NameSearchContext;
|
||
|
|
||
|
bool m_lookups_enabled;
|
||
|
|
||
|
/// The target to use in finding variables and types.
|
||
|
const lldb::TargetSP m_target;
|
||
|
/// The AST context requests are coming in for.
|
||
|
clang::ASTContext *m_ast_context;
|
||
|
/// The TypeSystemClang for m_ast_context.
|
||
|
TypeSystemClang *m_clang_ast_context;
|
||
|
/// The file manager paired with the AST context.
|
||
|
clang::FileManager *m_file_manager;
|
||
|
/// The target's AST importer.
|
||
|
std::shared_ptr<ClangASTImporter> m_ast_importer_sp;
|
||
|
std::set<const clang::Decl *> m_active_lexical_decls;
|
||
|
std::set<const char *> m_active_lookups;
|
||
|
};
|
||
|
|
||
|
} // namespace lldb_private
|
||
|
|
||
|
#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
|