ClangASTImporter.h revision 254721
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
22namespace lldb_private {
23
24class ClangASTMetrics
25{
26public:
27    static void DumpCounters (Log *log);
28    static void ClearLocalCounters ()
29    {
30        local_counters = { 0, 0, 0, 0, 0, 0 };
31    }
32
33    static void RegisterVisibleQuery ()
34    {
35        ++global_counters.m_visible_query_count;
36        ++local_counters.m_visible_query_count;
37    }
38
39    static void RegisterLexicalQuery ()
40    {
41        ++global_counters.m_lexical_query_count;
42        ++local_counters.m_lexical_query_count;
43    }
44
45    static void RegisterLLDBImport ()
46    {
47        ++global_counters.m_lldb_import_count;
48        ++local_counters.m_lldb_import_count;
49    }
50
51    static void RegisterClangImport ()
52    {
53        ++global_counters.m_clang_import_count;
54        ++local_counters.m_clang_import_count;
55    }
56
57    static void RegisterDeclCompletion ()
58    {
59        ++global_counters.m_decls_completed_count;
60        ++local_counters.m_decls_completed_count;
61    }
62
63    static void RegisterRecordLayout ()
64    {
65        ++global_counters.m_record_layout_count;
66        ++local_counters.m_record_layout_count;
67    }
68
69private:
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
86class ClangASTImporter
87{
88public:
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
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
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);
202private:
203    struct DeclOrigin
204    {
205        DeclOrigin () :
206            ctx(NULL),
207            decl(NULL)
208        {
209        }
210
211        DeclOrigin (clang::ASTContext *_ctx,
212                    clang::Decl *_decl) :
213            ctx(_ctx),
214            decl(_decl)
215        {
216        }
217
218        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
231        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:
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    {
293        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
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
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
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