[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen
This revision was automatically updated to reflect the committed changes. Closed by commit rL299982: Modular Codegen: Add/use a bit in serialized function definitions to trackā¦ (authored by dblaikie). Changed prior to commit: https://reviews.llvm.org/D29901?vs=91193=94886#toc Repository: rL LLVM https://reviews.llvm.org/D29901 Files: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/AST/ExternalASTSource.h cfe/trunk/include/clang/Basic/Module.h cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h cfe/trunk/include/clang/Serialization/ASTReader.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/AST/ExternalASTSource.cpp cfe/trunk/lib/Basic/Module.cpp cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/lib/Serialization/ASTWriterDecl.cpp cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.h cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.modulemap cfe/trunk/test/Modules/Inputs/codegen/foo.h cfe/trunk/test/Modules/Inputs/codegen/use.cpp cfe/trunk/test/Modules/codegen-nodep.test cfe/trunk/test/Modules/codegen.test Index: cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h === --- cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h +++ cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h @@ -90,7 +90,7 @@ /// initializers themselves. CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override; - ExtKind hasExternalDefinitions(unsigned ID) override; + ExtKind hasExternalDefinitions(const FunctionDecl *FD) override; /// \brief Find all declarations with the given name in the /// given context. Index: cfe/trunk/include/clang/Basic/Module.h === --- cfe/trunk/include/clang/Basic/Module.h +++ cfe/trunk/include/clang/Basic/Module.h @@ -215,8 +215,6 @@ /// and headers from used modules. unsigned NoUndeclaredIncludes : 1; - unsigned WithCodegen : 1; - /// \brief Describes the visibility of the various names within a /// particular module. enum NameVisibilityKind { Index: cfe/trunk/include/clang/Serialization/ASTReader.h === --- cfe/trunk/include/clang/Serialization/ASTReader.h +++ cfe/trunk/include/clang/Serialization/ASTReader.h @@ -1115,6 +1115,8 @@ /// predefines buffer may contain additional definitions. std::string SuggestedPredefines; + llvm::DenseMap BodySource; + /// \brief Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile ); @@ -1997,7 +1999,7 @@ /// \brief Return a descriptor for the corresponding module. llvm::Optional getSourceDescriptor(unsigned ID) override; - ExtKind hasExternalDefinitions(unsigned ID) override; + ExtKind hasExternalDefinitions(const FunctionDecl *FD) override; /// \brief Retrieve a selector from the given module with its local ID /// number. Index: cfe/trunk/include/clang/AST/ExternalASTSource.h === --- cfe/trunk/include/clang/AST/ExternalASTSource.h +++ cfe/trunk/include/clang/AST/ExternalASTSource.h @@ -172,7 +172,7 @@ enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy }; - virtual ExtKind hasExternalDefinitions(unsigned ID); + virtual ExtKind hasExternalDefinitions(const FunctionDecl *FD); /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. Index: cfe/trunk/include/clang/AST/ASTContext.h === --- cfe/trunk/include/clang/AST/ASTContext.h +++ cfe/trunk/include/clang/AST/ASTContext.h @@ -2510,7 +2510,7 @@ /// /// \returns true if the function/var must be CodeGen'ed/deserialized even if /// it is not used. - bool DeclMustBeEmitted(const Decl *D, bool ForModularCodegen = false); + bool DeclMustBeEmitted(const Decl *D); const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD); Index: cfe/trunk/test/Modules/Inputs/codegen/use.cpp === --- cfe/trunk/test/Modules/Inputs/codegen/use.cpp +++ cfe/trunk/test/Modules/Inputs/codegen/use.cpp @@ -0,0 +1,8 @@ +#include "foo.h" +void non_modular_use_of_implicit_dtor() { + implicit_dtor d1; + uninst_implicit_dtor d2; +} +void use_of_instantiated_declaration_without_definition() { + inst(); +} Index: cfe/trunk/test/Modules/Inputs/codegen/foo.h === --- cfe/trunk/test/Modules/Inputs/codegen/foo.h +++ cfe/trunk/test/Modules/Inputs/codegen/foo.h @@ -2,3 +2,29 @@ __builtin_va_list args; __builtin_va_start(args, fmt); } + +struct
[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen
dblaikie added a comment. Ping I've got a relatively small patch to add support for debug info types after this one & working on a patch on top of that to enable one/the other/both of these (to test their value independently/together). Might be more expedient to sit down & push through them all together side-by-side? Or not, not sure. https://reviews.llvm.org/D29901 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen
dblaikie updated this revision to Diff 91193. dblaikie added a comment. sync/resolve https://reviews.llvm.org/D29901 Files: include/clang/AST/ASTContext.h include/clang/AST/ExternalASTSource.h include/clang/Sema/MultiplexExternalSemaSource.h include/clang/Serialization/ASTReader.h lib/AST/ASTContext.cpp lib/AST/ExternalASTSource.cpp lib/Sema/MultiplexExternalSemaSource.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp test/Modules/Inputs/codegen/foo.h test/Modules/Inputs/codegen/use.cpp test/Modules/codegen.test Index: test/Modules/codegen.test === --- test/Modules/codegen.test +++ test/Modules/codegen.test @@ -3,8 +3,23 @@ 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 %s +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 -CHECK: $_Z2f1PKcz = comdat any -CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat -CHECK: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) +FOO: $_Z2f1PKcz = comdat any +FOO: $_ZN13implicit_dtorD1Ev = comdat any +USE: $_Z4instIiEvv = comdat any +FOO: $_ZN13implicit_dtorD2Ev = comdat any +FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat +FOO: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) + +Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user. +FIXME: Proactively instantiate any valid implicit special members to emit them into the module object. + +FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 { +FOO: define weak_odr void @_Z4instIfEvv() #0 comdat { +FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 { + +USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 { +USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat { +USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 { Index: test/Modules/Inputs/codegen/use.cpp === --- /dev/null +++ test/Modules/Inputs/codegen/use.cpp @@ -0,0 +1,8 @@ +#include "foo.h" +void non_modular_use_of_implicit_dtor() { + implicit_dtor d1; + uninst_implicit_dtor d2; +} +void use_of_instantiated_declaration_without_definition() { + inst(); +} Index: test/Modules/Inputs/codegen/foo.h === --- test/Modules/Inputs/codegen/foo.h +++ test/Modules/Inputs/codegen/foo.h @@ -2,3 +2,29 @@ __builtin_va_list args; __builtin_va_start(args, fmt); } + +struct non_trivial_dtor { + ~non_trivial_dtor(); +}; + +struct implicit_dtor { + non_trivial_dtor d; +}; + +struct uninst_implicit_dtor { + non_trivial_dtor d; +}; + +inline void use_implicit_dtor() { + implicit_dtor d; +} + +template +void inst() { +} + +inline void inst_decl() { + // cause inst's declaration to be instantiated, without a definition. + (void)sizeof(); + inst(); +} Index: lib/Serialization/ASTWriterDecl.cpp === --- lib/Serialization/ASTWriterDecl.cpp +++ lib/Serialization/ASTWriterDecl.cpp @@ -2157,7 +2157,7 @@ /// relatively painless since they would presumably only do it for top-level /// decls. static bool isRequiredDecl(const Decl *D, ASTContext , - bool WritingModule, bool ModularCode) { + bool WritingModule) { // An ObjCMethodDecl is never considered as "required" because its // implementation container always is. @@ -2173,7 +2173,7 @@ return false; } - return Context.DeclMustBeEmitted(D, ModularCode); + return Context.DeclMustBeEmitted(D); } void ASTWriter::WriteDecl(ASTContext , Decl *D) { @@ -2217,18 +2217,20 @@ // Note declarations that should be deserialized eagerly so that we can add // them to a record in the AST file later. - if (isRequiredDecl(D, Context, WritingModule, false)) + if (isRequiredDecl(D, Context, WritingModule)) EagerlyDeserializedDecls.push_back(ID); - else if (Context.getLangOpts().ModularCodegen && WritingModule && - isRequiredDecl(D, Context, true, true)) -ModularCodegenDecls.push_back(ID); } void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { // Switch case IDs are per function
[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen
dblaikie updated this revision to Diff 89931. dblaikie added a comment. - Simplify ModuleFile lookup - Build ModularCodegenDecls list from the same place the modular codegen bit is set on the decl - Cleanup no-longer-needed changes to DeclMustBeEmitted/isRequiredDecl https://reviews.llvm.org/D29901 Files: include/clang/AST/ASTContext.h include/clang/AST/ExternalASTSource.h include/clang/Sema/MultiplexExternalSemaSource.h include/clang/Serialization/ASTReader.h lib/AST/ASTContext.cpp lib/AST/ExternalASTSource.cpp lib/Sema/MultiplexExternalSemaSource.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp test/Modules/Inputs/codegen/foo.h test/Modules/Inputs/codegen/use.cpp test/Modules/codegen.test Index: test/Modules/codegen.test === --- test/Modules/codegen.test +++ test/Modules/codegen.test @@ -3,8 +3,23 @@ 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 %s +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 -CHECK: $_Z2f1PKcz = comdat any -CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat -CHECK: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) +FOO: $_Z2f1PKcz = comdat any +FOO: $_ZN13implicit_dtorD1Ev = comdat any +USE: $_Z4instIiEvv = comdat any +FOO: $_ZN13implicit_dtorD2Ev = comdat any +FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat +FOO: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) + +Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user. +FIXME: Proactively instantiate any valid implicit special members to emit them into the module object. + +FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 { +FOO: define weak_odr void @_Z4instIfEvv() #0 comdat { +FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 { + +USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 { +USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat { +USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 { Index: test/Modules/Inputs/codegen/use.cpp === --- /dev/null +++ test/Modules/Inputs/codegen/use.cpp @@ -0,0 +1,8 @@ +#include "foo.h" +void non_modular_use_of_implicit_dtor() { + implicit_dtor d1; + uninst_implicit_dtor d2; +} +void use_of_instantiated_declaration_without_definition() { + inst(); +} Index: test/Modules/Inputs/codegen/foo.h === --- test/Modules/Inputs/codegen/foo.h +++ test/Modules/Inputs/codegen/foo.h @@ -2,3 +2,29 @@ __builtin_va_list args; __builtin_va_start(args, fmt); } + +struct non_trivial_dtor { + ~non_trivial_dtor(); +}; + +struct implicit_dtor { + non_trivial_dtor d; +}; + +struct uninst_implicit_dtor { + non_trivial_dtor d; +}; + +inline void use_implicit_dtor() { + implicit_dtor d; +} + +template +void inst() { +} + +inline void inst_decl() { + // cause inst's declaration to be instantiated, without a definition. + (void)sizeof(); + inst(); +} Index: lib/Serialization/ASTWriterDecl.cpp === --- lib/Serialization/ASTWriterDecl.cpp +++ lib/Serialization/ASTWriterDecl.cpp @@ -2158,7 +2158,7 @@ /// relatively painless since they would presumably only do it for top-level /// decls. static bool isRequiredDecl(const Decl *D, ASTContext , - bool WritingModule, bool ModularCode) { + bool WritingModule) { // An ObjCMethodDecl is never considered as "required" because its // implementation container always is. @@ -2174,7 +2174,7 @@ return false; } - return Context.DeclMustBeEmitted(D, ModularCode); + return Context.DeclMustBeEmitted(D); } void ASTWriter::WriteDecl(ASTContext , Decl *D) { @@ -2218,18 +2218,20 @@ // Note declarations that should be deserialized eagerly so that we can add // them to a record in the AST file later. - if (isRequiredDecl(D, Context, WritingModule, false)) + if (isRequiredDecl(D, Context, WritingModule)) EagerlyDeserializedDecls.push_back(ID); - else if (Context.getLangOpts().ModularCodegen && WritingModule && -
[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen
dblaikie updated this revision to Diff 88792. dblaikie added a comment. - Simplify ModuleFile lookup https://reviews.llvm.org/D29901 Files: include/clang/AST/ExternalASTSource.h include/clang/Sema/MultiplexExternalSemaSource.h include/clang/Serialization/ASTReader.h lib/AST/ASTContext.cpp lib/AST/ExternalASTSource.cpp lib/Sema/MultiplexExternalSemaSource.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp test/Modules/Inputs/codegen/foo.h test/Modules/Inputs/codegen/use.cpp test/Modules/codegen.test Index: test/Modules/codegen.test === --- test/Modules/codegen.test +++ test/Modules/codegen.test @@ -3,8 +3,23 @@ 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 %s +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 -CHECK: $_Z2f1PKcz = comdat any -CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat -CHECK: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) +FOO: $_Z2f1PKcz = comdat any +FOO: $_ZN13implicit_dtorD1Ev = comdat any +USE: $_Z4instIiEvv = comdat any +FOO: $_ZN13implicit_dtorD2Ev = comdat any +FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat +FOO: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) + +Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user. +FIXME: Proactively instantiate any valid implicit special members to emit them into the module object. + +FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 { +FOO: define weak_odr void @_Z4instIfEvv() #0 comdat { +FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 { + +USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 { +USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat { +USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 { Index: test/Modules/Inputs/codegen/use.cpp === --- /dev/null +++ test/Modules/Inputs/codegen/use.cpp @@ -0,0 +1,8 @@ +#include "foo.h" +void non_modular_use_of_implicit_dtor() { + implicit_dtor d1; + uninst_implicit_dtor d2; +} +void use_of_instantiated_declaration_without_definition() { + inst(); +} Index: test/Modules/Inputs/codegen/foo.h === --- test/Modules/Inputs/codegen/foo.h +++ test/Modules/Inputs/codegen/foo.h @@ -2,3 +2,29 @@ __builtin_va_list args; __builtin_va_start(args, fmt); } + +struct non_trivial_dtor { + ~non_trivial_dtor(); +}; + +struct implicit_dtor { + non_trivial_dtor d; +}; + +struct uninst_implicit_dtor { + non_trivial_dtor d; +}; + +inline void use_implicit_dtor() { + implicit_dtor d; +} + +template +void inst() { +} + +inline void inst_decl() { + // cause inst's declaration to be instantiated, without a definition. + (void)sizeof(); + inst(); +} Index: lib/Serialization/ASTWriterDecl.cpp === --- lib/Serialization/ASTWriterDecl.cpp +++ lib/Serialization/ASTWriterDecl.cpp @@ -2224,6 +2224,8 @@ Writer->ClearSwitchCaseIDs(); assert(FD->doesThisDeclarationHaveABody()); + Record->push_back(Writer->Context->getLangOpts().ModularCodegen && +Writer->WritingModule); if (auto *CD = dyn_cast(FD)) { Record->push_back(CD->getNumCtorInitializers()); if (CD->getNumCtorInitializers()) Index: lib/Serialization/ASTReaderDecl.cpp === --- lib/Serialization/ASTReaderDecl.cpp +++ lib/Serialization/ASTReaderDecl.cpp @@ -423,6 +423,11 @@ } void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) { + if (Record.readInt()) { +Reader.BodySource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile +? ExternalASTSource::EK_Never +: ExternalASTSource::EK_Always; + } if (auto *CD = dyn_cast(FD)) { CD->NumCtorInitializers = Record.readInt(); if (CD->NumCtorInitializers) Index: lib/Serialization/ASTReader.cpp === --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -7911,16 +7911,11 @@ return None; }
[PATCH] D29901: Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen
dblaikie created this revision. Some decls are created not where they are written, but in other module files/users (implicit special members and function template implicit specializations). To correctly identify them, use a bit next to the definition to track the modular codegen property. Possible improvement would be to store this bit on the Decl itself, rather than a sidemap - happy to give that a whirl if it seems better. (actually it'd be two bits, since 3 states are required - currently reflected by "not in the map", "in the map with Always", "in the map with Never") Discussed whether the module file bit could be omitted in favor of reconstituting from the modular codegen decls list - best guess today is that the efficiency improvement of not having to deserialize the whole list whenever any function is queried by a module user is worth it for the small size increase of this redundant (list + bit-on-def) representation. https://reviews.llvm.org/D29901 Files: include/clang/AST/ExternalASTSource.h include/clang/Sema/MultiplexExternalSemaSource.h include/clang/Serialization/ASTReader.h lib/AST/ASTContext.cpp lib/AST/ExternalASTSource.cpp lib/Sema/MultiplexExternalSemaSource.cpp lib/Serialization/ASTReader.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp test/Modules/Inputs/codegen/foo.h test/Modules/Inputs/codegen/use.cpp test/Modules/codegen.test Index: test/Modules/codegen.test === --- test/Modules/codegen.test +++ test/Modules/codegen.test @@ -3,8 +3,23 @@ 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 %s +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 -CHECK: $_Z2f1PKcz = comdat any -CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat -CHECK: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) +FOO: $_Z2f1PKcz = comdat any +FOO: $_ZN13implicit_dtorD1Ev = comdat any +USE: $_Z4instIiEvv = comdat any +FOO: $_ZN13implicit_dtorD2Ev = comdat any +FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat +FOO: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) + +Test that implicit special members (like this dtor) are emitted into both module (if they're used there) and user. +FIXME: Proactively instantiate any valid implicit special members to emit them into the module object. + +FOO: define weak_odr void @_ZN13implicit_dtorD1Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 { +FOO: define weak_odr void @_Z4instIfEvv() #0 comdat { +FOO: define weak_odr void @_ZN13implicit_dtorD2Ev(%struct.implicit_dtor* %this) unnamed_addr #0 comdat align 2 { + +USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 { +USE: define linkonce_odr void @_Z4instIiEvv() #0 comdat { +USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev(%struct.uninst_implicit_dtor* %this) unnamed_addr #0 comdat align 2 { Index: test/Modules/Inputs/codegen/use.cpp === --- /dev/null +++ test/Modules/Inputs/codegen/use.cpp @@ -0,0 +1,8 @@ +#include "foo.h" +void non_modular_use_of_implicit_dtor() { + implicit_dtor d1; + uninst_implicit_dtor d2; +} +void use_of_instantiated_declaration_without_definition() { + inst(); +} Index: test/Modules/Inputs/codegen/foo.h === --- test/Modules/Inputs/codegen/foo.h +++ test/Modules/Inputs/codegen/foo.h @@ -2,3 +2,29 @@ __builtin_va_list args; __builtin_va_start(args, fmt); } + +struct non_trivial_dtor { + ~non_trivial_dtor(); +}; + +struct implicit_dtor { + non_trivial_dtor d; +}; + +struct uninst_implicit_dtor { + non_trivial_dtor d; +}; + +inline void use_implicit_dtor() { + implicit_dtor d; +} + +template +void inst() { +} + +inline void inst_decl() { + // cause inst's declaration to be instantiated, without a definition. + (void)sizeof(); + inst(); +} Index: lib/Serialization/ASTWriterDecl.cpp === --- lib/Serialization/ASTWriterDecl.cpp +++ lib/Serialization/ASTWriterDecl.cpp @@ -2224,6 +2224,8 @@ Writer->ClearSwitchCaseIDs(); assert(FD->doesThisDeclarationHaveABody()); + Record->push_back(Writer->Context->getLangOpts().ModularCodegen && +Writer->WritingModule); if (auto *CD = dyn_cast(FD)) { Record->push_back(CD->getNumCtorInitializers()); if (CD->getNumCtorInitializers()) Index: