xref: /llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h (revision 263fed7ce9d2c155af44829018673caa67fa4f47)
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.
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 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
87   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] DC
94   ///     The DeclContext being searched.
95   ///
96   /// \param[in] IsKindWeWant
97   ///     A callback function that returns true given the
98   ///     DeclKinds of desired Decls, and false otherwise.
99   ///
100   /// \param[in] Decls
101   ///     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] Record
110   ///     The record (in the parser's AST context) that needs to be
111   ///     laid out.
112   ///
113   /// \param[out] Size
114   ///     The total size of the record in bits.
115   ///
116   /// \param[out] Alignment
117   ///     The alignment of the record in bits.
118   ///
119   /// \param[in] FieldOffsets
120   ///     A map that must be populated with pairs of the record's
121   ///     fields (in the parser's AST context) and their offsets
122   ///     (measured in bits).
123   ///
124   /// \param[in] BaseOffsets
125   ///     A map that must be populated with pairs of the record's
126   ///     C++ concrete base classes (in the parser's AST context,
127   ///     and only if the record is a CXXRecordDecl and has base
128   ///     classes) and their offsets (measured in bytes).
129   ///
130   /// \param[in] VirtualBaseOffsets
131   ///     A map that must be populated with pairs of the record's
132   ///     C++ virtual base classes (in the parser's AST context,
133   ///     and only if the record is a CXXRecordDecl and has base
134   ///     classes) and their offsets (measured in bytes).
135   ///
136   /// \return
137   ///     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] Tag
149   ///     The Decl to be completed in place.
150   void CompleteType(clang::TagDecl *Tag) override;
151 
152   /// Complete an ObjCInterfaceDecl.
153   ///
154   /// \param[in] Class
155   ///     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 calling
159   /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that
160   /// this object has something to say about undefined names.
161   ///
162   /// \param[in] Consumer
163   ///     Unused.
164   void StartTranslationUnit(clang::ASTConsumer *Consumer) override;
165 
166   //
167   // APIs for NamespaceMapCompleter
168   //
169 
170   /// Look up the modules containing a given namespace and put the appropriate
171   /// entries in the namespace map.
172   ///
173   /// \param[in] namespace_map
174   ///     The map to be completed.
175   ///
176   /// \param[in] name
177   ///     The name of the namespace to be found.
178   ///
179   /// \param[in] parent_map
180   ///     The map for the namespace's parent namespace, if there is
181   ///     one.
182   void CompleteNamespaceMap(
183       ClangASTImporter::NamespaceMapSP &namespace_map, ConstString name,
184       ClangASTImporter::NamespaceMapSP &parent_map) const override;
185 
186   //
187   // Helper APIs
188   //
189 
190   clang::NamespaceDecl *
191   AddNamespace(NameSearchContext &context,
192                ClangASTImporter::NamespaceMapSP &namespace_decls);
193 
194   /// The worker function for FindExternalVisibleDeclsByName.
195   ///
196   /// \param[in] context
197   ///     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.h
208   /// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource
209   ///
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   clang::ExternalASTSource *CreateProxy() {
257     return new ClangASTSourceProxy(*this);
258   }
259 
260 protected:
261   /// Look for the complete version of an Objective-C interface, and return it
262   /// if found.
263   ///
264   /// \param[in] interface_decl
265   ///     An ObjCInterfaceDecl that may not be the complete one.
266   ///
267   /// \return
268   ///     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 a
274   /// NameSearchContext to make Decls for them.
275   ///
276   /// \param[in] context
277   ///     The NameSearchContext that can construct Decls for this name.
278   ///
279   /// \param[in] module
280   ///     If non-NULL, the module to query.
281   ///
282   /// \param[in] namespace_decl
283   ///     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] context
291   ///     The NameSearchContext that can construct Decls for this name.
292   ///     Its m_decl_name contains the selector and its m_decl_context
293   ///     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] context
299   ///     The NameSearchContext that can construct Decls for this name.
300   ///     Its m_decl_name contains the name and its m_decl_context
301   ///     is the containing object.
302   void FindObjCPropertyAndIvarDecls(NameSearchContext &context);
303 
304   /// Performs lookup into a namespace.
305   ///
306   /// \param context
307   ///     The NameSearchContext for a lookup inside a namespace.
308   void LookupInNamespace(NameSearchContext &context);
309 
310   /// A wrapper for TypeSystemClang::CopyType that sets a flag that
311   /// indicates that we should not respond to queries during import.
312   ///
313   /// \param[in] src_type
314   ///     The source type.
315   ///
316   /// \return
317   ///     The imported type.
318   CompilerType GuardedCopyType(const CompilerType &src_type);
319 
320   std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor();
321 
322 public:
323   /// Returns true if a name should be ignored by name lookup.
324   ///
325   /// \param[in] name
326   ///     The name to be considered.
327   ///
328   /// \param[in] ignore_all_dollar_names
329   ///     True if $-names of all sorts should be ignored.
330   ///
331   /// \return
332   ///     True if the name is one of a class of names that are ignored by
333   ///     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_decl
339   ///     The Decl to copy.
340   ///
341   /// \return
342   ///     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] decl
348   ///     The Decl whose origin is to be found.
349   ///
350   /// \return
351   ///     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's
355   /// ExternalASTSource.
356   TypeSystemClang *GetTypeSystem() const { return m_clang_ast_context; }
357 
358 private:
359   bool FindObjCPropertyAndIvarDeclsWithOrigin(
360       NameSearchContext &context,
361       DeclFromUser<const clang::ObjCInterfaceDecl> &origin_iface_decl);
362 
363 protected:
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 if
375   ///                  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_private
401 
402 #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
403