llunak updated this revision to Diff 258605.
llunak retitled this revision from "PerformPendingInstatiations() already in 
the PCH" to "Add option to instantiate templates already in the PCH".
llunak edited the summary of this revision.
llunak added a comment.

Changed to use -fpch-instantiate-templates to control the feature.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69585/new/

https://reviews.llvm.org/D69585

Files:
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/PCH/codegen.cpp
  clang/test/PCH/crash-12631281.cpp
  clang/test/PCH/cxx-alias-decl.cpp
  clang/test/PCH/cxx-dependent-sized-ext-vector.cpp
  clang/test/PCH/cxx-explicit-specifier.cpp
  clang/test/PCH/cxx-exprs.cpp
  clang/test/PCH/cxx-friends.cpp
  clang/test/PCH/cxx-member-init.cpp
  clang/test/PCH/cxx-ms-function-specialization-class-scope.cpp
  clang/test/PCH/cxx-static_assert.cpp
  clang/test/PCH/cxx-templates.cpp
  clang/test/PCH/cxx-variadic-templates-with-default-params.cpp
  clang/test/PCH/cxx-variadic-templates.cpp
  clang/test/PCH/cxx0x-default-delete.cpp
  clang/test/PCH/cxx11-constexpr.cpp
  clang/test/PCH/cxx11-enum-template.cpp
  clang/test/PCH/cxx11-exception-spec.cpp
  clang/test/PCH/cxx11-inheriting-ctors.cpp
  clang/test/PCH/cxx11-user-defined-literals.cpp
  clang/test/PCH/cxx1y-decltype-auto.cpp
  clang/test/PCH/cxx1y-deduced-return-type.cpp
  clang/test/PCH/cxx1y-default-initializer.cpp
  clang/test/PCH/cxx1y-init-captures.cpp
  clang/test/PCH/cxx1y-variable-templates.cpp
  clang/test/PCH/cxx1z-aligned-alloc.cpp
  clang/test/PCH/cxx1z-decomposition.cpp
  clang/test/PCH/cxx1z-using-declaration.cpp
  clang/test/PCH/cxx2a-bitfield-init.cpp
  clang/test/PCH/cxx2a-concept-specialization-expr.cpp
  clang/test/PCH/cxx2a-constraints.cpp
  clang/test/PCH/cxx2a-defaulted-comparison.cpp
  clang/test/PCH/cxx2a-requires-expr.cpp
  clang/test/PCH/cxx2a-template-lambdas.cpp
  clang/test/PCH/delayed-pch-instantiate.cpp
  clang/test/PCH/friend-template.cpp
  clang/test/PCH/implicitly-deleted.cpp
  clang/test/PCH/late-parsed-instantiations.cpp
  clang/test/PCH/local_static.cpp
  clang/test/PCH/macro-undef.cpp
  clang/test/PCH/make-integer-seq.cpp
  clang/test/PCH/ms-if-exists.cpp
  clang/test/PCH/pch-instantiate-templates-forward-decl.cpp
  clang/test/PCH/pch-instantiate-templates.cpp
  clang/test/PCH/pr18806.cpp
  clang/test/PCH/pragma-diag-section.cpp
  clang/test/PCH/rdar10830559.cpp
  clang/test/PCH/specialization-after-instantiation.cpp
  clang/test/PCH/type_pack_element.cpp

Index: clang/test/PCH/type_pack_element.cpp
===================================================================
--- clang/test/PCH/type_pack_element.cpp
+++ 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 <int i>
 struct X { };
 
Index: clang/test/PCH/specialization-after-instantiation.cpp
===================================================================
--- /dev/null
+++ 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 <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
Index: clang/test/PCH/rdar10830559.cpp
===================================================================
--- clang/test/PCH/rdar10830559.cpp
+++ 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
Index: clang/test/PCH/pragma-diag-section.cpp
===================================================================
--- clang/test/PCH/pragma-diag-section.cpp
+++ 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 @@
     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}}
     }
 };
 
Index: clang/test/PCH/pr18806.cpp
===================================================================
--- clang/test/PCH/pr18806.cpp
+++ 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
Index: clang/test/PCH/pch-instantiate-templates.cpp
===================================================================
--- /dev/null
+++ 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 <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}}
Index: clang/test/PCH/pch-instantiate-templates-forward-decl.cpp
===================================================================
--- /dev/null
+++ 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 <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}}
Index: clang/test/PCH/ms-if-exists.cpp
===================================================================
--- clang/test/PCH/ms-if-exists.cpp
+++ 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<typename T>
@@ -25,6 +28,6 @@
 };
 
 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
