diff options
-rw-r--r-- | include/clang/AST/ExternalASTSource.h | 2 | ||||
-rw-r--r-- | include/clang/Sema/MultiplexExternalSemaSource.h | 2 | ||||
-rw-r--r-- | include/clang/Serialization/ASTReader.h | 4 | ||||
-rw-r--r-- | lib/AST/ExternalASTSource.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 14 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.h | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/MultiplexExternalSemaSource.cpp | 4 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 3 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 19 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 6 | ||||
-rw-r--r-- | test/Modules/Inputs/codegen-nodep/foo.h | 10 | ||||
-rw-r--r-- | test/Modules/codegen-nodep.test | 6 | ||||
-rw-r--r-- | test/Modules/codegen.test | 12 |
14 files changed, 68 insertions, 22 deletions
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index f2b29cd9a7..d8dd18ecb8 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -172,7 +172,7 @@ public: enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy }; - virtual ExtKind hasExternalDefinitions(const FunctionDecl *FD); + virtual ExtKind hasExternalDefinitions(const Decl *D); /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h index 0386552dbe..1d681a0055 100644 --- a/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -90,7 +90,7 @@ public: /// initializers themselves. CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override; - ExtKind hasExternalDefinitions(const FunctionDecl *FD) override; + ExtKind hasExternalDefinitions(const Decl *D) override; /// \brief Find all declarations with the given name in the /// given context. diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 4e1c1cf57d..de122e63ba 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -1115,7 +1115,7 @@ private: /// predefines buffer may contain additional definitions. std::string SuggestedPredefines; - llvm::DenseMap<const FunctionDecl *, bool> BodySource; + llvm::DenseMap<const Decl *, bool> BodySource; /// \brief Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); @@ -1999,7 +1999,7 @@ public: /// \brief Return a descriptor for the corresponding module. llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override; - ExtKind hasExternalDefinitions(const FunctionDecl *FD) override; + ExtKind hasExternalDefinitions(const Decl *D) override; /// \brief Retrieve a selector from the given module with its local ID /// number. diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp index 958a67843b..182d38242f 100644 --- a/lib/AST/ExternalASTSource.cpp +++ b/lib/AST/ExternalASTSource.cpp @@ -29,7 +29,7 @@ ExternalASTSource::getSourceDescriptor(unsigned ID) { } ExternalASTSource::ExtKind -ExternalASTSource::hasExternalDefinitions(const FunctionDecl *FD) { +ExternalASTSource::hasExternalDefinitions(const Decl *D) { return EK_ReplyHazy; } diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 05987be845..818b51543d 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1820,6 +1820,10 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, if (DebugTypeExtRefs && isDefinedInClangModule(RD->getDefinition())) return true; + if (auto *ES = RD->getASTContext().getExternalSource()) + if (ES->hasExternalDefinitions(RD) == ExternalASTSource::EK_Always) + return true; + if (DebugKind > codegenoptions::LimitedDebugInfo) return false; @@ -2552,11 +2556,17 @@ void CGDebugInfo::completeTemplateDefinition( const ClassTemplateSpecializationDecl &SD) { if (DebugKind <= codegenoptions::DebugLineTablesOnly) return; + completeUnusedClass(SD); +} + +void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) { + if (DebugKind <= codegenoptions::DebugLineTablesOnly) + return; - completeClassData(&SD); + completeClassData(&D); // In case this type has no member function definitions being emitted, ensure // it is retained - RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr()); + RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr()); } llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) { diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index c6d1c66e13..5050ca0ad3 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -438,6 +438,7 @@ public: void completeClass(const RecordDecl *RD); void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD); + void completeUnusedClass(const CXXRecordDecl &D); /// Create debug info for a macro defined by a #define directive or a macro /// undefined by a #undef directive. diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 96358bf611..7fe8bf0412 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -3820,6 +3820,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { EmitDeclContext(cast<NamespaceDecl>(D)); break; case Decl::CXXRecord: + if (DebugInfo) { + if (auto *ES = D->getASTContext().getExternalSource()) + if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) + DebugInfo->completeUnusedClass(cast<CXXRecordDecl>(*D)); + } // Emit any static data members, they may be definitions. for (auto *I : cast<CXXRecordDecl>(D)->decls()) if (isa<VarDecl>(I) || isa<CXXRecordDecl>(I)) diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp index f749b7d139..b7e343c647 100644 --- a/lib/Sema/MultiplexExternalSemaSource.cpp +++ b/lib/Sema/MultiplexExternalSemaSource.cpp @@ -95,9 +95,9 @@ MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) { } ExternalASTSource::ExtKind -MultiplexExternalSemaSource::hasExternalDefinitions(const FunctionDecl *FD) { +MultiplexExternalSemaSource::hasExternalDefinitions(const Decl *D) { for (const auto &S : Sources) - if (auto EK = S->hasExternalDefinitions(FD)) + if (auto EK = S->hasExternalDefinitions(D)) if (EK != EK_ReplyHazy) return EK; return EK_ReplyHazy; diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index a51f144ae0..322fc863be 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -8147,8 +8147,7 @@ ASTReader::getSourceDescriptor(unsigned ID) { return None; } -ExternalASTSource::ExtKind -ASTReader::hasExternalDefinitions(const FunctionDecl *FD) { +ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(const Decl *FD) { auto I = BodySource.find(FD); if (I == BodySource.end()) return EK_ReplyHazy; diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 9b9b41a104..db7d55ec0b 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -119,7 +119,8 @@ namespace clang { } void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update); - void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data); + void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, + const CXXRecordDecl *D); void MergeDefinitionData(CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&NewDD); void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data); @@ -1490,7 +1491,7 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( } void ASTDeclReader::ReadCXXDefinitionData( - struct CXXRecordDecl::DefinitionData &Data) { + struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) { // Note: the caller has deserialized the IsLambda bit already. Data.UserDeclaredConstructor = Record.readInt(); Data.UserDeclaredSpecialMembers = Record.readInt(); @@ -1536,6 +1537,12 @@ void ASTDeclReader::ReadCXXDefinitionData( Data.HasDeclaredCopyAssignmentWithConstParam = Record.readInt(); Data.ODRHash = Record.readInt(); + if (Record.readInt()) { + Reader.BodySource[D] = Loc.F->Kind == ModuleKind::MK_MainFile + ? ExternalASTSource::EK_Never + : ExternalASTSource::EK_Always; + } + Data.NumBases = Record.readInt(); if (Data.NumBases) Data.Bases = ReadGlobalOffset(); @@ -1707,7 +1714,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { else DD = new (C) struct CXXRecordDecl::DefinitionData(D); - ReadCXXDefinitionData(*DD); + ReadCXXDefinitionData(*DD, D); // We might already have a definition for this record. This can happen either // because we're reading an update record, or because we've already done some @@ -2553,7 +2560,11 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { Var->isThisDeclarationADefinition() == VarDecl::Definition; if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) return Func->doesThisDeclarationHaveABody() || HasBody; - + + if (auto *ES = D->getASTContext().getExternalSource()) + if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) + return true; + return false; } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 23859c241d..ec59250e19 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -5770,6 +5770,12 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { Record->push_back(Data.HasDeclaredCopyConstructorWithConstParam); Record->push_back(Data.HasDeclaredCopyAssignmentWithConstParam); Record->push_back(Data.ODRHash); + bool ModularCodegen = Writer->Context->getLangOpts().ModularCodegen && + Writer->WritingModule && !D->isDependentType(); + Record->push_back(ModularCodegen); + if (ModularCodegen) + Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(D)); + // IsLambda bit is already saved. Record->push_back(Data.NumBases); diff --git a/test/Modules/Inputs/codegen-nodep/foo.h b/test/Modules/Inputs/codegen-nodep/foo.h index af91e8d263..e7b20a512d 100644 --- a/test/Modules/Inputs/codegen-nodep/foo.h +++ b/test/Modules/Inputs/codegen-nodep/foo.h @@ -1,5 +1,11 @@ template <typename T> -void ftempl() { +void foot() { } -inline void f() { +inline void foo() { } + +template <typename T> +struct bart { +}; +struct bar { +}; diff --git a/test/Modules/codegen-nodep.test b/test/Modules/codegen-nodep.test index cb2b4e37e9..0c3eb47a1e 100644 --- a/test/Modules/codegen-nodep.test +++ b/test/Modules/codegen-nodep.test @@ -7,7 +7,7 @@ RUN: %S/Inputs/codegen-nodep/foo.modulemap -o - \ RUN: | llvm-bcanalyzer - -dump \ RUN: | FileCheck %s -Ensure there's only one modular codegen decl - the sentinel plain inline -function, not any for the function template. +Ensure there are only two modular codegen decls (one for the class, one for the +function - none for the class and function templates). -CHECK: <MODULAR_CODEGEN_DECLS op0={{[0-9]+}}/> +CHECK: <MODULAR_CODEGEN_DECLS op0={{[0-9]+}} op1={{[0-9]+}}/> diff --git a/test/Modules/codegen.test b/test/Modules/codegen.test index 6807640e60..ce252e89eb 100644 --- a/test/Modules/codegen.test +++ b/test/Modules/codegen.test @@ -3,8 +3,8 @@ REQUIRES: x86-registered-target RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm -RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s -RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s +RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s +RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s FOO: $_Z2f1PKcz = comdat any FOO: $_ZN13implicit_dtorD1Ev = comdat any @@ -25,3 +25,11 @@ FOO: define weak_odr void @_ZN13implicit_dtorD2Ev USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev USE: define linkonce_odr void @_Z4instIiEvv USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev + +Modular debug info puts the definition of a class defined in a module in that +module's object. Users of the module only get a declaration. + +'distinct' is used for definition records (the flags field is empty/unspecified) +FOO: = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "implicit_dtor" +Declarations are non-distinct and include the 'DIFlagFwdDecl' flag. +USE: = !DICompositeType(tag: DW_TAG_structure_type, name: "implicit_dtor", {{.*}}, flags: DIFlagFwdDecl |