This revision was automatically updated to reflect the committed changes.
Closed by commit rGa45f713c6730: add option to instantiate templates already in 
the PCH (authored by llunak).

Changed prior to commit:
  https://reviews.llvm.org/D69585?vs=265918&id=272312#toc

Repository:
  rG LLVM Github Monorepo

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/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/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5926,6 +5926,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;
@@ -5956,6 +5957,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;
     }
 
@@ -6001,6 +6006,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
@@ -1010,6 +1010,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
@@ -3370,6 +3370,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.MatrixTypes = Args.hasArg(OPT_fenable_matrix);
 
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -1241,6 +1241,7 @@
     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 @@
   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
@@ -8804,9 +8804,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
@@ -1420,6 +1420,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
@@ -165,6 +165,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

Reply via email to