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
23namespace 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.
33class ClangASTSource : public clang::ExternalASTSource,
34 public ClangASTImporter::MapCompleter {
35public:
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.
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();
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 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
200 void SetLookupsEnabled(bool lookups_enabled) {
201 m_lookups_enabled = lookups_enabled;
202 }
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:
212 ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {}
213
214 bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
215 clang::DeclarationName Name) override {
216 return m_original.FindExternalVisibleDeclsByName(DC, Name);
217 }
218
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
226 void CompleteType(clang::TagDecl *Tag) override {
227 return m_original.CompleteType(Tag);
228 }
229
230 void CompleteType(clang::ObjCInterfaceDecl *Class) override {
231 return m_original.CompleteType(Class);
232 }
233
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
245 void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
246 return m_original.StartTranslationUnit(Consumer);
247 }
248
249 private:
250 ClangASTSource &m_original;
251 };
252
253 clang::ExternalASTSource *CreateProxy() {
254 return new ClangASTSourceProxy(*this);
255 }
256
257protected:
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 std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor();
318
319public:
320 /// Returns true if a name should be ignored by name lookup.
321 ///
322 /// \param[in] name
323 /// The name to be considered.
324 ///
325 /// \param[in] ignore_all_dollar_names
326 /// True if $-names of all sorts should be ignored.
327 ///
328 /// \return
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);
332
333 /// Copies a single Decl into the parser's AST context.
334 ///
335 /// \param[in] src_decl
336 /// The Decl to copy.
337 ///
338 /// \return
339 /// A copy of the Decl in m_ast_context, or NULL if the copy failed.
340 clang::Decl *CopyDecl(clang::Decl *src_decl);
341
342 /// Determined the origin of a single Decl, if it can be found.
343 ///
344 /// \param[in] decl
345 /// The Decl whose origin is to be found.
346 ///
347 /// \return
348 /// True if lookup succeeded; false otherwise.
349 ClangASTImporter::DeclOrigin GetDeclOrigin(const clang::Decl *decl);
350
351 /// Returns the TypeSystem that uses this ClangASTSource instance as it's
352 /// ExternalASTSource.
353 TypeSystemClang *GetTypeSystem() const { return m_clang_ast_context; }
354
355private:
356 bool FindObjCPropertyAndIvarDeclsWithOrigin(
357 NameSearchContext &context,
358 DeclFromUser<const clang::ObjCInterfaceDecl> &origin_iface_decl);
359
360protected:
361 bool FindObjCMethodDeclsWithOrigin(
362 NameSearchContext &context,
363 clang::ObjCInterfaceDecl *original_interface_decl, const char *log_info);
364
365 void FindDeclInModules(NameSearchContext &context, ConstString name);
366 void FindDeclInObjCRuntime(NameSearchContext &context, ConstString name);
367
368 /// Fills the namespace map of the given NameSearchContext.
369 ///
370 /// \param context The NameSearchContext with the namespace map to fill.
371 /// \param module_sp The module to search for namespaces or a nullptr if
372 /// the current target should be searched.
373 /// \param namespace_decl The DeclContext in which to search for namespaces.
374 void FillNamespaceMap(NameSearchContext &context, lldb::ModuleSP module_sp,
375 const CompilerDeclContext &namespace_decl);
376
377 clang::TagDecl *FindCompleteType(const clang::TagDecl *decl);
378
379 friend struct NameSearchContext;
380
381 bool m_lookups_enabled;
382
383 /// The target to use in finding variables and types.
384 const lldb::TargetSP m_target;
385 /// The AST context requests are coming in for.
386 clang::ASTContext *m_ast_context;
387 /// The TypeSystemClang for m_ast_context.
388 TypeSystemClang *m_clang_ast_context;
389 /// The file manager paired with the AST context.
390 clang::FileManager *m_file_manager;
391 /// The target's AST importer.
392 std::shared_ptr<ClangASTImporter> m_ast_importer_sp;
393 std::set<const clang::Decl *> m_active_lexical_decls;
394 std::set<const char *> m_active_lookups;
395};
396
397} // namespace lldb_private
398
399#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
400

source code of lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h