ClangASTImporter.h revision e1301a62783cf0d5457350b90830917841cbf6fc
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
15#include "lldb/lldb-types.h"
16
17#include "clang/AST/ASTImporter.h"
18#include "clang/Basic/FileManager.h"
19#include "clang/Basic/FileSystemOptions.h"
20#if defined(__GNUC__) && !defined(__clang__)
21// Gcc complains about ClangNamespaceDecl being an incomplete type
22// without this.
23#include "lldb/Symbol/ClangNamespaceDecl.h"
24#endif
25
26namespace lldb_private {
27
28class ClangASTImporter
29{
30public:
31    ClangASTImporter () :
32        m_file_manager(clang::FileSystemOptions())
33    {
34    }
35
36    clang::QualType
37    CopyType (clang::ASTContext *dst_ctx,
38              clang::ASTContext *src_ctx,
39              clang::QualType type);
40
41    lldb::clang_type_t
42    CopyType (clang::ASTContext *dst_ctx,
43              clang::ASTContext *src_ctx,
44              lldb::clang_type_t type);
45
46    clang::Decl *
47    CopyDecl (clang::ASTContext *dst_ctx,
48              clang::ASTContext *src_ctx,
49              clang::Decl *decl);
50
51    clang::Decl *
52    DeportDecl (clang::ASTContext *dst_ctx,
53                clang::ASTContext *src_ctx,
54                clang::Decl *decl);
55
56    void
57    CompleteTagDecl (clang::TagDecl *decl);
58
59    void
60    CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
61
62    bool
63    ResolveDeclOrigin (const clang::Decl *decl, clang::Decl **original_decl, clang::ASTContext **original_ctx)
64    {
65        DeclOrigin origin = GetDeclOrigin(decl);
66
67        if (original_decl)
68            *original_decl = origin.decl;
69
70        if (original_ctx)
71            *original_ctx = origin.ctx;
72
73        return origin.Valid();
74    }
75
76    //
77    // Namespace maps
78    //
79
80    typedef std::vector < std::pair<lldb::ModuleSP, ClangNamespaceDecl> > NamespaceMap;
81    typedef lldb::SharedPtr<NamespaceMap>::Type NamespaceMapSP;
82
83    void RegisterNamespaceMap (const clang::NamespaceDecl *decl,
84                               NamespaceMapSP &namespace_map);
85
86    NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl);
87
88    void BuildNamespaceMap (const clang::NamespaceDecl *decl);
89
90    //
91    // Objective-C interface maps
92    //
93
94    typedef std::vector <ClangASTType> ObjCInterfaceMap;
95    typedef lldb::SharedPtr<ObjCInterfaceMap>::Type ObjCInterfaceMapSP;
96
97    void BuildObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl);
98
99    ObjCInterfaceMapSP GetObjCInterfaceMap (const clang::ObjCInterfaceDecl *decl);
100
101    //
102    // Completers for the namespace and Objective-C interface maps
103    //
104
105    class MapCompleter
106    {
107    public:
108        virtual ~MapCompleter ();
109
110        virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map,
111                                           const ConstString &name,
112                                           NamespaceMapSP &parent_map) const = 0;
113
114        virtual void CompleteObjCInterfaceMap (ObjCInterfaceMapSP &objc_interface_map,
115                                               const ConstString &name) const = 0;
116    };
117
118    void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer)
119    {
120        ASTContextMetadataSP context_md;
121        ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
122
123        if (context_md_iter == m_metadata_map.end())
124        {
125            context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
126            m_metadata_map[dst_ctx] = context_md;
127        }
128        else
129        {
130            context_md = context_md_iter->second;
131        }
132
133        context_md->m_map_completer = &completer;
134    }
135
136    void ForgetDestination (clang::ASTContext *dst_ctx);
137    void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
138private:
139    struct DeclOrigin
140    {
141        DeclOrigin () :
142            ctx(NULL),
143            decl(NULL)
144        {
145        }
146
147        DeclOrigin (clang::ASTContext *_ctx,
148                    clang::Decl *_decl) :
149            ctx(_ctx),
150            decl(_decl)
151        {
152        }
153
154        DeclOrigin (const DeclOrigin &rhs)
155        {
156            ctx = rhs.ctx;
157            decl = rhs.decl;
158        }
159
160        void operator= (const DeclOrigin &rhs)
161        {
162            ctx = rhs.ctx;
163            decl = rhs.decl;
164        }
165
166        bool
167        Valid ()
168        {
169            return (ctx != NULL || decl != NULL);
170        }
171
172        clang::ASTContext  *ctx;
173        clang::Decl        *decl;
174    };
175
176    typedef std::map<const clang::Decl *, DeclOrigin>   OriginMap;
177
178    class Minion : public clang::ASTImporter
179    {
180    public:
181        Minion (ClangASTImporter &master,
182                clang::ASTContext *target_ctx,
183                clang::ASTContext *source_ctx) :
184            clang::ASTImporter(*target_ctx,
185                               master.m_file_manager,
186                               *source_ctx,
187                               master.m_file_manager,
188                               true /*minimal*/),
189            m_master(master),
190            m_source_ctx(source_ctx)
191        {
192        }
193
194        clang::Decl *Imported (clang::Decl *from, clang::Decl *to);
195
196        ClangASTImporter   &m_master;
197        clang::ASTContext  *m_source_ctx;
198    };
199
200    typedef lldb::SharedPtr<Minion>::Type                                   MinionSP;
201    typedef std::map<clang::ASTContext *, MinionSP>                         MinionMap;
202    typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP>          NamespaceMetaMap;
203    typedef std::map<const clang::ObjCInterfaceDecl *, ObjCInterfaceMapSP>  ObjCInterfaceMetaMap;
204
205    struct ASTContextMetadata
206    {
207        ASTContextMetadata(clang::ASTContext *dst_ctx) :
208            m_dst_ctx (dst_ctx),
209            m_minions (),
210            m_origins (),
211            m_namespace_maps (),
212            m_objc_interface_maps (),
213            m_map_completer (NULL)
214        {
215        }
216
217        clang::ASTContext      *m_dst_ctx;
218        MinionMap               m_minions;
219        OriginMap               m_origins;
220
221        NamespaceMetaMap        m_namespace_maps;
222        MapCompleter           *m_map_completer;
223
224        ObjCInterfaceMetaMap    m_objc_interface_maps;
225    };
226
227    typedef lldb::SharedPtr<ASTContextMetadata>::Type               ASTContextMetadataSP;
228
229    typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> ContextMetadataMap;
230
231    ContextMetadataMap      m_metadata_map;
232
233    ASTContextMetadataSP
234    GetContextMetadata (clang::ASTContext *dst_ctx)
235    {
236        ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
237
238        if (context_md_iter == m_metadata_map.end())
239        {
240            ASTContextMetadataSP context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
241            m_metadata_map[dst_ctx] = context_md;
242            return context_md;
243        }
244        else
245        {
246            return context_md_iter->second;
247        }
248    }
249
250    ASTContextMetadataSP
251    MaybeGetContextMetadata (clang::ASTContext *dst_ctx)
252    {
253        ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
254
255        if (context_md_iter != m_metadata_map.end())
256            return context_md_iter->second;
257        else
258            return ASTContextMetadataSP();
259    }
260
261    MinionSP
262    GetMinion (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx)
263    {
264        ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
265
266        MinionMap &minions = context_md->m_minions;
267        MinionMap::iterator minion_iter = minions.find(src_ctx);
268
269        if (minion_iter == minions.end())
270        {
271            MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx));
272            minions[src_ctx] = minion;
273            return minion;
274        }
275        else
276        {
277            return minion_iter->second;
278        }
279    }
280
281    DeclOrigin
282    GetDeclOrigin (const clang::Decl *decl);
283
284    clang::FileManager      m_file_manager;
285};
286
287}
288
289#endif
290