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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H 10 #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H 11 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 23 namespace lldb_private { 24 25 /// \class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h" 26 /// Provider for named objects defined in the debug info for Clang 27 /// 28 /// As Clang parses an expression, it may encounter names that are not defined 29 /// inside the expression, including variables, functions, and types. Clang 30 /// knows the name it is looking for, but nothing else. The ExternalSemaSource 31 /// class provides Decls (VarDecl, FunDecl, TypeDecl) to Clang for these 32 /// names, consulting the ClangExpressionDeclMap to do the actual lookups. 33 class ClangASTSource : public clang::ExternalASTSource, 34 public ClangASTImporter::MapCompleter { 35 public: 36 /// Constructor 37 /// 38 /// Initializes class variables. 39 /// 40 /// \param[in] target 41 /// A reference to the target containing debug information to use. 42 /// 43 /// \param[in] importer 44 /// The ClangASTImporter to use. 45 ClangASTSource(const lldb::TargetSP &target, 46 const std::shared_ptr<ClangASTImporter> &importer); 47 48 /// Destructor 49 ~ClangASTSource() override; 50 51 /// Interface stubs. GetExternalDecl(uint32_t)52 clang::Decl *GetExternalDecl(uint32_t) override { return nullptr; } GetExternalDeclStmt(uint64_t)53 clang::Stmt *GetExternalDeclStmt(uint64_t) override { return nullptr; } GetExternalSelector(uint32_t)54 clang::Selector GetExternalSelector(uint32_t) override { 55 return clang::Selector(); 56 } GetNumExternalSelectors()57 uint32_t GetNumExternalSelectors() override { return 0; } 58 clang::CXXBaseSpecifier * GetExternalCXXBaseSpecifiers(uint64_t Offset)59 GetExternalCXXBaseSpecifiers(uint64_t Offset) override { 60 return nullptr; 61 } MaterializeVisibleDecls(const clang::DeclContext * DC)62 void MaterializeVisibleDecls(const clang::DeclContext *DC) { return; } 63 64 void InstallASTContext(TypeSystemClang &ast_context); 65 66 // 67 // APIs for ExternalASTSource 68 // 69 70 /// Look up all Decls that match a particular name. Only handles 71 /// Identifiers and DeclContexts that are either NamespaceDecls or 72 /// TranslationUnitDecls. Calls SetExternalVisibleDeclsForName with the 73 /// result. 74 /// 75 /// The work for this function is done by 76 /// void FindExternalVisibleDecls (NameSearchContext &); 77 /// 78 /// \param[in] DC 79 /// The DeclContext to register the found Decls in. 80 /// 81 /// \param[in] Name 82 /// The name to find entries for. 83 /// 84 /// \return 85 /// Whatever SetExternalVisibleDeclsForName returns. 86 bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, 87 clang::DeclarationName Name) override; 88 89 /// Enumerate all Decls in a given lexical context. 90 /// 91 /// \param[in] DC 92 /// The DeclContext being searched. 93 /// 94 /// \param[in] IsKindWeWant 95 /// A callback function that returns true given the 96 /// DeclKinds of desired Decls, and false otherwise. 97 /// 98 /// \param[in] Decls 99 /// A vector that is filled in with matching Decls. 100 void FindExternalLexicalDecls( 101 const clang::DeclContext *DC, 102 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, 103 llvm::SmallVectorImpl<clang::Decl *> &Decls) override; 104 105 /// Specify the layout of the contents of a RecordDecl. 106 /// 107 /// \param[in] Record 108 /// The record (in the parser's AST context) that needs to be 109 /// laid out. 110 /// 111 /// \param[out] Size 112 /// The total size of the record in bits. 113 /// 114 /// \param[out] Alignment 115 /// The alignment of the record in bits. 116 /// 117 /// \param[in] FieldOffsets 118 /// A map that must be populated with pairs of the record's 119 /// fields (in the parser's AST context) and their offsets 120 /// (measured in bits). 121 /// 122 /// \param[in] BaseOffsets 123 /// A map that must be populated with pairs of the record's 124 /// C++ concrete base classes (in the parser's AST context, 125 /// and only if the record is a CXXRecordDecl and has base 126 /// classes) and their offsets (measured in bytes). 127 /// 128 /// \param[in] VirtualBaseOffsets 129 /// A map that must be populated with pairs of the record's 130 /// C++ virtual base classes (in the parser's AST context, 131 /// and only if the record is a CXXRecordDecl and has base 132 /// classes) and their offsets (measured in bytes). 133 /// 134 /// \return 135 /// True <=> the layout is valid. 136 bool layoutRecordType( 137 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, 138 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, 139 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 140 &BaseOffsets, 141 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 142 &VirtualBaseOffsets) override; 143 144 /// Complete a TagDecl. 145 /// 146 /// \param[in] Tag 147 /// The Decl to be completed in place. 148 void CompleteType(clang::TagDecl *Tag) override; 149 150 /// Complete an ObjCInterfaceDecl. 151 /// 152 /// \param[in] Class 153 /// The Decl to be completed in place. 154 void CompleteType(clang::ObjCInterfaceDecl *Class) override; 155 156 /// Called on entering a translation unit. Tells Clang by calling 157 /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that 158 /// this object has something to say about undefined names. 159 /// 160 /// \param[in] Consumer 161 /// Unused. 162 void StartTranslationUnit(clang::ASTConsumer *Consumer) override; 163 164 // 165 // APIs for NamespaceMapCompleter 166 // 167 168 /// Look up the modules containing a given namespace and put the appropriate 169 /// entries in the namespace map. 170 /// 171 /// \param[in] namespace_map 172 /// The map to be completed. 173 /// 174 /// \param[in] name 175 /// The name of the namespace to be found. 176 /// 177 /// \param[in] parent_map 178 /// The map for the namespace's parent namespace, if there is 179 /// one. 180 void CompleteNamespaceMap( 181 ClangASTImporter::NamespaceMapSP &namespace_map, ConstString name, 182 ClangASTImporter::NamespaceMapSP &parent_map) const override; 183 184 // 185 // Helper APIs 186 // 187 188 clang::NamespaceDecl * 189 AddNamespace(NameSearchContext &context, 190 ClangASTImporter::NamespaceMapSP &namespace_decls); 191 192 /// The worker function for FindExternalVisibleDeclsByName. 193 /// 194 /// \param[in] context 195 /// The NameSearchContext to use when filing results. 196 virtual void FindExternalVisibleDecls(NameSearchContext &context); 197 198 clang::Sema *getSema(); 199 SetLookupsEnabled(bool lookups_enabled)200 void SetLookupsEnabled(bool lookups_enabled) { 201 m_lookups_enabled = lookups_enabled; 202 } GetLookupsEnabled()203 bool GetLookupsEnabled() { return m_lookups_enabled; } 204 205 /// \class ClangASTSourceProxy ClangASTSource.h 206 /// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource 207 /// 208 /// Clang AST contexts like to own their AST sources, so this is a state- 209 /// free proxy object. 210 class ClangASTSourceProxy : public clang::ExternalASTSource { 211 public: ClangASTSourceProxy(ClangASTSource & original)212 ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {} 213 FindExternalVisibleDeclsByName(const clang::DeclContext * DC,clang::DeclarationName Name)214 bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC, 215 clang::DeclarationName Name) override { 216 return m_original.FindExternalVisibleDeclsByName(DC, Name); 217 } 218 FindExternalLexicalDecls(const clang::DeclContext * DC,llvm::function_ref<bool (clang::Decl::Kind)> IsKindWeWant,llvm::SmallVectorImpl<clang::Decl * > & Decls)219 void FindExternalLexicalDecls( 220 const clang::DeclContext *DC, 221 llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant, 222 llvm::SmallVectorImpl<clang::Decl *> &Decls) override { 223 return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls); 224 } 225 CompleteType(clang::TagDecl * Tag)226 void CompleteType(clang::TagDecl *Tag) override { 227 return m_original.CompleteType(Tag); 228 } 229 CompleteType(clang::ObjCInterfaceDecl * Class)230 void CompleteType(clang::ObjCInterfaceDecl *Class) override { 231 return m_original.CompleteType(Class); 232 } 233 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)234 bool layoutRecordType( 235 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, 236 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets, 237 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 238 &BaseOffsets, 239 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 240 &VirtualBaseOffsets) override { 241 return m_original.layoutRecordType(Record, Size, Alignment, FieldOffsets, 242 BaseOffsets, VirtualBaseOffsets); 243 } 244 StartTranslationUnit(clang::ASTConsumer * Consumer)245 void StartTranslationUnit(clang::ASTConsumer *Consumer) override { 246 return m_original.StartTranslationUnit(Consumer); 247 } 248 249 private: 250 ClangASTSource &m_original; 251 }; 252 CreateProxy()253 clang::ExternalASTSource *CreateProxy() { 254 return new ClangASTSourceProxy(*this); 255 } 256 257 protected: 258 /// Look for the complete version of an Objective-C interface, and return it 259 /// if found. 260 /// 261 /// \param[in] interface_decl 262 /// An ObjCInterfaceDecl that may not be the complete one. 263 /// 264 /// \return 265 /// NULL if the complete interface couldn't be found; 266 /// the complete interface otherwise. 267 clang::ObjCInterfaceDecl * 268 GetCompleteObjCInterface(const clang::ObjCInterfaceDecl *interface_decl); 269 270 /// Find all entities matching a given name in a given module, using a 271 /// NameSearchContext to make Decls for them. 272 /// 273 /// \param[in] context 274 /// The NameSearchContext that can construct Decls for this name. 275 /// 276 /// \param[in] module 277 /// If non-NULL, the module to query. 278 /// 279 /// \param[in] namespace_decl 280 /// If valid and module is non-NULL, the parent namespace. 281 void FindExternalVisibleDecls(NameSearchContext &context, 282 lldb::ModuleSP module, 283 CompilerDeclContext &namespace_decl); 284 285 /// Find all Objective-C methods matching a given selector. 286 /// 287 /// \param[in] context 288 /// The NameSearchContext that can construct Decls for this name. 289 /// Its m_decl_name contains the selector and its m_decl_context 290 /// is the containing object. 291 void FindObjCMethodDecls(NameSearchContext &context); 292 293 /// Find all Objective-C properties and ivars with a given name. 294 /// 295 /// \param[in] context 296 /// The NameSearchContext that can construct Decls for this name. 297 /// Its m_decl_name contains the name and its m_decl_context 298 /// is the containing object. 299 void FindObjCPropertyAndIvarDecls(NameSearchContext &context); 300 301 /// Performs lookup into a namespace. 302 /// 303 /// \param context 304 /// The NameSearchContext for a lookup inside a namespace. 305 void LookupInNamespace(NameSearchContext &context); 306 307 /// A wrapper for TypeSystemClang::CopyType that sets a flag that 308 /// indicates that we should not respond to queries during import. 309 /// 310 /// \param[in] src_type 311 /// The source type. 312 /// 313 /// \return 314 /// The imported type. 315 CompilerType GuardedCopyType(const CompilerType &src_type); 316 317 public: 318 /// Returns true if a name should be ignored by name lookup. 319 /// 320 /// \param[in] name 321 /// The name to be considered. 322 /// 323 /// \param[in] ignore_all_dollar_names 324 /// True if $-names of all sorts should be ignored. 325 /// 326 /// \return 327 /// True if the name is one of a class of names that are ignored by 328 /// global lookup for performance reasons. 329 bool IgnoreName(const ConstString name, bool ignore_all_dollar_names); 330 331 /// Copies a single Decl into the parser's AST context. 332 /// 333 /// \param[in] src_decl 334 /// The Decl to copy. 335 /// 336 /// \return 337 /// A copy of the Decl in m_ast_context, or NULL if the copy failed. 338 clang::Decl *CopyDecl(clang::Decl *src_decl); 339 340 /// Determined the origin of a single Decl, if it can be found. 341 /// 342 /// \param[in] decl 343 /// The Decl whose origin is to be found. 344 /// 345 /// \return 346 /// True if lookup succeeded; false otherwise. 347 ClangASTImporter::DeclOrigin GetDeclOrigin(const clang::Decl *decl); 348 349 /// Returns the TypeSystem that uses this ClangASTSource instance as it's 350 /// ExternalASTSource. GetTypeSystem()351 TypeSystemClang *GetTypeSystem() const { return m_clang_ast_context; } 352 353 protected: 354 bool FindObjCMethodDeclsWithOrigin( 355 NameSearchContext &context, 356 clang::ObjCInterfaceDecl *original_interface_decl, const char *log_info); 357 358 void FindDeclInModules(NameSearchContext &context, ConstString name); 359 void FindDeclInObjCRuntime(NameSearchContext &context, ConstString name); 360 361 /// Fills the namespace map of the given NameSearchContext. 362 /// 363 /// \param context The NameSearchContext with the namespace map to fill. 364 /// \param module_sp The module to search for namespaces or a nullptr if 365 /// the current target should be searched. 366 /// \param namespace_decl The DeclContext in which to search for namespaces. 367 void FillNamespaceMap(NameSearchContext &context, lldb::ModuleSP module_sp, 368 const CompilerDeclContext &namespace_decl); 369 370 clang::TagDecl *FindCompleteType(const clang::TagDecl *decl); 371 372 friend struct NameSearchContext; 373 374 bool m_lookups_enabled; 375 376 /// The target to use in finding variables and types. 377 const lldb::TargetSP m_target; 378 /// The AST context requests are coming in for. 379 clang::ASTContext *m_ast_context; 380 /// The TypeSystemClang for m_ast_context. 381 TypeSystemClang *m_clang_ast_context; 382 /// The file manager paired with the AST context. 383 clang::FileManager *m_file_manager; 384 /// The target's AST importer. 385 std::shared_ptr<ClangASTImporter> m_ast_importer_sp; 386 std::set<const clang::Decl *> m_active_lexical_decls; 387 std::set<const char *> m_active_lookups; 388 }; 389 390 } // namespace lldb_private 391 392 #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H 393