1 //===-- ClangASTSource.h ----------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
10 #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
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"
21 #include "llvm/ADT/SmallSet.h"
23 namespace lldb_private
{
25 /// \class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h"
26 /// Provider for named objects defined in the debug info for Clang
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
{
38 /// Initializes class variables.
41 /// A reference to the target containing debug information to use.
43 /// \param[in] importer
44 /// The ClangASTImporter to use.
45 ClangASTSource(const lldb::TargetSP
&target
,
46 const std::shared_ptr
<ClangASTImporter
> &importer
);
49 ~ClangASTSource() override
;
52 clang::Decl
*GetExternalDecl(uint32_t) override
{ return nullptr; }
53 clang::Stmt
*GetExternalDeclStmt(uint64_t) override
{ return nullptr; }
54 clang::Selector
GetExternalSelector(uint32_t) override
{
55 return clang::Selector();
57 uint32_t GetNumExternalSelectors() override
{ return 0; }
58 clang::CXXBaseSpecifier
*
59 GetExternalCXXBaseSpecifiers(uint64_t Offset
) override
{
62 void MaterializeVisibleDecls(const clang::DeclContext
*DC
) {}
64 void InstallASTContext(TypeSystemClang
&ast_context
);
67 // APIs for ExternalASTSource
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
75 /// The work for this function is done by
76 /// void FindExternalVisibleDecls (NameSearchContext &);
79 /// The DeclContext to register the found Decls in.
82 /// The name to find entries for.
85 /// Whatever SetExternalVisibleDeclsForName returns.
86 bool FindExternalVisibleDeclsByName(const clang::DeclContext
*DC
,
87 clang::DeclarationName Name
) override
;
89 /// Enumerate all Decls in a given lexical context.
92 /// The DeclContext being searched.
94 /// \param[in] IsKindWeWant
95 /// A callback function that returns true given the
96 /// DeclKinds of desired Decls, and false otherwise.
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
;
105 /// Specify the layout of the contents of a RecordDecl.
107 /// \param[in] Record
108 /// The record (in the parser's AST context) that needs to be
112 /// The total size of the record in bits.
114 /// \param[out] Alignment
115 /// The alignment of the record in bits.
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).
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).
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).
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
>
141 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
142 &VirtualBaseOffsets
) override
;
144 /// Complete a TagDecl.
147 /// The Decl to be completed in place.
148 void CompleteType(clang::TagDecl
*Tag
) override
;
150 /// Complete an ObjCInterfaceDecl.
153 /// The Decl to be completed in place.
154 void CompleteType(clang::ObjCInterfaceDecl
*Class
) override
;
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.
160 /// \param[in] Consumer
162 void StartTranslationUnit(clang::ASTConsumer
*Consumer
) override
;
165 // APIs for NamespaceMapCompleter
168 /// Look up the modules containing a given namespace and put the appropriate
169 /// entries in the namespace map.
171 /// \param[in] namespace_map
172 /// The map to be completed.
175 /// The name of the namespace to be found.
177 /// \param[in] parent_map
178 /// The map for the namespace's parent namespace, if there is
180 void CompleteNamespaceMap(
181 ClangASTImporter::NamespaceMapSP
&namespace_map
, ConstString name
,
182 ClangASTImporter::NamespaceMapSP
&parent_map
) const override
;
188 clang::NamespaceDecl
*
189 AddNamespace(NameSearchContext
&context
,
190 ClangASTImporter::NamespaceMapSP
&namespace_decls
);
192 /// The worker function for FindExternalVisibleDeclsByName.
194 /// \param[in] context
195 /// The NameSearchContext to use when filing results.
196 virtual void FindExternalVisibleDecls(NameSearchContext
&context
);
198 clang::Sema
*getSema();
200 void SetLookupsEnabled(bool lookups_enabled
) {
201 m_lookups_enabled
= lookups_enabled
;
203 bool GetLookupsEnabled() { return m_lookups_enabled
; }
205 /// \class ClangASTSourceProxy ClangASTSource.h
206 /// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource
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
{
212 ClangASTSourceProxy(ClangASTSource
&original
) : m_original(original
) {}
214 bool FindExternalVisibleDeclsByName(const clang::DeclContext
*DC
,
215 clang::DeclarationName Name
) override
{
216 return m_original
.FindExternalVisibleDeclsByName(DC
, Name
);
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
);
226 void CompleteType(clang::TagDecl
*Tag
) override
{
227 return m_original
.CompleteType(Tag
);
230 void CompleteType(clang::ObjCInterfaceDecl
*Class
) override
{
231 return m_original
.CompleteType(Class
);
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
>
239 llvm::DenseMap
<const clang::CXXRecordDecl
*, clang::CharUnits
>
240 &VirtualBaseOffsets
) override
{
241 return m_original
.layoutRecordType(Record
, Size
, Alignment
, FieldOffsets
,
242 BaseOffsets
, VirtualBaseOffsets
);
245 void StartTranslationUnit(clang::ASTConsumer
*Consumer
) override
{
246 return m_original
.StartTranslationUnit(Consumer
);
250 ClangASTSource
&m_original
;
253 clang::ExternalASTSource
*CreateProxy() {
254 return new ClangASTSourceProxy(*this);
258 /// Look for the complete version of an Objective-C interface, and return it
261 /// \param[in] interface_decl
262 /// An ObjCInterfaceDecl that may not be the complete one.
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
);
270 /// Find all entities matching a given name in a given module, using a
271 /// NameSearchContext to make Decls for them.
273 /// \param[in] context
274 /// The NameSearchContext that can construct Decls for this name.
276 /// \param[in] module
277 /// If non-NULL, the module to query.
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
);
285 /// Find all Objective-C methods matching a given selector.
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
);
293 /// Find all Objective-C properties and ivars with a given name.
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
);
301 /// Performs lookup into a namespace.
304 /// The NameSearchContext for a lookup inside a namespace.
305 void LookupInNamespace(NameSearchContext
&context
);
307 /// A wrapper for TypeSystemClang::CopyType that sets a flag that
308 /// indicates that we should not respond to queries during import.
310 /// \param[in] src_type
314 /// The imported type.
315 CompilerType
GuardedCopyType(const CompilerType
&src_type
);
317 std::shared_ptr
<ClangModulesDeclVendor
> GetClangModulesDeclVendor();
320 /// Returns true if a name should be ignored by name lookup.
323 /// The name to be considered.
325 /// \param[in] ignore_all_dollar_names
326 /// True if $-names of all sorts should be ignored.
329 /// True if the name is one of a class of names that are ignored by
330 /// global lookup for performance reasons.
331 bool IgnoreName(const ConstString name
, bool ignore_all_dollar_names
);
333 /// Copies a single Decl into the parser's AST context.
335 /// \param[in] src_decl
336 /// The Decl to copy.
339 /// A copy of the Decl in m_ast_context, or NULL if the copy failed.
340 clang::Decl
*CopyDecl(clang::Decl
*src_decl
);
342 /// Determined the origin of a single Decl, if it can be found.
345 /// The Decl whose origin is to be found.
348 /// True if lookup succeeded; false otherwise.
349 ClangASTImporter::DeclOrigin
GetDeclOrigin(const clang::Decl
*decl
);
351 /// Returns the TypeSystem that uses this ClangASTSource instance as it's
352 /// ExternalASTSource.
353 TypeSystemClang
*GetTypeSystem() const { return m_clang_ast_context
; }
356 bool FindObjCMethodDeclsWithOrigin(
357 NameSearchContext
&context
,
358 clang::ObjCInterfaceDecl
*original_interface_decl
, const char *log_info
);
360 void FindDeclInModules(NameSearchContext
&context
, ConstString name
);
361 void FindDeclInObjCRuntime(NameSearchContext
&context
, ConstString name
);
363 /// Fills the namespace map of the given NameSearchContext.
365 /// \param context The NameSearchContext with the namespace map to fill.
366 /// \param module_sp The module to search for namespaces or a nullptr if
367 /// the current target should be searched.
368 /// \param namespace_decl The DeclContext in which to search for namespaces.
369 void FillNamespaceMap(NameSearchContext
&context
, lldb::ModuleSP module_sp
,
370 const CompilerDeclContext
&namespace_decl
);
372 clang::TagDecl
*FindCompleteType(const clang::TagDecl
*decl
);
374 friend struct NameSearchContext
;
376 bool m_lookups_enabled
;
378 /// The target to use in finding variables and types.
379 const lldb::TargetSP m_target
;
380 /// The AST context requests are coming in for.
381 clang::ASTContext
*m_ast_context
;
382 /// The TypeSystemClang for m_ast_context.
383 TypeSystemClang
*m_clang_ast_context
;
384 /// The file manager paired with the AST context.
385 clang::FileManager
*m_file_manager
;
386 /// The target's AST importer.
387 std::shared_ptr
<ClangASTImporter
> m_ast_importer_sp
;
388 std::set
<const clang::Decl
*> m_active_lexical_decls
;
389 std::set
<const char *> m_active_lookups
;
392 } // namespace lldb_private
394 #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H