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
254 // it hasn't already deported. It proceeds until decls_to_deport is
257 // These calls must be paired. Leaving a minion in deport mode or
258 // trying to start deport minion with a new pair of queues will result
259 // in an assertion failure.
262 InitDeportWorkQueues(std::set<clang::NamedDecl *> *decls_to_deport,
263 std::set<clang::NamedDecl *> *decls_already_deported);
264 void ExecuteDeportWorkQueues();
266 void ImportDefinitionTo(clang::Decl *to, clang::Decl *from);
268 clang::Decl *Imported(clang::Decl *from, clang::Decl *to) override;
270 clang::Decl *GetOriginalDecl(clang::Decl *To) override;
272 std::set<clang::NamedDecl *> *m_decls_to_deport;
273 std::set<clang::NamedDecl *> *m_decls_already_deported;
274 ClangASTImporter &m_master;
275 clang::ASTContext *m_source_ctx;
278 typedef std::shared_ptr<Minion> MinionSP;
279 typedef std::map<clang::ASTContext *, MinionSP> MinionMap;
280 typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP>
283 struct ASTContextMetadata {
284 ASTContextMetadata(clang::ASTContext *dst_ctx)
285 : m_dst_ctx(dst_ctx), m_minions(), m_origins(), m_namespace_maps(),
286 m_map_completer(nullptr) {}
288 clang::ASTContext *m_dst_ctx;
292 NamespaceMetaMap m_namespace_maps;
293 MapCompleter *m_map_completer;
296 typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
297 typedef std::map<const clang::ASTContext *, ASTContextMetadataSP>
300 ContextMetadataMap m_metadata_map;
302 ASTContextMetadataSP GetContextMetadata(clang::ASTContext *dst_ctx) {
303 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
305 if (context_md_iter == m_metadata_map.end()) {
306 ASTContextMetadataSP context_md =
307 ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
308 m_metadata_map[dst_ctx] = context_md;
311 return context_md_iter->second;
315 ASTContextMetadataSP MaybeGetContextMetadata(clang::ASTContext *dst_ctx) {
316 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
318 if (context_md_iter != m_metadata_map.end())
319 return context_md_iter->second;
321 return ASTContextMetadataSP();
324 MinionSP GetMinion(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx) {
325 ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
327 MinionMap &minions = context_md->m_minions;
328 MinionMap::iterator minion_iter = minions.find(src_ctx);
330 if (minion_iter == minions.end()) {
331 MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx));
332 minions[src_ctx] = minion;
335 return minion_iter->second;
339 DeclOrigin GetDeclOrigin(const clang::Decl *decl);
341 clang::FileManager m_file_manager;
342 typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo>
343 RecordDeclToLayoutMap;
345 RecordDeclToLayoutMap m_record_decl_to_layout_map;
348 } // namespace lldb_private
350 #endif // liblldb_ClangASTImporter_h_