ClangASTImporter.h revision 309124
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// C Includes
14// C++ Includes
15#include <map>
16#include <memory>
17#include <set>
18#include <vector>
19
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"
27
28// Project includes
29#include "lldb/lldb-types.h"
30#include "lldb/Symbol/CompilerDeclContext.h"
31
32#include "llvm/ADT/DenseMap.h"
33
34namespace lldb_private {
35
36class ClangASTMetrics
37{
38public:
39    static void DumpCounters (Log *log);
40    static void ClearLocalCounters ()
41    {
42        local_counters = { 0, 0, 0, 0, 0, 0 };
43    }
44
45    static void RegisterVisibleQuery ()
46    {
47        ++global_counters.m_visible_query_count;
48        ++local_counters.m_visible_query_count;
49    }
50
51    static void RegisterLexicalQuery ()
52    {
53        ++global_counters.m_lexical_query_count;
54        ++local_counters.m_lexical_query_count;
55    }
56
57    static void RegisterLLDBImport ()
58    {
59        ++global_counters.m_lldb_import_count;
60        ++local_counters.m_lldb_import_count;
61    }
62
63    static void RegisterClangImport ()
64    {
65        ++global_counters.m_clang_import_count;
66        ++local_counters.m_clang_import_count;
67    }
68
69    static void RegisterDeclCompletion ()
70    {
71        ++global_counters.m_decls_completed_count;
72        ++local_counters.m_decls_completed_count;
73    }
74
75    static void RegisterRecordLayout ()
76    {
77        ++global_counters.m_record_layout_count;
78        ++local_counters.m_record_layout_count;
79    }
80
81private:
82    struct Counters
83    {
84        uint64_t    m_visible_query_count;
85        uint64_t    m_lexical_query_count;
86        uint64_t    m_lldb_import_count;
87        uint64_t    m_clang_import_count;
88        uint64_t    m_decls_completed_count;
89        uint64_t    m_record_layout_count;
90    };
91
92    static Counters global_counters;
93    static Counters local_counters;
94
95    static void DumpCounters (Log *log, Counters &counters);
96};
97
98class ClangASTImporter
99{
100public:
101    struct LayoutInfo
102    {
103        LayoutInfo() : bit_size(0), alignment(0), field_offsets(), base_offsets(), vbase_offsets() {}
104        uint64_t bit_size;
105        uint64_t alignment;
106        llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets;
107        llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
108        llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets;
109    };
110
111    ClangASTImporter () :
112        m_file_manager(clang::FileSystemOptions())
113    {
114    }
115
116    clang::QualType
117    CopyType (clang::ASTContext *dst_ctx,
118              clang::ASTContext *src_ctx,
119              clang::QualType type);
120
121    lldb::opaque_compiler_type_t
122    CopyType (clang::ASTContext *dst_ctx,
123              clang::ASTContext *src_ctx,
124              lldb::opaque_compiler_type_t type);
125
126    CompilerType
127    CopyType (ClangASTContext &dst,
128              const CompilerType &src_type);
129
130    clang::Decl *
131    CopyDecl (clang::ASTContext *dst_ctx,
132              clang::ASTContext *src_ctx,
133              clang::Decl *decl);
134
135    lldb::opaque_compiler_type_t
136    DeportType (clang::ASTContext *dst_ctx,
137                clang::ASTContext *src_ctx,
138                lldb::opaque_compiler_type_t type);
139
140    clang::Decl *
141    DeportDecl (clang::ASTContext *dst_ctx,
142                clang::ASTContext *src_ctx,
143                clang::Decl *decl);
144
145    void
146    InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout);
147
148    bool
149    LayoutRecordType(const clang::RecordDecl *record_decl, uint64_t &bit_size, uint64_t &alignment,
150                     llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets,
151                     llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
152                     llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
153
154    bool
155    CanImport(const CompilerType &type);
156
157    bool
158    Import(const CompilerType &type);
159
160    bool
161    CompleteType(const CompilerType &compiler_type);
162
163    void
164    CompleteDecl(clang::Decl *decl);
165
166    bool
167    CompleteTagDecl (clang::TagDecl *decl);
168
169    bool
170    CompleteTagDeclWithOrigin (clang::TagDecl *decl, clang::TagDecl *origin);
171
172    bool
173    CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
174
175    bool
176    CompleteAndFetchChildren (clang::QualType type);
177
178    bool
179    RequireCompleteType (clang::QualType type);
180
181    bool
182    ResolveDeclOrigin (const clang::Decl *decl, clang::Decl **original_decl, clang::ASTContext **original_ctx)
183    {
184        DeclOrigin origin = GetDeclOrigin(decl);
185
186        if (original_decl)
187            *original_decl = origin.decl;
188
189        if (original_ctx)
190            *original_ctx = origin.ctx;
191
192        return origin.Valid();
193    }
194
195    void
196    SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl);
197
198    ClangASTMetadata *
199    GetDeclMetadata (const clang::Decl *decl);
200
201    //
202    // Namespace maps
203    //
204
205    typedef std::vector < std::pair<lldb::ModuleSP, CompilerDeclContext> > NamespaceMap;
206    typedef std::shared_ptr<NamespaceMap> NamespaceMapSP;
207
208    void RegisterNamespaceMap (const clang::NamespaceDecl *decl,
209                               NamespaceMapSP &namespace_map);
210
211    NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl);
212
213    void BuildNamespaceMap (const clang::NamespaceDecl *decl);
214
215    //
216    // Completers for maps
217    //
218
219    class MapCompleter
220    {
221    public:
222        virtual ~MapCompleter ();
223
224        virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map,
225                                           const ConstString &name,
226                                           NamespaceMapSP &parent_map) const = 0;
227    };
228
229    void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer)
230    {
231        ASTContextMetadataSP context_md;
232        ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
233
234        if (context_md_iter == m_metadata_map.end())
235        {
236            context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
237            m_metadata_map[dst_ctx] = context_md;
238        }
239        else
240        {
241            context_md = context_md_iter->second;
242        }
243
244        context_md->m_map_completer = &completer;
245    }
246
247    void ForgetDestination (clang::ASTContext *dst_ctx);
248    void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
249
250private:
251    struct DeclOrigin
252    {
253        DeclOrigin () :
254            ctx(nullptr),
255            decl(nullptr)
256        {
257        }
258
259        DeclOrigin (clang::ASTContext *_ctx,
260                    clang::Decl *_decl) :
261            ctx(_ctx),
262            decl(_decl)
263        {
264        }
265
266        DeclOrigin (const DeclOrigin &rhs)
267        {
268            ctx = rhs.ctx;
269            decl = rhs.decl;
270        }
271
272        void operator= (const DeclOrigin &rhs)
273        {
274            ctx = rhs.ctx;
275            decl = rhs.decl;
276        }
277
278        bool
279        Valid ()
280        {
281            return (ctx != nullptr || decl != nullptr);
282        }
283
284        clang::ASTContext  *ctx;
285        clang::Decl        *decl;
286    };
287
288    typedef std::map<const clang::Decl *, DeclOrigin>   OriginMap;
289
290    class Minion : public clang::ASTImporter
291    {
292    public:
293        Minion (ClangASTImporter &master,
294                clang::ASTContext *target_ctx,
295                clang::ASTContext *source_ctx) :
296            clang::ASTImporter(*target_ctx,
297                               master.m_file_manager,
298                               *source_ctx,
299                               master.m_file_manager,
300                               true /*minimal*/),
301            m_decls_to_deport(nullptr),
302            m_decls_already_deported(nullptr),
303            m_master(master),
304            m_source_ctx(source_ctx)
305        {
306        }
307
308        // A call to "InitDeportWorkQueues" puts the minion into deport mode.
309        // In deport mode, every copied Decl that could require completion is
310        // recorded and placed into the decls_to_deport set.
311        //
312        // A call to "ExecuteDeportWorkQueues" completes all the Decls that
313        // are in decls_to_deport, adding any Decls it sees along the way that
314        // it hasn't already deported.  It proceeds until decls_to_deport is
315        // empty.
316        //
317        // These calls must be paired.  Leaving a minion in deport mode or
318        // trying to start deport minion with a new pair of queues will result
319        // in an assertion failure.
320
321        void InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport,
322                                   std::set<clang::NamedDecl *> *decls_already_deported);
323        void ExecuteDeportWorkQueues ();
324
325        void ImportDefinitionTo (clang::Decl *to, clang::Decl *from);
326
327        clang::Decl *Imported(clang::Decl *from, clang::Decl *to) override;
328
329        clang::Decl *GetOriginalDecl(clang::Decl *To) override;
330
331        std::set<clang::NamedDecl *>   *m_decls_to_deport;
332        std::set<clang::NamedDecl *>   *m_decls_already_deported;
333        ClangASTImporter               &m_master;
334        clang::ASTContext              *m_source_ctx;
335    };
336
337    typedef std::shared_ptr<Minion> MinionSP;
338    typedef std::map<clang::ASTContext *, MinionSP> MinionMap;
339    typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap;
340
341    struct ASTContextMetadata
342    {
343        ASTContextMetadata(clang::ASTContext *dst_ctx) :
344            m_dst_ctx (dst_ctx),
345            m_minions (),
346            m_origins (),
347            m_namespace_maps (),
348            m_map_completer (nullptr)
349        {
350        }
351
352        clang::ASTContext      *m_dst_ctx;
353        MinionMap               m_minions;
354        OriginMap               m_origins;
355
356        NamespaceMetaMap        m_namespace_maps;
357        MapCompleter           *m_map_completer;
358    };
359
360    typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
361    typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> ContextMetadataMap;
362
363    ContextMetadataMap m_metadata_map;
364
365    ASTContextMetadataSP
366    GetContextMetadata (clang::ASTContext *dst_ctx)
367    {
368        ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
369
370        if (context_md_iter == m_metadata_map.end())
371        {
372            ASTContextMetadataSP context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
373            m_metadata_map[dst_ctx] = context_md;
374            return context_md;
375        }
376        else
377        {
378            return context_md_iter->second;
379        }
380    }
381
382    ASTContextMetadataSP
383    MaybeGetContextMetadata (clang::ASTContext *dst_ctx)
384    {
385        ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
386
387        if (context_md_iter != m_metadata_map.end())
388            return context_md_iter->second;
389        else
390            return ASTContextMetadataSP();
391    }
392
393    MinionSP
394    GetMinion (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx)
395    {
396        ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
397
398        MinionMap &minions = context_md->m_minions;
399        MinionMap::iterator minion_iter = minions.find(src_ctx);
400
401        if (minion_iter == minions.end())
402        {
403            MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx));
404            minions[src_ctx] = minion;
405            return minion;
406        }
407        else
408        {
409            return minion_iter->second;
410        }
411    }
412
413    DeclOrigin
414    GetDeclOrigin (const clang::Decl *decl);
415
416    clang::FileManager      m_file_manager;
417    typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap;
418
419    RecordDeclToLayoutMap m_record_decl_to_layout_map;
420};
421
422} // namespace lldb_private
423
424#endif // liblldb_ClangASTImporter_h_
425