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")
def fno_pch_validate_input_files_content:
Flag <["-"], "fno_pch-validate-input-files-content">,
Group<f_Group>, Flags<[DriverOption]>;
+def fpch_instantiate_templates:
+ Flag <["-"], "fpch-instantiate-templates">,
+ Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Instantiate templates already while building a PCH">;
+def fno_pch_instantiate_templates:
+ Flag <["-"], "fno-pch-instantiate-templates">,
+ Group<f_Group>, Flags<[CC1Option]>;
def fmodules : Flag <["-"], "fmodules">, Group<f_Group>,
Flags<[DriverOption, CC1Option]>,
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:
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();
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);
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);
LateParsedInstantiations.begin(),
LateParsedInstantiations.end());
LateParsedInstantiations.clear();
+
+ if (LangOpts.PCHInstantiateTemplates) {
+ llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
+ PerformPendingInstantiations();
+ }
}
DiagnoseUnterminatedPragmaPack();
/// Performs template instantiation for all implicit template
/// instantiations we have seen until this point.
void Sema::PerformPendingInstantiations(bool LocalOnly) {
+ std::deque<PendingImplicitInstantiation> delayedPCHInstantiations;
while (!PendingLocalImplicitInstantiations.empty() ||
(!LocalOnly && !PendingInstantiations.empty())) {
PendingImplicitInstantiation Inst;
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;
}
InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true,
DefinitionRequired, true);
}
+
+ if (!LocalOnly && LangOpts.PCHInstantiateTemplates)
+ PendingInstantiations.swap(delayedPCHInstantiations);
}
void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
// 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
// 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<S>;
C<A>::A<char> a;
// 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
// 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 {};
// 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
// 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
// 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 {
// 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
// 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
#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;
// 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
// 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
// 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
// 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
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; };
// 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
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, "");
// 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
int k1 = (int)S<int>::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<char>::E::e;
#endif
// 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
// 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
// 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
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
// 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
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
// 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)
// 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
// 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
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}}
}
// 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
namespace diff_types {
#ifdef ERROR
- template<typename T> extern T err0; // expected-error {{redeclaration of 'err0' with a different type: 'T' vs 'float'}} // expected-note@42 {{previous declaration is here}}
- template<typename T> extern float err1; // expected-error {{redeclaration of 'err1' with a different type: 'float' vs 'T'}} // expected-note@43 {{previous declaration is here}}
+ template<typename T> extern T err0; // expected-error {{redeclaration of 'err0' with a different type: 'T' vs 'float'}} // expected-note@46 {{previous declaration is here}}
+ template<typename T> extern float err1; // expected-error {{redeclaration of 'err1' with a different type: 'float' vs 'T'}} // expected-note@47 {{previous declaration is here}}
#endif
template<typename T> extern T def;
}
// 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
// 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
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
// 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
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}}
}
// 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
// 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
// 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
//
// 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
// 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<typename T>
concept C = true;
// 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
--- /dev/null
+// 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 <int N>
+ void bar();
+};
+#endif
+
+#ifdef BODY
+// But the definition is only in the source, so the instantiation must be delayed until the TU.
+template <int N>
+void A::bar() {}
+
+void test(A *a) { a->foo(); }
+#endif
+
+// CHECK: define linkonce_odr void @_ZN1A3barILi0EEEvv
// 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
// 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;
// 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
// 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<int>();
static int 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
+// 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<typename T>
void *f() {
- void *p; // @11
- return p; // @12
+ void *p; // @15
+ return p; // @16
}
#undef NULL
template<typename T>
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<int>(); // expected-note {{instantiation}}
// 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 <class T, T... I>
struct Seq {
static constexpr T PackSize = sizeof...(I);
// 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<typename T>
};
template void f(HasFoo); // expected-note{{in instantiation of function template specialization 'f<HasFoo>' 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
--- /dev/null
+// 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 <typename T>
+void f();
+struct X; // @16
+void g() { f<X>(); } // @17 instantiation not performed yet
+
+template <typename T>
+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}}
--- /dev/null
+// 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 <typename T>
+struct A {
+ T foo() const { return "test"; } // @18
+};
+
+double bar(A<double> *a) {
+ return a->foo(); // @22
+}
+
+#endif
+
+// expected-error@18 {{cannot initialize return object}}
+// expected-note@22 {{in instantiation of member function}}
// 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
// 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
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}}
}
};
// 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
--- /dev/null
+// 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 <typename T>
+struct A {
+ int foo() const;
+};
+
+int bar(A<double> *a) {
+ return a->foo();
+}
+
+#endif // HEADER_H
+
+#ifdef BODY
+
+template <>
+int A<double>::foo() const { // expected-error {{explicit specialization of 'foo' after instantiation}} // expected-note@20 {{implicit instantiation first required here}}
+ return 10;
+}
+
+#endif // BODY
// 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 <int i>
struct X { };