Index: clang/include/clang/AST/DeclObjC.h =================================================================== --- clang/include/clang/AST/DeclObjC.h +++ clang/include/clang/AST/DeclObjC.h @@ -1504,7 +1504,9 @@ /// Determine whether this particular declaration of this class is /// actually also a definition. bool isThisDeclarationADefinition() const { - return getDefinition() == this; + if (!Data.getPointer()) + return false; + return Data.getPointer()->Definition == this; } /// Determine whether this class has been defined. @@ -2203,7 +2205,9 @@ /// Determine whether this particular declaration is also the /// definition. bool isThisDeclarationADefinition() const { - return getDefinition() == this; + if (!Data.getPointer()) + return false; + return Data.getPointer()->Definition == this; } /// Starts the definition of this Objective-C protocol. Index: clang/include/clang/AST/ExternalASTSource.h =================================================================== --- clang/include/clang/AST/ExternalASTSource.h +++ clang/include/clang/AST/ExternalASTSource.h @@ -309,6 +309,7 @@ SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name); +public: /// Increment the current generation. uint32_t incrementGeneration(ASTContext &C); }; Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -5398,8 +5398,8 @@ } // Prefer the definition, if there is one. - if (const ObjCInterfaceDecl *Def = Decl->getDefinition()) - Decl = Def; + //if (const ObjCInterfaceDecl *Def = Decl->getDefinition()) + // Decl = Def; void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment); auto *T = new (Mem) ObjCInterfaceType(Decl); Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -281,7 +281,7 @@ } void addDeclToContexts(Decl *FromD, Decl *ToD) { - if (Importer.isMinimalImport()) { + if (Importer.isMinimalImport() || Importer.getToContext().getLangOpts().DebuggerSupport || Importer.getFromContext().getLangOpts().DebuggerSupport) { // In minimal import case the decl must be added even if it is not // contained in original context, for LLDB compatibility. // FIXME: Check if a better solution is possible. Index: clang/lib/AST/DeclObjC.cpp =================================================================== --- clang/lib/AST/DeclObjC.cpp +++ clang/lib/AST/DeclObjC.cpp @@ -1499,7 +1499,7 @@ auto *Result = new (C, DC) ObjCInterfaceDecl(C, DC, atLoc, Id, typeParamList, ClassLoc, PrevDecl, isInternal); - Result->Data.setInt(!C.getLangOpts().Modules); + Result->Data.setInt(!C.getLangOpts().Modules && !C.getLangOpts().DebuggerSupport); C.getObjCInterfaceType(Result, PrevDecl); return Result; } @@ -1509,7 +1509,7 @@ auto *Result = new (C, ID) ObjCInterfaceDecl(C, nullptr, SourceLocation(), nullptr, nullptr, SourceLocation(), nullptr, false); - Result->Data.setInt(!C.getLangOpts().Modules); + Result->Data.setInt(false); return Result; } Index: lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h +++ lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h @@ -147,11 +147,11 @@ bool CompleteType(const CompilerType &compiler_type); - bool CompleteTagDecl(clang::TagDecl *decl); + bool CompleteTagDecl(const clang::TagDecl *decl); - bool CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin); + bool CompleteTagDeclWithOrigin(const clang::TagDecl *decl, clang::TagDecl *origin); - bool CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *interface_decl); + bool CompleteObjCInterfaceDecl(const clang::ObjCInterfaceDecl *interface_decl); bool CompleteAndFetchChildren(clang::QualType type); @@ -262,7 +262,7 @@ ASTImporterDelegate(ClangASTImporter &master, clang::ASTContext *target_ctx, clang::ASTContext *source_ctx) : clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx, - master.m_file_manager, true /*minimal*/), + master.m_file_manager, false /*minimal*/), m_master(master), m_source_ctx(source_ctx) { // Target and source ASTContext shouldn't be identical. Importing AST // nodes within the same AST doesn't make any sense as the whole idea Index: lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -266,12 +266,6 @@ tag_decl->setCompleteDefinition(true); } } - - tag_decl->setHasExternalLexicalStorage(false); - tag_decl->setHasExternalVisibleStorage(false); - } else if (auto *container_decl = dyn_cast(decl)) { - container_decl->setHasExternalLexicalStorage(false); - container_decl->setHasExternalVisibleStorage(false); } to_context_md->removeOrigin(decl); @@ -506,14 +500,7 @@ if (!CanImport(compiler_type)) return false; - if (Import(compiler_type)) { - TypeSystemClang::CompleteTagDeclarationDefinition(compiler_type); - return true; - } - - TypeSystemClang::SetHasExternalStorage(compiler_type.GetOpaqueQualType(), - false); - return false; + return Import(compiler_type); } bool ClangASTImporter::LayoutRecordType( @@ -524,6 +511,7 @@ &base_offsets, llvm::DenseMap &vbase_offsets) { + record_decl = record_decl->getDefinition(); RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find(record_decl); bool success = false; @@ -535,7 +523,6 @@ 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; @@ -550,13 +537,16 @@ m_record_decl_to_layout_map.insert(std::make_pair(decl, layout)); } -bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) { +bool ClangASTImporter::CompleteTagDecl(const TagDecl *decl) { DeclOrigin decl_origin = GetDeclOrigin(decl); if (!decl_origin.Valid()) return false; - if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl)) + clang::TagDecl *origin_decl = llvm::cast(decl_origin.decl); + + origin_decl = origin_decl->getDefinition(); + if (!origin_decl) return false; ImporterDelegateSP delegate_sp( @@ -564,51 +554,52 @@ ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, &decl->getASTContext()); - if (delegate_sp) - delegate_sp->ImportDefinitionTo(decl, decl_origin.decl); + llvm::Expected result = delegate_sp->Import(origin_decl); + if (result) + return true; + llvm::handleAllErrors(result.takeError(), [](clang::ImportError &e){ + abort(); + }); - return true; + return false; } -bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl, +bool ClangASTImporter::CompleteTagDeclWithOrigin(const clang::TagDecl *decl, clang::TagDecl *origin_decl) { - clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext(); - - if (!TypeSystemClang::GetCompleteDecl(origin_ast_ctx, origin_decl)) + origin_decl = origin_decl->getDefinition(); + if (!origin_decl) return false; - ImporterDelegateSP delegate_sp( - GetDelegate(&decl->getASTContext(), origin_ast_ctx)); - - if (delegate_sp) - delegate_sp->ImportDefinitionTo(decl, origin_decl); - + clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext(); ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - context_md->setOrigin(decl, DeclOrigin(origin_ast_ctx, origin_decl)); - return true; + + return CompleteTagDecl(decl); } -bool ClangASTImporter::CompleteObjCInterfaceDecl( - clang::ObjCInterfaceDecl *interface_decl) { +bool ClangASTImporter::CompleteObjCInterfaceDecl(const ObjCInterfaceDecl *interface_decl) { DeclOrigin decl_origin = GetDeclOrigin(interface_decl); if (!decl_origin.Valid()) return false; - if (!TypeSystemClang::GetCompleteDecl(decl_origin.ctx, decl_origin.decl)) + ObjCInterfaceDecl *origin_decl = llvm::cast(decl_origin.decl); + + origin_decl = origin_decl->getDefinition(); + if (!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)); + llvm::Expected result = delegate_sp->Import(origin_decl); + if (result) + return true; + llvm::handleAllErrors(result.takeError(), [](clang::ImportError &e){ + abort(); + }); - return true; + return false; } bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) { @@ -721,8 +712,15 @@ ClangASTImporter::DeclOrigin ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) { ASTContextMetadataSP context_md = GetContextMetadata(&decl->getASTContext()); - - return context_md->getOrigin(decl); + DeclOrigin o = context_md->getOrigin(decl); + if (o.Valid()) + return o; + if (const clang::TagDecl *td = dyn_cast(decl)) { + if (const clang::TagDecl *def = td->getDefinition()) { + o = context_md->getOrigin(def); + } + } + return o; } void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl, @@ -860,6 +858,17 @@ } } + if (clang::TagDecl *td = dyn_cast(From)) + if (clang::ExternalASTSource *s = getToContext().getExternalSource()) + if (!td->isThisDeclarationADefinition()) + s->incrementGeneration(getToContext()); + + if (clang::ObjCInterfaceDecl *td = dyn_cast(From)) + if (clang::ExternalASTSource *s = getToContext().getExternalSource()) + if (!td->isThisDeclarationADefinition()) + s->incrementGeneration(getToContext()); + + // If we have a forcefully completed type, try to find an actual definition // for it in other modules. const ClangASTMetadata *md = m_master.GetDeclMetadata(From); @@ -888,88 +897,11 @@ LLDB_LOG(log, "[ClangASTImporter] Complete definition not found"); } - // Disable the minimal import for fields that have record types. There is - // no point in minimally importing the record behind their type as Clang - // will anyway request their definition when the FieldDecl is added to the - // RecordDecl (as Clang will query the FieldDecl's type for things such - // as a deleted constexpr destructor). - // By importing the type ahead of time we avoid some corner cases where - // the FieldDecl's record is importing in the middle of Clang's - // `DeclContext::addDecl` logic. - if (clang::FieldDecl *fd = dyn_cast(From)) { - // This is only necessary because we do the 'minimal import'. Remove this - // once LLDB stopped using that mode. - assert(isMinimalImport() && "Only necessary for minimal import"); - QualType field_type = fd->getType(); - if (field_type->isRecordType()) { - // First get the underlying record and minimally import it. - clang::TagDecl *record_decl = field_type->getAsTagDecl(); - llvm::Expected imported = Import(record_decl); - if (!imported) - return imported.takeError(); - // Check how/if the import got redirected to a different AST. Now - // import the definition of what was actually imported. If there is no - // origin then that means the record was imported by just picking a - // compatible type in the target AST (in which case there is no more - // importing to do). - if (clang::Decl *origin = m_master.GetDeclOrigin(*imported).decl) { - if (llvm::Error def_err = ImportDefinition(record_decl)) - return std::move(def_err); - } - } - } - return ASTImporter::ImportImpl(From); } void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo( clang::Decl *to, clang::Decl *from) { - // We might have a forward declaration from a shared library that we - // gave external lexical storage so that Clang asks us about the full - // definition when it needs it. In this case the ASTImporter isn't aware - // that the forward decl from the shared library is the actual import - // target but would create a second declaration that would then be defined. - // We want that 'to' is actually complete after this function so let's - // tell the ASTImporter that 'to' was imported from 'from'. - MapImported(from, to); - ASTImporter::Imported(from, to); - - 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(to)) { - if (clang::TagDecl *from_tag = dyn_cast(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(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(to->getTranslationUnitDecl()), - from->getDeclKindName(), static_cast(to), name_string, - static_cast(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. @@ -996,8 +928,6 @@ Import(from_superclass); if (!imported_from_superclass_decl) { - LLDB_LOG_ERROR(log, imported_from_superclass_decl.takeError(), - "Couldn't import decl: {0}"); break; } @@ -1159,45 +1089,24 @@ from, m_source_ctx, &to->getASTContext()); } - if (auto *to_tag_decl = dyn_cast(to)) { - to_tag_decl->setHasExternalLexicalStorage(); - to_tag_decl->getPrimaryContext()->setMustBuildLookupTable(); - auto from_tag_decl = cast(from); - - LLDB_LOG( - log, - " [ClangASTImporter] To is a TagDecl - attributes {0}{1} [{2}->{3}]", - (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : ""), - (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete"), - (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete")); - } - if (auto *to_namespace_decl = dyn_cast(to)) { m_master.BuildNamespaceMap(to_namespace_decl); to_namespace_decl->setHasExternalVisibleStorage(); } if (auto *to_container_decl = dyn_cast(to)) { - to_container_decl->setHasExternalLexicalStorage(); - to_container_decl->setHasExternalVisibleStorage(); - if (log) { if (ObjCInterfaceDecl *to_interface_decl = llvm::dyn_cast(to_container_decl)) { LLDB_LOG( log, " [ClangASTImporter] To is an ObjCInterfaceDecl - attributes " - "{0}{1}{2}", - (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : ""), + "{0}", (to_interface_decl->hasDefinition() ? " HasDefinition" : "")); } else { LLDB_LOG( - log, " [ClangASTImporter] To is an {0}Decl - attributes {1}{2}", - ((Decl *)to_container_decl)->getDeclKindName(), - (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : ""), - (to_container_decl->hasExternalVisibleStorage() ? " Visible" : "")); + log, " [ClangASTImporter] To is an {0}Decl", + ((Decl *)to_container_decl)->getDeclKindName()); } } } Index: lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h +++ lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h @@ -153,6 +153,8 @@ /// The Decl to be completed in place. void CompleteType(clang::ObjCInterfaceDecl *Class) override; + void CompleteRedeclChain(const clang::Decl *D) override; + /// Called on entering a translation unit. Tells Clang by calling /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that /// this object has something to say about undefined names. @@ -231,6 +233,11 @@ return m_original.CompleteType(Class); } + void CompleteRedeclChain(const clang::Decl *D) override { + return m_original.CompleteRedeclChain(D); + } + + bool layoutRecordType( const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, llvm::DenseMap &FieldOffsets, Index: lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -341,6 +341,21 @@ LLDB_LOG(log, " [COID] {0}", ClangUtil::DumpDecl(interface_decl)); } +void ClangASTSource::CompleteRedeclChain(const Decl *d) { + if (const clang::TagDecl *td = llvm::dyn_cast(d)) { + m_ast_importer_sp->CompleteTagDecl(td); + if (!td->getDefinition()) { + if (TagDecl *alternate = FindCompleteType(td)) + m_ast_importer_sp->CompleteTagDeclWithOrigin(td, alternate); + } + } + if (const auto *od = llvm::dyn_cast(d)) { + if (ObjCInterfaceDecl *i = GetCompleteObjCInterface(od)) + m_ast_importer_sp->SetDeclOrigin(d, i); + m_ast_importer_sp->CompleteObjCInterfaceDecl(od); + } +} + clang::ObjCInterfaceDecl *ClangASTSource::GetCompleteObjCInterface( const clang::ObjCInterfaceDecl *interface_decl) { lldb::ProcessSP process(m_target->GetProcessSP()); @@ -379,7 +394,8 @@ ObjCInterfaceDecl *complete_iface_decl(complete_interface_type->getDecl()); - return complete_iface_decl; + ObjCInterfaceDecl *def = complete_iface_decl->getDefinition(); + return def; } void ClangASTSource::FindExternalLexicalDecls( Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h +++ lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h @@ -37,6 +37,8 @@ void CompleteType(clang::ObjCInterfaceDecl *objc_decl) override; + void CompleteRedeclChain(const clang::Decl *D) override; + bool layoutRecordType( const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, llvm::DenseMap &FieldOffsets, @@ -47,6 +49,10 @@ TypeSystemClang &GetTypeSystem() const { return m_ast; } + void bumpGeneration() { + incrementGeneration(m_ast.getASTContext()); + } + /// Module-related methods. /// \{ llvm::Optional Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.cpp @@ -17,7 +17,7 @@ char ClangExternalASTSourceCallbacks::ID; void ClangExternalASTSourceCallbacks::CompleteType(clang::TagDecl *tag_decl) { - m_ast.CompleteTagDecl(tag_decl); + //m_ast.CompleteTagDecl(tag_decl); } void ClangExternalASTSourceCallbacks::CompleteType( @@ -25,6 +25,13 @@ m_ast.CompleteObjCInterfaceDecl(objc_decl); } +void ClangExternalASTSourceCallbacks::CompleteRedeclChain(const clang::Decl *d) { + if (const clang::TagDecl *td = llvm::dyn_cast(d)) + m_ast.CompleteTagDecl(td); + if (const clang::ObjCInterfaceDecl *od = llvm::dyn_cast(d)) + m_ast.CompleteObjCInterfaceDecl(od); +} + bool ClangExternalASTSourceCallbacks::layoutRecordType( const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, llvm::DenseMap &FieldOffsets, Index: lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.h =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.h +++ lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.h @@ -36,6 +36,8 @@ static clang::TagDecl *GetAsTagDecl(const CompilerType &type); + static clang::ObjCInterfaceDecl *GetAsObjCDecl(const CompilerType &type); + /// Returns a textual representation of the given Decl's AST. Does not /// deserialize any child nodes. static std::string DumpDecl(const clang::Decl *d); Index: lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangUtil.cpp @@ -65,6 +65,18 @@ return qual_type->getAsTagDecl(); } +clang::ObjCInterfaceDecl *ClangUtil::GetAsObjCDecl(const CompilerType &type) { + clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type); + if (qual_type.isNull()) + return nullptr; + + if (const auto *ot = qual_type->getAsObjCInterfaceType()) + return ot->getInterface(); + if (const auto *ot = qual_type->getAsObjCInterfacePointerType()) + return ot->getInterfaceDecl(); + return nullptr; +} + std::string ClangUtil::DumpDecl(const clang::Decl *d) { if (!d) return "nullptr"; Index: lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp @@ -23,6 +23,8 @@ #include "llvm/IR/ValueSymbolTable.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/IR/LegacyPassManager.h" #include "clang/AST/ASTContext.h" Index: lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h =================================================================== --- lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h +++ lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h @@ -46,6 +46,11 @@ ISAToInterfaceMap; ISAToInterfaceMap m_isa_to_interface; + + typedef llvm::DenseMap + InterfaceToISAMap; + InterfaceToISAMap m_interface_to_isa; }; } // namespace lldb_private Index: lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp =================================================================== --- lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp +++ lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp @@ -28,86 +28,13 @@ AppleObjCExternalASTSource(AppleObjCDeclVendor &decl_vendor) : m_decl_vendor(decl_vendor) {} - bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx, - clang::DeclarationName name) override { - - Log *log(GetLogIfAllCategoriesSet( - LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? - - if (log) { - LLDB_LOGF(log, - "AppleObjCExternalASTSource::FindExternalVisibleDeclsByName" - " on (ASTContext*)%p Looking for %s in (%sDecl*)%p", - static_cast(&decl_ctx->getParentASTContext()), - name.getAsString().c_str(), decl_ctx->getDeclKindName(), - static_cast(decl_ctx)); - } - - do { - const clang::ObjCInterfaceDecl *interface_decl = - llvm::dyn_cast(decl_ctx); - - if (!interface_decl) - break; - - clang::ObjCInterfaceDecl *non_const_interface_decl = - const_cast(interface_decl); - - if (!m_decl_vendor.FinishDecl(non_const_interface_decl)) - break; - - clang::DeclContext::lookup_result result = - non_const_interface_decl->lookup(name); - - return (!result.empty()); - } while (false); - - SetNoExternalVisibleDeclsForName(decl_ctx, name); - return false; - } - - void CompleteType(clang::TagDecl *tag_decl) override { - - Log *log(GetLogIfAllCategoriesSet( - LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? - - LLDB_LOGF(log, - "AppleObjCExternalASTSource::CompleteType on " - "(ASTContext*)%p Completing (TagDecl*)%p named %s", - static_cast(&tag_decl->getASTContext()), - static_cast(tag_decl), tag_decl->getName().str().c_str()); - - LLDB_LOG(log, " AOEAS::CT Before:\n{1}", ClangUtil::DumpDecl(tag_decl)); - - LLDB_LOG(log, " AOEAS::CT After:{1}", ClangUtil::DumpDecl(tag_decl)); - - return; - } - - void CompleteType(clang::ObjCInterfaceDecl *interface_decl) override { - - Log *log(GetLogIfAllCategoriesSet( - LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? - - if (log) { - LLDB_LOGF(log, - "AppleObjCExternalASTSource::CompleteType on " - "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s", - static_cast(&interface_decl->getASTContext()), - static_cast(interface_decl), - interface_decl->getName().str().c_str()); - - LLDB_LOGF(log, " AOEAS::CT Before:"); - LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl)); - } - - m_decl_vendor.FinishDecl(interface_decl); - - if (log) { - LLDB_LOGF(log, " [CT] After:"); - LLDB_LOG(log, " [CT] {0}", ClangUtil::DumpDecl(interface_decl)); - } - return; + void CompleteRedeclChain(const clang::Decl *d) override { + using namespace clang; + auto *const_interface = llvm::dyn_cast(d); + if (!const_interface) + return; + auto *interface = const_cast(const_interface); + m_decl_vendor.FinishDecl(interface); } bool layoutRecordType( @@ -171,12 +98,11 @@ meta_data.SetISAPtr(isa); m_ast_ctx.SetMetadata(new_iface_decl, meta_data); - new_iface_decl->setHasExternalVisibleStorage(); - new_iface_decl->setHasExternalLexicalStorage(); - ast_ctx.getTranslationUnitDecl()->addDecl(new_iface_decl); m_isa_to_interface[isa] = new_iface_decl; + m_interface_to_isa[new_iface_decl] = isa; + m_ast_ctx.BumpGenerationCounter(); return new_iface_decl; } @@ -396,11 +322,22 @@ bool m_is_valid; }; -bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) { +bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *fwd_decl) { + if (fwd_decl->hasDefinition()) + return true; Log *log(GetLogIfAllCategoriesSet( LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel? + using namespace clang; - ClangASTMetadata *metadata = m_ast_ctx.GetMetadata(interface_decl); + QualType qt(fwd_decl->getTypeForDecl(), 0U); + CompilerType type(&m_ast_ctx, qt.getAsOpaquePtr()); + CompilerType definition_type = m_ast_ctx.RedeclTagDecl(type); + ObjCInterfaceDecl *interface_decl = ClangUtil::GetAsObjCDecl(definition_type); + + ObjCLanguageRuntime::ObjCISA isa = m_interface_to_isa[fwd_decl]; + m_isa_to_interface[isa] = interface_decl; + + ClangASTMetadata *metadata = m_ast_ctx.GetMetadata(fwd_decl); ObjCLanguageRuntime::ObjCISA objc_isa = 0; if (metadata) objc_isa = metadata->GetISAPtr(); @@ -408,14 +345,8 @@ if (!objc_isa) return false; - if (!interface_decl->hasExternalVisibleStorage()) - return true; - interface_decl->startDefinition(); - interface_decl->setHasExternalVisibleStorage(false); - interface_decl->setHasExternalLexicalStorage(false); - ObjCLanguageRuntime::ClassDescriptorSP descriptor = m_runtime.GetClassDescriptorFromISA(objc_isa); Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -76,6 +76,10 @@ typedef llvm::SmallPtrSet DIEPointerSet; typedef llvm::DenseMap DIEToDeclContextMap; + typedef llvm::DenseMap + DIEToRecordMap; + typedef llvm::DenseMap + DIEToObjCInterfaceMap; typedef std::multimap DeclContextToDIEMap; typedef llvm::DenseMap m_clang_ast_importer_up; /// @} + void RegisterDIE(DWARFDebugInfoEntry *die, lldb_private::CompilerType type); + clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die); clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die); @@ -201,7 +209,7 @@ FieldInfo &last_field_info); bool CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type, - lldb_private::CompilerType &clang_type); + lldb_private::CompilerType clang_type); bool CompleteEnumType(const DWARFDIE &die, lldb_private::Type *type, lldb_private::CompilerType &clang_type); Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -95,6 +95,17 @@ return *m_clang_ast_importer_up; } +void DWARFASTParserClang::RegisterDIE(DWARFDebugInfoEntry *die, + CompilerType type) { + if (clang::TagDecl *td = ClangUtil::GetAsTagDecl(type)) { + m_die_to_record_map[die] = td; + } else if (auto *od = ClangUtil::GetAsObjCDecl(type)) + m_die_to_objc_interface_map[die] = od; + else { + assert(false && "Unknown Decl kind?"); + } +} + /// Detect a forward declaration that is nested in a DW_TAG_module. static bool IsClangModuleFwdDecl(const DWARFDIE &Die) { if (!Die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0)) @@ -1410,6 +1421,20 @@ return type_sp; } +struct GenerationBumper { + TypeSystemClang &m_ts; + bool engaged = true; + explicit GenerationBumper(TypeSystemClang &ts) : m_ts(ts) { + } + ~GenerationBumper() { + if (engaged) + m_ts.BumpGenerationCounter(); + } + void engage() { + engaged = true; + } +}; + TypeSP DWARFASTParserClang::ParseStructureLikeDIE(const SymbolContext &sc, const DWARFDIE &die, @@ -1422,6 +1447,7 @@ Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_TYPE_COMPLETION | DWARF_LOG_LOOKUPS); + GenerationBumper bumper(m_ast); // UniqueDWARFASTType is large, so don't create a local variables on the // stack, put it on the heap. This function is often called recursively and // clang isn't good at sharing the stack space for variables in different @@ -1639,6 +1665,8 @@ m_ast.SetMetadata(class_template_decl, metadata); m_ast.SetMetadata(class_specialization_decl, metadata); + RegisterDIE(die.GetDIE(), clang_type); + bumper.engage(); } } @@ -1648,13 +1676,15 @@ decl_ctx, GetOwningClangModule(die), attrs.accessibility, attrs.name.GetCString(), tag_decl_kind, attrs.class_language, &metadata, attrs.exports_symbols); + RegisterDIE(die.GetDIE(), clang_type); + bumper.engage(); } } // Store a forward declaration to this class type in case any // parameters in any class methods need it for the clang types for // function prototypes. - LinkDeclContextToDIE(m_ast.GetDeclContextForType(clang_type), die); + LinkDeclContextToDIE(GetClangDeclContextContainingDIE(die, nullptr), die); type_sp = std::make_shared( die.GetID(), dwarf, attrs.name, attrs.byte_size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &attrs.decl, clang_type, @@ -1699,18 +1729,6 @@ } } } else if (clang_type_was_created) { - // Start the definition if the class is not objective C since the - // underlying decls respond to isCompleteDefinition(). Objective - // C decls don't respond to isCompleteDefinition() so we can't - // start the declaration definition right away. For C++ - // class/union/structs we want to start the definition in case the - // class is needed as the declaration context for a contained class - // or type without the need to complete that type.. - - if (attrs.class_language != eLanguageTypeObjC && - attrs.class_language != eLanguageTypeObjC_plus_plus) - TypeSystemClang::StartTagDeclarationDefinition(clang_type); - // Leave this as a forward declaration until we need to know the // details of the type. lldb_private::Type will automatically call // the SymbolFile virtual function @@ -1728,29 +1746,9 @@ dwarf->GetForwardDeclClangTypeToDie().try_emplace( ClangUtil::RemoveFastQualifiers(clang_type).GetOpaqueQualType(), *die.GetDIERef()); - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true); } } - // If we made a clang type, set the trivial abi if applicable: We only - // do this for pass by value - which implies the Trivial ABI. There - // isn't a way to assert that something that would normally be pass by - // value is pass by reference, so we ignore that attribute if set. - if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl && record_decl->getDefinition()) { - record_decl->setHasTrivialSpecialMemberForCall(); - } - } - - if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { - clang::CXXRecordDecl *record_decl = - m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); - if (record_decl) - record_decl->setArgPassingRestrictions( - clang::RecordDecl::APK_CannotPassInRegs); - } return type_sp; } @@ -1832,7 +1830,7 @@ return false; } if (const char *name = die.GetName()) { - template_param_infos.pack_name = name; + template_param_infos.pack_name = std::string(name); } return true; } @@ -1953,21 +1951,37 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, lldb_private::Type *type, - CompilerType &clang_type) { + CompilerType clang_type) { const dw_tag_t tag = die.Tag(); SymbolFileDWARF *dwarf = die.GetDWARF(); ClangASTImporter::LayoutInfo layout_info; - if (die.HasChildren()) { - const bool type_is_objc_object_or_interface = - TypeSystemClang::IsObjCObjectOrInterfaceType(clang_type); - if (type_is_objc_object_or_interface) { - // For objective C we don't start the definition when the class is - // created. - TypeSystemClang::StartTagDeclarationDefinition(clang_type); + ParsedDWARFTypeAttributes attrs(die); + // If we made a clang type, set the trivial abi if applicable: We only + // do this for pass by value - which implies the Trivial ABI. There + // isn't a way to assert that something that would normally be pass by + // value is pass by reference, so we ignore that attribute if set. + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_value) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl && record_decl->getDefinition()) { + record_decl->setHasTrivialSpecialMemberForCall(); } + } + if (attrs.calling_convention == llvm::dwarf::DW_CC_pass_by_reference) { + clang::CXXRecordDecl *record_decl = + m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()); + if (record_decl) + record_decl->setArgPassingRestrictions( + clang::RecordDecl::APK_CannotPassInRegs); + } + + if (die.HasChildren()) { + clang_type = m_ast.RedeclTagDecl(clang_type); + RegisterDIE(die.GetDIE(), clang_type); + TypeSystemClang::StartTagDeclarationDefinition(clang_type); int tag_decl_kind = -1; AccessType default_accessibility = eAccessNone; if (tag == DW_TAG_structure_type) { @@ -1996,6 +2010,8 @@ for (const DWARFDIE &die : member_function_dies) dwarf->ResolveType(die); + const bool type_is_objc_object_or_interface = + TypeSystemClang::IsObjCObjectOrInterfaceType(clang_type); if (type_is_objc_object_or_interface) { ConstString class_name(clang_type.GetTypeName()); if (class_name) { @@ -2069,7 +2085,6 @@ if (record_decl) GetClangASTImporter().SetRecordLayout(record_decl, layout_info); } - return (bool)clang_type; } @@ -2085,6 +2100,7 @@ } TypeSystemClang::CompleteTagDeclarationDefinition(clang_type); } + return (bool)clang_type; } @@ -2096,10 +2112,6 @@ std::lock_guard guard( dwarf->GetObjectFile()->GetModule()->GetMutex()); - // Disable external storage for this type so we don't get anymore - // clang::ExternalASTSource queries for this type. - m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), false); - if (!die) return false; @@ -3485,6 +3497,12 @@ clang::DeclContext * DWARFASTParserClang::GetCachedClangDeclContextForDIE(const DWARFDIE &die) { if (die) { + DIEToRecordMap::iterator pos2 = m_die_to_record_map.find(die.GetDIE()); + if (pos2 != m_die_to_record_map.end()) + return pos2->second; + DIEToObjCInterfaceMap::iterator pos3 = m_die_to_objc_interface_map.find(die.GetDIE()); + if (pos3 != m_die_to_objc_interface_map.end()) + return pos3->second; DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die.GetDIE()); if (pos != m_die_to_decl_ctx.end()) return pos->second; Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -49,6 +49,7 @@ namespace lldb_private { +class ClangExternalASTSourceCallbacks; class ClangASTMetadata; class ClangASTSource; class Declaration; @@ -235,9 +236,6 @@ CompilerType GetType(clang::QualType qt) { if (qt.getTypePtrOrNull() == nullptr) return CompilerType(); - // Check that the type actually belongs to this TypeSystemClang. - assert(qt->getAsTagDecl() == nullptr || - &qt->getAsTagDecl()->getASTContext() == &getASTContext()); return CompilerType(this, qt.getAsOpaquePtr()); } @@ -245,7 +243,7 @@ CompilerType GetTypeForDecl(clang::TagDecl *decl); - CompilerType GetTypeForDecl(clang::ObjCInterfaceDecl *objc_decl); + CompilerType GetTypeForDecl(const clang::ObjCInterfaceDecl *objc_decl); template CompilerType @@ -310,6 +308,19 @@ bool is_explicit = false); CompilerType CreateRecordType(clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, + lldb::AccessType access_type, + llvm::StringRef name, int kind, + lldb::LanguageType language, + ClangASTMetadata *metadata = nullptr, + bool exports_symbols = false) { + clang::NamedDecl *d = CreateRecordDecl(decl_ctx, owning_module, access_type, + name, kind, language, metadata, + exports_symbols); + return GetTypeForDecl(d); + } + + clang::NamedDecl *CreateRecordDecl(clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, lldb::AccessType access_type, llvm::StringRef name, int kind, @@ -317,8 +328,23 @@ ClangASTMetadata *metadata = nullptr, bool exports_symbols = false); + void BumpGenerationCounter(); + class TemplateParameterInfos { public: + TemplateParameterInfos() = default; + TemplateParameterInfos(const TemplateParameterInfos &o) { + *this = o; + } + TemplateParameterInfos &operator=(const TemplateParameterInfos &o) { + names = o.names; + args = o.args; + pack_name = o.pack_name; + if (o.packed_args) + packed_args = std::make_unique(*o.packed_args); + return *this; + } + bool IsValid() const { // Having a pack name but no packed args doesn't make sense, so mark // these template parameters as invalid. @@ -333,7 +359,7 @@ llvm::SmallVector names; llvm::SmallVector args; - const char * pack_name = nullptr; + llvm::Optional pack_name; std::unique_ptr packed_args; }; @@ -375,6 +401,17 @@ static bool RecordHasFields(const clang::RecordDecl *record_decl); CompilerType CreateObjCClass(llvm::StringRef name, + clang::DeclContext *decl_ctx, + OptionalClangModuleID owning_module, + bool isForwardDecl, bool isInternal, + ClangASTMetadata *metadata = nullptr) { + clang::ObjCInterfaceDecl *d = CreateObjCDecl(name, decl_ctx, owning_module, + isForwardDecl, isInternal, + metadata); + return GetTypeForDecl(d); + } + + clang::ObjCInterfaceDecl *CreateObjCDecl(llvm::StringRef name, clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, bool isForwardDecl, bool isInternal, @@ -456,9 +493,11 @@ PDBASTParser *GetPDBParser() override; // TypeSystemClang callbacks for external source lookups. - void CompleteTagDecl(clang::TagDecl *); + void CompleteTagDecl(const clang::TagDecl *); - void CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *); + void CompleteObjCInterfaceDecl(const clang::ObjCInterfaceDecl *); + + CompilerType RedeclTagDecl(CompilerType ct); bool LayoutRecordType( const clang::RecordDecl *record_decl, uint64_t &size, uint64_t &alignment, @@ -1064,6 +1103,7 @@ GetAsTemplateSpecialization(lldb::opaque_compiler_type_t type); // Classes that inherit from TypeSystemClang can see and modify these + ClangExternalASTSourceCallbacks *m_ast_callbacks = nullptr; std::string m_target_triple; std::unique_ptr m_ast_up; std::unique_ptr m_language_options_up; @@ -1096,6 +1136,14 @@ /// Maps Types to their associated ClangASTMetadata. TypeMetadataMap m_type_metadata; + struct ClassTemplateRedeclInfo { + TemplateParameterInfos m_template_args; + }; + + typedef llvm::DenseMap ClassTemplateRedeclInfoMap; + ClassTemplateRedeclInfoMap m_class_template_redecl_infos; + + /// The sema associated that is currently used to build this ASTContext. /// May be null if we are already done parsing this ASTContext or the /// ASTContext wasn't created by parsing source code. Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -41,6 +41,7 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/Threading.h" +#include "llvm/ADT/ScopeExit.h" #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" @@ -545,6 +546,7 @@ // This is needed to allocate the extra space for the owning module // on each decl. + Opts.Modules = true; Opts.ModulesLocalVisibility = 1; } @@ -761,7 +763,7 @@ GetASTMap().Insert(m_ast_up.get(), this); llvm::IntrusiveRefCntPtr ast_source_up( - new ClangExternalASTSourceCallbacks(*this)); + m_ast_callbacks = new ClangExternalASTSourceCallbacks(*this)); SetExternalSource(ast_source_up); } @@ -1230,7 +1232,7 @@ return GetType(getASTContext().getTagDeclType(decl)); } -CompilerType TypeSystemClang::GetTypeForDecl(ObjCInterfaceDecl *decl) { +CompilerType TypeSystemClang::GetTypeForDecl(const ObjCInterfaceDecl *decl) { return GetType(getASTContext().getObjCInterfaceType(decl)); } @@ -1281,8 +1283,7 @@ return ast_source->RegisterModule(module); } -CompilerType TypeSystemClang::CreateRecordType( - clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, +clang::NamedDecl *TypeSystemClang::CreateRecordDecl(clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, AccessType access_type, llvm::StringRef name, int kind, LanguageType language, ClangASTMetadata *metadata, bool exports_symbols) { ASTContext &ast = getASTContext(); @@ -1294,7 +1295,7 @@ language == eLanguageTypeObjC_plus_plus) { bool isForwardDecl = true; bool isInternal = false; - return CreateObjCClass(name, decl_ctx, owning_module, isForwardDecl, + return CreateObjCDecl(name, decl_ctx, owning_module, isForwardDecl, isInternal, metadata); } @@ -1351,9 +1352,14 @@ if (decl_ctx) decl_ctx->addDecl(decl); - return GetType(ast.getTagDeclType(decl)); + return decl; } - return CompilerType(); + return nullptr; +} + +void TypeSystemClang::BumpGenerationCounter() { + if (m_ast_up) + m_ast_up->getExternalSource()->incrementGeneration(*m_ast_up); } namespace { @@ -1396,8 +1402,8 @@ if (template_param_infos.packed_args) { IdentifierInfo *identifier_info = nullptr; - if (template_param_infos.pack_name && template_param_infos.pack_name[0]) - identifier_info = &ast.Idents.get(template_param_infos.pack_name); + if (template_param_infos.pack_name && !template_param_infos.pack_name->empty()) + identifier_info = &ast.Idents.get(template_param_infos.pack_name->c_str()); const bool parameter_pack_true = true; if (!template_param_infos.packed_args->args.empty() && @@ -1618,6 +1624,8 @@ class_template_decl->init(template_cxx_decl, template_param_list); template_cxx_decl->setDescribedClassTemplate(class_template_decl); SetOwningModule(class_template_decl, owning_module); + ast.getInjectedClassNameType(template_cxx_decl, + class_template_decl->getInjectedClassNameSpecialization()); if (class_template_decl) { if (access_type != eAccessNone) @@ -1687,6 +1695,10 @@ class_template_specialization_decl->setSpecializationKind( TSK_ExplicitSpecialization); + ClassTemplateRedeclInfo redecl_info; + redecl_info.m_template_args = template_param_infos; + m_class_template_redecl_infos[class_template_specialization_decl] = redecl_info; + return class_template_specialization_decl; } @@ -1801,7 +1813,7 @@ #pragma mark Objective-C Classes -CompilerType TypeSystemClang::CreateObjCClass( +clang::ObjCInterfaceDecl *TypeSystemClang::CreateObjCDecl( llvm::StringRef name, clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, bool isForwardDecl, bool isInternal, ClangASTMetadata *metadata) { @@ -1820,7 +1832,7 @@ if (decl && metadata) SetMetadata(decl, *metadata); - return GetType(ast.getObjCInterfaceType(decl)); + return decl; } static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) { @@ -2516,23 +2528,21 @@ if (tag_decl->isCompleteDefinition()) return true; - if (!tag_decl->hasExternalLexicalStorage()) - return false; - ast_source->CompleteType(tag_decl); - return !tag_decl->getTypeForDecl()->isIncompleteType(); + tag_decl = tag_decl->getDefinition(); + + return tag_decl && !tag_decl->getTypeForDecl()->isIncompleteType(); } else if (clang::ObjCInterfaceDecl *objc_interface_decl = llvm::dyn_cast(decl)) { if (objc_interface_decl->getDefinition()) return true; - if (!objc_interface_decl->hasExternalLexicalStorage()) - return false; - ast_source->CompleteType(objc_interface_decl); - return !objc_interface_decl->getTypeForDecl()->isIncompleteType(); + objc_interface_decl = objc_interface_decl->getDefinition(); + + return objc_interface_decl && !objc_interface_decl->getTypeForDecl()->isIncompleteType(); } else { return false; } @@ -2566,6 +2576,12 @@ auto It = m_decl_metadata.find(object); if (It != m_decl_metadata.end()) return &It->second; + if (auto *td = llvm::dyn_cast(object)) + if (td->isThisDeclarationADefinition() && td->getPreviousDecl()) + return GetMetadata(td->getPreviousDecl()); + if (auto *od = llvm::dyn_cast(object)) + if (od->isThisDeclarationADefinition() && od->getPreviousDecl()) + return GetMetadata(od->getPreviousDecl()); return nullptr; } @@ -2675,7 +2691,7 @@ return nullptr; } -static bool GetCompleteQualType(clang::ASTContext *ast, +static QualType GetCompleteQualType(clang::ASTContext *ast, clang::QualType qual_type, bool allow_completion = true) { qual_type = RemoveWrappingTypes(qual_type); @@ -2693,33 +2709,10 @@ } break; case clang::Type::Record: { clang::CXXRecordDecl *cxx_record_decl = qual_type->getAsCXXRecordDecl(); - if (cxx_record_decl) { - if (cxx_record_decl->hasExternalLexicalStorage()) { - const bool is_complete = cxx_record_decl->isCompleteDefinition(); - const bool fields_loaded = - cxx_record_decl->hasLoadedFieldsFromExternalStorage(); - if (is_complete && fields_loaded) - return true; - - if (!allow_completion) - return false; - - // Call the field_begin() accessor to for it to use the external source - // to load the fields... - clang::ExternalASTSource *external_ast_source = - ast->getExternalSource(); - if (external_ast_source) { - external_ast_source->CompleteType(cxx_record_decl); - if (cxx_record_decl->isCompleteDefinition()) { - cxx_record_decl->field_begin(); - cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); - } - } - } - } - const clang::TagType *tag_type = - llvm::cast(qual_type.getTypePtr()); - return !tag_type->isIncompleteType(); + cxx_record_decl = cxx_record_decl->getDefinition(); + if (!cxx_record_decl) + return QualType(); + return QualType(cxx_record_decl->getTypeForDecl(), 0); } break; case clang::Type::Enum: { @@ -2729,10 +2722,7 @@ clang::TagDecl *tag_decl = tag_type->getDecl(); if (tag_decl) { if (tag_decl->getDefinition()) - return true; - - if (!allow_completion) - return false; + return QualType(tag_decl->getTypeForDecl(), 0); if (tag_decl->hasExternalLexicalStorage()) { if (ast) { @@ -2740,11 +2730,11 @@ ast->getExternalSource(); if (external_ast_source) { external_ast_source->CompleteType(tag_decl); - return !tag_type->isIncompleteType(); + return QualType(tag_decl->getTypeForDecl(), 0); } } } - return false; + return QualType(tag_decl->getTypeForDecl(), 0); } } @@ -2756,27 +2746,10 @@ 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 (class_interface_decl->getDefinition()) - return true; - - if (!allow_completion) - return false; - - if (class_interface_decl->hasExternalLexicalStorage()) { - if (ast) { - clang::ExternalASTSource *external_ast_source = - ast->getExternalSource(); - if (external_ast_source) { - external_ast_source->CompleteType(class_interface_decl); - return !objc_class_type->isIncompleteType(); - } - } - } - return false; - } + if (!class_interface_decl) + return qual_type; + if (clang::ObjCInterfaceDecl *def = class_interface_decl->getDefinition()) + return QualType(class_interface_decl->getTypeForDecl(), 0); } } break; @@ -2789,7 +2762,7 @@ break; } - return true; + return qual_type; } static clang::ObjCIvarDecl::AccessControl @@ -2988,8 +2961,8 @@ bool TypeSystemClang::IsCompleteType(lldb::opaque_compiler_type_t type) { const bool allow_completion = false; - return GetCompleteQualType(&getASTContext(), GetQualType(type), - allow_completion); + return !GetCompleteQualType(&getASTContext(), GetQualType(type), + allow_completion).isNull(); } bool TypeSystemClang::IsConst(lldb::opaque_compiler_type_t type) { @@ -3774,8 +3747,8 @@ if (!type) return false; const bool allow_completion = true; - return GetCompleteQualType(&getASTContext(), GetQualType(type), - allow_completion); + return !GetCompleteQualType(&getASTContext(), GetQualType(type), + allow_completion).isNull(); } ConstString TypeSystemClang::GetTypeName(lldb::opaque_compiler_type_t type) { @@ -4352,7 +4325,8 @@ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type)); switch (qual_type->getTypeClass()) { case clang::Type::Record: - if (GetCompleteQualType(&getASTContext(), qual_type)) { + qual_type = GetCompleteQualType(&getASTContext(), qual_type); + if (!qual_type.isNull()) { const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = record_type->getDecl(); @@ -4416,7 +4390,8 @@ clang::QualType qual_type = RemoveWrappingTypes(GetCanonicalQualType(type)); switch (qual_type->getTypeClass()) { case clang::Type::Record: - if (GetCompleteQualType(&getASTContext(), qual_type)) { + qual_type = GetCompleteQualType(&getASTContext(), qual_type); + if (!qual_type.isNull()) { const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = record_type->getDecl(); @@ -5338,7 +5313,8 @@ case clang::Type::Complex: return 0; case clang::Type::Record: - if (GetCompleteQualType(&getASTContext(), qual_type)) { + qual_type = GetCompleteQualType(&getASTContext(), qual_type); + if (!qual_type.isNull()) { const clang::RecordType *record_type = llvm::cast(qual_type.getTypePtr()); const clang::RecordDecl *record_decl = record_type->getDecl(); @@ -5382,7 +5358,8 @@ case clang::Type::ObjCObject: case clang::Type::ObjCInterface: - if (GetCompleteQualType(&getASTContext(), qual_type)) { + qual_type = GetCompleteQualType(&getASTContext(), qual_type); + if (!qual_type.isNull()) { const clang::ObjCObjectType *objc_class_type = llvm::dyn_cast(qual_type.getTypePtr()); assert(objc_class_type); @@ -5391,18 +5368,22 @@ objc_class_type->getInterface(); if (class_interface_decl) { + auto *def = class_interface_decl->getDefinition(); + class_interface_decl = def; + if (class_interface_decl) { - clang::ObjCInterfaceDecl *superclass_interface_decl = - class_interface_decl->getSuperClass(); - if (superclass_interface_decl) { - if (omit_empty_base_classes) { - if (ObjCDeclHasIVars(superclass_interface_decl, true)) + clang::ObjCInterfaceDecl *superclass_interface_decl = + class_interface_decl->getSuperClass(); + if (superclass_interface_decl) { + if (omit_empty_base_classes) { + if (ObjCDeclHasIVars(superclass_interface_decl, true)) + ++num_children; + } else ++num_children; - } else - ++num_children; - } + } - num_children += class_interface_decl->ivar_size(); + num_children += class_interface_decl->ivar_size(); + } } } } @@ -6309,7 +6290,6 @@ objc_class_type->getInterface(); if (class_interface_decl) { - const clang::ASTRecordLayout &interface_layout = getASTContext().getASTObjCInterfaceLayout(class_interface_decl); clang::ObjCInterfaceDecl *superclass_interface_decl = @@ -8027,6 +8007,10 @@ if (class_interface_decl == nullptr) return nullptr; + class_interface_decl = class_interface_decl->getDefinition(); + if (class_interface_decl == nullptr) + return nullptr; + TypeSystemClang *lldb_ast = llvm::dyn_cast(type.GetTypeSystem()); if (lldb_ast == nullptr) @@ -8096,8 +8080,7 @@ auto *objc_method_decl = clang::ObjCMethodDecl::CreateDeserialized(ast, 0); objc_method_decl->setDeclName(method_selector); objc_method_decl->setReturnType(method_function_prototype->getReturnType()); - objc_method_decl->setDeclContext( - lldb_ast->GetDeclContextForType(ClangUtil::GetQualType(type))); + objc_method_decl->setDeclContext(class_interface_decl); objc_method_decl->setInstanceMethod(isInstance); objc_method_decl->setVariadic(isVariadic); objc_method_decl->setPropertyAccessor(isPropertyAccessor); @@ -8258,9 +8241,6 @@ if (!cxx_record_decl->isCompleteDefinition()) cxx_record_decl->completeDefinition(); - cxx_record_decl->setHasLoadedFieldsFromExternalStorage(true); - cxx_record_decl->setHasExternalLexicalStorage(false); - cxx_record_decl->setHasExternalVisibleStorage(false); return true; } } @@ -9107,7 +9087,7 @@ if (!objc_class_type) break; clang::ObjCInterfaceDecl *class_interface_decl = - objc_class_type->getInterface(); + objc_class_type->getInterface()->getDefinition(); if (!class_interface_decl) break; if (level == eDescriptionLevelVerbose) @@ -9267,17 +9247,17 @@ return nullptr; } -void TypeSystemClang::CompleteTagDecl(clang::TagDecl *decl) { +void TypeSystemClang::CompleteTagDecl(const clang::TagDecl *decl) { SymbolFile *sym_file = GetSymbolFile(); if (sym_file) { - CompilerType clang_type = GetTypeForDecl(decl); + CompilerType clang_type = GetTypeForDecl(const_cast(decl)); if (clang_type) sym_file->CompleteType(clang_type); } } void TypeSystemClang::CompleteObjCInterfaceDecl( - clang::ObjCInterfaceDecl *decl) { + const clang::ObjCInterfaceDecl *decl) { SymbolFile *sym_file = GetSymbolFile(); if (sym_file) { CompilerType clang_type = GetTypeForDecl(decl); @@ -9286,6 +9266,35 @@ } } +CompilerType TypeSystemClang::RedeclTagDecl(CompilerType ct) { + if (clang::TagDecl *d = ClangUtil::GetAsTagDecl(ct)) { + if (auto *c = dyn_cast(d)) { + auto redecl_info = m_class_template_redecl_infos.find(c); + assert(redecl_info != m_class_template_redecl_infos.end()); + TemplateParameterInfos template_infos = redecl_info->second.m_template_args; + auto *ctd = CreateClassTemplateSpecializationDecl(d->getDeclContext()->getRedeclContext(), OptionalClangModuleID(), c->getSpecializedTemplate(), d->getTagKind(), template_infos); + ctd->setPreviousDecl(c); + return CompilerType(this, clang::QualType(ctd->getTypeForDecl(), 0U).getAsOpaquePtr()); + } + CompilerType res = CreateRecordType(d->getDeclContext()->getRedeclContext(), + OptionalClangModuleID(), + lldb::eAccessPublic, d->getName(), d->getTagKind(), + eLanguageTypeC_plus_plus, nullptr); + clang::TagDecl *td = ClangUtil::GetAsTagDecl(res); + td->setPreviousDecl(d); + return res; + } + if (clang::ObjCInterfaceDecl *d = ClangUtil::GetAsObjCDecl(ct)) { + CompilerType res = CreateRecordType(d->getDeclContext()->getRedeclContext(), OptionalClangModuleID(), + lldb::eAccessPublic, d->getName(), /*tag_kind=*/0, + eLanguageTypeObjC, nullptr); + clang::ObjCInterfaceDecl *td = ClangUtil::GetAsObjCDecl(res); + td->setPreviousDecl(d); + return res; + } + return ct; +} + DWARFASTParser *TypeSystemClang::GetDWARFParser() { if (!m_dwarf_ast_parser_up) m_dwarf_ast_parser_up = std::make_unique(*this); Index: lldb/test/API/lang/c/modules/TestCModules.py =================================================================== --- lldb/test/API/lang/c/modules/TestCModules.py +++ lldb/test/API/lang/c/modules/TestCModules.py @@ -68,7 +68,9 @@ f = open(log_file) log_lines = f.readlines() f.close() - os.remove(log_file) +# os.remove(log_file) + print(log_file) + self.assertIn("struct __sFILE definition", " ".join(log_lines)) self.assertEqual(" ".join(log_lines).count("struct __sFILE definition"), 1)