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