summaryrefslogtreecommitdiff
path: root/include/lldb/Symbol/ClangASTImporter.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/lldb/Symbol/ClangASTImporter.h')
-rw-r--r--include/lldb/Symbol/ClangASTImporter.h371
1 files changed, 371 insertions, 0 deletions
diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h
new file mode 100644
index 0000000000000..10df7da893a84
--- /dev/null
+++ b/include/lldb/Symbol/ClangASTImporter.h
@@ -0,0 +1,371 @@
+//===-- ClangASTImporter.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ClangASTImporter_h_
+#define liblldb_ClangASTImporter_h_
+
+#include <map>
+#include <set>
+
+#include "lldb/lldb-types.h"
+#include "clang/AST/ASTImporter.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "lldb/Symbol/ClangNamespaceDecl.h"
+
+namespace lldb_private {
+
+class ClangASTMetrics
+{
+public:
+ static void DumpCounters (Log *log);
+ static void ClearLocalCounters ()
+ {
+ local_counters = { 0, 0, 0, 0, 0, 0 };
+ }
+
+ static void RegisterVisibleQuery ()
+ {
+ ++global_counters.m_visible_query_count;
+ ++local_counters.m_visible_query_count;
+ }
+
+ static void RegisterLexicalQuery ()
+ {
+ ++global_counters.m_lexical_query_count;
+ ++local_counters.m_lexical_query_count;
+ }
+
+ static void RegisterLLDBImport ()
+ {
+ ++global_counters.m_lldb_import_count;
+ ++local_counters.m_lldb_import_count;
+ }
+
+ static void RegisterClangImport ()
+ {
+ ++global_counters.m_clang_import_count;
+ ++local_counters.m_clang_import_count;
+ }
+
+ static void RegisterDeclCompletion ()
+ {
+ ++global_counters.m_decls_completed_count;
+ ++local_counters.m_decls_completed_count;
+ }
+
+ static void RegisterRecordLayout ()
+ {
+ ++global_counters.m_record_layout_count;
+ ++local_counters.m_record_layout_count;
+ }
+
+private:
+ struct Counters
+ {
+ uint64_t m_visible_query_count;
+ uint64_t m_lexical_query_count;
+ uint64_t m_lldb_import_count;
+ uint64_t m_clang_import_count;
+ uint64_t m_decls_completed_count;
+ uint64_t m_record_layout_count;
+ };
+
+ static Counters global_counters;
+ static Counters local_counters;
+
+ static void DumpCounters (Log *log, Counters &counters);
+};
+
+class ClangASTImporter
+{
+public:
+ ClangASTImporter () :
+ m_file_manager(clang::FileSystemOptions())
+ {
+ }
+
+ clang::QualType
+ CopyType (clang::ASTContext *dst_ctx,
+ clang::ASTContext *src_ctx,
+ clang::QualType type);
+
+ lldb::clang_type_t
+ CopyType (clang::ASTContext *dst_ctx,
+ clang::ASTContext *src_ctx,
+ lldb::clang_type_t type);
+
+ clang::Decl *
+ CopyDecl (clang::ASTContext *dst_ctx,
+ clang::ASTContext *src_ctx,
+ clang::Decl *decl);
+
+ lldb::clang_type_t
+ DeportType (clang::ASTContext *dst_ctx,
+ clang::ASTContext *src_ctx,
+ lldb::clang_type_t type);
+
+ clang::Decl *
+ DeportDecl (clang::ASTContext *dst_ctx,
+ clang::ASTContext *src_ctx,
+ clang::Decl *decl);
+
+ void
+ CompleteDecl (clang::Decl *decl);
+
+ bool
+ CompleteTagDecl (clang::TagDecl *decl);
+
+ bool
+ CompleteTagDeclWithOrigin (clang::TagDecl *decl, clang::TagDecl *origin);
+
+ bool
+ CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl);
+
+ bool
+ RequireCompleteType (clang::QualType type);
+
+ bool
+ ResolveDeclOrigin (const clang::Decl *decl, clang::Decl **original_decl, clang::ASTContext **original_ctx)
+ {
+ DeclOrigin origin = GetDeclOrigin(decl);
+
+ if (original_decl)
+ *original_decl = origin.decl;
+
+ if (original_ctx)
+ *original_ctx = origin.ctx;
+
+ return origin.Valid();
+ }
+
+ void
+ SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl);
+
+ ClangASTMetadata *
+ GetDeclMetadata (const clang::Decl *decl);
+
+ //
+ // Namespace maps
+ //
+
+ typedef std::vector < std::pair<lldb::ModuleSP, ClangNamespaceDecl> > NamespaceMap;
+ typedef std::shared_ptr<NamespaceMap> NamespaceMapSP;
+
+ void RegisterNamespaceMap (const clang::NamespaceDecl *decl,
+ NamespaceMapSP &namespace_map);
+
+ NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl);
+
+ void BuildNamespaceMap (const clang::NamespaceDecl *decl);
+
+ //
+ // Comleters for maps
+ //
+
+ class MapCompleter
+ {
+ public:
+ virtual ~MapCompleter ();
+
+ virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map,
+ const ConstString &name,
+ NamespaceMapSP &parent_map) const = 0;
+ };
+
+ void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer)
+ {
+ ASTContextMetadataSP context_md;
+ ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
+
+ if (context_md_iter == m_metadata_map.end())
+ {
+ context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
+ m_metadata_map[dst_ctx] = context_md;
+ }
+ else
+ {
+ context_md = context_md_iter->second;
+ }
+
+ context_md->m_map_completer = &completer;
+ }
+
+ void ForgetDestination (clang::ASTContext *dst_ctx);
+ void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx);
+private:
+ struct DeclOrigin
+ {
+ DeclOrigin () :
+ ctx(NULL),
+ decl(NULL)
+ {
+ }
+
+ DeclOrigin (clang::ASTContext *_ctx,
+ clang::Decl *_decl) :
+ ctx(_ctx),
+ decl(_decl)
+ {
+ }
+
+ DeclOrigin (const DeclOrigin &rhs)
+ {
+ ctx = rhs.ctx;
+ decl = rhs.decl;
+ }
+
+ void operator= (const DeclOrigin &rhs)
+ {
+ ctx = rhs.ctx;
+ decl = rhs.decl;
+ }
+
+ bool
+ Valid ()
+ {
+ return (ctx != NULL || decl != NULL);
+ }
+
+ clang::ASTContext *ctx;
+ clang::Decl *decl;
+ };
+
+ typedef std::map<const clang::Decl *, DeclOrigin> OriginMap;
+
+ class Minion : public clang::ASTImporter
+ {
+ public:
+ Minion (ClangASTImporter &master,
+ clang::ASTContext *target_ctx,
+ clang::ASTContext *source_ctx) :
+ clang::ASTImporter(*target_ctx,
+ master.m_file_manager,
+ *source_ctx,
+ master.m_file_manager,
+ true /*minimal*/),
+ m_decls_to_deport(NULL),
+ m_decls_already_deported(NULL),
+ m_master(master),
+ m_source_ctx(source_ctx)
+ {
+ }
+
+ // A call to "InitDeportWorkQueues" puts the minion into deport mode.
+ // In deport mode, every copied Decl that could require completion is
+ // recorded and placed into the decls_to_deport set.
+ //
+ // A call to "ExecuteDeportWorkQueues" completes all the Decls that
+ // are in decls_to_deport, adding any Decls it sees along the way that
+ // it hasn't already deported. It proceeds until decls_to_deport is
+ // empty.
+ //
+ // These calls must be paired. Leaving a minion in deport mode or
+ // trying to start deport minion with a new pair of queues will result
+ // in an assertion failure.
+
+ void InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport,
+ std::set<clang::NamedDecl *> *decls_already_deported);
+ void ExecuteDeportWorkQueues ();
+
+ void ImportDefinitionTo (clang::Decl *to, clang::Decl *from);
+
+ clang::Decl *Imported (clang::Decl *from, clang::Decl *to);
+
+ std::set<clang::NamedDecl *> *m_decls_to_deport;
+ std::set<clang::NamedDecl *> *m_decls_already_deported;
+ ClangASTImporter &m_master;
+ clang::ASTContext *m_source_ctx;
+ };
+
+ typedef std::shared_ptr<Minion> MinionSP;
+ typedef std::map<clang::ASTContext *, MinionSP> MinionMap;
+ typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap;
+
+ struct ASTContextMetadata
+ {
+ ASTContextMetadata(clang::ASTContext *dst_ctx) :
+ m_dst_ctx (dst_ctx),
+ m_minions (),
+ m_origins (),
+ m_namespace_maps (),
+ m_map_completer (NULL)
+ {
+ }
+
+ clang::ASTContext *m_dst_ctx;
+ MinionMap m_minions;
+ OriginMap m_origins;
+
+ NamespaceMetaMap m_namespace_maps;
+ MapCompleter *m_map_completer;
+ };
+
+ typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP;
+ typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> ContextMetadataMap;
+
+ ContextMetadataMap m_metadata_map;
+
+ ASTContextMetadataSP
+ GetContextMetadata (clang::ASTContext *dst_ctx)
+ {
+ ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
+
+ if (context_md_iter == m_metadata_map.end())
+ {
+ ASTContextMetadataSP context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
+ m_metadata_map[dst_ctx] = context_md;
+ return context_md;
+ }
+ else
+ {
+ return context_md_iter->second;
+ }
+ }
+
+ ASTContextMetadataSP
+ MaybeGetContextMetadata (clang::ASTContext *dst_ctx)
+ {
+ ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
+
+ if (context_md_iter != m_metadata_map.end())
+ return context_md_iter->second;
+ else
+ return ASTContextMetadataSP();
+ }
+
+ MinionSP
+ GetMinion (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx)
+ {
+ ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx);
+
+ MinionMap &minions = context_md->m_minions;
+ MinionMap::iterator minion_iter = minions.find(src_ctx);
+
+ if (minion_iter == minions.end())
+ {
+ MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx));
+ minions[src_ctx] = minion;
+ return minion;
+ }
+ else
+ {
+ return minion_iter->second;
+ }
+ }
+
+ DeclOrigin
+ GetDeclOrigin (const clang::Decl *decl);
+
+ clang::FileManager m_file_manager;
+};
+
+}
+
+#endif