forked from OSchip/llvm-project
Fixed the way ClangASTImporter deports types from
ASTContexts that will not stay around. Before, we did this in a very half-hearted way. Now we maintain work queues of all Decls that need to be completed before the source ASTContext can go away; we then expunge their origins completely. <rdar://problem/13511875> llvm-svn: 178410
This commit is contained in:
parent
7b0c94e207
commit
e55bc8a9c1
|
@ -11,6 +11,7 @@
|
|||
#define liblldb_ClangASTImporter_h_
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "lldb/lldb-types.h"
|
||||
|
||||
|
@ -250,17 +251,38 @@ private:
|
|||
*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);
|
||||
|
||||
ClangASTImporter &m_master;
|
||||
clang::ASTContext *m_source_ctx;
|
||||
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;
|
||||
|
|
|
@ -113,37 +113,27 @@ lldb::clang_type_t
|
|||
ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
|
||||
clang::ASTContext *src_ctx,
|
||||
lldb::clang_type_t type)
|
||||
{
|
||||
{
|
||||
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
|
||||
|
||||
if (!minion_sp)
|
||||
return NULL;
|
||||
|
||||
std::set<NamedDecl *> decls_to_deport;
|
||||
std::set<NamedDecl *> decls_already_deported;
|
||||
|
||||
minion_sp->InitDeportWorkQueues(&decls_to_deport,
|
||||
&decls_already_deported);
|
||||
|
||||
lldb::clang_type_t result = CopyType(dst_ctx, src_ctx, type);
|
||||
|
||||
minion_sp->ExecuteDeportWorkQueues();
|
||||
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
QualType qual_type = QualType::getFromOpaquePtr(type);
|
||||
|
||||
if (const TagType *tag_type = qual_type->getAs<TagType>())
|
||||
{
|
||||
TagDecl *tag_decl = tag_type->getDecl();
|
||||
const TagType *result_tag_type = QualType::getFromOpaquePtr(result)->getAs<TagType>();
|
||||
TagDecl *result_tag_decl = result_tag_type->getDecl();
|
||||
|
||||
if (tag_decl)
|
||||
{
|
||||
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
|
||||
|
||||
minion_sp->ImportDefinitionTo(result_tag_decl, tag_decl);
|
||||
|
||||
ASTContextMetadataSP to_context_md = GetContextMetadata(dst_ctx);
|
||||
|
||||
OriginMap::iterator oi = to_context_md->m_origins.find(result_tag_decl);
|
||||
|
||||
if (oi != to_context_md->m_origins.end() &&
|
||||
oi->second.ctx == src_ctx)
|
||||
to_context_md->m_origins.erase(oi);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
clang::Decl *
|
||||
|
@ -160,31 +150,23 @@ ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx,
|
|||
src_ctx,
|
||||
dst_ctx);
|
||||
|
||||
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
|
||||
|
||||
if (!minion_sp)
|
||||
return NULL;
|
||||
|
||||
std::set<NamedDecl *> decls_to_deport;
|
||||
std::set<NamedDecl *> decls_already_deported;
|
||||
|
||||
minion_sp->InitDeportWorkQueues(&decls_to_deport,
|
||||
&decls_already_deported);
|
||||
|
||||
clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl);
|
||||
|
||||
minion_sp->ExecuteDeportWorkQueues();
|
||||
|
||||
if (!result)
|
||||
return NULL;
|
||||
|
||||
ClangASTContext::GetCompleteDecl (src_ctx, decl);
|
||||
|
||||
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
|
||||
|
||||
if (minion_sp && isa<TagDecl>(decl))
|
||||
minion_sp->ImportDefinitionTo(result, decl);
|
||||
|
||||
ASTContextMetadataSP to_context_md = GetContextMetadata(dst_ctx);
|
||||
|
||||
OriginMap::iterator oi = to_context_md->m_origins.find(result);
|
||||
|
||||
if (oi != to_context_md->m_origins.end() &&
|
||||
oi->second.ctx == src_ctx)
|
||||
to_context_md->m_origins.erase(oi);
|
||||
|
||||
if (TagDecl *result_tag_decl = dyn_cast<TagDecl>(result))
|
||||
{
|
||||
result_tag_decl->setHasExternalLexicalStorage(false);
|
||||
result_tag_decl->setHasExternalVisibleStorage(false);
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf(" [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p",
|
||||
|
@ -468,6 +450,63 @@ ClangASTImporter::MapCompleter::~MapCompleter ()
|
|||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ClangASTImporter::Minion::InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport,
|
||||
std::set<clang::NamedDecl *> *decls_already_deported)
|
||||
{
|
||||
assert(!m_decls_to_deport); // TODO make debug only
|
||||
assert(!m_decls_already_deported);
|
||||
|
||||
m_decls_to_deport = decls_to_deport;
|
||||
m_decls_already_deported = decls_already_deported;
|
||||
}
|
||||
|
||||
void
|
||||
ClangASTImporter::Minion::ExecuteDeportWorkQueues ()
|
||||
{
|
||||
assert(m_decls_to_deport); // TODO make debug only
|
||||
assert(m_decls_already_deported);
|
||||
|
||||
ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&getToContext());
|
||||
|
||||
while (!m_decls_to_deport->empty())
|
||||
{
|
||||
NamedDecl *decl = *m_decls_to_deport->begin();
|
||||
|
||||
m_decls_already_deported->insert(decl);
|
||||
m_decls_to_deport->erase(decl);
|
||||
|
||||
DeclOrigin &origin = to_context_md->m_origins[decl];
|
||||
|
||||
assert (origin.ctx == m_source_ctx); // otherwise we should never have added this
|
||||
// because it doesn't need to be deported
|
||||
|
||||
Decl *original_decl = to_context_md->m_origins[decl].decl;
|
||||
|
||||
ClangASTContext::GetCompleteDecl (m_source_ctx, original_decl);
|
||||
|
||||
if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl))
|
||||
{
|
||||
if (TagDecl *original_tag_decl = dyn_cast<TagDecl>(original_decl))
|
||||
if (original_tag_decl->isCompleteDefinition())
|
||||
ImportDefinitionTo(tag_decl, original_tag_decl);
|
||||
|
||||
tag_decl->setHasExternalLexicalStorage(false);
|
||||
tag_decl->setHasExternalVisibleStorage(false);
|
||||
}
|
||||
else if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl))
|
||||
{
|
||||
interface_decl->setHasExternalLexicalStorage(false);
|
||||
interface_decl->setHasExternalVisibleStorage(false);
|
||||
}
|
||||
|
||||
to_context_md->m_origins.erase(decl);
|
||||
}
|
||||
|
||||
m_decls_to_deport = NULL;
|
||||
m_decls_already_deported = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from)
|
||||
{
|
||||
|
@ -594,6 +633,17 @@ clang::Decl
|
|||
}
|
||||
else
|
||||
{
|
||||
if (m_decls_to_deport && m_decls_already_deported)
|
||||
{
|
||||
if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to))
|
||||
{
|
||||
NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
|
||||
|
||||
if (!m_decls_already_deported->count(to_named_decl))
|
||||
m_decls_to_deport->insert(to_named_decl);
|
||||
}
|
||||
|
||||
}
|
||||
to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
|
||||
|
||||
if (log)
|
||||
|
@ -630,15 +680,13 @@ clang::Decl
|
|||
|
||||
to_tag_decl->setHasExternalLexicalStorage();
|
||||
to_tag_decl->setMustBuildLookupTable();
|
||||
|
||||
|
||||
if (log)
|
||||
log->Printf(" [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]",
|
||||
(to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
|
||||
(to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""),
|
||||
(from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
|
||||
(to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
|
||||
|
||||
to_tag_decl = NULL;
|
||||
}
|
||||
|
||||
if (isa<NamespaceDecl>(from))
|
||||
|
@ -656,7 +704,7 @@ clang::Decl
|
|||
|
||||
to_interface_decl->setHasExternalLexicalStorage();
|
||||
to_interface_decl->setHasExternalVisibleStorage();
|
||||
|
||||
|
||||
/*to_interface_decl->setExternallyCompleted();*/
|
||||
|
||||
if (log)
|
||||
|
|
Loading…
Reference in New Issue