2011-06-25 08:44:06 +08:00
|
|
|
//===-- ClangASTImporter.cpp ------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/Decl.h"
|
2012-01-14 06:55:55 +08:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2011-07-30 10:42:06 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
2012-12-04 02:29:55 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2011-07-30 10:42:06 +08:00
|
|
|
#include "lldb/Core/Log.h"
|
2011-10-22 07:04:20 +08:00
|
|
|
#include "lldb/Core/Module.h"
|
2011-06-25 08:44:06 +08:00
|
|
|
#include "lldb/Symbol/ClangASTContext.h"
|
|
|
|
#include "lldb/Symbol/ClangASTImporter.h"
|
2012-04-13 08:10:03 +08:00
|
|
|
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
|
2015-07-09 02:03:41 +08:00
|
|
|
#include "lldb/Utility/LLDBAssert.h"
|
2011-06-25 08:44:06 +08:00
|
|
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
using namespace clang;
|
|
|
|
|
2013-03-09 04:04:57 +08:00
|
|
|
ClangASTMetrics::Counters ClangASTMetrics::global_counters = { 0, 0, 0, 0, 0, 0 };
|
|
|
|
ClangASTMetrics::Counters ClangASTMetrics::local_counters = { 0, 0, 0, 0, 0, 0 };
|
|
|
|
|
2013-03-28 07:08:40 +08:00
|
|
|
void ClangASTMetrics::DumpCounters (Log *log, ClangASTMetrics::Counters &counters)
|
2013-03-09 04:04:57 +08:00
|
|
|
{
|
2013-03-13 01:45:38 +08:00
|
|
|
log->Printf(" Number of visible Decl queries by name : %" PRIu64, counters.m_visible_query_count);
|
|
|
|
log->Printf(" Number of lexical Decl queries : %" PRIu64, counters.m_lexical_query_count);
|
|
|
|
log->Printf(" Number of imports initiated by LLDB : %" PRIu64, counters.m_lldb_import_count);
|
|
|
|
log->Printf(" Number of imports conducted by Clang : %" PRIu64, counters.m_clang_import_count);
|
|
|
|
log->Printf(" Number of Decls completed : %" PRIu64, counters.m_decls_completed_count);
|
|
|
|
log->Printf(" Number of records laid out : %" PRIu64, counters.m_record_layout_count);
|
2013-03-09 04:04:57 +08:00
|
|
|
}
|
|
|
|
|
2013-03-28 07:08:40 +08:00
|
|
|
void ClangASTMetrics::DumpCounters (Log *log)
|
2013-03-09 04:04:57 +08:00
|
|
|
{
|
|
|
|
if (!log)
|
|
|
|
return;
|
|
|
|
|
|
|
|
log->Printf("== ClangASTMetrics output ==");
|
|
|
|
log->Printf("-- Global metrics --");
|
|
|
|
DumpCounters (log, global_counters);
|
|
|
|
log->Printf("-- Local metrics --");
|
|
|
|
DumpCounters (log, local_counters);
|
|
|
|
}
|
|
|
|
|
|
|
|
clang::QualType
|
2011-11-17 02:20:47 +08:00
|
|
|
ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
|
|
|
|
clang::ASTContext *src_ast,
|
2011-06-25 08:44:06 +08:00
|
|
|
clang::QualType type)
|
|
|
|
{
|
2011-11-17 02:20:47 +08:00
|
|
|
MinionSP minion_sp (GetMinion(dst_ast, src_ast));
|
2011-07-30 10:42:06 +08:00
|
|
|
|
2011-07-07 02:55:08 +08:00
|
|
|
if (minion_sp)
|
|
|
|
return minion_sp->Import(type);
|
2011-07-30 10:42:06 +08:00
|
|
|
|
2011-07-07 02:55:08 +08:00
|
|
|
return QualType();
|
2011-06-25 08:44:06 +08:00
|
|
|
}
|
|
|
|
|
2011-11-17 03:07:39 +08:00
|
|
|
lldb::clang_type_t
|
|
|
|
ClangASTImporter::CopyType (clang::ASTContext *dst_ast,
|
|
|
|
clang::ASTContext *src_ast,
|
|
|
|
lldb::clang_type_t type)
|
|
|
|
{
|
|
|
|
return CopyType (dst_ast, src_ast, QualType::getFromOpaquePtr(type)).getAsOpaquePtr();
|
|
|
|
}
|
|
|
|
|
2011-06-25 08:44:06 +08:00
|
|
|
clang::Decl *
|
2011-11-17 02:20:47 +08:00
|
|
|
ClangASTImporter::CopyDecl (clang::ASTContext *dst_ast,
|
|
|
|
clang::ASTContext *src_ast,
|
2011-06-25 08:44:06 +08:00
|
|
|
clang::Decl *decl)
|
|
|
|
{
|
2011-07-07 02:55:08 +08:00
|
|
|
MinionSP minion_sp;
|
2011-06-25 08:44:06 +08:00
|
|
|
|
2011-11-17 02:20:47 +08:00
|
|
|
minion_sp = GetMinion(dst_ast, src_ast);
|
2011-06-25 08:44:06 +08:00
|
|
|
|
2011-07-07 02:55:08 +08:00
|
|
|
if (minion_sp)
|
2011-11-05 06:46:46 +08:00
|
|
|
{
|
|
|
|
clang::Decl *result = minion_sp->Import(decl);
|
|
|
|
|
|
|
|
if (!result)
|
|
|
|
{
|
2013-03-28 07:08:40 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2011-11-05 06:46:46 +08:00
|
|
|
|
2011-11-05 08:08:12 +08:00
|
|
|
if (log)
|
|
|
|
{
|
2014-10-16 07:27:12 +08:00
|
|
|
lldb::user_id_t user_id = LLDB_INVALID_UID;
|
2012-10-27 10:54:13 +08:00
|
|
|
ClangASTMetadata *metadata = GetDeclMetadata(decl);
|
|
|
|
if (metadata)
|
|
|
|
user_id = metadata->GetUserID();
|
|
|
|
|
2011-11-05 08:08:12 +08:00
|
|
|
if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl))
|
2012-11-30 05:49:15 +08:00
|
|
|
log->Printf(" [ClangASTImporter] WARNING: Failed to import a %s '%s', metadata 0x%" PRIx64,
|
2012-04-18 06:30:04 +08:00
|
|
|
decl->getDeclKindName(),
|
|
|
|
named_decl->getNameAsString().c_str(),
|
2012-10-27 10:54:13 +08:00
|
|
|
user_id);
|
2011-11-05 08:08:12 +08:00
|
|
|
else
|
2012-11-30 05:49:15 +08:00
|
|
|
log->Printf(" [ClangASTImporter] WARNING: Failed to import a %s, metadata 0x%" PRIx64,
|
2012-04-18 06:30:04 +08:00
|
|
|
decl->getDeclKindName(),
|
2012-10-27 10:54:13 +08:00
|
|
|
user_id);
|
2011-11-05 08:08:12 +08:00
|
|
|
}
|
2011-11-05 06:46:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2011-07-30 10:42:06 +08:00
|
|
|
|
2014-04-20 21:17:36 +08:00
|
|
|
return nullptr;
|
2011-06-25 08:44:06 +08:00
|
|
|
}
|
|
|
|
|
2015-07-09 02:03:41 +08:00
|
|
|
class DeclContextOverride
|
|
|
|
{
|
|
|
|
private:
|
|
|
|
struct Backup
|
|
|
|
{
|
|
|
|
clang::DeclContext *decl_context;
|
|
|
|
clang::DeclContext *lexical_decl_context;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::map<clang::Decl *, Backup> m_backups;
|
|
|
|
|
|
|
|
void OverrideOne(clang::Decl *decl)
|
|
|
|
{
|
|
|
|
if (m_backups.find(decl) != m_backups.end())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_backups[decl] = { decl->getDeclContext(), decl->getLexicalDeclContext() };
|
|
|
|
|
|
|
|
decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl());
|
|
|
|
decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ChainPassesThrough(clang::Decl *decl,
|
|
|
|
clang::DeclContext *base,
|
|
|
|
clang::DeclContext *(clang::Decl::*contextFromDecl)(),
|
|
|
|
clang::DeclContext *(clang::DeclContext::*contextFromContext)())
|
|
|
|
{
|
|
|
|
for (DeclContext *decl_ctx = (decl->*contextFromDecl)();
|
|
|
|
decl_ctx;
|
|
|
|
decl_ctx = (decl_ctx->*contextFromContext)())
|
|
|
|
{
|
|
|
|
if (decl_ctx == base)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
clang::Decl *GetEscapedChild(clang::Decl *decl, clang::DeclContext *base = nullptr)
|
|
|
|
{
|
|
|
|
if (base)
|
|
|
|
{
|
|
|
|
// decl's DeclContext chains must pass through base.
|
|
|
|
|
|
|
|
if (!ChainPassesThrough(decl, base, &clang::Decl::getDeclContext, &clang::DeclContext::getParent) ||
|
|
|
|
!ChainPassesThrough(decl, base, &clang::Decl::getLexicalDeclContext, &clang::DeclContext::getLexicalParent))
|
|
|
|
{
|
|
|
|
return decl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base = clang::dyn_cast<clang::DeclContext>(decl);
|
|
|
|
|
|
|
|
if (!base)
|
|
|
|
{
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clang::DeclContext *context = clang::dyn_cast<clang::DeclContext>(decl))
|
|
|
|
{
|
|
|
|
for (clang::Decl *decl : context->decls())
|
|
|
|
{
|
|
|
|
if (clang::Decl *escaped_child = GetEscapedChild(decl))
|
|
|
|
{
|
|
|
|
return escaped_child;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Override(clang::Decl *decl)
|
|
|
|
{
|
|
|
|
if (clang::Decl *escaped_child = GetEscapedChild(decl))
|
|
|
|
{
|
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
log->Printf(" [ClangASTImporter] DeclContextOverride couldn't override (%sDecl*)%p - its child (%sDecl*)%p escapes",
|
|
|
|
decl->getDeclKindName(), static_cast<void*>(decl),
|
|
|
|
escaped_child->getDeclKindName(), static_cast<void*>(escaped_child));
|
|
|
|
lldbassert(0 && "Couldn't override!");
|
|
|
|
}
|
|
|
|
|
|
|
|
OverrideOne(decl);
|
|
|
|
}
|
|
|
|
|
|
|
|
public:
|
|
|
|
DeclContextOverride()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void OverrideAllDeclsFromContainingFunction(clang::Decl *decl)
|
|
|
|
{
|
|
|
|
for (DeclContext *decl_context = decl->getLexicalDeclContext();
|
|
|
|
decl_context;
|
|
|
|
decl_context = decl_context->getLexicalParent())
|
|
|
|
{
|
|
|
|
DeclContext *redecl_context = decl_context->getRedeclContext();
|
|
|
|
|
|
|
|
if (llvm::isa<FunctionDecl>(redecl_context) &&
|
|
|
|
llvm::isa<TranslationUnitDecl>(redecl_context->getLexicalParent()))
|
|
|
|
{
|
|
|
|
for (clang::Decl *child_decl : decl_context->decls())
|
|
|
|
{
|
|
|
|
Override(child_decl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~DeclContextOverride()
|
|
|
|
{
|
|
|
|
for (const std::pair<clang::Decl *, Backup> &backup : m_backups)
|
|
|
|
{
|
|
|
|
backup.first->setDeclContext(backup.second.decl_context);
|
|
|
|
backup.first->setLexicalDeclContext(backup.second.lexical_decl_context);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2011-12-17 05:06:35 +08:00
|
|
|
lldb::clang_type_t
|
|
|
|
ClangASTImporter::DeportType (clang::ASTContext *dst_ctx,
|
|
|
|
clang::ASTContext *src_ctx,
|
|
|
|
lldb::clang_type_t type)
|
2013-03-30 10:31:21 +08:00
|
|
|
{
|
|
|
|
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
|
2011-12-17 05:06:35 +08:00
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
if (!minion_sp)
|
2014-04-20 21:17:36 +08:00
|
|
|
return nullptr;
|
2011-12-17 05:06:35 +08:00
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
std::set<NamedDecl *> decls_to_deport;
|
|
|
|
std::set<NamedDecl *> decls_already_deported;
|
2011-12-17 05:06:35 +08:00
|
|
|
|
2015-07-09 02:03:41 +08:00
|
|
|
DeclContextOverride decl_context_override;
|
|
|
|
|
|
|
|
if (const clang::TagType *tag_type = clang::QualType::getFromOpaquePtr(type)->getAs<TagType>())
|
|
|
|
{
|
|
|
|
decl_context_override.OverrideAllDeclsFromContainingFunction(tag_type->getDecl());
|
|
|
|
}
|
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
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)
|
2014-04-20 21:17:36 +08:00
|
|
|
return nullptr;
|
2011-12-17 05:06:35 +08:00
|
|
|
|
|
|
|
return result;
|
2013-03-30 10:31:21 +08:00
|
|
|
|
2011-12-17 05:06:35 +08:00
|
|
|
}
|
|
|
|
|
2011-12-06 11:41:14 +08:00
|
|
|
clang::Decl *
|
|
|
|
ClangASTImporter::DeportDecl (clang::ASTContext *dst_ctx,
|
|
|
|
clang::ASTContext *src_ctx,
|
|
|
|
clang::Decl *decl)
|
|
|
|
{
|
2013-03-28 07:08:40 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-02-28 11:12:58 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf(" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from (ASTContext*)%p to (ASTContex*)%p",
|
2014-04-04 12:06:10 +08:00
|
|
|
decl->getDeclKindName(), static_cast<void*>(decl),
|
|
|
|
static_cast<void*>(src_ctx),
|
|
|
|
static_cast<void*>(dst_ctx));
|
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
MinionSP minion_sp (GetMinion (dst_ctx, src_ctx));
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
if (!minion_sp)
|
2014-04-20 21:17:36 +08:00
|
|
|
return nullptr;
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
std::set<NamedDecl *> decls_to_deport;
|
|
|
|
std::set<NamedDecl *> decls_already_deported;
|
2015-07-09 02:03:41 +08:00
|
|
|
|
|
|
|
DeclContextOverride decl_context_override;
|
|
|
|
|
|
|
|
decl_context_override.OverrideAllDeclsFromContainingFunction(decl);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
minion_sp->InitDeportWorkQueues(&decls_to_deport,
|
|
|
|
&decls_already_deported);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
clang::Decl *result = CopyDecl(dst_ctx, src_ctx, decl);
|
|
|
|
|
|
|
|
minion_sp->ExecuteDeportWorkQueues();
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
if (!result)
|
2014-04-20 21:17:36 +08:00
|
|
|
return nullptr;
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-02-28 11:12:58 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf(" [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p",
|
2014-04-04 12:06:10 +08:00
|
|
|
decl->getDeclKindName(), static_cast<void*>(decl),
|
|
|
|
result->getDeclKindName(), static_cast<void*>(result));
|
|
|
|
|
2011-12-06 11:41:14 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-02-04 16:49:35 +08:00
|
|
|
void
|
|
|
|
ClangASTImporter::CompleteDecl (clang::Decl *decl)
|
|
|
|
{
|
2013-03-28 07:08:40 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2012-02-04 16:49:35 +08:00
|
|
|
|
2014-04-04 12:06:10 +08:00
|
|
|
if (log)
|
2012-02-04 16:49:35 +08:00
|
|
|
log->Printf(" [ClangASTImporter] CompleteDecl called on (%sDecl*)%p",
|
2014-04-04 12:06:10 +08:00
|
|
|
decl->getDeclKindName(), static_cast<void*>(decl));
|
|
|
|
|
2012-02-04 16:49:35 +08:00
|
|
|
if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl))
|
|
|
|
{
|
|
|
|
if (!interface_decl->getDefinition())
|
|
|
|
{
|
|
|
|
interface_decl->startDefinition();
|
|
|
|
CompleteObjCInterfaceDecl(interface_decl);
|
|
|
|
}
|
|
|
|
}
|
2012-07-17 11:23:13 +08:00
|
|
|
else if (ObjCProtocolDecl *protocol_decl = dyn_cast<ObjCProtocolDecl>(decl))
|
2012-02-04 16:49:35 +08:00
|
|
|
{
|
|
|
|
if (!protocol_decl->getDefinition())
|
|
|
|
protocol_decl->startDefinition();
|
|
|
|
}
|
|
|
|
else if (TagDecl *tag_decl = dyn_cast<TagDecl>(decl))
|
|
|
|
{
|
|
|
|
if (!tag_decl->getDefinition() && !tag_decl->isBeingDefined())
|
|
|
|
{
|
|
|
|
tag_decl->startDefinition();
|
|
|
|
CompleteTagDecl(tag_decl);
|
|
|
|
tag_decl->setCompleteDefinition(true);
|
|
|
|
}
|
|
|
|
}
|
2012-03-30 08:51:13 +08:00
|
|
|
else
|
|
|
|
{
|
2012-02-04 16:49:35 +08:00
|
|
|
assert (0 && "CompleteDecl called on a Decl that can't be completed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-09 07:45:45 +08:00
|
|
|
bool
|
2011-07-30 10:42:06 +08:00
|
|
|
ClangASTImporter::CompleteTagDecl (clang::TagDecl *decl)
|
2013-03-09 04:04:57 +08:00
|
|
|
{
|
|
|
|
ClangASTMetrics::RegisterDeclCompletion();
|
|
|
|
|
2011-07-30 10:42:06 +08:00
|
|
|
DeclOrigin decl_origin = GetDeclOrigin(decl);
|
|
|
|
|
|
|
|
if (!decl_origin.Valid())
|
2011-12-09 07:45:45 +08:00
|
|
|
return false;
|
2011-07-30 10:42:06 +08:00
|
|
|
|
|
|
|
if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
|
2011-12-09 07:45:45 +08:00
|
|
|
return false;
|
2011-07-30 10:42:06 +08:00
|
|
|
|
2011-11-17 02:20:47 +08:00
|
|
|
MinionSP minion_sp (GetMinion(&decl->getASTContext(), decl_origin.ctx));
|
2011-07-30 10:42:06 +08:00
|
|
|
|
|
|
|
if (minion_sp)
|
2012-01-14 06:55:55 +08:00
|
|
|
minion_sp->ImportDefinitionTo(decl, decl_origin.decl);
|
|
|
|
|
2011-12-09 07:45:45 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin_decl)
|
|
|
|
{
|
2013-03-09 04:04:57 +08:00
|
|
|
ClangASTMetrics::RegisterDeclCompletion();
|
|
|
|
|
2011-12-09 07:45:45 +08:00
|
|
|
clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext();
|
|
|
|
|
|
|
|
if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
MinionSP minion_sp (GetMinion(&decl->getASTContext(), origin_ast_ctx));
|
|
|
|
|
|
|
|
if (minion_sp)
|
2012-01-14 06:55:55 +08:00
|
|
|
minion_sp->ImportDefinitionTo(decl, origin_decl);
|
|
|
|
|
2011-12-09 07:45:45 +08:00
|
|
|
ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
|
|
|
|
|
|
|
|
OriginMap &origins = context_md->m_origins;
|
|
|
|
|
|
|
|
origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl);
|
|
|
|
|
|
|
|
return true;
|
2011-07-30 10:42:06 +08:00
|
|
|
}
|
|
|
|
|
2011-12-09 07:45:45 +08:00
|
|
|
bool
|
2011-07-30 10:42:06 +08:00
|
|
|
ClangASTImporter::CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl)
|
2011-06-25 08:44:06 +08:00
|
|
|
{
|
2013-03-09 04:04:57 +08:00
|
|
|
ClangASTMetrics::RegisterDeclCompletion();
|
2011-07-30 10:42:06 +08:00
|
|
|
|
|
|
|
DeclOrigin decl_origin = GetDeclOrigin(interface_decl);
|
2011-06-25 08:44:06 +08:00
|
|
|
|
2011-07-30 10:42:06 +08:00
|
|
|
if (!decl_origin.Valid())
|
2011-12-09 07:45:45 +08:00
|
|
|
return false;
|
2011-06-25 08:44:06 +08:00
|
|
|
|
2011-07-30 10:42:06 +08:00
|
|
|
if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl))
|
2011-12-09 07:45:45 +08:00
|
|
|
return false;
|
2011-06-25 08:44:06 +08:00
|
|
|
|
2011-11-17 02:20:47 +08:00
|
|
|
MinionSP minion_sp (GetMinion(&interface_decl->getASTContext(), decl_origin.ctx));
|
2011-06-25 08:44:06 +08:00
|
|
|
|
2011-07-07 02:55:08 +08:00
|
|
|
if (minion_sp)
|
2012-01-14 06:55:55 +08:00
|
|
|
minion_sp->ImportDefinitionTo(interface_decl, decl_origin.decl);
|
2015-04-14 02:32:54 +08:00
|
|
|
|
|
|
|
if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass())
|
|
|
|
RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0));
|
|
|
|
|
2011-12-09 07:45:45 +08:00
|
|
|
return true;
|
2011-06-25 08:44:06 +08:00
|
|
|
}
|
2011-07-30 10:42:06 +08:00
|
|
|
|
2013-03-22 06:15:41 +08:00
|
|
|
bool
|
|
|
|
ClangASTImporter::RequireCompleteType (clang::QualType type)
|
|
|
|
{
|
|
|
|
if (type.isNull())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (const TagType *tag_type = type->getAs<TagType>())
|
|
|
|
{
|
2015-04-09 05:52:45 +08:00
|
|
|
TagDecl *tag_decl = tag_type->getDecl();
|
|
|
|
|
|
|
|
if (tag_decl->getDefinition() || tag_decl->isBeingDefined())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return CompleteTagDecl(tag_decl);
|
2013-03-22 06:15:41 +08:00
|
|
|
}
|
|
|
|
if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>())
|
|
|
|
{
|
|
|
|
if (ObjCInterfaceDecl *objc_interface_decl = objc_object_type->getInterface())
|
|
|
|
return CompleteObjCInterfaceDecl(objc_interface_decl);
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (const ArrayType *array_type = type->getAsArrayTypeUnsafe())
|
|
|
|
{
|
|
|
|
return RequireCompleteType(array_type->getElementType());
|
|
|
|
}
|
|
|
|
if (const AtomicType *atomic_type = type->getAs<AtomicType>())
|
|
|
|
{
|
|
|
|
return RequireCompleteType(atomic_type->getPointeeType());
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-10-27 10:54:13 +08:00
|
|
|
ClangASTMetadata *
|
2012-04-13 08:10:03 +08:00
|
|
|
ClangASTImporter::GetDeclMetadata (const clang::Decl *decl)
|
|
|
|
{
|
|
|
|
DeclOrigin decl_origin = GetDeclOrigin(decl);
|
|
|
|
|
|
|
|
if (decl_origin.Valid())
|
2013-03-27 09:48:02 +08:00
|
|
|
return ClangASTContext::GetMetadata(decl_origin.ctx, decl_origin.decl);
|
2012-04-13 08:10:03 +08:00
|
|
|
else
|
2013-03-27 09:48:02 +08:00
|
|
|
return ClangASTContext::GetMetadata(&decl->getASTContext(), decl);
|
2012-04-13 08:10:03 +08:00
|
|
|
}
|
|
|
|
|
2011-11-17 05:40:57 +08:00
|
|
|
ClangASTImporter::DeclOrigin
|
|
|
|
ClangASTImporter::GetDeclOrigin(const clang::Decl *decl)
|
|
|
|
{
|
|
|
|
ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
|
|
|
|
|
|
|
|
OriginMap &origins = context_md->m_origins;
|
|
|
|
|
|
|
|
OriginMap::iterator iter = origins.find(decl);
|
|
|
|
|
|
|
|
if (iter != origins.end())
|
|
|
|
return iter->second;
|
|
|
|
else
|
|
|
|
return DeclOrigin();
|
|
|
|
}
|
|
|
|
|
2012-09-21 07:21:16 +08:00
|
|
|
void
|
|
|
|
ClangASTImporter::SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl)
|
|
|
|
{
|
|
|
|
ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
|
|
|
|
|
|
|
|
OriginMap &origins = context_md->m_origins;
|
|
|
|
|
|
|
|
OriginMap::iterator iter = origins.find(decl);
|
|
|
|
|
|
|
|
if (iter != origins.end())
|
|
|
|
{
|
|
|
|
iter->second.decl = original_decl;
|
|
|
|
iter->second.ctx = &original_decl->getASTContext();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-10-12 08:12:34 +08:00
|
|
|
ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl,
|
|
|
|
NamespaceMapSP &namespace_map)
|
|
|
|
{
|
2011-11-17 05:40:57 +08:00
|
|
|
ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
|
|
|
|
|
|
|
|
context_md->m_namespace_maps[decl] = namespace_map;
|
2011-10-12 08:12:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ClangASTImporter::NamespaceMapSP
|
|
|
|
ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl)
|
|
|
|
{
|
2011-11-17 05:40:57 +08:00
|
|
|
ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
|
|
|
|
|
|
|
|
NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps;
|
2011-10-12 08:12:34 +08:00
|
|
|
|
2011-11-17 05:40:57 +08:00
|
|
|
NamespaceMetaMap::iterator iter = namespace_maps.find(decl);
|
|
|
|
|
|
|
|
if (iter != namespace_maps.end())
|
2011-10-12 08:12:34 +08:00
|
|
|
return iter->second;
|
|
|
|
else
|
|
|
|
return NamespaceMapSP();
|
|
|
|
}
|
|
|
|
|
2011-10-22 06:18:07 +08:00
|
|
|
void
|
|
|
|
ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl)
|
|
|
|
{
|
2012-10-13 01:34:26 +08:00
|
|
|
assert (decl);
|
2011-11-17 05:40:57 +08:00
|
|
|
ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext());
|
|
|
|
|
2011-10-22 06:18:07 +08:00
|
|
|
const DeclContext *parent_context = decl->getDeclContext();
|
|
|
|
const NamespaceDecl *parent_namespace = dyn_cast<NamespaceDecl>(parent_context);
|
|
|
|
NamespaceMapSP parent_map;
|
|
|
|
|
|
|
|
if (parent_namespace)
|
|
|
|
parent_map = GetNamespaceMap(parent_namespace);
|
|
|
|
|
|
|
|
NamespaceMapSP new_map;
|
|
|
|
|
|
|
|
new_map.reset(new NamespaceMap);
|
|
|
|
|
2011-11-17 05:40:57 +08:00
|
|
|
if (context_md->m_map_completer)
|
2011-10-22 06:18:07 +08:00
|
|
|
{
|
|
|
|
std::string namespace_string = decl->getDeclName().getAsString();
|
|
|
|
|
2011-11-17 05:40:57 +08:00
|
|
|
context_md->m_map_completer->CompleteNamespaceMap (new_map, ConstString(namespace_string.c_str()), parent_map);
|
2011-10-22 06:18:07 +08:00
|
|
|
}
|
|
|
|
|
2011-12-06 11:41:14 +08:00
|
|
|
context_md->m_namespace_maps[decl] = new_map;
|
2011-10-22 06:18:07 +08:00
|
|
|
}
|
|
|
|
|
2011-11-17 02:20:47 +08:00
|
|
|
void
|
2011-11-29 08:42:02 +08:00
|
|
|
ClangASTImporter::ForgetDestination (clang::ASTContext *dst_ast)
|
2011-11-17 02:20:47 +08:00
|
|
|
{
|
2013-03-28 07:08:40 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2012-01-14 06:55:55 +08:00
|
|
|
if (log)
|
2014-04-04 12:06:10 +08:00
|
|
|
log->Printf(" [ClangASTImporter] Forgetting destination (ASTContext*)%p",
|
|
|
|
static_cast<void*>(dst_ast));
|
2012-01-14 06:55:55 +08:00
|
|
|
|
2011-11-17 05:40:57 +08:00
|
|
|
m_metadata_map.erase(dst_ast);
|
2011-11-17 02:20:47 +08:00
|
|
|
}
|
|
|
|
|
2011-11-29 08:42:02 +08:00
|
|
|
void
|
|
|
|
ClangASTImporter::ForgetSource (clang::ASTContext *dst_ast, clang::ASTContext *src_ast)
|
|
|
|
{
|
|
|
|
ASTContextMetadataSP md = MaybeGetContextMetadata (dst_ast);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-03-28 07:08:40 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2012-01-14 06:55:55 +08:00
|
|
|
if (log)
|
2014-04-04 12:06:10 +08:00
|
|
|
log->Printf(" [ClangASTImporter] Forgetting source->dest (ASTContext*)%p->(ASTContext*)%p",
|
|
|
|
static_cast<void*>(src_ast), static_cast<void*>(dst_ast));
|
|
|
|
|
2011-11-29 08:42:02 +08:00
|
|
|
if (!md)
|
|
|
|
return;
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-29 08:42:02 +08:00
|
|
|
md->m_minions.erase(src_ast);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-29 08:42:02 +08:00
|
|
|
for (OriginMap::iterator iter = md->m_origins.begin();
|
|
|
|
iter != md->m_origins.end();
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (iter->second.ctx == src_ast)
|
|
|
|
md->m_origins.erase(iter++);
|
|
|
|
else
|
|
|
|
++iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-06 11:41:14 +08:00
|
|
|
ClangASTImporter::MapCompleter::~MapCompleter ()
|
2011-10-22 06:18:07 +08:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
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];
|
2015-07-24 08:23:29 +08:00
|
|
|
UNUSED_IF_ASSERT_DISABLED(origin);
|
2013-03-30 10:31:21 +08:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-04-20 21:17:36 +08:00
|
|
|
m_decls_to_deport = nullptr;
|
|
|
|
m_decls_already_deported = nullptr;
|
2013-03-30 10:31:21 +08:00
|
|
|
}
|
|
|
|
|
2012-01-14 06:55:55 +08:00
|
|
|
void
|
|
|
|
ClangASTImporter::Minion::ImportDefinitionTo (clang::Decl *to, clang::Decl *from)
|
|
|
|
{
|
|
|
|
ASTImporter::Imported(from, to);
|
2012-02-04 16:49:35 +08:00
|
|
|
|
|
|
|
ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to);
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (to_objc_interface)
|
|
|
|
to_objc_interface->startDefinition();
|
|
|
|
|
|
|
|
CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to);
|
2012-01-14 06:55:55 +08:00
|
|
|
|
2012-02-04 16:49:35 +08:00
|
|
|
if (to_cxx_record)
|
|
|
|
to_cxx_record->startDefinition();
|
|
|
|
*/
|
|
|
|
|
2012-01-14 06:55:55 +08:00
|
|
|
ImportDefinition(from);
|
2012-02-04 16:49:35 +08:00
|
|
|
|
2012-01-20 02:23:06 +08:00
|
|
|
// If we're dealing with an Objective-C class, ensure that the inheritance has
|
|
|
|
// been set up correctly. The ASTImporter may not do this correctly if the
|
|
|
|
// class was originally sourced from symbols.
|
|
|
|
|
2012-02-04 16:49:35 +08:00
|
|
|
if (to_objc_interface)
|
2012-01-20 02:23:06 +08:00
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass();
|
|
|
|
|
|
|
|
if (to_superclass)
|
|
|
|
break; // we're not going to override it if it's set
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *from_objc_interface = dyn_cast<ObjCInterfaceDecl>(from);
|
|
|
|
|
|
|
|
if (!from_objc_interface)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass();
|
|
|
|
|
|
|
|
if (!from_superclass)
|
|
|
|
break;
|
|
|
|
|
|
|
|
Decl *imported_from_superclass_decl = Import(from_superclass);
|
|
|
|
|
|
|
|
if (!imported_from_superclass_decl)
|
|
|
|
break;
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *imported_from_superclass = dyn_cast<ObjCInterfaceDecl>(imported_from_superclass_decl);
|
|
|
|
|
|
|
|
if (!imported_from_superclass)
|
|
|
|
break;
|
|
|
|
|
2012-02-04 16:49:35 +08:00
|
|
|
if (!to_objc_interface->hasDefinition())
|
|
|
|
to_objc_interface->startDefinition();
|
|
|
|
|
2015-07-07 18:11:16 +08:00
|
|
|
to_objc_interface->setSuperClass(
|
|
|
|
m_source_ctx->getTrivialTypeSourceInfo(m_source_ctx->getObjCInterfaceType(imported_from_superclass)));
|
2012-01-20 02:23:06 +08:00
|
|
|
}
|
|
|
|
while (0);
|
|
|
|
}
|
2012-01-14 06:55:55 +08:00
|
|
|
}
|
|
|
|
|
2013-07-12 06:46:58 +08:00
|
|
|
clang::Decl *
|
|
|
|
ClangASTImporter::Minion::Imported (clang::Decl *from, clang::Decl *to)
|
2011-07-30 10:42:06 +08:00
|
|
|
{
|
2013-03-09 04:04:57 +08:00
|
|
|
ClangASTMetrics::RegisterClangImport();
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-03-28 07:08:40 +08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2014-08-02 06:42:38 +08:00
|
|
|
lldb::user_id_t user_id = LLDB_INVALID_UID;
|
|
|
|
ClangASTMetadata *metadata = m_master.GetDeclMetadata(from);
|
|
|
|
if (metadata)
|
|
|
|
user_id = metadata->GetUserID();
|
|
|
|
|
2011-11-18 11:28:09 +08:00
|
|
|
if (log)
|
|
|
|
{
|
|
|
|
if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from))
|
|
|
|
{
|
2012-05-26 02:12:26 +08:00
|
|
|
std::string name_string;
|
|
|
|
llvm::raw_string_ostream name_stream(name_string);
|
|
|
|
from_named_decl->printName(name_stream);
|
|
|
|
name_stream.flush();
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2012-11-30 05:49:15 +08:00
|
|
|
log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p, named %s (from (Decl*)%p), metadata 0x%" PRIx64,
|
2014-04-04 12:06:10 +08:00
|
|
|
from->getDeclKindName(), static_cast<void*>(to),
|
|
|
|
name_string.c_str(), static_cast<void*>(from),
|
2012-10-27 10:54:13 +08:00
|
|
|
user_id);
|
2011-11-18 11:28:09 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-11-30 05:49:15 +08:00
|
|
|
log->Printf(" [ClangASTImporter] Imported (%sDecl*)%p (from (Decl*)%p), metadata 0x%" PRIx64,
|
2014-04-04 12:06:10 +08:00
|
|
|
from->getDeclKindName(), static_cast<void*>(to),
|
|
|
|
static_cast<void*>(from), user_id);
|
2011-11-18 11:28:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-17 06:23:28 +08:00
|
|
|
ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&to->getASTContext());
|
|
|
|
ASTContextMetadataSP from_context_md = m_master.MaybeGetContextMetadata(m_source_ctx);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-17 06:23:28 +08:00
|
|
|
if (from_context_md)
|
|
|
|
{
|
|
|
|
OriginMap &origins = from_context_md->m_origins;
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-17 06:23:28 +08:00
|
|
|
OriginMap::iterator origin_iter = origins.find(from);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-17 06:23:28 +08:00
|
|
|
if (origin_iter != origins.end())
|
2011-11-18 11:28:09 +08:00
|
|
|
{
|
2014-08-02 06:42:38 +08:00
|
|
|
if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
|
|
|
|
user_id != LLDB_INVALID_UID)
|
|
|
|
{
|
2015-07-21 00:55:19 +08:00
|
|
|
if (origin_iter->second.ctx != &to->getASTContext())
|
|
|
|
to_context_md->m_origins[to] = origin_iter->second;
|
2014-08-02 06:42:38 +08:00
|
|
|
}
|
|
|
|
|
Fixed a bug in the ASTImporter that affects
types that have been imported multiple times.
The discussion below uses this diagram:
ASTContext A B C
Decl Da Db Dc
ASTImporter \-Iab-/\-Iac-/
\-----Iac----/
When a Decl D is imported from ASTContext A to
ASTContext B, the ASTImporter Iab records the
pair <Da, Db> in a DenseMap. That way, if Iab
ever encounters Da again (for example, as the
DeclContext for another Decl), it can use the
imported version. This is not an optimization,
it is critical: if I import the field "st_dev"
as part of importing "struct stat," the field
must have DeclContext equal to the parent
structure or we end up with multiple different
Decls containing different parts of "struct
stat." "struct stat" is imported once and
recorded in the DenseMap; then the ASTImporter
finds that same version when looking for the
DeclContext of "st_dev."
The bug arises when Db is imported into another
ASTContext C and ASTContext B goes away. This
often occurs when LLDB produces result variables
for expressions. Ibc is aware of the transport
of Db to Dc, but a brand new ASTImporter, Iac,
is responsible for completing Dc from its source
upon request. That ASTImporter has no mappings,
so it will produce a clone of Dc when attempting
to import its children. That means that type
completion operations on Dc will fail.
The solution is to create Iac as soon as Ibc
imports D from B to C, and inform Iac of the
mapping between Da and Dc. This allows type
completion to happen correctly.
llvm-svn: 147016
2011-12-21 07:55:47 +08:00
|
|
|
MinionSP direct_completer = m_master.GetMinion(&to->getASTContext(), origin_iter->second.ctx);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
Fixed a bug in the ASTImporter that affects
types that have been imported multiple times.
The discussion below uses this diagram:
ASTContext A B C
Decl Da Db Dc
ASTImporter \-Iab-/\-Iac-/
\-----Iac----/
When a Decl D is imported from ASTContext A to
ASTContext B, the ASTImporter Iab records the
pair <Da, Db> in a DenseMap. That way, if Iab
ever encounters Da again (for example, as the
DeclContext for another Decl), it can use the
imported version. This is not an optimization,
it is critical: if I import the field "st_dev"
as part of importing "struct stat," the field
must have DeclContext equal to the parent
structure or we end up with multiple different
Decls containing different parts of "struct
stat." "struct stat" is imported once and
recorded in the DenseMap; then the ASTImporter
finds that same version when looking for the
DeclContext of "st_dev."
The bug arises when Db is imported into another
ASTContext C and ASTContext B goes away. This
often occurs when LLDB produces result variables
for expressions. Ibc is aware of the transport
of Db to Dc, but a brand new ASTImporter, Iac,
is responsible for completing Dc from its source
upon request. That ASTImporter has no mappings,
so it will produce a clone of Dc when attempting
to import its children. That means that type
completion operations on Dc will fail.
The solution is to create Iac as soon as Ibc
imports D from B to C, and inform Iac of the
mapping between Da and Dc. This allows type
completion to happen correctly.
llvm-svn: 147016
2011-12-21 07:55:47 +08:00
|
|
|
if (direct_completer.get() != this)
|
|
|
|
direct_completer->ASTImporter::Imported(origin_iter->second.decl, to);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-18 11:28:09 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf(" [ClangASTImporter] Propagated origin (Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to (ASTContext*)%p",
|
2014-04-04 12:06:10 +08:00
|
|
|
static_cast<void*>(origin_iter->second.decl),
|
|
|
|
static_cast<void*>(origin_iter->second.ctx),
|
|
|
|
static_cast<void*>(&from->getASTContext()),
|
|
|
|
static_cast<void*>(&to->getASTContext()));
|
2011-11-18 11:28:09 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-03-30 10:31:21 +08:00
|
|
|
if (m_decls_to_deport && m_decls_already_deported)
|
|
|
|
{
|
|
|
|
if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to))
|
|
|
|
{
|
|
|
|
NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2013-03-30 10:31:21 +08:00
|
|
|
if (!m_decls_already_deported->count(to_named_decl))
|
|
|
|
m_decls_to_deport->insert(to_named_decl);
|
|
|
|
}
|
|
|
|
}
|
2014-08-02 06:42:38 +08:00
|
|
|
|
|
|
|
if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() ||
|
|
|
|
user_id != LLDB_INVALID_UID)
|
|
|
|
{
|
|
|
|
to_context_md->m_origins[to] = DeclOrigin(m_source_ctx, from);
|
|
|
|
}
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-18 11:28:09 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf(" [ClangASTImporter] Decl has no origin information in (ASTContext*)%p",
|
2014-04-04 12:06:10 +08:00
|
|
|
static_cast<void*>(&from->getASTContext()));
|
2011-11-18 11:28:09 +08:00
|
|
|
}
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-17 06:23:28 +08:00
|
|
|
if (clang::NamespaceDecl *to_namespace = dyn_cast<clang::NamespaceDecl>(to))
|
|
|
|
{
|
|
|
|
clang::NamespaceDecl *from_namespace = dyn_cast<clang::NamespaceDecl>(from);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-17 06:23:28 +08:00
|
|
|
NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps;
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-17 06:23:28 +08:00
|
|
|
NamespaceMetaMap::iterator namespace_map_iter = namespace_maps.find(from_namespace);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-17 06:23:28 +08:00
|
|
|
if (namespace_map_iter != namespace_maps.end())
|
|
|
|
to_context_md->m_namespace_maps[to_namespace] = namespace_map_iter->second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
to_context_md->m_origins[to] = DeclOrigin (m_source_ctx, from);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-18 11:28:09 +08:00
|
|
|
if (log)
|
|
|
|
log->Printf(" [ClangASTImporter] Sourced origin (Decl*)%p/(ASTContext*)%p into (ASTContext*)%p",
|
2014-04-04 12:06:10 +08:00
|
|
|
static_cast<void*>(from),
|
|
|
|
static_cast<void*>(m_source_ctx),
|
|
|
|
static_cast<void*>(&to->getASTContext()));
|
2011-11-17 06:23:28 +08:00
|
|
|
}
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-07-30 10:42:06 +08:00
|
|
|
if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from))
|
|
|
|
{
|
|
|
|
TagDecl *to_tag_decl = dyn_cast<TagDecl>(to);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-07-30 10:42:06 +08:00
|
|
|
to_tag_decl->setHasExternalLexicalStorage();
|
2012-09-25 06:25:51 +08:00
|
|
|
to_tag_decl->setMustBuildLookupTable();
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-07-30 10:42:06 +08:00
|
|
|
if (log)
|
2011-11-18 11:28:09 +08:00
|
|
|
log->Printf(" [ClangASTImporter] To is a TagDecl - attributes %s%s [%s->%s]",
|
2011-07-30 10:42:06 +08:00
|
|
|
(to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
|
2011-11-10 03:33:21 +08:00
|
|
|
(to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""),
|
|
|
|
(from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"),
|
|
|
|
(to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"));
|
2011-07-30 10:42:06 +08:00
|
|
|
}
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-10-22 06:18:07 +08:00
|
|
|
if (isa<NamespaceDecl>(from))
|
|
|
|
{
|
|
|
|
NamespaceDecl *to_namespace_decl = dyn_cast<NamespaceDecl>(to);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-10-22 06:18:07 +08:00
|
|
|
m_master.BuildNamespaceMap(to_namespace_decl);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-10-22 06:18:07 +08:00
|
|
|
to_namespace_decl->setHasExternalVisibleStorage();
|
|
|
|
}
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-18 11:28:09 +08:00
|
|
|
if (isa<ObjCInterfaceDecl>(from))
|
2011-07-30 10:42:06 +08:00
|
|
|
{
|
|
|
|
ObjCInterfaceDecl *to_interface_decl = dyn_cast<ObjCInterfaceDecl>(to);
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-15 10:11:17 +08:00
|
|
|
to_interface_decl->setHasExternalLexicalStorage();
|
2011-11-10 03:33:21 +08:00
|
|
|
to_interface_decl->setHasExternalVisibleStorage();
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2012-02-04 16:49:35 +08:00
|
|
|
/*to_interface_decl->setExternallyCompleted();*/
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-11-15 10:11:17 +08:00
|
|
|
if (log)
|
2011-11-18 11:28:09 +08:00
|
|
|
log->Printf(" [ClangASTImporter] To is an ObjCInterfaceDecl - attributes %s%s%s",
|
2011-11-15 10:11:17 +08:00
|
|
|
(to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""),
|
|
|
|
(to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""),
|
2012-02-04 16:49:35 +08:00
|
|
|
(to_interface_decl->hasDefinition() ? " HasDefinition" : ""));
|
2011-07-30 10:42:06 +08:00
|
|
|
}
|
2014-04-04 12:06:10 +08:00
|
|
|
|
2011-07-30 10:42:06 +08:00
|
|
|
return clang::ASTImporter::Imported(from, to);
|
2011-08-10 10:10:13 +08:00
|
|
|
}
|
2013-10-10 06:33:34 +08:00
|
|
|
|
|
|
|
clang::Decl *ClangASTImporter::Minion::GetOriginalDecl (clang::Decl *To)
|
|
|
|
{
|
|
|
|
ASTContextMetadataSP to_context_md = m_master.GetContextMetadata(&To->getASTContext());
|
|
|
|
|
|
|
|
if (!to_context_md)
|
2014-04-20 21:17:36 +08:00
|
|
|
return nullptr;
|
2013-10-10 06:33:34 +08:00
|
|
|
|
|
|
|
OriginMap::iterator iter = to_context_md->m_origins.find(To);
|
|
|
|
|
|
|
|
if (iter == to_context_md->m_origins.end())
|
2014-04-20 21:17:36 +08:00
|
|
|
return nullptr;
|
2013-10-10 06:33:34 +08:00
|
|
|
|
|
|
|
return const_cast<clang::Decl*>(iter->second.decl);
|
|
|
|
}
|