1 //===-- ClangASTImporter.h --------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef liblldb_ClangASTImporter_h_
11 #define liblldb_ClangASTImporter_h_
20 // Other libraries and framework includes
21 #include "clang/AST/ASTImporter.h"
22 #include "clang/AST/CharUnits.h"
23 #include "clang/AST/Decl.h"
24 #include "clang/AST/DeclCXX.h"
25 #include "clang/Basic/FileManager.h"
26 #include "clang/Basic/FileSystemOptions.h"
29 #include "lldb/Symbol/CompilerDeclContext.h"
30 #include "lldb/lldb-types.h"
32 #include "llvm/ADT/DenseMap.h"
34 namespace lldb_private {
36 class ClangASTMetrics {
38 static void DumpCounters(Log *log);
39 static void ClearLocalCounters() { local_counters = {0, 0, 0, 0, 0, 0}; }
41 static void RegisterVisibleQuery() {
42 ++global_counters.m_visible_query_count;
43 ++local_counters.m_visible_query_count;
46 static void RegisterLexicalQuery() {
47 ++global_counters.m_lexical_query_count;
48 ++local_counters.m_lexical_query_count;
51 static void RegisterLLDBImport() {
52 ++global_counters.m_lldb_import_count;
53 ++local_counters.m_lldb_import_count;
56 static void RegisterClangImport() {
57 ++global_counters.m_clang_import_count;
58 ++local_counters.m_clang_import_count;
61 static void RegisterDeclCompletion() {
62 ++global_counters.m_decls_completed_count;
63 ++local_counters.m_decls_completed_count;
66 static void RegisterRecordLayout() {
67 ++global_counters.m_record_layout_count;
68 ++local_counters.m_record_layout_count;
73 uint64_t m_visible_query_count;
74 uint64_t m_lexical_query_count;
75 uint64_t m_lldb_import_count;
76 uint64_t m_clang_import_count;
77 uint64_t m_decls_completed_count;
78 uint64_t m_record_layout_count;
81 static Counters global_counters;
82 static Counters local_counters;
84 static void DumpCounters(Log *log, Counters &counters);
87 class ClangASTImporter {
91 : bit_size(0), alignment(0), field_offsets(), base_offsets(),
95 llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
96 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
97 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
101 ClangASTImporter() : m_file_manager(clang::FileSystemOptions()) {}
103 clang::QualType CopyType(clang::ASTContext *dst_ctx,
104 clang::ASTContext *src_ctx, clang::QualType type);
106 lldb::opaque_compiler_type_t CopyType(clang::ASTContext *dst_ctx,
107 clang::ASTContext *src_ctx,
108 lldb::opaque_compiler_type_t type);
110 CompilerType CopyType(ClangASTContext &dst, const CompilerType &src_type);
112 clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx,
115 lldb::opaque_compiler_type_t DeportType(clang::ASTContext *dst_ctx,
116 clang::ASTContext *src_ctx,
117 lldb::opaque_compiler_type_t type);
119 clang::Decl *DeportDecl(clang::ASTContext *dst_ctx,
120 clang::ASTContext *src_ctx, clang::Decl *decl);
122 void InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout);
124 bool LayoutRecordType(
125 const clang::RecordDecl *record_decl, uint64_t &bit_size,
127 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
128 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
130 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
133 bool CanImport(const CompilerType &type);
135 bool Import(const CompilerType &type);
137 bool CompleteType(const CompilerType &compiler_type);
139 void CompleteDecl(clang::Decl *decl);
141 bool CompleteTagDecl(clang::TagDecl *decl);
143 bool CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin);
145 bool CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *interface_decl);
147 bool CompleteAndFetchChildren(clang::QualType type);
149 bool RequireCompleteType(clang::QualType type);
151 bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl,
152 clang::ASTContext **original_ctx) {
153 DeclOrigin origin = GetDeclOrigin(decl);
156 *original_decl = origin.decl;
159 *original_ctx = origin.ctx;
161 return origin.Valid();
164 void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl);
166 ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl);
172 typedef std::vector<std::pair<lldb::ModuleSP, CompilerDeclContext>>
174 typedef std::shared_ptr<NamespaceMap> NamespaceMapSP;
176 void RegisterNamespaceMap(const clang::NamespaceDecl *decl,
177 NamespaceMapSP &namespace_map);
179 NamespaceMapSP GetNamespaceMap(const clang::NamespaceDecl *decl);
181 void BuildNamespaceMap(const clang::NamespaceDecl *decl);
184 // Completers for maps
189 virtual ~MapCompleter();
191 virtual void CompleteNamespaceMap(NamespaceMapSP &namespace_map,
192 const ConstString &name,
193 NamespaceMapSP &parent_map) const = 0;
196 void InstallMapCompleter(clang::ASTContext *dst_ctx,
197 MapCompleter &completer) {
198 ASTContextMetadataSP context_md;
199 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
201 if (context_md_iter == m_metadata_map.end()) {
202 context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
203 m_metadata_map[dst_ctx] = context_md;
205 context_md = context_md_iter->second;
208 context_md->m_map_completer = &completer;
211 void ForgetDestination(clang::ASTContext *dst_ctx);
212 void ForgetSource(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
216 DeclOrigin() : ctx(nullptr), decl(nullptr) {}
218 DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl)
219 : ctx(_ctx), decl(_decl) {}
221 DeclOrigin(const DeclOrigin &rhs) {
226 void operator=(const DeclOrigin &rhs) {
231 bool Valid() { return (ctx != nullptr || decl != nullptr); }
233 clang::ASTContext *ctx;
237 typedef std::map<const clang::Decl *, DeclOrigin> OriginMap;
239 class Minion : public clang::ASTImporter {
241 Minion(ClangASTImporter &master, clang::ASTContext *target_ctx,
242 clang::ASTContext *source_ctx)
243 : clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx,
244 master.m_file_manager, true /*minimal*/),
245 m_decls_to_deport(nullptr), m_decls_already_deported(nullptr),
246 m_master(master), m_source_ctx(source_ctx) {}
248 // A call to "InitDeportWorkQueues" puts the minion into deport mode.
249 // In deport mode, every copied Decl that could require completion is
250 // recorded and placed into the decls_to_deport set.
252 // A call to "ExecuteDeportWorkQueues" completes all the Decls that
253 // are in decls_to_deport, adding any Decls it sees along the way that it
254 // hasn't already deported. It proceeds until decls_to_deport is empty.
256 // These calls must be paired. Leaving a minion in deport mode or trying
257 // to start deport minion with a new pair of queues will result in an
258 // assertion failure.
261 InitDeportWorkQueues(std::set<clang::NamedDecl *> *decls_to_deport,
262 std::set<clang::NamedDecl *> *decls_already_deported);
263 void ExecuteDeportWorkQueues();
265 void ImportDefinitionTo(clang::Decl *to, clang::Decl *from);
267 clang::Decl *Imported(clang::Decl *from, clang::Decl *to) override;
269 clang::Decl *GetOriginalDecl(clang::Decl *To) override;
271 std::set<clang::NamedDecl *> *m_decls_to_deport;
272 std::set<clang::NamedDecl *> *m_decls_already_deported;
273 ClangASTImporter &m_master;
274 clang::ASTContext *m_source_ctx;
277 typedef std::shared_ptr<Minion> MinionSP;
278 typedef std::map<clang::ASTContext *, MinionSP> MinionMap;
279 typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP>
282 struct ASTContextMetadata {
283 ASTContextMetadata(clang::ASTContext *dst_ctx)
284 : m_dst_ctx(dst_ctx), m_minions(), m_origins(), m_namespace_maps(),
285 m_map_completer(nullptr) {}
287 clang::ASTContext *m_dst_ctx;
291 NamespaceMetaMap m_namespace_maps;
292 MapCompleter *m_map_completer;
295 typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
296 typedef std::map<const clang::ASTContext *, ASTContextMetadataSP>
299 ContextMetadataMap m_metadata_map;
301 ASTContextMetadataSP GetContextMetadata(clang::ASTContext *dst_ctx) {
302 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
304 if (context_md_iter == m_metadata_map.end()) {
305 ASTContextMetadataSP context_md =
306 ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
307 m_metadata_map[dst_ctx] = context_md;
310 return context_md_iter->second;
314 ASTContextMetadataSP MaybeGetContextMetadata(clang::ASTContext *dst_ctx) {
315 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
317 if (context_md_iter != m_metadata_map.end())
318 return context_md_iter->second;
320 return ASTContextMetadataSP();
323 MinionSP GetMinion(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx) {
324 ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
326 MinionMap &minions = context_md->m_minions;
327 MinionMap::iterator minion_iter = minions.find(src_ctx);
329 if (minion_iter == minions.end()) {
330 MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx));
331 minions[src_ctx] = minion;
334 return minion_iter->second;
338 DeclOrigin GetDeclOrigin(const clang::Decl *decl);
340 clang::FileManager m_file_manager;
341 typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo>
342 RecordDeclToLayoutMap;
344 RecordDeclToLayoutMap m_record_decl_to_layout_map;
347 } // namespace lldb_private
349 #endif // liblldb_ClangASTImporter_h_