]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/include/lldb/Symbol/ClangASTImporter.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / include / lldb / Symbol / ClangASTImporter.h
1 //===-- ClangASTImporter.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 liblldb_ClangASTImporter_h_
10 #define liblldb_ClangASTImporter_h_
11
12 #include <map>
13 #include <memory>
14 #include <set>
15 #include <vector>
16
17 #include "clang/AST/ASTImporter.h"
18 #include "clang/AST/CharUnits.h"
19 #include "clang/AST/Decl.h"
20 #include "clang/AST/DeclCXX.h"
21 #include "clang/Basic/FileManager.h"
22 #include "clang/Basic/FileSystemOptions.h"
23
24 #include "lldb/Host/FileSystem.h"
25 #include "lldb/Symbol/CompilerDeclContext.h"
26 #include "lldb/Symbol/CxxModuleHandler.h"
27 #include "lldb/lldb-types.h"
28
29 #include "llvm/ADT/DenseMap.h"
30
31 namespace lldb_private {
32
33 class ClangASTMetrics {
34 public:
35   static void DumpCounters(Log *log);
36   static void ClearLocalCounters() { local_counters = {0, 0, 0, 0, 0, 0}; }
37
38   static void RegisterVisibleQuery() {
39     ++global_counters.m_visible_query_count;
40     ++local_counters.m_visible_query_count;
41   }
42
43   static void RegisterLexicalQuery() {
44     ++global_counters.m_lexical_query_count;
45     ++local_counters.m_lexical_query_count;
46   }
47
48   static void RegisterLLDBImport() {
49     ++global_counters.m_lldb_import_count;
50     ++local_counters.m_lldb_import_count;
51   }
52
53   static void RegisterClangImport() {
54     ++global_counters.m_clang_import_count;
55     ++local_counters.m_clang_import_count;
56   }
57
58   static void RegisterDeclCompletion() {
59     ++global_counters.m_decls_completed_count;
60     ++local_counters.m_decls_completed_count;
61   }
62
63   static void RegisterRecordLayout() {
64     ++global_counters.m_record_layout_count;
65     ++local_counters.m_record_layout_count;
66   }
67
68 private:
69   struct Counters {
70     uint64_t m_visible_query_count;
71     uint64_t m_lexical_query_count;
72     uint64_t m_lldb_import_count;
73     uint64_t m_clang_import_count;
74     uint64_t m_decls_completed_count;
75     uint64_t m_record_layout_count;
76   };
77
78   static Counters global_counters;
79   static Counters local_counters;
80
81   static void DumpCounters(Log *log, Counters &counters);
82 };
83
84 class ClangASTImporter {
85 public:
86   struct LayoutInfo {
87     LayoutInfo()
88         : bit_size(0), alignment(0), field_offsets(), base_offsets(),
89           vbase_offsets() {}
90     uint64_t bit_size;
91     uint64_t alignment;
92     llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
93     llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
94     llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
95         vbase_offsets;
96   };
97
98   ClangASTImporter()
99       : m_file_manager(clang::FileSystemOptions(),
100                        FileSystem::Instance().GetVirtualFileSystem()) {}
101
102   clang::QualType CopyType(clang::ASTContext *dst_ctx,
103                            clang::ASTContext *src_ctx, clang::QualType type);
104
105   lldb::opaque_compiler_type_t CopyType(clang::ASTContext *dst_ctx,
106                                         clang::ASTContext *src_ctx,
107                                         lldb::opaque_compiler_type_t type);
108
109   CompilerType CopyType(ClangASTContext &dst, const CompilerType &src_type);
110
111   clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx,
112                         clang::Decl *decl);
113
114   lldb::opaque_compiler_type_t DeportType(clang::ASTContext *dst_ctx,
115                                           clang::ASTContext *src_ctx,
116                                           lldb::opaque_compiler_type_t type);
117
118   clang::Decl *DeportDecl(clang::ASTContext *dst_ctx,
119                           clang::ASTContext *src_ctx, clang::Decl *decl);
120
121   void InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout);
122
123   bool LayoutRecordType(
124       const clang::RecordDecl *record_decl, uint64_t &bit_size,
125       uint64_t &alignment,
126       llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
127       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
128           &base_offsets,
129       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
130           &vbase_offsets);
131
132   bool CanImport(const CompilerType &type);
133
134   bool Import(const CompilerType &type);
135
136   bool CompleteType(const CompilerType &compiler_type);
137
138   void CompleteDecl(clang::Decl *decl);
139
140   bool CompleteTagDecl(clang::TagDecl *decl);
141
142   bool CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin);
143
144   bool CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *interface_decl);
145
146   bool CompleteAndFetchChildren(clang::QualType type);
147
148   bool RequireCompleteType(clang::QualType type);
149
150   bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl,
151                          clang::ASTContext **original_ctx) {
152     DeclOrigin origin = GetDeclOrigin(decl);
153
154     if (original_decl)
155       *original_decl = origin.decl;
156
157     if (original_ctx)
158       *original_ctx = origin.ctx;
159
160     return origin.Valid();
161   }
162
163   void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl);
164
165   ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl);
166
167   //
168   // Namespace maps
169   //
170
171   typedef std::vector<std::pair<lldb::ModuleSP, CompilerDeclContext>>
172       NamespaceMap;
173   typedef std::shared_ptr<NamespaceMap> NamespaceMapSP;
174
175   void RegisterNamespaceMap(const clang::NamespaceDecl *decl,
176                             NamespaceMapSP &namespace_map);
177
178   NamespaceMapSP GetNamespaceMap(const clang::NamespaceDecl *decl);
179
180   void BuildNamespaceMap(const clang::NamespaceDecl *decl);
181
182   //
183   // Completers for maps
184   //
185
186   class MapCompleter {
187   public:
188     virtual ~MapCompleter();
189
190     virtual void CompleteNamespaceMap(NamespaceMapSP &namespace_map,
191                                       ConstString name,
192                                       NamespaceMapSP &parent_map) const = 0;
193   };
194
195   void InstallMapCompleter(clang::ASTContext *dst_ctx,
196                            MapCompleter &completer) {
197     ASTContextMetadataSP context_md;
198     ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
199
200     if (context_md_iter == m_metadata_map.end()) {
201       context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
202       m_metadata_map[dst_ctx] = context_md;
203     } else {
204       context_md = context_md_iter->second;
205     }
206
207     context_md->m_map_completer = &completer;
208   }
209
210   void ForgetDestination(clang::ASTContext *dst_ctx);
211   void ForgetSource(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
212
213 private:
214   struct DeclOrigin {
215     DeclOrigin() : ctx(nullptr), decl(nullptr) {}
216
217     DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl)
218         : ctx(_ctx), decl(_decl) {}
219
220     DeclOrigin(const DeclOrigin &rhs) {
221       ctx = rhs.ctx;
222       decl = rhs.decl;
223     }
224
225     void operator=(const DeclOrigin &rhs) {
226       ctx = rhs.ctx;
227       decl = rhs.decl;
228     }
229
230     bool Valid() { return (ctx != nullptr || decl != nullptr); }
231
232     clang::ASTContext *ctx;
233     clang::Decl *decl;
234   };
235
236   typedef std::map<const clang::Decl *, DeclOrigin> OriginMap;
237
238   /// ASTImporter that intercepts and records the import process of the
239   /// underlying ASTImporter.
240   ///
241   /// This class updates the map from declarations to their original
242   /// declarations and can record and complete declarations that have been
243   /// imported in a certain interval.
244   ///
245   /// When intercepting a declaration import, the ASTImporterDelegate uses the
246   /// CxxModuleHandler to replace any missing or malformed declarations with
247   /// their counterpart from a C++ module.
248   class ASTImporterDelegate : public clang::ASTImporter {
249   public:
250     ASTImporterDelegate(ClangASTImporter &master, clang::ASTContext *target_ctx,
251                         clang::ASTContext *source_ctx)
252         : clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx,
253                              master.m_file_manager, true /*minimal*/),
254           m_decls_to_deport(nullptr), m_decls_already_deported(nullptr),
255           m_master(master), m_source_ctx(source_ctx) {}
256
257     /// Scope guard that attaches a CxxModuleHandler to an ASTImporterDelegate
258     /// and deattaches it at the end of the scope. Supports being used multiple
259     /// times on the same ASTImporterDelegate instance in nested scopes.
260     class CxxModuleScope {
261       /// The handler we attach to the ASTImporterDelegate.
262       CxxModuleHandler m_handler;
263       /// The ASTImporterDelegate we are supposed to attach the handler to.
264       ASTImporterDelegate &m_delegate;
265       /// True iff we attached the handler to the ASTImporterDelegate.
266       bool m_valid = false;
267
268     public:
269       CxxModuleScope(ASTImporterDelegate &delegate, clang::ASTContext *dst_ctx)
270           : m_delegate(delegate) {
271         // If the delegate doesn't have a CxxModuleHandler yet, create one
272         // and attach it.
273         if (!delegate.m_std_handler) {
274           m_handler = CxxModuleHandler(delegate, dst_ctx);
275           m_valid = true;
276           delegate.m_std_handler = &m_handler;
277         }
278       }
279       ~CxxModuleScope() {
280         if (m_valid) {
281           // Make sure no one messed with the handler we placed.
282           assert(m_delegate.m_std_handler == &m_handler);
283           m_delegate.m_std_handler = nullptr;
284         }
285       }
286     };
287
288   protected:
289     llvm::Expected<clang::Decl *> ImportImpl(clang::Decl *From) override;
290
291   public:
292     // A call to "InitDeportWorkQueues" puts the delegate into deport mode.
293     // In deport mode, every copied Decl that could require completion is
294     // recorded and placed into the decls_to_deport set.
295     //
296     // A call to "ExecuteDeportWorkQueues" completes all the Decls that
297     // are in decls_to_deport, adding any Decls it sees along the way that it
298     // hasn't already deported.  It proceeds until decls_to_deport is empty.
299     //
300     // These calls must be paired.  Leaving a delegate in deport mode or trying
301     // to start deport delegate with a new pair of queues will result in an
302     // assertion failure.
303
304     void
305     InitDeportWorkQueues(std::set<clang::NamedDecl *> *decls_to_deport,
306                          std::set<clang::NamedDecl *> *decls_already_deported);
307     void ExecuteDeportWorkQueues();
308
309     void ImportDefinitionTo(clang::Decl *to, clang::Decl *from);
310
311     void Imported(clang::Decl *from, clang::Decl *to) override;
312
313     clang::Decl *GetOriginalDecl(clang::Decl *To) override;
314
315     /// Decls we should ignore when mapping decls back to their original
316     /// ASTContext. Used by the CxxModuleHandler to mark declarations that
317     /// were created from the 'std' C++ module to prevent that the Importer
318     /// tries to sync them with the broken equivalent in the debug info AST.
319     std::set<clang::Decl *> m_decls_to_ignore;
320     std::set<clang::NamedDecl *> *m_decls_to_deport;
321     std::set<clang::NamedDecl *> *m_decls_already_deported;
322     ClangASTImporter &m_master;
323     clang::ASTContext *m_source_ctx;
324     CxxModuleHandler *m_std_handler = nullptr;
325   };
326
327   typedef std::shared_ptr<ASTImporterDelegate> ImporterDelegateSP;
328   typedef std::map<clang::ASTContext *, ImporterDelegateSP> DelegateMap;
329   typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP>
330       NamespaceMetaMap;
331
332   struct ASTContextMetadata {
333     ASTContextMetadata(clang::ASTContext *dst_ctx)
334         : m_dst_ctx(dst_ctx), m_delegates(), m_origins(), m_namespace_maps(),
335           m_map_completer(nullptr) {}
336
337     clang::ASTContext *m_dst_ctx;
338     DelegateMap m_delegates;
339     OriginMap m_origins;
340
341     NamespaceMetaMap m_namespace_maps;
342     MapCompleter *m_map_completer;
343   };
344
345   typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
346   typedef std::map<const clang::ASTContext *, ASTContextMetadataSP>
347       ContextMetadataMap;
348
349   ContextMetadataMap m_metadata_map;
350
351   ASTContextMetadataSP GetContextMetadata(clang::ASTContext *dst_ctx) {
352     ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
353
354     if (context_md_iter == m_metadata_map.end()) {
355       ASTContextMetadataSP context_md =
356           ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
357       m_metadata_map[dst_ctx] = context_md;
358       return context_md;
359     } else {
360       return context_md_iter->second;
361     }
362   }
363
364   ASTContextMetadataSP MaybeGetContextMetadata(clang::ASTContext *dst_ctx) {
365     ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
366
367     if (context_md_iter != m_metadata_map.end())
368       return context_md_iter->second;
369     else
370       return ASTContextMetadataSP();
371   }
372
373   ImporterDelegateSP GetDelegate(clang::ASTContext *dst_ctx,
374                                  clang::ASTContext *src_ctx) {
375     ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
376
377     DelegateMap &delegates = context_md->m_delegates;
378     DelegateMap::iterator delegate_iter = delegates.find(src_ctx);
379
380     if (delegate_iter == delegates.end()) {
381       ImporterDelegateSP delegate =
382           ImporterDelegateSP(new ASTImporterDelegate(*this, dst_ctx, src_ctx));
383       delegates[src_ctx] = delegate;
384       return delegate;
385     } else {
386       return delegate_iter->second;
387     }
388   }
389
390   DeclOrigin GetDeclOrigin(const clang::Decl *decl);
391
392   clang::FileManager m_file_manager;
393   typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo>
394       RecordDeclToLayoutMap;
395
396   RecordDeclToLayoutMap m_record_decl_to_layout_map;
397 };
398
399 } // namespace lldb_private
400
401 #endif // liblldb_ClangASTImporter_h_