Index: clang/test/PCH/make-integer-seq.cpp
===================================================================
--- clang/test/PCH/make-integer-seq.cpp
+++ 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 <class T, T... I>
 struct Seq {
     static constexpr T PackSize = sizeof...(I);
Index: clang/test/PCH/macro-undef.cpp
===================================================================
--- clang/test/PCH/macro-undef.cpp
+++ 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<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}}
Index: clang/test/PCH/local_static.cpp
===================================================================
--- clang/test/PCH/local_static.cpp
+++ 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<int>();
   static int s;
Index: clang/test/PCH/late-parsed-instantiations.cpp
===================================================================
--- clang/test/PCH/late-parsed-instantiations.cpp
+++ 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
Index: clang/test/PCH/implicitly-deleted.cpp
===================================================================
--- clang/test/PCH/implicitly-deleted.cpp
+++ 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;
Index: clang/test/PCH/friend-template.cpp
===================================================================
--- clang/test/PCH/friend-template.cpp
+++ 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
Index: clang/test/PCH/delayed-pch-instantiate.cpp
===================================================================
--- /dev/null
+++ 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 <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
Index: clang/test/PCH/cxx2a-template-lambdas.cpp
===================================================================
--- clang/test/PCH/cxx2a-template-lambdas.cpp
+++ 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
Index: clang/test/PCH/cxx2a-requires-expr.cpp
===================================================================
--- clang/test/PCH/cxx2a-requires-expr.cpp
+++ 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<typename T>
 concept C = true;
 
Index: clang/test/PCH/cxx2a-defaulted-comparison.cpp
===================================================================
--- clang/test/PCH/cxx2a-defaulted-comparison.cpp
+++ 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
 
Index: clang/test/PCH/cxx2a-constraints.cpp
===================================================================
--- clang/test/PCH/cxx2a-constraints.cpp
+++ 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
Index: clang/test/PCH/cxx2a-concept-specialization-expr.cpp
===================================================================
--- clang/test/PCH/cxx2a-concept-specialization-expr.cpp
+++ 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
Index: clang/test/PCH/cxx2a-bitfield-init.cpp
===================================================================
--- clang/test/PCH/cxx2a-bitfield-init.cpp
+++ 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
Index: clang/test/PCH/cxx1z-using-declaration.cpp
===================================================================
--- clang/test/PCH/cxx1z-using-declaration.cpp
+++ 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 @@
   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}}
 }
 
Index: clang/test/PCH/cxx1z-decomposition.cpp
===================================================================
--- clang/test/PCH/cxx1z-decomposition.cpp
+++ 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 @@
 
 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
Index: clang/test/PCH/cxx1z-aligned-alloc.cpp
===================================================================
--- clang/test/PCH/cxx1z-aligned-alloc.cpp
+++ 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
Index: clang/test/PCH/cxx1y-variable-templates.cpp
===================================================================
--- clang/test/PCH/cxx1y-variable-templates.cpp
+++ 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 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;
   }
Index: clang/test/PCH/cxx1y-init-captures.cpp
===================================================================
--- clang/test/PCH/cxx1y-init-captures.cpp
+++ 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 @@
 
 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}}
 }
 
Index: clang/test/PCH/cxx1y-default-initializer.cpp
===================================================================
--- clang/test/PCH/cxx1y-default-initializer.cpp
+++ 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
 
Index: clang/test/PCH/cxx1y-deduced-return-type.cpp
===================================================================
--- clang/test/PCH/cxx1y-deduced-return-type.cpp
+++ 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)
Index: clang/test/PCH/cxx1y-decltype-auto.cpp
===================================================================
--- clang/test/PCH/cxx1y-decltype-auto.cpp
+++ 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 @@
   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
Index: clang/test/PCH/cxx11-user-defined-literals.cpp
===================================================================
--- clang/test/PCH/cxx11-user-defined-literals.cpp
+++ 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 *l = f(&k);
 struct S {};
 int m = f(S()); // expected-error {{no matching}}
-                // expected-note@11 {{substitution failure}}
+                // expected-note@14 {{substitution failure}}
 
 #endif
