• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- ClangASTImporter.h --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_ClangASTImporter_h_
11 #define liblldb_ClangASTImporter_h_
12 
13 #include <map>
14 #include <set>
15 
16 #include "lldb/lldb-types.h"
17 #include "clang/AST/ASTImporter.h"
18 #include "clang/Basic/FileManager.h"
19 #include "clang/Basic/FileSystemOptions.h"
20 #include "lldb/Symbol/ClangNamespaceDecl.h"
21 
22 namespace lldb_private {
23 
24 class ClangASTMetrics
25 {
26 public:
27     static void DumpCounters (Log *log);
ClearLocalCounters()28     static void ClearLocalCounters ()
29     {
30         local_counters = { 0, 0, 0, 0, 0, 0 };
31     }
32 
RegisterVisibleQuery()33     static void RegisterVisibleQuery ()
34     {
35         ++global_counters.m_visible_query_count;
36         ++local_counters.m_visible_query_count;
37     }
38 
RegisterLexicalQuery()39     static void RegisterLexicalQuery ()
40     {
41         ++global_counters.m_lexical_query_count;
42         ++local_counters.m_lexical_query_count;
43     }
44 
RegisterLLDBImport()45     static void RegisterLLDBImport ()
46     {
47         ++global_counters.m_lldb_import_count;
48         ++local_counters.m_lldb_import_count;
49     }
50 
RegisterClangImport()51     static void RegisterClangImport ()
52     {
53         ++global_counters.m_clang_import_count;
54         ++local_counters.m_clang_import_count;
55     }
56 
RegisterDeclCompletion()57     static void RegisterDeclCompletion ()
58     {
59         ++global_counters.m_decls_completed_count;
60         ++local_counters.m_decls_completed_count;
61     }
62 
RegisterRecordLayout()63     static void RegisterRecordLayout ()
64     {
65         ++global_counters.m_record_layout_count;
66         ++local_counters.m_record_layout_count;
67     }
68 
69 private:
70     struct Counters
71     {
72         uint64_t    m_visible_query_count;
73         uint64_t    m_lexical_query_count;
74         uint64_t    m_lldb_import_count;
75         uint64_t    m_clang_import_count;
76         uint64_t    m_decls_completed_count;
77         uint64_t    m_record_layout_count;
78     };
79 
80     static Counters global_counters;
81     static Counters local_counters;
82 
83     static void DumpCounters (Log *log, Counters &counters);
84 };
85 
86 class ClangASTImporter
87 {
88 public:
ClangASTImporter()89     ClangASTImporter () :
90         m_file_manager(clang::FileSystemOptions())
91     {
92     }
93 
94     clang::QualType
95     CopyType (clang::ASTContext *dst_ctx,
96               clang::ASTContext *src_ctx,
97               clang::QualType type);
98 
99     lldb::clang_type_t
100     CopyType (clang::ASTContext *dst_ctx,
101               clang::ASTContext *src_ctx,
102               lldb::clang_type_t type);
103 
104     clang::Decl *
105     CopyDecl (clang::ASTContext *dst_ctx,
106               clang::ASTContext *src_ctx,
107               clang::Decl *decl);
108 
109     lldb::clang_type_t
110     DeportType (clang::ASTContext *dst_ctx,
111                 clang::ASTContext *src_ctx,
112                 lldb::clang_type_t type);
113 
114     clang::Decl *
115     DeportDecl (clang::ASTContext *dst_ctx,
116                 clang::ASTContext *src_ctx,
117                 clang::Decl *decl);
118 
119     void
120     CompleteDecl (clang::Decl *decl);
121 
122     bool
123     CompleteTagDecl (clang::TagDecl *decl);
124 
125     bool
126     CompleteTagDeclWithOrigin (clang::TagDecl *decl, clang::TagDecl *origin);
127 
128     bool
129     CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
130 
131     bool
132     RequireCompleteType (clang::QualType type);
133 
134     bool
ResolveDeclOrigin(const clang::Decl * decl,clang::Decl ** original_decl,clang::ASTContext ** original_ctx)135     ResolveDeclOrigin (const clang::Decl *decl, clang::Decl **original_decl, clang::ASTContext **original_ctx)
136     {
137         DeclOrigin origin = GetDeclOrigin(decl);
138 
139         if (original_decl)
140             *original_decl = origin.decl;
141 
142         if (original_ctx)
143             *original_ctx = origin.ctx;
144 
145         return origin.Valid();
146     }
147 
148     void
149     SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl);
150 
151     ClangASTMetadata *
152     GetDeclMetadata (const clang::Decl *decl);
153 
154     //
155     // Namespace maps
156     //
157 
158     typedef std::vector < std::pair<lldb::ModuleSP, ClangNamespaceDecl> > NamespaceMap;
159     typedef std::shared_ptr<NamespaceMap> NamespaceMapSP;
160 
161     void RegisterNamespaceMap (const clang::NamespaceDecl *decl,
162                                NamespaceMapSP &namespace_map);
163 
164     NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl);
165 
166     void BuildNamespaceMap (const clang::NamespaceDecl *decl);
167 
168     //
169     // Comleters for maps
170     //
171 
172     class MapCompleter
173     {
174     public:
175         virtual ~MapCompleter ();
176 
177         virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map,
178                                            const ConstString &name,
179                                            NamespaceMapSP &parent_map) const = 0;
180     };
181 
InstallMapCompleter(clang::ASTContext * dst_ctx,MapCompleter & completer)182     void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer)
183     {
184         ASTContextMetadataSP context_md;
185         ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
186 
187         if (context_md_iter == m_metadata_map.end())
188         {
189             context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
190             m_metadata_map[dst_ctx] = context_md;
191         }
192         else
193         {
194             context_md = context_md_iter->second;
195         }
196 
197         context_md->m_map_completer = &completer;
198     }
199 
200     void ForgetDestination (clang::ASTContext *dst_ctx);
201     void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
202 private:
203     struct DeclOrigin
204     {
DeclOriginDeclOrigin205         DeclOrigin () :
206             ctx(NULL),
207             decl(NULL)
208         {
209         }
210 
DeclOriginDeclOrigin211         DeclOrigin (clang::ASTContext *_ctx,
212                     clang::Decl *_decl) :
213             ctx(_ctx),
214             decl(_decl)
215         {
216         }
217 
DeclOriginDeclOrigin218         DeclOrigin (const DeclOrigin &rhs)
219         {
220             ctx = rhs.ctx;
221             decl = rhs.decl;
222         }
223 
224         void operator= (const DeclOrigin &rhs)
225         {
226             ctx = rhs.ctx;
227             decl = rhs.decl;
228         }
229 
230         bool
ValidDeclOrigin231         Valid ()
232         {
233             return (ctx != NULL || decl != NULL);
234         }
235 
236         clang::ASTContext  *ctx;
237         clang::Decl        *decl;
238     };
239 
240     typedef std::map<const clang::Decl *, DeclOrigin>   OriginMap;
241 
242     class Minion : public clang::ASTImporter
243     {
244     public:
Minion(ClangASTImporter & master,clang::ASTContext * target_ctx,clang::ASTContext * source_ctx)245         Minion (ClangASTImporter &master,
246                 clang::ASTContext *target_ctx,
247                 clang::ASTContext *source_ctx) :
248             clang::ASTImporter(*target_ctx,
249                                master.m_file_manager,
250                                *source_ctx,
251                                master.m_file_manager,
252                                true /*minimal*/),
253             m_decls_to_deport(NULL),
254             m_decls_already_deported(NULL),
255             m_master(master),
256             m_source_ctx(source_ctx)
257         {
258         }
259 
260         // A call to "InitDeportWorkQueues" puts the minion into deport mode.
261         // In deport mode, every copied Decl that could require completion is
262         // recorded and placed into the decls_to_deport set.
263         //
264         // A call to "ExecuteDeportWorkQueues" completes all the Decls that
265         // are in decls_to_deport, adding any Decls it sees along the way that
266         // it hasn't already deported.  It proceeds until decls_to_deport is
267         // empty.
268         //
269         // These calls must be paired.  Leaving a minion in deport mode or
270         // trying to start deport minion with a new pair of queues will result
271         // in an assertion failure.
272 
273         void InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport,
274                                    std::set<clang::NamedDecl *> *decls_already_deported);
275         void ExecuteDeportWorkQueues ();
276 
277         void ImportDefinitionTo (clang::Decl *to, clang::Decl *from);
278 
279         clang::Decl *Imported (clang::Decl *from, clang::Decl *to);
280 
281         std::set<clang::NamedDecl *>   *m_decls_to_deport;
282         std::set<clang::NamedDecl *>   *m_decls_already_deported;
283         ClangASTImporter               &m_master;
284         clang::ASTContext              *m_source_ctx;
285     };
286 
287     typedef std::shared_ptr<Minion> MinionSP;
288     typedef std::map<clang::ASTContext *, MinionSP> MinionMap;
289     typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap;
290 
291     struct ASTContextMetadata
292     {
ASTContextMetadataASTContextMetadata293         ASTContextMetadata(clang::ASTContext *dst_ctx) :
294             m_dst_ctx (dst_ctx),
295             m_minions (),
296             m_origins (),
297             m_namespace_maps (),
298             m_map_completer (NULL)
299         {
300         }
301 
302         clang::ASTContext      *m_dst_ctx;
303         MinionMap               m_minions;
304         OriginMap               m_origins;
305 
306         NamespaceMetaMap        m_namespace_maps;
307         MapCompleter           *m_map_completer;
308     };
309 
310     typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
311     typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> ContextMetadataMap;
312 
313     ContextMetadataMap m_metadata_map;
314 
315     ASTContextMetadataSP
GetContextMetadata(clang::ASTContext * dst_ctx)316     GetContextMetadata (clang::ASTContext *dst_ctx)
317     {
318         ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
319 
320         if (context_md_iter == m_metadata_map.end())
321         {
322             ASTContextMetadataSP context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
323             m_metadata_map[dst_ctx] = context_md;
324             return context_md;
325         }
326         else
327         {
328             return context_md_iter->second;
329         }
330     }
331 
332     ASTContextMetadataSP
MaybeGetContextMetadata(clang::ASTContext * dst_ctx)333     MaybeGetContextMetadata (clang::ASTContext *dst_ctx)
334     {
335         ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
336 
337         if (context_md_iter != m_metadata_map.end())
338             return context_md_iter->second;
339         else
340             return ASTContextMetadataSP();
341     }
342 
343     MinionSP
GetMinion(clang::ASTContext * dst_ctx,clang::ASTContext * src_ctx)344     GetMinion (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx)
345     {
346         ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
347 
348         MinionMap &minions = context_md->m_minions;
349         MinionMap::iterator minion_iter = minions.find(src_ctx);
350 
351         if (minion_iter == minions.end())
352         {
353             MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx));
354             minions[src_ctx] = minion;
355             return minion;
356         }
357         else
358         {
359             return minion_iter->second;
360         }
361     }
362 
363     DeclOrigin
364     GetDeclOrigin (const clang::Decl *decl);
365 
366     clang::FileManager      m_file_manager;
367 };
368 
369 }
370 
371 #endif
372