Home | History | Annotate | Download | only in Symbol
      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);
     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 
     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:
     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);
    202 private:
    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