Index: clang/test/PCH/cxx11-inheriting-ctors.cpp
===================================================================
--- clang/test/PCH/cxx11-inheriting-ctors.cpp
+++ 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
Index: clang/test/PCH/cxx11-exception-spec.cpp
===================================================================
--- clang/test/PCH/cxx11-exception-spec.cpp
+++ 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
Index: clang/test/PCH/cxx11-enum-template.cpp
===================================================================
--- clang/test/PCH/cxx11-enum-template.cpp
+++ 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 @@
 
 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
Index: clang/test/PCH/cxx11-constexpr.cpp
===================================================================
--- clang/test/PCH/cxx11-constexpr.cpp
+++ 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 @@
 
 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, "");
 
Index: clang/test/PCH/cxx0x-default-delete.cpp
===================================================================
--- clang/test/PCH/cxx0x-default-delete.cpp
+++ 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 @@
 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; };
Index: clang/test/PCH/cxx-variadic-templates.cpp
===================================================================
--- clang/test/PCH/cxx-variadic-templates.cpp
+++ 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
Index: clang/test/PCH/cxx-variadic-templates-with-default-params.cpp
===================================================================
--- clang/test/PCH/cxx-variadic-templates-with-default-params.cpp
+++ 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
Index: clang/test/PCH/cxx-templates.cpp
===================================================================
--- clang/test/PCH/cxx-templates.cpp
+++ 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
 
Index: clang/test/PCH/cxx-static_assert.cpp
===================================================================
--- clang/test/PCH/cxx-static_assert.cpp
+++ 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 @@
 
 #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;
 
Index: clang/test/PCH/cxx-ms-function-specialization-class-scope.cpp
===================================================================
--- clang/test/PCH/cxx-ms-function-specialization-class-scope.cpp
+++ 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
 
 
Index: clang/test/PCH/cxx-member-init.cpp
===================================================================
--- clang/test/PCH/cxx-member-init.cpp
+++ 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 {
Index: clang/test/PCH/cxx-friends.cpp
===================================================================
--- clang/test/PCH/cxx-friends.cpp
+++ 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
Index: clang/test/PCH/cxx-exprs.cpp
===================================================================
--- clang/test/PCH/cxx-exprs.cpp
+++ 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
Index: clang/test/PCH/cxx-explicit-specifier.cpp
===================================================================
--- clang/test/PCH/cxx-explicit-specifier.cpp
+++ 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 {};
Index: clang/test/PCH/cxx-dependent-sized-ext-vector.cpp
===================================================================
--- clang/test/PCH/cxx-dependent-sized-ext-vector.cpp
+++ 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
Index: clang/test/PCH/cxx-alias-decl.cpp
===================================================================
--- clang/test/PCH/cxx-alias-decl.cpp
+++ 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<S>;
 C<A>::A<char> a;
 
Index: clang/test/PCH/crash-12631281.cpp
===================================================================
--- clang/test/PCH/crash-12631281.cpp
+++ 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
Index: clang/test/PCH/codegen.cpp
===================================================================
--- clang/test/PCH/codegen.cpp
+++ clang/test/PCH/codegen.cpp
@@ -15,6 +15,18 @@
 // 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
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5920,6 +5920,7 @@
 /// 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;
@@ -5950,6 +5951,10 @@
         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;
     }
 
@@ -5995,6 +6000,9 @@
     InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true,
                                   DefinitionRequired, true);
   }
+
+  if (!LocalOnly && LangOpts.PCHInstantiateTemplates)
+    PendingInstantiations.swap(delayedPCHInstantiations);
 }
 
 void Sema::PerformDependentDiagnostics(const DeclContext *Pattern,
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -1009,6 +1009,11 @@
                                  LateParsedInstantiations.begin(),
                                  LateParsedInstantiations.end());
     LateParsedInstantiations.clear();
+
+    if (LangOpts.PCHInstantiateTemplates) {
+      llvm::TimeTraceScope TimeScope("PerformPendingInstantiations");
+      PerformPendingInstantiations();
+    }
   }
 
   DiagnoseUnterminatedPragmaPack();
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -3321,6 +3321,7 @@
 
   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.MaxTokens = getLastArgIntValue(Args, OPT_fmax_tokens_EQ, 0, Diags);
 
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -5606,6 +5606,9 @@
   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);
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -8782,9 +8782,17 @@
       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:
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1457,6 +1457,13 @@
 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]>,
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -164,6 +164,7 @@
 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")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D69585: Add option ... Luboš Luňák via Phabricator via cfe-commits

Reply via email to