From a45f713c673001abb4fe0612b909c698073eb356 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Sun, 19 Apr 2020 17:49:47 +0200 Subject: [PATCH] add option to instantiate templates already in the PCH Add -fpch-instantiate-templates which makes template instantiations be performed already in the PCH instead of it being done in every single file that uses the PCH (but every single file will still do it as well in order to handle its own instantiations). I can see 20-30% build time saved with the few tests I've tried. The change may reorder compiler output and also generated code, but should be generally safe and produce functionally identical code. There are some rare cases that do not compile with it, such as test/PCH/pch-instantiate-templates-forward-decl.cpp. If template instantiation bailed out instead of reporting the error, these instantiations could even be postponed, which would make them work. Enable this by default for clang-cl. MSVC creates PCHs by compiling them using an empty .cpp file, which means templates are instantiated while building the PCH and so the .h needs to be self-contained, making test/PCH/pch-instantiate-templates-forward-decl.cpp to fail with MSVC anyway. So the option being enabled for clang-cl matches this. Differential Revision: https://reviews.llvm.org/D69585 --- clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Driver/Options.td | 7 +++++ clang/include/clang/Sema/Sema.h | 14 ++++++++-- clang/lib/Driver/ToolChains/Clang.cpp | 4 +++ clang/lib/Frontend/CompilerInvocation.cpp | 1 + clang/lib/Sema/Sema.cpp | 5 ++++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 ++++++ clang/test/PCH/crash-12631281.cpp | 4 +++ clang/test/PCH/cxx-alias-decl.cpp | 3 ++ clang/test/PCH/cxx-dependent-sized-ext-vector.cpp | 3 ++ clang/test/PCH/cxx-explicit-specifier.cpp | 3 ++ clang/test/PCH/cxx-exprs.cpp | 3 ++ clang/test/PCH/cxx-friends.cpp | 4 +++ clang/test/PCH/cxx-member-init.cpp | 3 ++ .../cxx-ms-function-specialization-class-scope.cpp | 3 ++ clang/test/PCH/cxx-static_assert.cpp | 5 +++- clang/test/PCH/cxx-templates.cpp | 5 ++++ .../cxx-variadic-templates-with-default-params.cpp | 3 ++ clang/test/PCH/cxx-variadic-templates.cpp | 4 +++ clang/test/PCH/cxx0x-default-delete.cpp | 9 ++++-- clang/test/PCH/cxx11-constexpr.cpp | 7 +++-- clang/test/PCH/cxx11-enum-template.cpp | 5 +++- clang/test/PCH/cxx11-exception-spec.cpp | 6 ++++ clang/test/PCH/cxx11-inheriting-ctors.cpp | 7 +++++ clang/test/PCH/cxx11-user-defined-literals.cpp | 5 +++- clang/test/PCH/cxx1y-decltype-auto.cpp | 5 +++- clang/test/PCH/cxx1y-deduced-return-type.cpp | 4 +++ clang/test/PCH/cxx1y-default-initializer.cpp | 4 +++ clang/test/PCH/cxx1y-init-captures.cpp | 5 +++- clang/test/PCH/cxx1y-variable-templates.cpp | 8 ++++-- clang/test/PCH/cxx1z-aligned-alloc.cpp | 3 ++ clang/test/PCH/cxx1z-decomposition.cpp | 5 +++- clang/test/PCH/cxx1z-using-declaration.cpp | 11 +++++--- clang/test/PCH/cxx2a-bitfield-init.cpp | 2 ++ .../test/PCH/cxx2a-concept-specialization-expr.cpp | 3 ++ clang/test/PCH/cxx2a-constraints.cpp | 3 ++ clang/test/PCH/cxx2a-defaulted-comparison.cpp | 3 ++ clang/test/PCH/cxx2a-requires-expr.cpp | 3 ++ clang/test/PCH/cxx2a-template-lambdas.cpp | 3 ++ clang/test/PCH/delayed-pch-instantiate.cpp | 30 ++++++++++++++++++++ clang/test/PCH/friend-template.cpp | 3 ++ clang/test/PCH/implicitly-deleted.cpp | 4 +++ clang/test/PCH/late-parsed-instantiations.cpp | 3 ++ clang/test/PCH/local_static.cpp | 4 +++ clang/test/PCH/macro-undef.cpp | 24 +++++++++------- clang/test/PCH/make-integer-seq.cpp | 3 ++ clang/test/PCH/ms-if-exists.cpp | 5 +++- .../PCH/pch-instantiate-templates-forward-decl.cpp | 30 ++++++++++++++++++++ clang/test/PCH/pch-instantiate-templates.cpp | 28 +++++++++++++++++++ clang/test/PCH/pr18806.cpp | 3 ++ clang/test/PCH/pragma-diag-section.cpp | 7 +++-- clang/test/PCH/rdar10830559.cpp | 3 ++ .../PCH/specialization-after-instantiation.cpp | 32 ++++++++++++++++++++++ clang/test/PCH/type_pack_element.cpp | 3 ++ 54 files changed, 333 insertions(+), 33 deletions(-) create mode 100644 clang/test/PCH/delayed-pch-instantiate.cpp create mode 100644 clang/test/PCH/pch-instantiate-templates-forward-decl.cpp create mode 100644 clang/test/PCH/pch-instantiate-templates.cpp create mode 100644 clang/test/PCH/specialization-after-instantiation.cpp diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 9236327..bc0c17a 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -165,6 +165,7 @@ BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None, BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch") BENIGN_LANGOPT(BuildingPCHWithObjectFile, 1, 0, "building a pch which has a corresponding object file") BENIGN_LANGOPT(CacheGeneratedPCH, 1, 0, "cache generated PCH files in memory") +BENIGN_LANGOPT(PCHInstantiateTemplates, 1, 0, "instantiate templates while building a PCH") COMPATIBLE_LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses") BENIGN_LANGOPT(ModulesSearchAll , 1, 1, "searching even non-imported modules to find unresolved references") COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "requiring declaration of module uses and all headers to be in modules") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 7c362d7..8ad582c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1420,6 +1420,13 @@ def fpch_validate_input_files_content: def fno_pch_validate_input_files_content: Flag <["-"], "fno_pch-validate-input-files-content">, Group, Flags<[DriverOption]>; +def fpch_instantiate_templates: + Flag <["-"], "fpch-instantiate-templates">, + Group, Flags<[CC1Option]>, + HelpText<"Instantiate templates already while building a PCH">; +def fno_pch_instantiate_templates: + Flag <["-"], "fno-pch-instantiate-templates">, + Group, Flags<[CC1Option]>; def fmodules : Flag <["-"], "fmodules">, Group, Flags<[DriverOption, CC1Option]>, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 85c5ab4..8c8e981 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8804,9 +8804,17 @@ public: S.VTableUses.swap(SavedVTableUses); // Restore the set of pending implicit instantiations. - assert(S.PendingInstantiations.empty() && - "PendingInstantiations should be empty before it is discarded."); - S.PendingInstantiations.swap(SavedPendingInstantiations); + if (S.TUKind != TU_Prefix || !S.LangOpts.PCHInstantiateTemplates) { + assert(S.PendingInstantiations.empty() && + "PendingInstantiations should be empty before it is discarded."); + S.PendingInstantiations.swap(SavedPendingInstantiations); + } else { + // Template instantiations in the PCH may be delayed until the TU. + S.PendingInstantiations.swap(SavedPendingInstantiations); + S.PendingInstantiations.insert(S.PendingInstantiations.end(), + SavedPendingInstantiations.begin(), + SavedPendingInstantiations.end()); + } } private: diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 70d0fe0..aa18727 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1241,6 +1241,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, if (YcArg && JA.getKind() >= Action::PrecompileJobClass && JA.getKind() <= Action::AssembleJobClass) { CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj")); + CmdArgs.push_back(Args.MakeArgString("-fpch-instantiate-templates")); } if (YcArg || YuArg) { StringRef ThroughHeader = YcArg ? YcArg->getValue() : YuArg->getValue(); @@ -5633,6 +5634,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasFlag(options::OPT_fpch_validate_input_files_content, options::OPT_fno_pch_validate_input_files_content, false)) CmdArgs.push_back("-fvalidate-ast-input-files-content"); + if (Args.hasFlag(options::OPT_fpch_instantiate_templates, + options::OPT_fno_pch_instantiate_templates, false)) + CmdArgs.push_back("-fpch-instantiate-templates"); Args.AddLastArg(CmdArgs, options::OPT_fexperimental_new_pass_manager, options::OPT_fno_experimental_new_pass_manager); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f322cc7..1cd4830 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3370,6 +3370,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.CompleteMemberPointers = Args.hasArg(OPT_fcomplete_member_pointers); Opts.BuildingPCHWithObjectFile = Args.hasArg(OPT_building_pch_with_obj); + Opts.PCHInstantiateTemplates = Args.hasArg(OPT_fpch_instantiate_templates); Opts.MatrixTypes = Args.hasArg(OPT_fenable_matrix); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 49fbde8..fc3fb52 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1010,6 +1010,11 @@ void Sema::ActOnEndOfTranslationUnit() { LateParsedInstantiations.begin(), LateParsedInstantiations.end()); LateParsedInstantiations.clear(); + + if (LangOpts.PCHInstantiateTemplates) { + llvm::TimeTraceScope TimeScope("PerformPendingInstantiations"); + PerformPendingInstantiations(); + } } DiagnoseUnterminatedPragmaPack(); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 7d0777c..1fff6b8 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5926,6 +5926,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, /// Performs template instantiation for all implicit template /// instantiations we have seen until this point. void Sema::PerformPendingInstantiations(bool LocalOnly) { + std::deque delayedPCHInstantiations; while (!PendingLocalImplicitInstantiations.empty() || (!LocalOnly && !PendingInstantiations.empty())) { PendingImplicitInstantiation Inst; @@ -5956,6 +5957,10 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { if (Function->isDefined()) Function->setInstantiationIsPending(false); } + // Definition of a PCH-ed template declaration may be available only in the TU. + if (!LocalOnly && LangOpts.PCHInstantiateTemplates && + TUKind == TU_Prefix && Function->instantiationIsPending()) + delayedPCHInstantiations.push_back(Inst); continue; } @@ -6001,6 +6006,9 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true, DefinitionRequired, true); } + + if (!LocalOnly && LangOpts.PCHInstantiateTemplates) + PendingInstantiations.swap(delayedPCHInstantiations); } void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, diff --git a/clang/test/PCH/crash-12631281.cpp b/clang/test/PCH/crash-12631281.cpp index f309bca..f7bf65e 100644 --- a/clang/test/PCH/crash-12631281.cpp +++ b/clang/test/PCH/crash-12631281.cpp @@ -1,5 +1,9 @@ // RUN: %clang_cc1 -std=c++11 %s -emit-pch -o %t.pch // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -include-pch %t.pch -verify + +// RUN: %clang_cc1 -std=c++11 %s -emit-pch -fpch-instantiate-templates -o %t.pch +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -include-pch %t.pch -verify + // expected-no-diagnostics // rdar://12631281 diff --git a/clang/test/PCH/cxx-alias-decl.cpp b/clang/test/PCH/cxx-alias-decl.cpp index 872658f..2fdf40c 100644 --- a/clang/test/PCH/cxx-alias-decl.cpp +++ b/clang/test/PCH/cxx-alias-decl.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -x c++ -std=c++11 -emit-pch -o %t %S/cxx-alias-decl.h // RUN: %clang_cc1 -x c++ -std=c++11 -include-pch %t -fsyntax-only -emit-llvm -o - %s +// RUN: %clang_cc1 -x c++ -std=c++11 -emit-pch -fpch-instantiate-templates -o %t %S/cxx-alias-decl.h +// RUN: %clang_cc1 -x c++ -std=c++11 -include-pch %t -fsyntax-only -emit-llvm -o - %s + template struct T; C::A a; diff --git a/clang/test/PCH/cxx-dependent-sized-ext-vector.cpp b/clang/test/PCH/cxx-dependent-sized-ext-vector.cpp index 29c06f7..93fb561 100644 --- a/clang/test/PCH/cxx-dependent-sized-ext-vector.cpp +++ b/clang/test/PCH/cxx-dependent-sized-ext-vector.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++11 -emit-pch %s -o %t // RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s +// RUN: %clang_cc1 -std=c++11 -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s + #ifndef HEADER_INCLUDED #define HEADER_INCLUDED diff --git a/clang/test/PCH/cxx-explicit-specifier.cpp b/clang/test/PCH/cxx-explicit-specifier.cpp index 9c7b056..ede0730 100644 --- a/clang/test/PCH/cxx-explicit-specifier.cpp +++ b/clang/test/PCH/cxx-explicit-specifier.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t-cxx2a // RUN: %clang_cc1 -std=c++2a -DUSE_PCH -include-pch %t-cxx2a %s -ast-print -verify | FileCheck %s +// RUN: %clang_cc1 -std=c++2a -emit-pch -fpch-instantiate-templates %s -o %t-cxx2a +// RUN: %clang_cc1 -std=c++2a -DUSE_PCH -include-pch %t-cxx2a %s -ast-print -verify | FileCheck %s + #ifndef USE_PCH namespace inheriting_constructor { struct S {}; diff --git a/clang/test/PCH/cxx-exprs.cpp b/clang/test/PCH/cxx-exprs.cpp index e02bb0a..2551d36 100644 --- a/clang/test/PCH/cxx-exprs.cpp +++ b/clang/test/PCH/cxx-exprs.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++11 -emit-pch -o %t %s // RUN: %clang_cc1 -include-pch %t -verify -std=c++11 %s +// RUN: %clang_cc1 -std=c++11 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -include-pch %t -verify -std=c++11 %s + // expected-no-diagnostics #ifndef HEADER diff --git a/clang/test/PCH/cxx-friends.cpp b/clang/test/PCH/cxx-friends.cpp index 9c75f92..d1610be 100644 --- a/clang/test/PCH/cxx-friends.cpp +++ b/clang/test/PCH/cxx-friends.cpp @@ -5,6 +5,10 @@ // RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-friends.h // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s -error-on-deserialized-decl doNotDeserialize +// Test with pch and template instantiation in the pch. +// RUN: %clang_cc1 -x c++-header -emit-pch -fpch-instantiate-templates -o %t %S/cxx-friends.h +// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s -error-on-deserialized-decl doNotDeserialize + // Test with modules. // RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/cxx-friends.h -fmodules // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s -error-on-deserialized-decl doNotDeserialize -fmodules diff --git a/clang/test/PCH/cxx-member-init.cpp b/clang/test/PCH/cxx-member-init.cpp index 78fd744..1bced56 100644 --- a/clang/test/PCH/cxx-member-init.cpp +++ b/clang/test/PCH/cxx-member-init.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -x c++ -std=c++11 -DHEADER -emit-pch -o %t %s // RUN: %clang_cc1 -x c++ -std=c++11 -DHEADER -include-pch %t -fsyntax-only -emit-llvm -o - %s +// RUN: %clang_cc1 -x c++ -std=c++11 -DHEADER -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -x c++ -std=c++11 -DHEADER -include-pch %t -fsyntax-only -emit-llvm -o - %s + #ifdef HEADER int n; struct S { diff --git a/clang/test/PCH/cxx-ms-function-specialization-class-scope.cpp b/clang/test/PCH/cxx-ms-function-specialization-class-scope.cpp index f97a8d1..af1f5ac 100644 --- a/clang/test/PCH/cxx-ms-function-specialization-class-scope.cpp +++ b/clang/test/PCH/cxx-ms-function-specialization-class-scope.cpp @@ -1,6 +1,9 @@ // REQUIRES: x86-registered-target // RUN: %clang_cc1 -fms-extensions -triple i386-unknown-unknown -x c++-header -emit-pch -o %t %S/cxx-ms-function-specialization-class-scope.h // RUN: %clang_cc1 -fms-extensions -triple i386-unknown-unknown -include-pch %t -fsyntax-only -verify %s + +// RUN: %clang_cc1 -fms-extensions -triple i386-unknown-unknown -x c++-header -emit-pch -fpch-instantiate-templates -o %t %S/cxx-ms-function-specialization-class-scope.h +// RUN: %clang_cc1 -fms-extensions -triple i386-unknown-unknown -include-pch %t -fsyntax-only -verify %s // expected-no-diagnostics diff --git a/clang/test/PCH/cxx-static_assert.cpp b/clang/test/PCH/cxx-static_assert.cpp index be6c0ab..4946b76 100644 --- a/clang/test/PCH/cxx-static_assert.cpp +++ b/clang/test/PCH/cxx-static_assert.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++11 -emit-pch -o %t %s // RUN: %clang_cc1 -include-pch %t -verify -std=c++11 %s +// RUN: %clang_cc1 -std=c++11 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -include-pch %t -verify -std=c++11 %s + #ifndef HEADER #define HEADER @@ -14,7 +17,7 @@ template struct T { #else -// expected-error@12 {{static_assert failed due to requirement '1 == 2' "N is not 2!"}} +// expected-error@15 {{static_assert failed due to requirement '1 == 2' "N is not 2!"}} T<1> t1; // expected-note {{in instantiation of template class 'T<1>' requested here}} T<2> t2; diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index cd2787d..3e1c3cee 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/test/PCH/cxx-templates.cpp @@ -17,6 +17,11 @@ // RUN: %clang_cc1 -std=c++17 -triple %itanium_abi_triple -fcxx-exceptions -fdelayed-template-parsing -fexceptions -include-pch %t -verify %s // RUN: %clang_cc1 -std=c++17 -triple %itanium_abi_triple -fcxx-exceptions -fdelayed-template-parsing -fexceptions -include-pch %t %s -emit-llvm -o - -DNO_ERRORS | FileCheck %s +// Test with pch and template instantiation in the pch. +// RUN: %clang_cc1 -std=c++17 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -fpch-instantiate-templates -x c++-header -emit-pch -o %t %S/cxx-templates.h +// RUN: %clang_cc1 -std=c++17 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -include-pch %t -verify %s +// RUN: %clang_cc1 -std=c++17 -triple %itanium_abi_triple -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -DNO_ERRORS | FileCheck %s + // CHECK: define weak_odr {{.*}}void @_ZN2S4IiE1mEv // CHECK: define linkonce_odr {{.*}}void @_ZN2S3IiE1mEv diff --git a/clang/test/PCH/cxx-variadic-templates-with-default-params.cpp b/clang/test/PCH/cxx-variadic-templates-with-default-params.cpp index 2c14820..dfa10df 100644 --- a/clang/test/PCH/cxx-variadic-templates-with-default-params.cpp +++ b/clang/test/PCH/cxx-variadic-templates-with-default-params.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -std=c++11 -x c++-header -emit-pch -o %t %s // RUN: %clang_cc1 -std=c++11 -include-pch %t -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++11 -x c++-header -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -std=c++11 -include-pch %t -fsyntax-only -verify %s + // expected-no-diagnostics // PR25271: Ensure that default template arguments prior to a parameter pack diff --git a/clang/test/PCH/cxx-variadic-templates.cpp b/clang/test/PCH/cxx-variadic-templates.cpp index dc00758..87b101d 100644 --- a/clang/test/PCH/cxx-variadic-templates.cpp +++ b/clang/test/PCH/cxx-variadic-templates.cpp @@ -7,6 +7,10 @@ // RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s -ast-dump -o - // RUN: %clang_cc1 -std=c++11 -include-pch %t %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -std=c++11 -x c++-header -emit-pch -fpch-instantiate-templates -o %t %S/cxx-variadic-templates.h +// RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s -ast-dump -o - +// RUN: %clang_cc1 -std=c++11 -include-pch %t %s -emit-llvm -o - | FileCheck %s + // expected-no-diagnostics // CHECK: allocate_shared diff --git a/clang/test/PCH/cxx0x-default-delete.cpp b/clang/test/PCH/cxx0x-default-delete.cpp index 230f6a6..bca4607 100644 --- a/clang/test/PCH/cxx0x-default-delete.cpp +++ b/clang/test/PCH/cxx0x-default-delete.cpp @@ -4,6 +4,9 @@ // RUN: %clang_cc1 -x c++-header -std=c++11 -emit-pch -o %t %s // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -include-pch %t %s +// RUN: %clang_cc1 -x c++-header -std=c++11 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -include-pch %t %s + #ifndef PASS1 #define PASS1 @@ -30,11 +33,11 @@ struct A { foo::foo() { } // expected-error{{definition of explicitly defaulted default constructor}} foo f; void fn() { - f.bar(); // expected-error{{deleted function}} expected-note@12{{deleted here}} + f.bar(); // expected-error{{deleted function}} expected-note@15{{deleted here}} } -baz bz; // expected-error{{deleted function}} expected-note@16{{deleted here}} -quux qx; // expected-error{{private destructor}} expected-note@20{{private here}} +baz bz; // expected-error{{deleted function}} expected-note@19{{deleted here}} +quux qx; // expected-error{{private destructor}} expected-note@23{{private here}} struct B { A a; }; struct C { mutable A a; }; diff --git a/clang/test/PCH/cxx11-constexpr.cpp b/clang/test/PCH/cxx11-constexpr.cpp index 8b722ce..b315b47 100644 --- a/clang/test/PCH/cxx11-constexpr.cpp +++ b/clang/test/PCH/cxx11-constexpr.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t // RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s + #ifndef HEADER_INCLUDED #define HEADER_INCLUDED @@ -31,9 +34,9 @@ constexpr T plus_seven(T other) { static_assert(D(4).k == 9, ""); constexpr int f(C c) { return 0; } // expected-error {{not a literal type}} -// expected-note@13 {{not an aggregate and has no constexpr constructors}} +// expected-note@16 {{not an aggregate and has no constexpr constructors}} constexpr B b; // expected-error {{constant expression}} expected-note {{non-constexpr}} - // expected-note@9 {{here}} + // expected-note@12 {{here}} static_assert(plus_seven(3) == 10, ""); diff --git a/clang/test/PCH/cxx11-enum-template.cpp b/clang/test/PCH/cxx11-enum-template.cpp index ca70601..52c4781 100644 --- a/clang/test/PCH/cxx11-enum-template.cpp +++ b/clang/test/PCH/cxx11-enum-template.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t // RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s + #ifndef HEADER_INCLUDED #define HEADER_INCLUDED @@ -20,7 +23,7 @@ template struct S; int k1 = (int)S::E::e; int k2 = (int)decltype(b)::e; -int k3 = (int)decltype(c)::e; // expected-error@10 {{conversion from 'double' to 'int'}} expected-note {{here}} +int k3 = (int)decltype(c)::e; // expected-error@13 {{conversion from 'double' to 'int'}} expected-note {{here}} int k4 = (int)S::E::e; #endif diff --git a/clang/test/PCH/cxx11-exception-spec.cpp b/clang/test/PCH/cxx11-exception-spec.cpp index 8c7388a..3341e29 100644 --- a/clang/test/PCH/cxx11-exception-spec.cpp +++ b/clang/test/PCH/cxx11-exception-spec.cpp @@ -2,6 +2,12 @@ // RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.1 -emit-pch %s -o %t.2 // RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.2 -verify %s // RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.2 -emit-llvm-only %s + +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch -fpch-instantiate-templates %s -o %t.1 +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.1 -emit-pch -fpch-instantiate-templates %s -o %t.2 +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.2 -verify %s +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t.2 -emit-llvm-only %s + // expected-no-diagnostics #ifndef PHASE1_DONE diff --git a/clang/test/PCH/cxx11-inheriting-ctors.cpp b/clang/test/PCH/cxx11-inheriting-ctors.cpp index bf9a2b7..6229fb4 100644 --- a/clang/test/PCH/cxx11-inheriting-ctors.cpp +++ b/clang/test/PCH/cxx11-inheriting-ctors.cpp @@ -4,10 +4,17 @@ // RxN: %clang_cc1 -std=c++11 -emit-pch -o %t.12 -include %s %s // RxN: %clang_cc1 -std=c++11 -include-pch %t.12 -verify %s // +// RxN: %clang_cc1 -std=c++11 -emit-pch -fpch-instantiate-templates -o %t.12 -include %s %s +// RxN: %clang_cc1 -std=c++11 -include-pch %t.12 -verify %s +// // Emit with definitions in update records: // RxN: %clang_cc1 -std=c++11 -emit-pch -o %t.1 %s // RxN: %clang_cc1 -std=c++11 -include-pch %t.1 -emit-pch -o %t.2 -verify %s // RxN: %clang_cc1 -std=c++11 -include-pch %t.1 -include-pch %t.2 -verify %s +// +// RxN: %clang_cc1 -std=c++11 -emit-pch -fpch-instantiate-templates -o %t.1 %s +// RxN: %clang_cc1 -std=c++11 -include-pch %t.1 -emit-pch -fpch-instantiate-templates -o %t.2 -verify %s +// RxN: %clang_cc1 -std=c++11 -include-pch %t.1 -include-pch %t.2 -verify %s // expected-no-diagnostics diff --git a/clang/test/PCH/cxx11-user-defined-literals.cpp b/clang/test/PCH/cxx11-user-defined-literals.cpp index 7ad17f5..cf3dc8c 100644 --- a/clang/test/PCH/cxx11-user-defined-literals.cpp +++ b/clang/test/PCH/cxx11-user-defined-literals.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch %s -o %t // RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic-errors -std=c++11 -include-pch %t -verify %s + #ifndef HEADER_INCLUDED #define HEADER_INCLUDED @@ -17,6 +20,6 @@ int k = f(0); int *l = f(&k); struct S {}; int m = f(S()); // expected-error {{no matching}} - // expected-note@11 {{substitution failure}} + // expected-note@14 {{substitution failure}} #endif diff --git a/clang/test/PCH/cxx1y-decltype-auto.cpp b/clang/test/PCH/cxx1y-decltype-auto.cpp index a1c9339..8a85283 100644 --- a/clang/test/PCH/cxx1y-decltype-auto.cpp +++ b/clang/test/PCH/cxx1y-decltype-auto.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t -verify %s + #ifndef HEADER_INCLUDED #define HEADER_INCLUDED @@ -18,7 +21,7 @@ struct Z { int x : 5; // expected-note {{bit-field}} }; -// expected-error@12 {{non-const reference cannot bind to bit-field 'x'}} +// expected-error@15 {{non-const reference cannot bind to bit-field 'x'}} template void f(Z); // expected-note {{in instantiation of}} #endif diff --git a/clang/test/PCH/cxx1y-deduced-return-type.cpp b/clang/test/PCH/cxx1y-deduced-return-type.cpp index a61dda2..1862249 100644 --- a/clang/test/PCH/cxx1y-deduced-return-type.cpp +++ b/clang/test/PCH/cxx1y-deduced-return-type.cpp @@ -6,6 +6,10 @@ // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch %s -o %t.b // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch -fpch-instantiate-templates %s -o %t.a +// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch -fpch-instantiate-templates %s -o %t.b +// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s + // expected-no-diagnostics #if !defined(HEADER1) diff --git a/clang/test/PCH/cxx1y-default-initializer.cpp b/clang/test/PCH/cxx1y-default-initializer.cpp index acb6337..a971ba6 100644 --- a/clang/test/PCH/cxx1y-default-initializer.cpp +++ b/clang/test/PCH/cxx1y-default-initializer.cpp @@ -3,6 +3,10 @@ // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.1 -emit-pch -o %t.2 %s // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.2 -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch -fpch-instantiate-templates -o %t.1 %s +// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.1 -emit-pch -fpch-instantiate-templates -o %t.2 %s +// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.2 -verify %s + #ifndef HEADER_1 #define HEADER_1 diff --git a/clang/test/PCH/cxx1y-init-captures.cpp b/clang/test/PCH/cxx1y-init-captures.cpp index 3c8fc14..7f8a9fa 100644 --- a/clang/test/PCH/cxx1y-init-captures.cpp +++ b/clang/test/PCH/cxx1y-init-captures.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t -verify %s + #ifndef HEADER #define HEADER @@ -21,7 +24,7 @@ int y = counter(); void g() { f(0); // ok - // expected-error@15 {{lvalue of type 'const char *const'}} + // expected-error@18 {{lvalue of type 'const char *const'}} f("foo"); // expected-note {{here}} } diff --git a/clang/test/PCH/cxx1y-variable-templates.cpp b/clang/test/PCH/cxx1y-variable-templates.cpp index 29b66a1..faa9b3d 100644 --- a/clang/test/PCH/cxx1y-variable-templates.cpp +++ b/clang/test/PCH/cxx1y-variable-templates.cpp @@ -7,6 +7,10 @@ // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch %s -o %t.b -DHEADER2 // RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s -DHEADERUSE +// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch -fpch-instantiate-templates %s -o %t.a -DHEADER1 +// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch -fpch-instantiate-templates %s -o %t.b -DHEADER2 +// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s -DHEADERUSE + #ifndef ERROR // expected-no-diagnostics #endif @@ -89,8 +93,8 @@ namespace join { namespace diff_types { #ifdef ERROR - template extern T err0; // expected-error {{redeclaration of 'err0' with a different type: 'T' vs 'float'}} // expected-note@42 {{previous declaration is here}} - template extern float err1; // expected-error {{redeclaration of 'err1' with a different type: 'float' vs 'T'}} // expected-note@43 {{previous declaration is here}} + template extern T err0; // expected-error {{redeclaration of 'err0' with a different type: 'T' vs 'float'}} // expected-note@46 {{previous declaration is here}} + template extern float err1; // expected-error {{redeclaration of 'err1' with a different type: 'float' vs 'T'}} // expected-note@47 {{previous declaration is here}} #endif template extern T def; } diff --git a/clang/test/PCH/cxx1z-aligned-alloc.cpp b/clang/test/PCH/cxx1z-aligned-alloc.cpp index c49b910..c1becbd 100644 --- a/clang/test/PCH/cxx1z-aligned-alloc.cpp +++ b/clang/test/PCH/cxx1z-aligned-alloc.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -emit-pch %s -o %t // RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic -fsized-deallocation -std=c++1z -include-pch %t -verify %s + // expected-no-diagnostics #ifndef HEADER diff --git a/clang/test/PCH/cxx1z-decomposition.cpp b/clang/test/PCH/cxx1z-decomposition.cpp index e033577..2f817b4 100644 --- a/clang/test/PCH/cxx1z-decomposition.cpp +++ b/clang/test/PCH/cxx1z-decomposition.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch %s -o %t // RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s + #ifndef HEADER #define HEADER @@ -26,7 +29,7 @@ int k = decomp(arr); static_assert(foo({1, 2}) == 12); -// expected-error@12 {{cannot decompose non-class, non-array type 'const int'}} +// expected-error@15 {{cannot decompose non-class, non-array type 'const int'}} int z = decomp(10); // expected-note {{instantiation of}} #endif diff --git a/clang/test/PCH/cxx1z-using-declaration.cpp b/clang/test/PCH/cxx1z-using-declaration.cpp index a185ff1..dd0e59f 100644 --- a/clang/test/PCH/cxx1z-using-declaration.cpp +++ b/clang/test/PCH/cxx1z-using-declaration.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch %s -o %t // RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s +// RUN: %clang_cc1 -pedantic -std=c++1z -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -pedantic -std=c++1z -include-pch %t -verify %s + #ifndef HEADER #define HEADER @@ -25,10 +28,10 @@ void test() { a.g(); a.g(0); a.g(0, 0); - // expected-error@13 {{no match}} - // expected-note@16 {{candidate}} - // expected-note@17 {{candidate}} - // expected-note@18 {{candidate}} + // expected-error@16 {{no match}} + // expected-note@19 {{candidate}} + // expected-note@20 {{candidate}} + // expected-note@21 {{candidate}} a.g(0, 0, 0); // expected-note {{instantiation of}} } diff --git a/clang/test/PCH/cxx2a-bitfield-init.cpp b/clang/test/PCH/cxx2a-bitfield-init.cpp index 344f3cb..ab7c3ce 100644 --- a/clang/test/PCH/cxx2a-bitfield-init.cpp +++ b/clang/test/PCH/cxx2a-bitfield-init.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -std=c++2a -include %s -verify %s // RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t // RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s -DPCH +// RUN: %clang_cc1 -std=c++2a -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s -DPCH #ifndef HEADER #define HEADER diff --git a/clang/test/PCH/cxx2a-concept-specialization-expr.cpp b/clang/test/PCH/cxx2a-concept-specialization-expr.cpp index 6227d57..386fee2 100644 --- a/clang/test/PCH/cxx2a-concept-specialization-expr.cpp +++ b/clang/test/PCH/cxx2a-concept-specialization-expr.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t // RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s +// RUN: %clang_cc1 -std=c++2a -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s + // expected-no-diagnostics #ifndef HEADER diff --git a/clang/test/PCH/cxx2a-constraints.cpp b/clang/test/PCH/cxx2a-constraints.cpp index 593d962..d8b7933 100644 --- a/clang/test/PCH/cxx2a-constraints.cpp +++ b/clang/test/PCH/cxx2a-constraints.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t // RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s +// RUN: %clang_cc1 -std=c++2a -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s + // expected-no-diagnostics #ifndef HEADER diff --git a/clang/test/PCH/cxx2a-defaulted-comparison.cpp b/clang/test/PCH/cxx2a-defaulted-comparison.cpp index 4fb0b83..8fea0fb 100644 --- a/clang/test/PCH/cxx2a-defaulted-comparison.cpp +++ b/clang/test/PCH/cxx2a-defaulted-comparison.cpp @@ -2,6 +2,9 @@ // // RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t.pch // RUN: %clang_cc1 -std=c++2a -include-pch %t.pch %s -verify +// +// RUN: %clang_cc1 -std=c++2a -emit-pch -fpch-instantiate-templates %s -o %t.pch +// RUN: %clang_cc1 -std=c++2a -include-pch %t.pch %s -verify // expected-no-diagnostics diff --git a/clang/test/PCH/cxx2a-requires-expr.cpp b/clang/test/PCH/cxx2a-requires-expr.cpp index 5548db4..d958f3a 100644 --- a/clang/test/PCH/cxx2a-requires-expr.cpp +++ b/clang/test/PCH/cxx2a-requires-expr.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -emit-pch -std=c++2a -o %t %s // RUN: %clang_cc1 -std=c++2a -x ast -ast-print %t | FileCheck %s +// RUN: %clang_cc1 -emit-pch -std=c++2a -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -std=c++2a -x ast -ast-print %t | FileCheck %s + template concept C = true; diff --git a/clang/test/PCH/cxx2a-template-lambdas.cpp b/clang/test/PCH/cxx2a-template-lambdas.cpp index c9d923f..c11de0a 100644 --- a/clang/test/PCH/cxx2a-template-lambdas.cpp +++ b/clang/test/PCH/cxx2a-template-lambdas.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t // RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s +// RUN: %clang_cc1 -std=c++2a -emit-pch -fpch-instantiate-templates %s -o %t +// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s + // expected-no-diagnostics #ifndef HEADER diff --git a/clang/test/PCH/delayed-pch-instantiate.cpp b/clang/test/PCH/delayed-pch-instantiate.cpp new file mode 100644 index 0000000..cf7a9f2 --- /dev/null +++ b/clang/test/PCH/delayed-pch-instantiate.cpp @@ -0,0 +1,30 @@ +// Test this without pch. +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -DBODY %s -o - | FileCheck %s + +// Test with pch. +// RUN: %clang_cc1 -emit-pch -o %t %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -include-pch %t -DBODY %s -o - | FileCheck %s + +// RUN: %clang_cc1 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -include-pch %t -DBODY %s -o - | FileCheck %s + +// expected-no-diagnostics + +#ifndef HEADER_H +#define HEADER_H +struct A { + void foo() { bar<0>(); } // This will trigger implicit instantiation of bar<0>() in the PCH. + template + void bar(); +}; +#endif + +#ifdef BODY +// But the definition is only in the source, so the instantiation must be delayed until the TU. +template +void A::bar() {} + +void test(A *a) { a->foo(); } +#endif + +// CHECK: define linkonce_odr void @_ZN1A3barILi0EEEvv diff --git a/clang/test/PCH/friend-template.cpp b/clang/test/PCH/friend-template.cpp index 989819b..a608879 100644 --- a/clang/test/PCH/friend-template.cpp +++ b/clang/test/PCH/friend-template.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 -emit-pch -o %t %s // RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s +// RUN: %clang_cc1 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify %s + // expected-no-diagnostics #ifndef HEADER diff --git a/clang/test/PCH/implicitly-deleted.cpp b/clang/test/PCH/implicitly-deleted.cpp index 5238fd3..669bdac 100644 --- a/clang/test/PCH/implicitly-deleted.cpp +++ b/clang/test/PCH/implicitly-deleted.cpp @@ -1,5 +1,9 @@ // RUN: %clang_cc1 -std=c++11 -x c++-header %s -emit-pch -o %t.pch // RUN: %clang_cc1 -std=c++11 -x c++ /dev/null -include-pch %t.pch + +// RUN: %clang_cc1 -std=c++11 -x c++-header %s -emit-pch -fpch-instantiate-templates -o %t.pch +// RUN: %clang_cc1 -std=c++11 -x c++ /dev/null -include-pch %t.pch + class move_only { move_only(const move_only&) = delete; move_only(move_only&&); }; struct sb { move_only il; diff --git a/clang/test/PCH/late-parsed-instantiations.cpp b/clang/test/PCH/late-parsed-instantiations.cpp index cbcc063..7a78781 100644 --- a/clang/test/PCH/late-parsed-instantiations.cpp +++ b/clang/test/PCH/late-parsed-instantiations.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -emit-pch %s -o %t.pch -verify // RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -include-pch %t.pch %s -verify +// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -emit-pch -fpch-instantiate-templates %s -o %t.pch -verify +// RUN: %clang_cc1 -fdelayed-template-parsing -std=c++14 -include-pch %t.pch %s -verify + #ifndef HEADER_INCLUDED #define HEADER_INCLUDED diff --git a/clang/test/PCH/local_static.cpp b/clang/test/PCH/local_static.cpp index b4131bf..d198d84 100644 --- a/clang/test/PCH/local_static.cpp +++ b/clang/test/PCH/local_static.cpp @@ -8,6 +8,10 @@ // RUN: %clang_cc1 -triple x86_64-apple-macosx10.9.0 -include-pch %t.pch -emit-llvm -o %t.pch.ll %s // RUN: FileCheck --input-file %t.pch.ll %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9.0 -x c++-header -emit-pch -fpch-instantiate-templates -o %t.pch %S/local_static.h +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.9.0 -include-pch %t.pch -emit-llvm -o %t.pch.ll %s +// RUN: FileCheck --input-file %t.pch.ll %s + void test(Bar &b) { b.f(); static int s; diff --git a/clang/test/PCH/macro-undef.cpp b/clang/test/PCH/macro-undef.cpp index bfe87d1..4ec935d 100644 --- a/clang/test/PCH/macro-undef.cpp +++ b/clang/test/PCH/macro-undef.cpp @@ -2,31 +2,35 @@ // RUN: %clang_cc1 -std=c++98 -fsyntax-only -include-pch %t %s -Wuninitialized -verify // RUN: %clang_cc1 -std=c++98 -fsyntax-only -include-pch %t %s -Wuninitialized -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s +// RUN: %clang_cc1 -std=c++98 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -include-pch %t %s -Wuninitialized -verify +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -include-pch %t %s -Wuninitialized -fdiagnostics-parseable-fixits 2>&1 | FileCheck %s + #ifndef HEADER #define HEADER #define NULL 0 template void *f() { - void *p; // @11 - return p; // @12 + void *p; // @15 + return p; // @16 } #undef NULL template void *g() { - void *p; // @17 - return p; // @18 + void *p; // @21 + return p; // @22 } #else -// expected-warning@12 {{uninitialized}} -// expected-note@11 {{initialize}} -// CHECK: fix-it:"{{.*}}":{11:10-11:10}:" = NULL" +// expected-warning@16 {{uninitialized}} +// expected-note@15 {{initialize}} +// CHECK: fix-it:"{{.*}}":{15:10-15:10}:" = NULL" -// expected-warning@18 {{uninitialized}} -// expected-note@17 {{initialize}} -// CHECK: fix-it:"{{.*}}":{17:10-17:10}:" = 0" +// expected-warning@22 {{uninitialized}} +// expected-note@21 {{initialize}} +// CHECK: fix-it:"{{.*}}":{21:10-21:10}:" = 0" int main() { f(); // expected-note {{instantiation}} diff --git a/clang/test/PCH/make-integer-seq.cpp b/clang/test/PCH/make-integer-seq.cpp index 3622c33..a52349c 100644 --- a/clang/test/PCH/make-integer-seq.cpp +++ b/clang/test/PCH/make-integer-seq.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -o %t.pch // RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch +// RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -fpch-instantiate-templates -o %t.pch +// RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch + template struct Seq { static constexpr T PackSize = sizeof...(I); diff --git a/clang/test/PCH/ms-if-exists.cpp b/clang/test/PCH/ms-if-exists.cpp index be29ac6..c875b1d 100644 --- a/clang/test/PCH/ms-if-exists.cpp +++ b/clang/test/PCH/ms-if-exists.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -x c++ -fms-extensions -fsyntax-only -emit-pch -o %t %s // RUN: %clang_cc1 -x c++ -fms-extensions -fsyntax-only -include-pch %t %s -verify +// RUN: %clang_cc1 -x c++ -fms-extensions -fsyntax-only -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -x c++ -fms-extensions -fsyntax-only -include-pch %t %s -verify + #ifndef HEADER #define HEADER template @@ -25,6 +28,6 @@ struct HasBar { }; template void f(HasFoo); // expected-note{{in instantiation of function template specialization 'f' requested here}} - // expected-error@14{{no viable conversion from 'HasFoo' to 'int *'}} + // expected-error@17{{no viable conversion from 'HasFoo' to 'int *'}} template void f(HasBar); #endif diff --git a/clang/test/PCH/pch-instantiate-templates-forward-decl.cpp b/clang/test/PCH/pch-instantiate-templates-forward-decl.cpp new file mode 100644 index 0000000..a7b418d --- /dev/null +++ b/clang/test/PCH/pch-instantiate-templates-forward-decl.cpp @@ -0,0 +1,30 @@ +// Test this without pch. +// RUN: %clang_cc1 -fsyntax-only %s -DBODY + +// Test with pch. +// RUN: %clang_cc1 -emit-pch -o %t %s +// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -DBODY + +// Test with pch with template instantiation in the pch. +// RUN: %clang_cc1 -emit-pch -fpch-instantiate-templates -o %t %s -verify + +#ifndef HEADER_H +#define HEADER_H + +template +void f(); +struct X; // @16 +void g() { f(); } // @17 instantiation not performed yet + +template +void f() { T t; }; // @20 + +#endif + +#ifdef BODY +struct X {}; +#endif + +// expected-error@20 {{variable has incomplete type}} +// expected-note@17 {{in instantiation of function template specialization}} +// expected-note@16 {{forward declaration}} diff --git a/clang/test/PCH/pch-instantiate-templates.cpp b/clang/test/PCH/pch-instantiate-templates.cpp new file mode 100644 index 0000000..20aadf8 --- /dev/null +++ b/clang/test/PCH/pch-instantiate-templates.cpp @@ -0,0 +1,28 @@ +// Test this without pch, template will be instantiated. +// RUN: %clang_cc1 -fsyntax-only %s -verify=expected + +// Test with pch, template will be instantiated in the TU. +// RUN: %clang_cc1 -emit-pch -o %t %s -verify=ok +// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -verify=expected + +// Test with pch with template instantiation in the pch. +// RUN: %clang_cc1 -emit-pch -fpch-instantiate-templates -o %t %s -verify=expected + +// ok-no-diagnostics + +#ifndef HEADER_H +#define HEADER_H + +template +struct A { + T foo() const { return "test"; } // @18 +}; + +double bar(A *a) { + return a->foo(); // @22 +} + +#endif + +// expected-error@18 {{cannot initialize return object}} +// expected-note@22 {{in instantiation of member function}} diff --git a/clang/test/PCH/pr18806.cpp b/clang/test/PCH/pr18806.cpp index c28320d..28ceb82 100644 --- a/clang/test/PCH/pr18806.cpp +++ b/clang/test/PCH/pr18806.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++11 -emit-pch -o %t %s // RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s +// RUN: %clang_cc1 -std=c++11 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s + // expected-no-diagnostics // Before the patch, this test triggered an assert violation in diff --git a/clang/test/PCH/pragma-diag-section.cpp b/clang/test/PCH/pragma-diag-section.cpp index eea6bd7..7f72f3c 100644 --- a/clang/test/PCH/pragma-diag-section.cpp +++ b/clang/test/PCH/pragma-diag-section.cpp @@ -5,6 +5,9 @@ // RUN: %clang_cc1 %s -emit-pch -o %t // RUN: %clang_cc1 %s -include-pch %t -verify -fsyntax-only -Wuninitialized +// RUN: %clang_cc1 %s -emit-pch -fpch-instantiate-templates -o %t +// RUN: %clang_cc1 %s -include-pch %t -verify -fsyntax-only -Wuninitialized + #ifndef HEADER #define HEADER @@ -27,8 +30,8 @@ struct TS2 { void m() { T a; T b = a; // expected-warning {{variable 'a' is uninitialized}} \ - expected-note@41 {{in instantiation of member function}} \ - expected-note@28 {{initialize the variable 'a' to silence}} + expected-note@44 {{in instantiation of member function}} \ + expected-note@31 {{initialize the variable 'a' to silence}} } }; diff --git a/clang/test/PCH/rdar10830559.cpp b/clang/test/PCH/rdar10830559.cpp index aa19da4..0144f34 100644 --- a/clang/test/PCH/rdar10830559.cpp +++ b/clang/test/PCH/rdar10830559.cpp @@ -6,6 +6,9 @@ // RUN: %clang_cc1 -emit-pch -o %t %s // RUN: %clang_cc1 -include-pch %t -emit-llvm-only %t.empty.cpp +// RUN: %clang_cc1 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -include-pch %t -emit-llvm-only %t.empty.cpp + // rdar://10830559 //#pragma ms_struct on diff --git a/clang/test/PCH/specialization-after-instantiation.cpp b/clang/test/PCH/specialization-after-instantiation.cpp new file mode 100644 index 0000000..a10a075 --- /dev/null +++ b/clang/test/PCH/specialization-after-instantiation.cpp @@ -0,0 +1,32 @@ +// Test this without pch. +// RUN: %clang_cc1 -fsyntax-only -verify -DBODY %s + +// Test with pch. +// RUN: %clang_cc1 -emit-pch -o %t %s +// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify -DBODY %s + +// RUN: %clang_cc1 -emit-pch -fpch-instantiate-templates -o %t %s +// RUN: %clang_cc1 -include-pch %t -fsyntax-only -verify -DBODY %s + +#ifndef HEADER_H +#define HEADER_H + +template +struct A { + int foo() const; +}; + +int bar(A *a) { + return a->foo(); +} + +#endif // HEADER_H + +#ifdef BODY + +template <> +int A::foo() const { // expected-error {{explicit specialization of 'foo' after instantiation}} // expected-note@20 {{implicit instantiation first required here}} + return 10; +} + +#endif // BODY diff --git a/clang/test/PCH/type_pack_element.cpp b/clang/test/PCH/type_pack_element.cpp index c4ed6c8..9d1106bf 100644 --- a/clang/test/PCH/type_pack_element.cpp +++ b/clang/test/PCH/type_pack_element.cpp @@ -1,6 +1,9 @@ // RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -o %t.pch // RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch +// RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -fpch-instantiate-templates -o %t.pch +// RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch + template struct X { }; -- 2.7.4