diff options
Diffstat (limited to 'lldb/source/Symbol/ClangASTImporter.cpp')
-rw-r--r-- | lldb/source/Symbol/ClangASTImporter.cpp | 1165 |
1 files changed, 0 insertions, 1165 deletions
diff --git a/lldb/source/Symbol/ClangASTImporter.cpp b/lldb/source/Symbol/ClangASTImporter.cpp deleted file mode 100644 index 8cb404231a8d..000000000000 --- a/lldb/source/Symbol/ClangASTImporter.cpp +++ /dev/null @@ -1,1165 +0,0 @@ -//===-- ClangASTImporter.cpp ------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "lldb/Symbol/ClangASTImporter.h" -#include "lldb/Core/Module.h" -#include "lldb/Symbol/ClangASTContext.h" -#include "lldb/Symbol/ClangASTMetadata.h" -#include "lldb/Symbol/ClangUtil.h" -#include "lldb/Utility/LLDBAssert.h" -#include "lldb/Utility/Log.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/Sema/Lookup.h" -#include "clang/Sema/Sema.h" -#include "llvm/Support/raw_ostream.h" - -#include <memory> - -using namespace lldb_private; -using namespace clang; - -CompilerType ClangASTImporter::CopyType(ClangASTContext &dst_ast, - const CompilerType &src_type) { - clang::ASTContext &dst_clang_ast = dst_ast.getASTContext(); - - ClangASTContext *src_ast = - llvm::dyn_cast_or_null<ClangASTContext>(src_type.GetTypeSystem()); - if (!src_ast) - return CompilerType(); - - clang::ASTContext &src_clang_ast = src_ast->getASTContext(); - - clang::QualType src_qual_type = ClangUtil::GetQualType(src_type); - - ImporterDelegateSP delegate_sp(GetDelegate(&dst_clang_ast, &src_clang_ast)); - if (!delegate_sp) - return CompilerType(); - - ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, &dst_clang_ast); - - 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 CompilerType(); - } - - lldb::opaque_compiler_type_t dst_clang_type = ret_or_error->getAsOpaquePtr(); - - if (dst_clang_type) - return CompilerType(&dst_ast, dst_clang_type); - return CompilerType(); -} - -clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_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); - - if (!delegate_sp) - return nullptr; - - llvm::Expected<clang::Decl *> result = delegate_sp->Import(decl); - if (!result) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - LLDB_LOG_ERROR(log, result.takeError(), "Couldn't import decl: {0}"); - if (log) { - lldb::user_id_t user_id = LLDB_INVALID_UID; - ClangASTMetadata *metadata = GetDeclMetadata(decl); - if (metadata) - user_id = metadata->GetUserID(); - - if (NamedDecl *named_decl = dyn_cast<NamedDecl>(decl)) - LLDB_LOGF(log, - " [ClangASTImporter] WARNING: Failed to import a %s " - "'%s', metadata 0x%" PRIx64, - decl->getDeclKindName(), - named_decl->getNameAsString().c_str(), user_id); - else - LLDB_LOGF(log, - " [ClangASTImporter] WARNING: Failed to import a %s, " - "metadata 0x%" PRIx64, - decl->getDeclKindName(), user_id); - } - return nullptr; - } - - return *result; -} - -class DeclContextOverride { -private: - struct Backup { - clang::DeclContext *decl_context; - clang::DeclContext *lexical_decl_context; - }; - - llvm::DenseMap<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)); - - LLDB_LOGF(log, - " [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); - } - } -}; - -namespace { -/// Completes all imported TagDecls at the end of the scope. -/// -/// While in a CompleteTagDeclsScope, every decl that could be completed will -/// be completed at the end of the scope (including all Decls that are -/// imported while completing the original Decls). -class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener { - ClangASTImporter::ImporterDelegateSP m_delegate; - 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; - -public: - /// Constructs a CompleteTagDeclsScope. - /// \param importer The ClangASTImporter that we should observe. - /// \param dst_ctx The ASTContext to which Decls are imported. - /// \param src_ctx The ASTContext from which Decls are imported. - explicit CompleteTagDeclsScope(ClangASTImporter &importer, - clang::ASTContext *dst_ctx, - clang::ASTContext *src_ctx) - : m_delegate(importer.GetDelegate(dst_ctx, src_ctx)), m_dst_ctx(dst_ctx), - m_src_ctx(src_ctx), importer(importer) { - m_delegate->SetImportListener(this); - } - - virtual ~CompleteTagDeclsScope() { - ClangASTImporter::ASTContextMetadataSP to_context_md = - importer.GetContextMetadata(m_dst_ctx); - - // Complete all decls we collected until now. - while (!m_decls_to_complete.empty()) { - NamedDecl *decl = m_decls_to_complete.pop_back_val(); - m_decls_already_completed.insert(decl); - - // We should only complete decls coming from the source context. - assert(to_context_md->m_origins[decl].ctx == m_src_ctx); - - Decl *original_decl = to_context_md->m_origins[decl].decl; - - // Complete the decl now. - ClangASTContext::GetCompleteDecl(m_src_ctx, original_decl); - if (auto *tag_decl = dyn_cast<TagDecl>(decl)) { - if (auto *original_tag_decl = dyn_cast<TagDecl>(original_decl)) { - if (original_tag_decl->isCompleteDefinition()) { - m_delegate->ImportDefinitionTo(tag_decl, original_tag_decl); - tag_decl->setCompleteDefinition(true); - } - } - - tag_decl->setHasExternalLexicalStorage(false); - tag_decl->setHasExternalVisibleStorage(false); - } else if (auto *container_decl = dyn_cast<ObjCContainerDecl>(decl)) { - container_decl->setHasExternalLexicalStorage(false); - container_decl->setHasExternalVisibleStorage(false); - } - - to_context_md->m_origins.erase(decl); - } - - // Stop listening to imported decls. We do this after clearing the - // Decls we needed to import to catch all Decls they might have pulled in. - m_delegate->RemoveImportListener(); - } - - void NewDeclImported(clang::Decl *from, clang::Decl *to) override { - // Filter out decls that we can't complete later. - if (!isa<TagDecl>(to) && !isa<ObjCInterfaceDecl>(to)) - return; - RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from); - // We don't need to complete injected class name decls. - if (from_record_decl && from_record_decl->isInjectedClassName()) - return; - - NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to); - // Check if we already completed this type. - if (m_decls_already_completed.count(to_named_decl) != 0) - return; - m_decls_to_complete.push_back(to_named_decl); - } -}; -} // namespace - -CompilerType ClangASTImporter::DeportType(ClangASTContext &dst, - const CompilerType &src_type) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - 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 = ClangUtil::GetQualType(src_type)->getAs<TagType>()) - decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl()); - - CompleteTagDeclsScope complete_scope(*this, &dst.getASTContext(), - &src_ctxt->getASTContext()); - return CopyType(dst, src_type); -} - -clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_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", - decl->getDeclKindName(), static_cast<void *>(decl), - static_cast<void *>(src_ctx), static_cast<void *>(dst_ctx)); - - DeclContextOverride decl_context_override; - - decl_context_override.OverrideAllDeclsFromContainingFunction(decl); - - clang::Decl *result; - { - CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx); - result = CopyDecl(dst_ctx, decl); - } - - if (!result) - return nullptr; - - LLDB_LOGF( - log, - " [ClangASTImporter] DeportDecl deported (%sDecl*)%p to (%sDecl*)%p", - decl->getDeclKindName(), static_cast<void *>(decl), - result->getDeclKindName(), static_cast<void *>(result)); - - return result; -} - -bool ClangASTImporter::CanImport(const CompilerType &type) { - if (!ClangUtil::IsClangType(type)) - return false; - - // TODO: remove external completion BOOL - // CompleteAndFetchChildren should get the Decl out and check for the - - clang::QualType qual_type( - ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) { - case clang::Type::Record: { - const clang::CXXRecordDecl *cxx_record_decl = - qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) { - if (GetDeclOrigin(cxx_record_decl).Valid()) - return true; - } - } break; - - case clang::Type::Enum: { - clang::EnumDecl *enum_decl = - llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) { - if (GetDeclOrigin(enum_decl).Valid()) - return true; - } - } break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: { - const clang::ObjCObjectType *objc_class_type = - llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) { - clang::ObjCInterfaceDecl *class_interface_decl = - objc_class_type->getInterface(); - // 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 (GetDeclOrigin(class_interface_decl).Valid()) - return true; - } - } - } break; - - case clang::Type::Typedef: - return CanImport(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType() - .getAsOpaquePtr())); - - case clang::Type::Auto: - return CanImport(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::AutoType>(qual_type) - ->getDeducedType() - .getAsOpaquePtr())); - - case clang::Type::Elaborated: - return CanImport(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::ElaboratedType>(qual_type) - ->getNamedType() - .getAsOpaquePtr())); - - case clang::Type::Paren: - return CanImport(CompilerType( - type.GetTypeSystem(), - llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); - - default: - break; - } - - return false; -} - -bool ClangASTImporter::Import(const CompilerType &type) { - if (!ClangUtil::IsClangType(type)) - return false; - // TODO: remove external completion BOOL - // CompleteAndFetchChildren should get the Decl out and check for the - - clang::QualType qual_type( - ClangUtil::GetCanonicalQualType(ClangUtil::RemoveFastQualifiers(type))); - - const clang::Type::TypeClass type_class = qual_type->getTypeClass(); - switch (type_class) { - case clang::Type::Record: { - const clang::CXXRecordDecl *cxx_record_decl = - qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) { - if (GetDeclOrigin(cxx_record_decl).Valid()) - return CompleteAndFetchChildren(qual_type); - } - } break; - - case clang::Type::Enum: { - clang::EnumDecl *enum_decl = - llvm::cast<clang::EnumType>(qual_type)->getDecl(); - if (enum_decl) { - if (GetDeclOrigin(enum_decl).Valid()) - return CompleteAndFetchChildren(qual_type); - } - } break; - - case clang::Type::ObjCObject: - case clang::Type::ObjCInterface: { - const clang::ObjCObjectType *objc_class_type = - llvm::dyn_cast<clang::ObjCObjectType>(qual_type); - if (objc_class_type) { - clang::ObjCInterfaceDecl *class_interface_decl = - objc_class_type->getInterface(); - // 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 (GetDeclOrigin(class_interface_decl).Valid()) - return CompleteAndFetchChildren(qual_type); - } - } - } break; - - case clang::Type::Typedef: - return Import(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::TypedefType>(qual_type) - ->getDecl() - ->getUnderlyingType() - .getAsOpaquePtr())); - - case clang::Type::Auto: - return Import(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::AutoType>(qual_type) - ->getDeducedType() - .getAsOpaquePtr())); - - case clang::Type::Elaborated: - return Import(CompilerType(type.GetTypeSystem(), - llvm::cast<clang::ElaboratedType>(qual_type) - ->getNamedType() - .getAsOpaquePtr())); - - case clang::Type::Paren: - return Import(CompilerType( - type.GetTypeSystem(), - llvm::cast<clang::ParenType>(qual_type)->desugar().getAsOpaquePtr())); - - default: - break; - } - return false; -} - -bool ClangASTImporter::CompleteType(const CompilerType &compiler_type) { - if (!CanImport(compiler_type)) - return false; - - if (Import(compiler_type)) { - ClangASTContext::CompleteTagDeclarationDefinition(compiler_type); - return true; - } - - ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(), - false); - return false; -} - -bool ClangASTImporter::LayoutRecordType( - const clang::RecordDecl *record_decl, uint64_t &bit_size, - uint64_t &alignment, - llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> - &base_offsets, - llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> - &vbase_offsets) { - RecordDeclToLayoutMap::iterator pos = - m_record_decl_to_layout_map.find(record_decl); - bool success = false; - base_offsets.clear(); - vbase_offsets.clear(); - if (pos != m_record_decl_to_layout_map.end()) { - bit_size = pos->second.bit_size; - alignment = pos->second.alignment; - field_offsets.swap(pos->second.field_offsets); - base_offsets.swap(pos->second.base_offsets); - vbase_offsets.swap(pos->second.vbase_offsets); - m_record_decl_to_layout_map.erase(pos); - success = true; - } else { - bit_size = 0; - alignment = 0; - field_offsets.clear(); - } - return success; -} - -void ClangASTImporter::SetRecordLayout(clang::RecordDecl *decl, - const LayoutInfo &layout) { - m_record_decl_to_layout_map.insert(std::make_pair(decl, layout)); -} - -void ClangASTImporter::CompleteDecl(clang::Decl *decl) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - LLDB_LOGF(log, " [ClangASTImporter] CompleteDecl called on (%sDecl*)%p", - decl->getDeclKindName(), static_cast<void *>(decl)); - - if (ObjCInterfaceDecl *interface_decl = dyn_cast<ObjCInterfaceDecl>(decl)) { - if (!interface_decl->getDefinition()) { - interface_decl->startDefinition(); - CompleteObjCInterfaceDecl(interface_decl); - } - } else if (ObjCProtocolDecl *protocol_decl = - dyn_cast<ObjCProtocolDecl>(decl)) { - 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); - } - } else { - assert(0 && "CompleteDecl called on a Decl that can't be completed"); - } -} - -bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) { - DeclOrigin decl_origin = GetDeclOrigin(decl); - - if (!decl_origin.Valid()) - return false; - - if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl)) - return false; - - ImporterDelegateSP delegate_sp( - GetDelegate(&decl->getASTContext(), decl_origin.ctx)); - - ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, - &decl->getASTContext()); - if (delegate_sp) - delegate_sp->ImportDefinitionTo(decl, decl_origin.decl); - - return true; -} - -bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl, - clang::TagDecl *origin_decl) { - clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext(); - - if (!ClangASTContext::GetCompleteDecl(origin_ast_ctx, origin_decl)) - return false; - - ImporterDelegateSP delegate_sp( - GetDelegate(&decl->getASTContext(), origin_ast_ctx)); - - if (delegate_sp) - delegate_sp->ImportDefinitionTo(decl, origin_decl); - - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - OriginMap &origins = context_md->m_origins; - - origins[decl] = DeclOrigin(origin_ast_ctx, origin_decl); - - return true; -} - -bool ClangASTImporter::CompleteObjCInterfaceDecl( - clang::ObjCInterfaceDecl *interface_decl) { - DeclOrigin decl_origin = GetDeclOrigin(interface_decl); - - if (!decl_origin.Valid()) - return false; - - if (!ClangASTContext::GetCompleteDecl(decl_origin.ctx, decl_origin.decl)) - return false; - - ImporterDelegateSP delegate_sp( - GetDelegate(&interface_decl->getASTContext(), decl_origin.ctx)); - - if (delegate_sp) - delegate_sp->ImportDefinitionTo(interface_decl, decl_origin.decl); - - if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass()) - RequireCompleteType(clang::QualType(super_class->getTypeForDecl(), 0)); - - return true; -} - -bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) { - if (!RequireCompleteType(type)) - return false; - - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); - - if (const TagType *tag_type = type->getAs<TagType>()) { - TagDecl *tag_decl = tag_type->getDecl(); - - DeclOrigin decl_origin = GetDeclOrigin(tag_decl); - - if (!decl_origin.Valid()) - return false; - - ImporterDelegateSP delegate_sp( - GetDelegate(&tag_decl->getASTContext(), decl_origin.ctx)); - - ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, - &tag_decl->getASTContext()); - - TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(decl_origin.decl); - - for (Decl *origin_child_decl : origin_tag_decl->decls()) { - llvm::Expected<Decl *> imported_or_err = - delegate_sp->Import(origin_child_decl); - if (!imported_or_err) { - LLDB_LOG_ERROR(log, imported_or_err.takeError(), - "Couldn't import decl: {0}"); - return false; - } - } - - if (RecordDecl *record_decl = dyn_cast<RecordDecl>(origin_tag_decl)) - record_decl->setHasLoadedFieldsFromExternalStorage(true); - - return true; - } - - if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) { - if (ObjCInterfaceDecl *objc_interface_decl = - objc_object_type->getInterface()) { - DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl); - - if (!decl_origin.Valid()) - return false; - - ImporterDelegateSP delegate_sp( - GetDelegate(&objc_interface_decl->getASTContext(), decl_origin.ctx)); - - ObjCInterfaceDecl *origin_interface_decl = - llvm::dyn_cast<ObjCInterfaceDecl>(decl_origin.decl); - - for (Decl *origin_child_decl : origin_interface_decl->decls()) { - llvm::Expected<Decl *> imported_or_err = - delegate_sp->Import(origin_child_decl); - if (!imported_or_err) { - LLDB_LOG_ERROR(log, imported_or_err.takeError(), - "Couldn't import decl: {0}"); - return false; - } - } - - return true; - } - return false; - } - - return true; -} - -bool ClangASTImporter::RequireCompleteType(clang::QualType type) { - if (type.isNull()) - return false; - - if (const TagType *tag_type = type->getAs<TagType>()) { - TagDecl *tag_decl = tag_type->getDecl(); - - if (tag_decl->getDefinition() || tag_decl->isBeingDefined()) - return true; - - return CompleteTagDecl(tag_decl); - } - if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) { - if (ObjCInterfaceDecl *objc_interface_decl = - objc_object_type->getInterface()) - return CompleteObjCInterfaceDecl(objc_interface_decl); - 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; -} - -ClangASTMetadata *ClangASTImporter::GetDeclMetadata(const clang::Decl *decl) { - DeclOrigin decl_origin = GetDeclOrigin(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 -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; - return DeclOrigin(); -} - -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(); - return; - } - origins[decl] = DeclOrigin(&original_decl->getASTContext(), original_decl); -} - -void ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl, - NamespaceMapSP &namespace_map) { - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - context_md->m_namespace_maps[decl] = namespace_map; -} - -ClangASTImporter::NamespaceMapSP -ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) { - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps; - - NamespaceMetaMap::iterator iter = namespace_maps.find(decl); - - if (iter != namespace_maps.end()) - return iter->second; - return NamespaceMapSP(); -} - -void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) { - assert(decl); - ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - 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 = std::make_shared<NamespaceMap>(); - - if (context_md->m_map_completer) { - std::string namespace_string = decl->getDeclName().getAsString(); - - context_md->m_map_completer->CompleteNamespaceMap( - new_map, ConstString(namespace_string.c_str()), parent_map); - } - - context_md->m_namespace_maps[decl] = new_map; -} - -void ClangASTImporter::ForgetDestination(clang::ASTContext *dst_ast) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - LLDB_LOGF(log, - " [ClangASTImporter] Forgetting destination (ASTContext*)%p", - static_cast<void *>(dst_ast)); - - m_metadata_map.erase(dst_ast); -} - -void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast, - clang::ASTContext *src_ast) { - ASTContextMetadataSP md = MaybeGetContextMetadata(dst_ast); - - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - LLDB_LOGF(log, - " [ClangASTImporter] Forgetting source->dest " - "(ASTContext*)%p->(ASTContext*)%p", - static_cast<void *>(src_ast), static_cast<void *>(dst_ast)); - - if (!md) - return; - - md->m_delegates.erase(src_ast); - - 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; - } -} - -ClangASTImporter::MapCompleter::~MapCompleter() { return; } - -llvm::Expected<Decl *> -ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) { - if (m_std_handler) { - llvm::Optional<Decl *> D = m_std_handler->Import(From); - if (D) { - // Make sure we don't use this decl later to map it back to it's original - // decl. The decl the CxxModuleHandler created has nothing to do with - // the one from debug info, and linking those two would just cause the - // ASTImporter to try 'updating' the module decl with the minimal one from - // the debug info. - m_decls_to_ignore.insert(*D); - return *D; - } - } - - // 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); -} - -void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo( - clang::Decl *to, clang::Decl *from) { - ASTImporter::Imported(from, to); - - /* - if (to_objc_interface) - to_objc_interface->startDefinition(); - - CXXRecordDecl *to_cxx_record = dyn_cast<CXXRecordDecl>(to); - - if (to_cxx_record) - to_cxx_record->startDefinition(); - */ - - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS); - - if (llvm::Error err = ImportDefinition(from)) { - LLDB_LOG_ERROR(log, std::move(err), - "[ClangASTImporter] Error during importing definition: {0}"); - return; - } - - if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(to)) { - if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(from)) { - to_tag->setCompleteDefinition(from_tag->isCompleteDefinition()); - - if (Log *log_ast = - lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_AST)) { - std::string name_string; - if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) { - llvm::raw_string_ostream name_stream(name_string); - from_named_decl->printName(name_stream); - name_stream.flush(); - } - LLDB_LOG(log_ast, "==== [ClangASTImporter][TUDecl: {0}] Imported " - "({1}Decl*){2}, named {3} (from " - "(Decl*){4})", - static_cast<void *>(to->getTranslationUnitDecl()), - from->getDeclKindName(), static_cast<void *>(to), name_string, - static_cast<void *>(from)); - - // Log the AST of the TU. - std::string ast_string; - llvm::raw_string_ostream ast_stream(ast_string); - to->getTranslationUnitDecl()->dump(ast_stream); - LLDB_LOG(log_ast, "{0}", ast_string); - } - } - } - - // 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. - - if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(to)) { - 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; - - llvm::Expected<Decl *> imported_from_superclass_decl = - Import(from_superclass); - - if (!imported_from_superclass_decl) { - LLDB_LOG_ERROR(log, imported_from_superclass_decl.takeError(), - "Couldn't import decl: {0}"); - break; - } - - ObjCInterfaceDecl *imported_from_superclass = - dyn_cast<ObjCInterfaceDecl>(*imported_from_superclass_decl); - - if (!imported_from_superclass) - break; - - if (!to_objc_interface->hasDefinition()) - to_objc_interface->startDefinition(); - - to_objc_interface->setSuperClass(m_source_ctx->getTrivialTypeSourceInfo( - m_source_ctx->getObjCInterfaceType(imported_from_superclass))); - } while (false); - } -} - -void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, - clang::Decl *to) { - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); - - // Some decls shouldn't be tracked here because they were not created by - // copying 'from' to 'to'. Just exit early for those. - if (m_decls_to_ignore.find(to) != m_decls_to_ignore.end()) - return clang::ASTImporter::Imported(from, to); - - lldb::user_id_t user_id = LLDB_INVALID_UID; - ClangASTMetadata *metadata = m_master.GetDeclMetadata(from); - if (metadata) - user_id = metadata->GetUserID(); - - if (log) { - if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(from)) { - std::string name_string; - llvm::raw_string_ostream name_stream(name_string); - from_named_decl->printName(name_stream); - name_stream.flush(); - - LLDB_LOGF(log, - " [ClangASTImporter] Imported (%sDecl*)%p, named %s (from " - "(Decl*)%p), metadata 0x%" PRIx64, - from->getDeclKindName(), static_cast<void *>(to), - name_string.c_str(), static_cast<void *>(from), user_id); - } else { - LLDB_LOGF(log, - " [ClangASTImporter] Imported (%sDecl*)%p (from " - "(Decl*)%p), metadata 0x%" PRIx64, - from->getDeclKindName(), static_cast<void *>(to), - static_cast<void *>(from), user_id); - } - } - - ASTContextMetadataSP to_context_md = - m_master.GetContextMetadata(&to->getASTContext()); - ASTContextMetadataSP from_context_md = - m_master.MaybeGetContextMetadata(m_source_ctx); - - if (from_context_md) { - OriginMap &origins = from_context_md->m_origins; - - OriginMap::iterator origin_iter = origins.find(from); - - if (origin_iter != origins.end()) { - if (to_context_md->m_origins.find(to) == to_context_md->m_origins.end() || - user_id != LLDB_INVALID_UID) { - if (origin_iter->second.ctx != &to->getASTContext()) - to_context_md->m_origins[to] = origin_iter->second; - } - - ImporterDelegateSP direct_completer = - m_master.GetDelegate(&to->getASTContext(), origin_iter->second.ctx); - - if (direct_completer.get() != this) - direct_completer->ASTImporter::Imported(origin_iter->second.decl, to); - - LLDB_LOGF(log, - " [ClangASTImporter] Propagated origin " - "(Decl*)%p/(ASTContext*)%p from (ASTContext*)%p to " - "(ASTContext*)%p", - static_cast<void *>(origin_iter->second.decl), - static_cast<void *>(origin_iter->second.ctx), - static_cast<void *>(&from->getASTContext()), - static_cast<void *>(&to->getASTContext())); - } else { - if (m_new_decl_listener) - m_new_decl_listener->NewDeclImported(from, to); - - 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); - } - - LLDB_LOGF(log, - " [ClangASTImporter] Decl has no origin information in " - "(ASTContext*)%p", - static_cast<void *>(&from->getASTContext())); - } - - if (clang::NamespaceDecl *to_namespace = - dyn_cast<clang::NamespaceDecl>(to)) { - clang::NamespaceDecl *from_namespace = - dyn_cast<clang::NamespaceDecl>(from); - - NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps; - - NamespaceMetaMap::iterator namespace_map_iter = - namespace_maps.find(from_namespace); - - 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); - - LLDB_LOGF(log, - " [ClangASTImporter] Sourced origin " - "(Decl*)%p/(ASTContext*)%p into (ASTContext*)%p", - static_cast<void *>(from), static_cast<void *>(m_source_ctx), - static_cast<void *>(&to->getASTContext())); - } - - if (TagDecl *from_tag_decl = dyn_cast<TagDecl>(from)) { - TagDecl *to_tag_decl = dyn_cast<TagDecl>(to); - - to_tag_decl->setHasExternalLexicalStorage(); - to_tag_decl->getPrimaryContext()->setMustBuildLookupTable(); - - LLDB_LOGF( - log, - " [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")); - } - - if (isa<NamespaceDecl>(from)) { - NamespaceDecl *to_namespace_decl = dyn_cast<NamespaceDecl>(to); - - m_master.BuildNamespaceMap(to_namespace_decl); - - to_namespace_decl->setHasExternalVisibleStorage(); - } - - if (isa<ObjCContainerDecl>(from)) { - ObjCContainerDecl *to_container_decl = dyn_cast<ObjCContainerDecl>(to); - - to_container_decl->setHasExternalLexicalStorage(); - to_container_decl->setHasExternalVisibleStorage(); - - /*to_interface_decl->setExternallyCompleted();*/ - - if (log) { - if (ObjCInterfaceDecl *to_interface_decl = - llvm::dyn_cast<ObjCInterfaceDecl>(to_container_decl)) { - LLDB_LOGF( - log, - " [ClangASTImporter] To is an ObjCInterfaceDecl - attributes " - "%s%s%s", - (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""), - (to_interface_decl->hasDefinition() ? " HasDefinition" : "")); - } else { - LLDB_LOGF( - log, " [ClangASTImporter] To is an %sDecl - attributes %s%s", - ((Decl *)to_container_decl)->getDeclKindName(), - (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_container_decl->hasExternalVisibleStorage() ? " Visible" : "")); - } - } - } -} - -clang::Decl * -ClangASTImporter::ASTImporterDelegate::GetOriginalDecl(clang::Decl *To) { - return m_master.GetDeclOrigin(To).decl; -} |