403 lines · c
1//===-- ClangASTSource.h ----------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H10#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H11 12#include <set>13 14#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"15#include "Plugins/ExpressionParser/Clang/NameSearchContext.h"16#include "lldb/Symbol/CompilerType.h"17#include "lldb/Target/Target.h"18#include "clang/AST/ExternalASTSource.h"19#include "clang/Basic/IdentifierTable.h"20 21#include "llvm/ADT/SmallSet.h"22 23namespace lldb_private {24 25/// \class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h"26/// Provider for named objects defined in the debug info for Clang27///28/// As Clang parses an expression, it may encounter names that are not defined29/// inside the expression, including variables, functions, and types. Clang30/// knows the name it is looking for, but nothing else. The ExternalSemaSource31/// class provides Decls (VarDecl, FunDecl, TypeDecl) to Clang for these32/// names, consulting the ClangExpressionDeclMap to do the actual lookups.33class ClangASTSource : public clang::ExternalASTSource,34 public ClangASTImporter::MapCompleter {35public:36 /// Constructor37 ///38 /// Initializes class variables.39 ///40 /// \param[in] target41 /// A reference to the target containing debug information to use.42 ///43 /// \param[in] importer44 /// The ClangASTImporter to use.45 ClangASTSource(const lldb::TargetSP &target,46 const std::shared_ptr<ClangASTImporter> &importer);47 48 /// Destructor49 ~ClangASTSource() override;50 51 /// Interface stubs.52 clang::Decl *GetExternalDecl(clang::GlobalDeclID) override { return nullptr; }53 clang::Stmt *GetExternalDeclStmt(uint64_t) override { return nullptr; }54 clang::Selector GetExternalSelector(uint32_t) override {55 return clang::Selector();56 }57 uint32_t GetNumExternalSelectors() override { return 0; }58 clang::CXXBaseSpecifier *59 GetExternalCXXBaseSpecifiers(uint64_t Offset) override {60 return nullptr;61 }62 void MaterializeVisibleDecls(const clang::DeclContext *DC) {}63 64 void InstallASTContext(TypeSystemClang &ast_context);65 66 //67 // APIs for ExternalASTSource68 //69 70 /// Look up all Decls that match a particular name. Only handles71 /// Identifiers and DeclContexts that are either NamespaceDecls or72 /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with the73 /// result.74 ///75 /// The work for this function is done by76 /// void FindExternalVisibleDecls (NameSearchContext &);77 ///78 /// \param[in] DC79 /// The DeclContext to register the found Decls in.80 ///81 /// \param[in] Name82 /// The name to find entries for.83 ///84 /// \return85 /// Whatever SetExternalVisibleDeclsForName returns.86 bool87 FindExternalVisibleDeclsByName(const clang::DeclContext *DC,88 clang::DeclarationName Name,89 const clang::DeclContext *OriginalDC) override;90 91 /// Enumerate all Decls in a given lexical context.92 ///93 /// \param[in] DC94 /// The DeclContext being searched.95 ///96 /// \param[in] IsKindWeWant97 /// A callback function that returns true given the98 /// DeclKinds of desired Decls, and false otherwise.99 ///100 /// \param[in] Decls101 /// A vector that is filled in with matching Decls.102 void FindExternalLexicalDecls(103 const clang::DeclContext *DC,104 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,105 llvm::SmallVectorImpl<clang::Decl *> &Decls) override;106 107 /// Specify the layout of the contents of a RecordDecl.108 ///109 /// \param[in] Record110 /// The record (in the parser's AST context) that needs to be111 /// laid out.112 ///113 /// \param[out] Size114 /// The total size of the record in bits.115 ///116 /// \param[out] Alignment117 /// The alignment of the record in bits.118 ///119 /// \param[in] FieldOffsets120 /// A map that must be populated with pairs of the record's121 /// fields (in the parser's AST context) and their offsets122 /// (measured in bits).123 ///124 /// \param[in] BaseOffsets125 /// A map that must be populated with pairs of the record's126 /// C++ concrete base classes (in the parser's AST context,127 /// and only if the record is a CXXRecordDecl and has base128 /// classes) and their offsets (measured in bytes).129 ///130 /// \param[in] VirtualBaseOffsets131 /// A map that must be populated with pairs of the record's132 /// C++ virtual base classes (in the parser's AST context,133 /// and only if the record is a CXXRecordDecl and has base134 /// classes) and their offsets (measured in bytes).135 ///136 /// \return137 /// True <=> the layout is valid.138 bool layoutRecordType(139 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,140 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,141 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>142 &BaseOffsets,143 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>144 &VirtualBaseOffsets) override;145 146 /// Complete a TagDecl.147 ///148 /// \param[in] Tag149 /// The Decl to be completed in place.150 void CompleteType(clang::TagDecl *Tag) override;151 152 /// Complete an ObjCInterfaceDecl.153 ///154 /// \param[in] Class155 /// The Decl to be completed in place.156 void CompleteType(clang::ObjCInterfaceDecl *Class) override;157 158 /// Called on entering a translation unit. Tells Clang by calling159 /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that160 /// this object has something to say about undefined names.161 ///162 /// \param[in] Consumer163 /// Unused.164 void StartTranslationUnit(clang::ASTConsumer *Consumer) override;165 166 //167 // APIs for NamespaceMapCompleter168 //169 170 /// Look up the modules containing a given namespace and put the appropriate171 /// entries in the namespace map.172 ///173 /// \param[in] namespace_map174 /// The map to be completed.175 ///176 /// \param[in] name177 /// The name of the namespace to be found.178 ///179 /// \param[in] parent_map180 /// The map for the namespace's parent namespace, if there is181 /// one.182 void CompleteNamespaceMap(183 ClangASTImporter::NamespaceMapSP &namespace_map, ConstString name,184 ClangASTImporter::NamespaceMapSP &parent_map) const override;185 186 //187 // Helper APIs188 //189 190 clang::NamespaceDecl *191 AddNamespace(NameSearchContext &context,192 ClangASTImporter::NamespaceMapSP &namespace_decls);193 194 /// The worker function for FindExternalVisibleDeclsByName.195 ///196 /// \param[in] context197 /// The NameSearchContext to use when filing results.198 virtual void FindExternalVisibleDecls(NameSearchContext &context);199 200 clang::Sema *getSema();201 202 void SetLookupsEnabled(bool lookups_enabled) {203 m_lookups_enabled = lookups_enabled;204 }205 bool GetLookupsEnabled() { return m_lookups_enabled; }206 207 /// \class ClangASTSourceProxy ClangASTSource.h208 /// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource209 ///210 /// Clang AST contexts like to own their AST sources, so this is a state-211 /// free proxy object.212 class ClangASTSourceProxy : public clang::ExternalASTSource {213 public:214 ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {}215 216 bool FindExternalVisibleDeclsByName(217 const clang::DeclContext *DC, clang::DeclarationName Name,218 const clang::DeclContext *OriginalDC) override {219 return m_original.FindExternalVisibleDeclsByName(DC, Name, OriginalDC);220 }221 222 void FindExternalLexicalDecls(223 const clang::DeclContext *DC,224 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,225 llvm::SmallVectorImpl<clang::Decl *> &Decls) override {226 return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls);227 }228 229 void CompleteType(clang::TagDecl *Tag) override {230 return m_original.CompleteType(Tag);231 }232 233 void CompleteType(clang::ObjCInterfaceDecl *Class) override {234 return m_original.CompleteType(Class);235 }236 237 bool layoutRecordType(238 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,239 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,240 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>241 &BaseOffsets,242 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>243 &VirtualBaseOffsets) override {244 return m_original.layoutRecordType(Record, Size, Alignment, FieldOffsets,245 BaseOffsets, VirtualBaseOffsets);246 }247 248 void StartTranslationUnit(clang::ASTConsumer *Consumer) override {249 return m_original.StartTranslationUnit(Consumer);250 }251 252 private:253 ClangASTSource &m_original;254 };255 256 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> CreateProxy() {257 return llvm::makeIntrusiveRefCnt<ClangASTSourceProxy>(*this);258 }259 260protected:261 /// Look for the complete version of an Objective-C interface, and return it262 /// if found.263 ///264 /// \param[in] interface_decl265 /// An ObjCInterfaceDecl that may not be the complete one.266 ///267 /// \return268 /// NULL if the complete interface couldn't be found;269 /// the complete interface otherwise.270 clang::ObjCInterfaceDecl *271 GetCompleteObjCInterface(const clang::ObjCInterfaceDecl *interface_decl);272 273 /// Find all entities matching a given name in a given module, using a274 /// NameSearchContext to make Decls for them.275 ///276 /// \param[in] context277 /// The NameSearchContext that can construct Decls for this name.278 ///279 /// \param[in] module280 /// If non-NULL, the module to query.281 ///282 /// \param[in] namespace_decl283 /// If valid and module is non-NULL, the parent namespace.284 void FindExternalVisibleDecls(NameSearchContext &context,285 lldb::ModuleSP module,286 CompilerDeclContext &namespace_decl);287 288 /// Find all Objective-C methods matching a given selector.289 ///290 /// \param[in] context291 /// The NameSearchContext that can construct Decls for this name.292 /// Its m_decl_name contains the selector and its m_decl_context293 /// is the containing object.294 void FindObjCMethodDecls(NameSearchContext &context);295 296 /// Find all Objective-C properties and ivars with a given name.297 ///298 /// \param[in] context299 /// The NameSearchContext that can construct Decls for this name.300 /// Its m_decl_name contains the name and its m_decl_context301 /// is the containing object.302 void FindObjCPropertyAndIvarDecls(NameSearchContext &context);303 304 /// Performs lookup into a namespace.305 ///306 /// \param context307 /// The NameSearchContext for a lookup inside a namespace.308 void LookupInNamespace(NameSearchContext &context);309 310 /// A wrapper for TypeSystemClang::CopyType that sets a flag that311 /// indicates that we should not respond to queries during import.312 ///313 /// \param[in] src_type314 /// The source type.315 ///316 /// \return317 /// The imported type.318 CompilerType GuardedCopyType(const CompilerType &src_type);319 320 std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor();321 322public:323 /// Returns true if a name should be ignored by name lookup.324 ///325 /// \param[in] name326 /// The name to be considered.327 ///328 /// \param[in] ignore_all_dollar_names329 /// True if $-names of all sorts should be ignored.330 ///331 /// \return332 /// True if the name is one of a class of names that are ignored by333 /// global lookup for performance reasons.334 bool IgnoreName(const ConstString name, bool ignore_all_dollar_names);335 336 /// Copies a single Decl into the parser's AST context.337 ///338 /// \param[in] src_decl339 /// The Decl to copy.340 ///341 /// \return342 /// A copy of the Decl in m_ast_context, or NULL if the copy failed.343 clang::Decl *CopyDecl(clang::Decl *src_decl);344 345 /// Determined the origin of a single Decl, if it can be found.346 ///347 /// \param[in] decl348 /// The Decl whose origin is to be found.349 ///350 /// \return351 /// True if lookup succeeded; false otherwise.352 ClangASTImporter::DeclOrigin GetDeclOrigin(const clang::Decl *decl);353 354 /// Returns the TypeSystem that uses this ClangASTSource instance as it's355 /// ExternalASTSource.356 TypeSystemClang *GetTypeSystem() const { return m_clang_ast_context; }357 358private:359 bool FindObjCPropertyAndIvarDeclsWithOrigin(360 NameSearchContext &context,361 DeclFromUser<const clang::ObjCInterfaceDecl> &origin_iface_decl);362 363protected:364 bool FindObjCMethodDeclsWithOrigin(365 NameSearchContext &context,366 clang::ObjCInterfaceDecl *original_interface_decl, const char *log_info);367 368 void FindDeclInModules(NameSearchContext &context, ConstString name);369 void FindDeclInObjCRuntime(NameSearchContext &context, ConstString name);370 371 /// Fills the namespace map of the given NameSearchContext.372 ///373 /// \param context The NameSearchContext with the namespace map to fill.374 /// \param module_sp The module to search for namespaces or a nullptr if375 /// the current target should be searched.376 /// \param namespace_decl The DeclContext in which to search for namespaces.377 void FillNamespaceMap(NameSearchContext &context, lldb::ModuleSP module_sp,378 const CompilerDeclContext &namespace_decl);379 380 clang::TagDecl *FindCompleteType(const clang::TagDecl *decl);381 382 friend struct NameSearchContext;383 384 bool m_lookups_enabled;385 386 /// The target to use in finding variables and types.387 const lldb::TargetSP m_target;388 /// The AST context requests are coming in for.389 clang::ASTContext *m_ast_context;390 /// The TypeSystemClang for m_ast_context.391 TypeSystemClang *m_clang_ast_context;392 /// The file manager paired with the AST context.393 clang::FileManager *m_file_manager;394 /// The target's AST importer.395 std::shared_ptr<ClangASTImporter> m_ast_importer_sp;396 std::set<const clang::Decl *> m_active_lexical_decls;397 std::set<const char *> m_active_lookups;398};399 400} // namespace lldb_private401 402#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H403