summaryrefslogtreecommitdiff
path: root/lldb/source/Symbol/ClangASTImporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Symbol/ClangASTImporter.cpp')
-rw-r--r--lldb/source/Symbol/ClangASTImporter.cpp240
1 files changed, 97 insertions, 143 deletions
diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp
index 92d51f79a007..8cb404231a8d 100644
--- a/lldb/source/Symbol/ClangASTImporter.cpp
+++ b/lldb/source/Symbol/ClangASTImporter.cpp
@@ -9,7 +9,7 @@
#include "lldb/Symbol/ClangASTImporter.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangASTMetadata.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
@@ -25,90 +25,46 @@
using namespace lldb_private;
using namespace clang;
-ClangASTMetrics::Counters ClangASTMetrics::global_counters = {0, 0, 0, 0, 0, 0};
-ClangASTMetrics::Counters ClangASTMetrics::local_counters = {0, 0, 0, 0, 0, 0};
-
-void ClangASTMetrics::DumpCounters(Log *log,
- ClangASTMetrics::Counters &counters) {
- LLDB_LOGF(log, " Number of visible Decl queries by name : %" PRIu64,
- counters.m_visible_query_count);
- LLDB_LOGF(log, " Number of lexical Decl queries : %" PRIu64,
- counters.m_lexical_query_count);
- LLDB_LOGF(log, " Number of imports initiated by LLDB : %" PRIu64,
- counters.m_lldb_import_count);
- LLDB_LOGF(log, " Number of imports conducted by Clang : %" PRIu64,
- counters.m_clang_import_count);
- LLDB_LOGF(log, " Number of Decls completed : %" PRIu64,
- counters.m_decls_completed_count);
- LLDB_LOGF(log, " Number of records laid out : %" PRIu64,
- counters.m_record_layout_count);
-}
-
-void ClangASTMetrics::DumpCounters(Log *log) {
- if (!log)
- return;
+CompilerType ClangASTImporter::CopyType(ClangASTContext &dst_ast,
+ const CompilerType &src_type) {
+ clang::ASTContext &dst_clang_ast = dst_ast.getASTContext();
- LLDB_LOGF(log, "== ClangASTMetrics output ==");
- LLDB_LOGF(log, "-- Global metrics --");
- DumpCounters(log, global_counters);
- LLDB_LOGF(log, "-- Local metrics --");
- DumpCounters(log, local_counters);
-}
+ ClangASTContext *src_ast =
+ llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
+ if (!src_ast)
+ return CompilerType();
-clang::QualType ClangASTImporter::CopyType(clang::ASTContext *dst_ast,
- clang::ASTContext *src_ast,
- clang::QualType type) {
- ImporterDelegateSP delegate_sp(GetDelegate(dst_ast, src_ast));
+ clang::ASTContext &src_clang_ast = src_ast->getASTContext();
- ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, dst_ast);
+ clang::QualType src_qual_type = ClangUtil::GetQualType(src_type);
+ ImporterDelegateSP delegate_sp(GetDelegate(&dst_clang_ast, &src_clang_ast));
if (!delegate_sp)
- return QualType();
+ return CompilerType();
+
+ ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, &dst_clang_ast);
- llvm::Expected<QualType> ret_or_error = delegate_sp->Import(type);
+ llvm::Expected<QualType> ret_or_error = delegate_sp->Import(src_qual_type);
if (!ret_or_error) {
Log *log =
lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
LLDB_LOG_ERROR(log, ret_or_error.takeError(),
"Couldn't import type: {0}");
- return QualType();
+ return CompilerType();
}
- return *ret_or_error;
-}
-lldb::opaque_compiler_type_t
-ClangASTImporter::CopyType(clang::ASTContext *dst_ast,
- clang::ASTContext *src_ast,
- lldb::opaque_compiler_type_t type) {
- return CopyType(dst_ast, src_ast, QualType::getFromOpaquePtr(type))
- .getAsOpaquePtr();
-}
-
-CompilerType ClangASTImporter::CopyType(ClangASTContext &dst_ast,
- const CompilerType &src_type) {
- clang::ASTContext *dst_clang_ast = dst_ast.getASTContext();
- if (dst_clang_ast) {
- ClangASTContext *src_ast =
- llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem());
- if (src_ast) {
- clang::ASTContext *src_clang_ast = src_ast->getASTContext();
- if (src_clang_ast) {
- lldb::opaque_compiler_type_t dst_clang_type = CopyType(
- dst_clang_ast, src_clang_ast, src_type.GetOpaqueQualType());
+ lldb::opaque_compiler_type_t dst_clang_type = ret_or_error->getAsOpaquePtr();
- if (dst_clang_type)
- return CompilerType(&dst_ast, dst_clang_type);
- }
- }
- }
+ if (dst_clang_type)
+ return CompilerType(&dst_ast, dst_clang_type);
return CompilerType();
}
clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast,
- clang::ASTContext *src_ast,
clang::Decl *decl) {
ImporterDelegateSP delegate_sp;
+ clang::ASTContext *src_ast = &decl->getASTContext();
delegate_sp = GetDelegate(dst_ast, src_ast);
ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, dst_ast);
@@ -151,7 +107,7 @@ private:
clang::DeclContext *lexical_decl_context;
};
- std::map<clang::Decl *, Backup> m_backups;
+ llvm::DenseMap<clang::Decl *, Backup> m_backups;
void OverrideOne(clang::Decl *decl) {
if (m_backups.find(decl) != m_backups.end()) {
@@ -258,10 +214,8 @@ namespace {
/// imported while completing the original Decls).
class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener {
ClangASTImporter::ImporterDelegateSP m_delegate;
- // FIXME: Investigate how many decls we usually have in these sets and
- // see if we can use SmallPtrSet instead here.
- std::set<NamedDecl *> m_decls_to_complete;
- std::set<NamedDecl *> m_decls_already_completed;
+ llvm::SmallVector<NamedDecl *, 32> m_decls_to_complete;
+ llvm::SmallPtrSet<NamedDecl *, 32> m_decls_already_completed;
clang::ASTContext *m_dst_ctx;
clang::ASTContext *m_src_ctx;
ClangASTImporter &importer;
@@ -285,10 +239,8 @@ public:
// Complete all decls we collected until now.
while (!m_decls_to_complete.empty()) {
- NamedDecl *decl = *m_decls_to_complete.begin();
-
+ NamedDecl *decl = m_decls_to_complete.pop_back_val();
m_decls_already_completed.insert(decl);
- m_decls_to_complete.erase(decl);
// We should only complete decls coming from the source context.
assert(to_context_md->m_origins[decl].ctx == m_src_ctx);
@@ -333,46 +285,39 @@ public:
// Check if we already completed this type.
if (m_decls_already_completed.count(to_named_decl) != 0)
return;
- m_decls_to_complete.insert(to_named_decl);
+ m_decls_to_complete.push_back(to_named_decl);
}
};
} // namespace
-lldb::opaque_compiler_type_t
-ClangASTImporter::DeportType(clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx,
- lldb::opaque_compiler_type_t type) {
+CompilerType ClangASTImporter::DeportType(ClangASTContext &dst,
+ const CompilerType &src_type) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
- LLDB_LOGF(log,
- " [ClangASTImporter] DeportType called on (%sType*)0x%llx "
- "from (ASTContext*)%p to (ASTContext*)%p",
- QualType::getFromOpaquePtr(type)->getTypeClassName(),
- (unsigned long long)type, static_cast<void *>(src_ctx),
- static_cast<void *>(dst_ctx));
+ ClangASTContext *src_ctxt =
+ llvm::cast<ClangASTContext>(src_type.GetTypeSystem());
+
+ LLDB_LOG(log,
+ " [ClangASTImporter] DeportType called on ({0}Type*){1:x} "
+ "from (ASTContext*){2:x} to (ASTContext*){3:x}",
+ src_type.GetTypeName(), src_type.GetOpaqueQualType(),
+ &src_ctxt->getASTContext(), &dst.getASTContext());
DeclContextOverride decl_context_override;
- if (auto *t = QualType::getFromOpaquePtr(type)->getAs<TagType>())
+ if (auto *t = ClangUtil::GetQualType(src_type)->getAs<TagType>())
decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl());
- lldb::opaque_compiler_type_t result;
- {
- CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx);
- result = CopyType(dst_ctx, src_ctx, type);
- }
-
- if (!result)
- return nullptr;
-
- return result;
+ CompleteTagDeclsScope complete_scope(*this, &dst.getASTContext(),
+ &src_ctxt->getASTContext());
+ return CopyType(dst, src_type);
}
clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx,
- clang::ASTContext *src_ctx,
clang::Decl *decl) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+ clang::ASTContext *src_ctx = &decl->getASTContext();
LLDB_LOGF(log,
" [ClangASTImporter] DeportDecl called on (%sDecl*)%p from "
"(ASTContext*)%p to (ASTContext*)%p",
@@ -386,7 +331,7 @@ clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx,
clang::Decl *result;
{
CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx);
- result = CopyDecl(dst_ctx, src_ctx, decl);
+ result = CopyDecl(dst_ctx, decl);
}
if (!result)
@@ -417,7 +362,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
const clang::CXXRecordDecl *cxx_record_decl =
qual_type->getAsCXXRecordDecl();
if (cxx_record_decl) {
- if (ResolveDeclOrigin(cxx_record_decl, nullptr, nullptr))
+ if (GetDeclOrigin(cxx_record_decl).Valid())
return true;
}
} break;
@@ -426,7 +371,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
clang::EnumDecl *enum_decl =
llvm::cast<clang::EnumType>(qual_type)->getDecl();
if (enum_decl) {
- if (ResolveDeclOrigin(enum_decl, nullptr, nullptr))
+ if (GetDeclOrigin(enum_decl).Valid())
return true;
}
} break;
@@ -441,7 +386,7 @@ bool ClangASTImporter::CanImport(const CompilerType &type) {
// We currently can't complete objective C types through the newly added
// ASTContext because it only supports TagDecl objects right now...
if (class_interface_decl) {
- if (ResolveDeclOrigin(class_interface_decl, nullptr, nullptr))
+ if (GetDeclOrigin(class_interface_decl).Valid())
return true;
}
}
@@ -493,7 +438,7 @@ bool ClangASTImporter::Import(const CompilerType &type) {
const clang::CXXRecordDecl *cxx_record_decl =
qual_type->getAsCXXRecordDecl();
if (cxx_record_decl) {
- if (ResolveDeclOrigin(cxx_record_decl, nullptr, nullptr))
+ if (GetDeclOrigin(cxx_record_decl).Valid())
return CompleteAndFetchChildren(qual_type);
}
} break;
@@ -502,7 +447,7 @@ bool ClangASTImporter::Import(const CompilerType &type) {
clang::EnumDecl *enum_decl =
llvm::cast<clang::EnumType>(qual_type)->getDecl();
if (enum_decl) {
- if (ResolveDeclOrigin(enum_decl, nullptr, nullptr))
+ if (GetDeclOrigin(enum_decl).Valid())
return CompleteAndFetchChildren(qual_type);
}
} break;
@@ -517,7 +462,7 @@ bool ClangASTImporter::Import(const CompilerType &type) {
// We currently can't complete objective C types through the newly added
// ASTContext because it only supports TagDecl objects right now...
if (class_interface_decl) {
- if (ResolveDeclOrigin(class_interface_decl, nullptr, nullptr))
+ if (GetDeclOrigin(class_interface_decl).Valid())
return CompleteAndFetchChildren(qual_type);
}
}
@@ -596,7 +541,7 @@ bool ClangASTImporter::LayoutRecordType(
return success;
}
-void ClangASTImporter::InsertRecordDecl(clang::RecordDecl *decl,
+void ClangASTImporter::SetRecordLayout(clang::RecordDecl *decl,
const LayoutInfo &layout) {
m_record_decl_to_layout_map.insert(std::make_pair(decl, layout));
}
@@ -628,8 +573,6 @@ void ClangASTImporter::CompleteDecl(clang::Decl *decl) {
}
bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
- ClangASTMetrics::RegisterDeclCompletion();
-
DeclOrigin decl_origin = GetDeclOrigin(decl);
if (!decl_origin.Valid())
@@ -651,8 +594,6 @@ bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) {
bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl,
clang::TagDecl *origin_decl) {
- ClangASTMetrics::RegisterDeclCompletion();
-
clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext();
if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl))
@@ -675,8 +616,6 @@ bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl,
bool ClangASTImporter::CompleteObjCInterfaceDecl(
clang::ObjCInterfaceDecl *interface_decl) {
- ClangASTMetrics::RegisterDeclCompletion();
-
DeclOrigin decl_origin = GetDeclOrigin(interface_decl);
if (!decl_origin.Valid())
@@ -729,9 +668,8 @@ bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) {
}
}
- if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl)) {
+ if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl))
record_decl->setHasLoadedFieldsFromExternalStorage(true);
- }
return true;
}
@@ -761,9 +699,8 @@ bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) {
}
return true;
- } else {
- return false;
}
+ return false;
}
return true;
@@ -785,15 +722,12 @@ bool ClangASTImporter::RequireCompleteType(clang::QualType type) {
if (ObjCInterfaceDecl *objc_interface_decl =
objc_object_type->getInterface())
return CompleteObjCInterfaceDecl(objc_interface_decl);
- else
- return false;
+ return false;
}
- if (const ArrayType *array_type = type->getAsArrayTypeUnsafe()) {
+ if (const ArrayType *array_type = type->getAsArrayTypeUnsafe())
return RequireCompleteType(array_type->getElementType());
- }
- if (const AtomicType *atomic_type = type->getAs<AtomicType>()) {
+ if (const AtomicType *atomic_type = type->getAs<AtomicType>())
return RequireCompleteType(atomic_type->getPointeeType());
- }
return true;
}
@@ -801,10 +735,12 @@ bool ClangASTImporter::RequireCompleteType(clang::QualType type) {
ClangASTMetadata *ClangASTImporter::GetDeclMetadata(const clang::Decl *decl) {
DeclOrigin decl_origin = GetDeclOrigin(decl);
- if (decl_origin.Valid())
- return ClangASTContext::GetMetadata(decl_origin.ctx, decl_origin.decl);
- else
- return ClangASTContext::GetMetadata(&decl->getASTContext(), decl);
+ if (decl_origin.Valid()) {
+ ClangASTContext *ast = ClangASTContext::GetASTContext(decl_origin.ctx);
+ return ast->GetMetadata(decl_origin.decl);
+ }
+ ClangASTContext *ast = ClangASTContext::GetASTContext(&decl->getASTContext());
+ return ast->GetMetadata(decl);
}
ClangASTImporter::DeclOrigin
@@ -817,8 +753,7 @@ ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) {
if (iter != origins.end())
return iter->second;
- else
- return DeclOrigin();
+ return DeclOrigin();
}
void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl,
@@ -832,9 +767,9 @@ void ClangASTImporter::SetDeclOrigin(const clang::Decl *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);
+ return;
}
+ origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl);
}
void ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl,
@@ -854,8 +789,7 @@ ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) {
if (iter != namespace_maps.end())
return iter->second;
- else
- return NamespaceMapSP();
+ return NamespaceMapSP();
}
void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) {
@@ -936,6 +870,39 @@ ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) {
}
}
+ // Check which ASTContext this declaration originally came from.
+ DeclOrigin origin = m_master.GetDeclOrigin(From);
+ // If it originally came from the target ASTContext then we can just
+ // pretend that the original is the one we imported. This can happen for
+ // example when inspecting a persistent declaration from the scratch
+ // ASTContext (which will provide the declaration when parsing the
+ // expression and then we later try to copy the declaration back to the
+ // scratch ASTContext to store the result).
+ // Without this check we would ask the ASTImporter to import a declaration
+ // into the same ASTContext where it came from (which doesn't make a lot of
+ // sense).
+ if (origin.Valid() && origin.ctx == &getToContext()) {
+ RegisterImportedDecl(From, origin.decl);
+ return origin.decl;
+ }
+
+ // This declaration came originally from another ASTContext. Instead of
+ // copying our potentially incomplete 'From' Decl we instead go to the
+ // original ASTContext and copy the original to the target. This is not
+ // only faster than first completing our current decl and then copying it
+ // to the target, but it also prevents that indirectly copying the same
+ // declaration to the same target requires the ASTImporter to merge all
+ // the different decls that appear to come from different ASTContexts (even
+ // though all these different source ASTContexts just got a copy from
+ // one source AST).
+ if (origin.Valid()) {
+ auto R = m_master.CopyDecl(&getToContext(), origin.decl);
+ if (R) {
+ RegisterImportedDecl(From, R);
+ return R;
+ }
+ }
+
return ASTImporter::ImportImpl(From);
}
@@ -1037,8 +1004,6 @@ void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(
void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
clang::Decl *to) {
- ClangASTMetrics::RegisterClangImport();
-
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
// Some decls shouldn't be tracked here because they were not created by
@@ -1196,16 +1161,5 @@ void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from,
clang::Decl *
ClangASTImporter::ASTImporterDelegate::GetOriginalDecl(clang::Decl *To) {
- ASTContextMetadataSP to_context_md =
- m_master.GetContextMetadata(&To->getASTContext());
-
- if (!to_context_md)
- return nullptr;
-
- OriginMap::iterator iter = to_context_md->m_origins.find(To);
-
- if (iter == to_context_md->m_origins.end())
- return nullptr;
-
- return const_cast<clang::Decl *>(iter->second.decl);
+ return m_master.GetDeclOrigin(To).decl;
}