• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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