diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3234,7 +3234,8 @@ case MODULAR_CODEGEN_DECLS: // FIXME: Skip reading this record if our ASTConsumer doesn't care about // them (ie: if we're not codegenerating this module). - if (F.Kind == MK_MainFile) + if (F.Kind == MK_MainFile || + getContext().getLangOpts().BuildingPCHWithObjectFile) for (unsigned I = 0, N = Record.size(); I != N; ++I) EagerlyDeserializedDecls.push_back(getGlobalDeclID(F, Record[I])); break; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -503,8 +503,12 @@ } void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) { - if (Record.readInt()) + if (Record.readInt()) { Reader.DefinitionSource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile; + if (Reader.getContext().getLangOpts().BuildingPCHWithObjectFile && + Reader.DeclIsFromPCHWithObjectFile(FD)) + Reader.DefinitionSource[FD] = true; + } if (auto *CD = dyn_cast(FD)) { CD->setNumCtorInitializers(Record.readInt()); if (CD->getNumCtorInitializers()) @@ -1431,8 +1435,12 @@ Reader.getContext().setBlockVarCopyInit(VD, CopyExpr, Record.readInt()); } - if (VD->getStorageDuration() == SD_Static && Record.readInt()) + if (VD->getStorageDuration() == SD_Static && Record.readInt()) { Reader.DefinitionSource[VD] = Loc.F->Kind == ModuleKind::MK_MainFile; + if (Reader.getContext().getLangOpts().BuildingPCHWithObjectFile && + Reader.DeclIsFromPCHWithObjectFile(VD)) + Reader.DefinitionSource[VD] = true; + } enum VarKind { VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization @@ -1691,8 +1699,12 @@ Data.ODRHash = Record.readInt(); Data.HasODRHash = true; - if (Record.readInt()) + if (Record.readInt()) { Reader.DefinitionSource[D] = Loc.F->Kind == ModuleKind::MK_MainFile; + if (Reader.getContext().getLangOpts().BuildingPCHWithObjectFile && + Reader.DeclIsFromPCHWithObjectFile(D)) + Reader.DefinitionSource[D] = true; + } Data.NumBases = Record.readInt(); if (Data.NumBases) diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5688,8 +5688,8 @@ // getODRHash will compute the ODRHash if it has not been previously computed. Record->push_back(D->getODRHash()); - bool ModulesDebugInfo = Writer->Context->getLangOpts().ModulesDebugInfo && - Writer->WritingModule && !D->isDependentType(); + bool ModulesDebugInfo = + Writer->Context->getLangOpts().ModulesDebugInfo && !D->isDependentType(); Record->push_back(ModulesDebugInfo); if (ModulesDebugInfo) Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(D)); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2458,9 +2458,10 @@ assert(FD->doesThisDeclarationHaveABody()); bool ModulesCodegen = false; - if (Writer->WritingModule && !FD->isDependentContext()) { + if (!FD->isDependentContext()) { Optional Linkage; - if (Writer->WritingModule->Kind == Module::ModuleInterfaceUnit) { + if (Writer->WritingModule && + Writer->WritingModule->Kind == Module::ModuleInterfaceUnit) { // When building a C++ Modules TS module interface unit, a strong // definition in the module interface is provided by the compilation of // that module interface unit, not by its users. (Inline functions are diff --git a/clang/test/Modules/Inputs/codegen-flags/foo.h b/clang/test/Modules/Inputs/codegen-flags/foo.h --- a/clang/test/Modules/Inputs/codegen-flags/foo.h +++ b/clang/test/Modules/Inputs/codegen-flags/foo.h @@ -1,4 +1,7 @@ +#ifndef FOO_H +#define FOO_H struct foo { }; inline void f1() { } +#endif diff --git a/clang/test/PCH/codegen.cpp b/clang/test/PCH/codegen.cpp new file mode 100644 --- /dev/null +++ b/clang/test/PCH/codegen.cpp @@ -0,0 +1,42 @@ +// This test is the PCH version of Modules/codegen-flags.test . It uses its inputs. +// The purpose of this test is just verify that the codegen options work with PCH as well. +// All the codegen functionality should be tested in Modules/. + +// RUN: rm -rf %t +// RUN: mkdir -p %t +// REQUIRES: x86-registered-target + +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++-header -building-pch-with-obj -emit-pch %S/../Modules/Inputs/codegen-flags/foo.h -o %t/foo-cg.pch +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-debuginfo -x c++-header -building-pch-with-obj -emit-pch %S/../Modules/Inputs/codegen-flags/foo.h -o %t/foo-di.pch + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %s -include-pch %t/foo-cg.pch -building-pch-with-obj -fmodules-codegen | FileCheck --check-prefix=CG %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %s -include-pch %t/foo-di.pch -building-pch-with-obj -fmodules-debuginfo | FileCheck --check-prefix=DI %s + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -include-pch %t/foo-cg.pch %S/../Modules/Inputs/codegen-flags/use.cpp | FileCheck --check-prefix=CG-USE %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -include-pch %t/foo-di.pch %S/../Modules/Inputs/codegen-flags/use.cpp | FileCheck --check-prefix=DI-USE %s + +// Test with template instantiation in the pch. + +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++-header -building-pch-with-obj -emit-pch -fpch-instantiate-templates %S/../Modules/Inputs/codegen-flags/foo.h -o %t/foo-cg.pch +// RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-debuginfo -x c++-header -building-pch-with-obj -emit-pch -fpch-instantiate-templates %S/../Modules/Inputs/codegen-flags/foo.h -o %t/foo-di.pch + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %s -include-pch %t/foo-cg.pch -building-pch-with-obj -fmodules-codegen | FileCheck --check-prefix=CG %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %s -include-pch %t/foo-di.pch -building-pch-with-obj -fmodules-debuginfo | FileCheck --check-prefix=DI %s + +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -include-pch %t/foo-cg.pch %S/../Modules/Inputs/codegen-flags/use.cpp | FileCheck --check-prefix=CG-USE %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -include-pch %t/foo-di.pch %S/../Modules/Inputs/codegen-flags/use.cpp | FileCheck --check-prefix=DI-USE %s + + +// CG: define weak_odr void @_Z2f1v +// CG: DICompileUnit +// CG-NOT: DICompositeType + +// CG-USE: declare void @_Z2f1v +// CG-USE: DICompileUnit +// CG-USE: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo" + +// DI-NOT: define +// DI: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo" + +// DI-USE: define linkonce_odr void @_Z2f1v +// DI-USE: = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", {{.*}}, flags: DIFlagFwdDecl