sepavloff updated this revision to Diff 53853.
sepavloff added a comment.
Herald added a subscriber: klimek.

Updated patch

Get rid of '%qt' format, instead print template parameters always. It requires
about 10 tests to be fixed. However printing parameters still can be suppressed,
it is required for proper work of AST matchers, - a matcher may want to match
names like 'Y::f' where 'Y' is a template. Template parameters are printed as
they were written in template declarations.


http://reviews.llvm.org/D16396

Files:
  include/clang/AST/DeclBase.h
  include/clang/AST/PrettyPrinter.h
  include/clang/Basic/DiagnosticGroups.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/AST/Decl.cpp
  lib/AST/DeclBase.cpp
  lib/ASTMatchers/ASTMatchersInternal.cpp
  lib/Sema/SemaOverload.cpp
  lib/Sema/SemaTemplateInstantiateDecl.cpp
  test/CXX/temp/temp.decls/temp.mem/p1.cpp
  test/Modules/merge-using-decls.cpp
  test/OpenMP/parallel_ast_print.cpp
  test/OpenMP/parallel_sections_ast_print.cpp
  test/OpenMP/target_parallel_ast_print.cpp
  test/OpenMP/task_ast_print.cpp
  test/OpenMP/teams_ast_print.cpp
  test/OpenMP/threadprivate_ast_print.cpp
  test/SemaCXX/PR10177.cpp
  test/SemaCXX/dllexport.cpp
  test/SemaCXX/dllimport.cpp
  test/SemaCXX/undefined-internal.cpp
  test/SemaTemplate/undefined-template.cpp

Index: test/SemaTemplate/undefined-template.cpp
===================================================================
--- /dev/null
+++ test/SemaTemplate/undefined-template.cpp
@@ -0,0 +1,139 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -Wundefined-func-template %s
+
+template <class T> struct C1 {
+  static char s_var_1;
+  static char s_var_2;
+  static void s_func_1();
+  static void s_func_2();
+  void meth_1();
+  void meth_2();
+  template <class T1> static char s_tvar_2;
+  template <class T1> static void s_tfunc_2();
+  template<typename T1> struct C2 {
+    static char s_var_2;
+    static void s_func_2();
+    void meth_2();
+    template <class T2> static char s_tvar_2;
+    template <class T2> void tmeth_2();
+  };
+};
+
+extern template char C1<int>::s_var_2;
+extern template void C1<int>::s_func_2();
+extern template void C1<int>::meth_2();
+extern template char C1<int>::s_tvar_2<char>;
+extern template void C1<int>::s_tfunc_2<char>();
+extern template void C1<int>::C2<long>::s_var_2;
+extern template void C1<int>::C2<long>::s_func_2();
+extern template void C1<int>::C2<long>::meth_2();
+extern template char C1<int>::C2<long>::s_tvar_2<char>;
+extern template void C1<int>::C2<long>::tmeth_2<char>();
+
+char func_01() {
+  return C1<int>::s_var_2;
+}
+
+char func_02() {
+  return C1<int>::s_var_1; // expected-warning{{instantiation of variable 'C1<int>::s_var_1' required here, but 'C1<T>::s_var_1' is not defined}}
+                           // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_var_1' is explicitly instantiated in another translation unit}}
+}
+
+char func_03() {
+  return C1<char>::s_var_2; // expected-warning{{instantiation of variable 'C1<char>::s_var_2' required here, but 'C1<T>::s_var_2' is not defined}}
+                            // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::s_var_2' is explicitly instantiated in another translation unit}}
+}
+
+void func_04() {
+  C1<int>::s_func_1(); // expected-warning{{instantiation of function 'C1<int>::s_func_1' required here, but 'C1<T>::s_func_1' is not defined}}
+                       // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_func_1' is explicitly instantiated in another translation unit}}
+}
+
+void func_05() {
+  C1<int>::s_func_2();
+}
+
+void func_06() {
+  C1<char>::s_func_2(); // expected-warning{{instantiation of function 'C1<char>::s_func_2' required here, but 'C1<T>::s_func_2' is not defined}}
+                        // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::s_func_2' is explicitly instantiated in another translation unit}}
+}
+
+void func_07(C1<int> *x) {
+  x->meth_1();  // expected-warning{{instantiation of function 'C1<int>::meth_1' required here, but 'C1<T>::meth_1' is not defined}}
+                // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::meth_1' is explicitly instantiated in another translation unit}}
+}
+
+void func_08(C1<int> *x) {
+  x->meth_2();
+}
+
+void func_09(C1<char> *x) {
+  x->meth_1();  // expected-warning{{instantiation of function 'C1<char>::meth_1' required here, but 'C1<T>::meth_1' is not defined}}
+                // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::meth_1' is explicitly instantiated in another translation unit}}
+}
+
+char func_10() {
+  return C1<int>::s_tvar_2<char>;
+}
+
+char func_11() {
+  return C1<int>::s_tvar_2<long>; // expected-warning{{instantiation of variable 'C1<int>::s_tvar_2<long>' required here, but 'C1<T>::s_tvar_2<T1>' is not defined}}
+                                  // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_tvar_2<long>' is explicitly instantiated in another translation unit}}
+}
+
+void func_12() {
+  C1<int>::s_tfunc_2<char>();
+}
+
+void func_13() {
+  C1<int>::s_tfunc_2<long>(); // expected-warning{{instantiation of function 'C1<int>::s_tfunc_2<long>' required here, but 'C1<T>::s_tfunc_2<T1>' is not defined}}
+                              // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_tfunc_2<long>' is explicitly instantiated in another translation unit}}
+}
+
+char func_14() {
+  return C1<int>::C2<long>::s_var_2;
+}
+
+char func_15() {
+  return C1<int>::C2<char>::s_var_2;  //expected-warning {{instantiation of variable 'C1<int>::C2<char>::s_var_2' required here, but 'C1<T>::C2<T1>::s_var_2' is not defined}}
+                                      // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::s_var_2' is explicitly instantiated in another translation unit}}
+}
+
+void func_16() {
+  C1<int>::C2<long>::s_func_2();
+}
+
+void func_17() {
+  C1<int>::C2<char>::s_func_2(); // expected-warning{{instantiation of function 'C1<int>::C2<char>::s_func_2' required here, but 'C1<T>::C2<T1>::s_func_2' is not defined}}
+                        // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::s_func_2' is explicitly instantiated in another translation unit}}
+}
+
+void func_18(C1<int>::C2<long> *x) {
+  x->meth_2();
+}
+
+void func_19(C1<int>::C2<char> *x) {
+  x->meth_2();   // expected-warning{{instantiation of function 'C1<int>::C2<char>::meth_2' required here, but 'C1<T>::C2<T1>::meth_2' is not defined}}
+                        // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::meth_2' is explicitly instantiated in another translation unit}}
+}
+
+char func_20() {
+  return C1<int>::C2<long>::s_tvar_2<char>;
+}
+
+char func_21() {
+  return C1<int>::C2<long>::s_tvar_2<long>; // expected-warning{{instantiation of variable 'C1<int>::C2<long>::s_tvar_2<long>' required here, but 'C1<T>::C2<T1>::s_tvar_2<T2>' is not defined}}
+                                  // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<long>::s_tvar_2<long>' is explicitly instantiated in another translation unit}}
+}
+
+void func_22(C1<int>::C2<long> *x) {
+  x->tmeth_2<char>();
+}
+
+void func_23(C1<int>::C2<long> *x) {
+  x->tmeth_2<int>();    // expected-warning{{instantiation of function 'C1<int>::C2<long>::tmeth_2<int>' required here, but 'C1<T>::C2<T1>::tmeth_2<T2>' is not defined}}
+                        // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<long>::tmeth_2<int>' is explicitly instantiated in another translation unit}}
+}
+
+int main() {
+  return 0;
+}
Index: test/SemaCXX/undefined-internal.cpp
===================================================================
--- test/SemaCXX/undefined-internal.cpp
+++ test/SemaCXX/undefined-internal.cpp
@@ -82,6 +82,7 @@
     static int var; // expected-warning {{variable 'test5::B<test5::(anonymous namespace)::A>::var' has internal linkage but is not defined}}
     static void foo(); // expected-warning {{function 'test5::B<test5::(anonymous namespace)::A>::foo' has internal linkage but is not defined}}
   };
+  extern template int B<A>::var;
 
   void test() {
     B<A>::var = 0; // expected-note {{used here}}
Index: test/SemaCXX/dllimport.cpp
===================================================================
--- test/SemaCXX/dllimport.cpp
+++ test/SemaCXX/dllimport.cpp
@@ -136,10 +136,10 @@
 
 // Declare, then reject definition.
 template<typename T> __declspec(dllimport) extern int ExternVarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-template<typename T>                              int ExternVarTmplDeclInit = 1; // expected-warning{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>                              int ExternVarTmplDeclInit = 1; // expected-warning{{'ExternVarTmplDeclInit<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 
 template<typename T> __declspec(dllimport) int VarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-template<typename T>                       int VarTmplDeclInit = 1; // expected-warning{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>                       int VarTmplDeclInit = 1; // expected-warning{{'VarTmplDeclInit<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 
 // Redeclarations
 template<typename T> __declspec(dllimport) extern int VarTmplRedecl1;
@@ -149,18 +149,18 @@
 template<typename T> __declspec(dllimport) int VarTmplRedecl2;
 
 template<typename T> __declspec(dllimport) extern int VarTmplRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-template<typename T>                       extern int VarTmplRedecl3; // expected-warning{{'VarTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>                       extern int VarTmplRedecl3; // expected-warning{{'VarTmplRedecl3<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 
 template<typename T>                       extern int VarTmplRedecl4; // expected-note{{previous declaration is here}}
-template<typename T> __declspec(dllimport) extern int VarTmplRedecl4; // expected-error{{redeclaration of 'VarTmplRedecl4' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) extern int VarTmplRedecl4; // expected-error{{redeclaration of 'VarTmplRedecl4<T>' cannot add 'dllimport' attribute}}
 
 // External linkage is required.
-template<typename T> __declspec(dllimport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllimport'}}
-template<typename T> __declspec(dllimport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllimport'}}
-namespace    { template<typename T> __declspec(dllimport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllimport'}}
+template<typename T> __declspec(dllimport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl<T>' must have external linkage when declared 'dllimport'}}
+template<typename T> __declspec(dllimport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl<T>' must have external linkage when declared 'dllimport'}}
+namespace    { template<typename T> __declspec(dllimport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl<T>' must have external linkage when declared 'dllimport'}}
 namespace ns { template<typename T> __declspec(dllimport) int ExternalVarTmpl; }
 
-template<typename T> __declspec(dllimport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{definition of dllimport data}} // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllimport'}}
+template<typename T> __declspec(dllimport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{definition of dllimport data}} // expected-error{{'InternalAutoTypeVarTmpl<T>' must have external linkage when declared 'dllimport'}}
 
 
 template<typename T> int VarTmpl;
@@ -329,7 +329,7 @@
 // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
 // expected-warning@+5{{'dllimport' attribute ignored on inline function}}
 // expected-warning@+6{{'dllimport' attribute ignored on inline function}}
-// expected-warning@+9{{'inlineFuncTmplDef' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+9{{'inlineFuncTmplDef<T>' redeclared inline; 'dllimport' attribute ignored}}
 #endif
 template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {}
 template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {}
@@ -345,17 +345,17 @@
 template<typename T> __declspec(dllimport) void funcTmplRedecl1();
 
 template<typename T> __declspec(dllimport) void funcTmplRedecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-template<typename T>                       void funcTmplRedecl2(); // expected-warning{{'funcTmplRedecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>                       void funcTmplRedecl2(); // expected-warning{{'funcTmplRedecl2<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 
 template<typename T> __declspec(dllimport) void funcTmplRedecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
-template<typename T>                       void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>                       void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 
 template<typename T>                       void funcTmplRedecl4(); // expected-note{{previous declaration is here}}
-template<typename T> __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4<T>' cannot add 'dllimport' attribute}}
 
 #ifdef MS
 template<typename T>                       void funcTmplRedecl5(); // expected-note{{previous declaration is here}}
-template<typename T> __declspec(dllimport) inline void funcTmplRedecl5() {} // expected-error{{redeclaration of 'funcTmplRedecl5' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) inline void funcTmplRedecl5() {} // expected-error{{redeclaration of 'funcTmplRedecl5<T>' cannot add 'dllimport' attribute}}
 #endif
 
 // Function template friends
@@ -370,15 +370,15 @@
   template<typename T> friend __declspec(dllimport) inline void funcTmplFriend5();
 };
 template<typename T> __declspec(dllimport) void funcTmplFriend1();
-template<typename T>                       void funcTmplFriend2(); // expected-warning{{'funcTmplFriend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-template<typename T>                       void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
-template<typename T> __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllimport' attribute}}
+template<typename T>                       void funcTmplFriend2(); // expected-warning{{'funcTmplFriend2<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>                       void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4<T>' cannot add 'dllimport' attribute}}
 template<typename T>                       inline void funcTmplFriend5() {}
 
 // External linkage is required.
-template<typename T> __declspec(dllimport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllimport'}}
-template<typename T> __declspec(dllimport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllimport'}}
-namespace    { template<typename T> __declspec(dllimport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllimport'}}
+template<typename T> __declspec(dllimport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl<T>' must have external linkage when declared 'dllimport'}}
+template<typename T> __declspec(dllimport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl<T>' must have external linkage when declared 'dllimport'}}
+namespace    { template<typename T> __declspec(dllimport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl<T>' must have external linkage when declared 'dllimport'}}
 namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl(); }
 
 
@@ -743,14 +743,14 @@
 #endif // __has_feature(cxx_variable_templates)
 };
 
-template<typename T>        void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>        void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 template<typename T>        void ImportMemberTmpl::normalInlineDecl() {}
-template<typename T>        void ImportMemberTmpl::staticDef() {} // expected-warning{{'ImportMemberTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>        void ImportMemberTmpl::staticDef() {} // expected-warning{{'ImportMemberTmpl::staticDef<T>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 template<typename T>        void ImportMemberTmpl::staticInlineDecl() {}
 
 #ifdef GNU
-// expected-warning@+3{{ImportMemberTmpl::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
-// expected-warning@+3{{ImportMemberTmpl::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+3{{ImportMemberTmpl::normalInlineDef<T>' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+3{{ImportMemberTmpl::staticInlineDef<T>' redeclared inline; 'dllimport' attribute ignored}}
 #endif
 template<typename T> inline void ImportMemberTmpl::normalInlineDef() {}
 template<typename T> inline void ImportMemberTmpl::staticInlineDef() {}
@@ -783,31 +783,31 @@
 #endif // __has_feature(cxx_variable_templates)
 };
 
-template<typename T> __declspec(dllimport)        void MemTmplRedecl::normalDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void MemTmplRedecl::normalDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::normalDef<T>' cannot add 'dllimport' attribute}}
                                                                                             // expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
 #ifdef MS
-template<typename T> __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef<T>' cannot add 'dllimport' attribute}}
 #else
 template<typename T> __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {}  // expected-warning{{'dllimport' attribute ignored on inline function}}
 #endif
-template<typename T> __declspec(dllimport)        void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllimport' attribute}}
-template<typename T> __declspec(dllimport)        void MemTmplRedecl::staticDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl<T>' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void MemTmplRedecl::staticDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::staticDef<T>' cannot add 'dllimport' attribute}}
                                                                                             // expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
 #ifdef MS
-template<typename T> __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef<T>' cannot add 'dllimport' attribute}}
 #else
 template<typename T> __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {}  // expected-warning{{'dllimport' attribute ignored on inline function}}
 #endif
-template<typename T> __declspec(dllimport)        void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl<T>' cannot add 'dllimport' attribute}}
 
 #if __has_feature(cxx_variable_templates)
-template<typename T> __declspec(dllimport)        int  MemTmplRedecl::StaticField = 1;      // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        int  MemTmplRedecl::StaticField = 1;      // expected-error{{redeclaration of 'MemTmplRedecl::StaticField<T>' cannot add 'dllimport' attribute}}
                                                                                             // expected-error@-1{{definition of dllimport static field not allowed}}
                                                                                             // expected-note@-2{{attribute is here}}
-template<typename T> __declspec(dllimport) const  int  MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) const  int  MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField<T>' cannot add 'dllimport' attribute}}
                                                                                             // expected-error@-1{{definition of dllimport static field not allowed}}
                                                                                             // expected-note@-2{{attribute is here}}
-template<typename T> __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField;     // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField;     // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField<T>' cannot add 'dllimport' attribute}}
                                                                                             // expected-error@-1{{definition of dllimport static field not allowed}}
                                                                                             // expected-note@-2{{attribute is here}}
 #endif // __has_feature(cxx_variable_templates)
@@ -1013,21 +1013,21 @@
 
 // NB: MSVC is inconsistent here and disallows *InlineDef on class templates,
 // but allows it on classes. We allow both.
-template<typename T>        void ImportClassTmplMembers<T>::normalDef() {} // expected-warning{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>        void ImportClassTmplMembers<T>::normalDef() {} // expected-warning{{'ImportClassTmplMembers<T>::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 #ifdef GNU
-// expected-warning@+2{{'ImportClassTmplMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+2{{'ImportClassTmplMembers<T>::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
 #endif
 template<typename T> inline void ImportClassTmplMembers<T>::normalInlineDef() {}
 template<typename T>        void ImportClassTmplMembers<T>::normalInlineDecl() {}
-template<typename T>        void ImportClassTmplMembers<T>::virtualDef() {} // expected-warning{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>        void ImportClassTmplMembers<T>::virtualDef() {} // expected-warning{{'ImportClassTmplMembers<T>::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 #ifdef GNU
-// expected-warning@+2{{'ImportClassTmplMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+2{{'ImportClassTmplMembers<T>::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}}
 #endif
 template<typename T> inline void ImportClassTmplMembers<T>::virtualInlineDef() {}
 template<typename T>        void ImportClassTmplMembers<T>::virtualInlineDecl() {}
-template<typename T>        void ImportClassTmplMembers<T>::staticDef() {} // expected-warning{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T>        void ImportClassTmplMembers<T>::staticDef() {} // expected-warning{{'ImportClassTmplMembers<T>::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 #ifdef GNU
-// expected-warning@+2{{'ImportClassTmplMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+2{{'ImportClassTmplMembers<T>::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
 #endif
 template<typename T> inline void ImportClassTmplMembers<T>::staticInlineDef() {}
 template<typename T>        void ImportClassTmplMembers<T>::staticInlineDecl() {}
@@ -1061,33 +1061,33 @@
   constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}}
 };
 
-template<typename T> __declspec(dllimport)        void CTMR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void CTMR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMR<T>::normalDef' cannot add 'dllimport' attribute}}
                                                                                        // expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> __declspec(dllimport)        void CTMR<T>::normalInlineDecl() {}  // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllimport' attribute}}
-template<typename T> __declspec(dllimport)        void CTMR<T>::virtualDef() {}        // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void CTMR<T>::normalInlineDecl() {}  // expected-error{{redeclaration of 'CTMR<T>::normalInlineDecl' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void CTMR<T>::virtualDef() {}        // expected-error{{redeclaration of 'CTMR<T>::virtualDef' cannot add 'dllimport' attribute}}
                                                                                        // expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> __declspec(dllimport)        void CTMR<T>::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllimport' attribute}}
-template<typename T> __declspec(dllimport)        void CTMR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void CTMR<T>::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR<T>::virtualInlineDecl' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void CTMR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMR<T>::staticDef' cannot add 'dllimport' attribute}}
                                                                                        // expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> __declspec(dllimport)        void CTMR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        void CTMR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMR<T>::staticInlineDecl' cannot add 'dllimport' attribute}}
 
 #ifdef MS
-template<typename T> __declspec(dllimport) inline void CTMR<T>::normalInlineDef() {}   // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllimport' attribute}}
-template<typename T> __declspec(dllimport) inline void CTMR<T>::virtualInlineDef() {}  // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllimport' attribute}}
-template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) inline void CTMR<T>::normalInlineDef() {}   // expected-error{{redeclaration of 'CTMR<T>::normalInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) inline void CTMR<T>::virtualInlineDef() {}  // expected-error{{redeclaration of 'CTMR<T>::virtualInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMR<T>::staticInlineDef' cannot add 'dllimport' attribute}}
 #else
 template<typename T> __declspec(dllimport) inline void CTMR<T>::normalInlineDef() {}   // expected-warning{{'dllimport' attribute ignored on inline function}}
 template<typename T> __declspec(dllimport) inline void CTMR<T>::virtualInlineDef() {}  // expected-warning{{'dllimport' attribute ignored on inline function}}
 template<typename T> __declspec(dllimport) inline void CTMR<T>::staticInlineDef() {}   // expected-warning{{'dllimport' attribute ignored on inline function}}
 #endif
 
-template<typename T> __declspec(dllimport)        int  CTMR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport)        int  CTMR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMR<T>::StaticField' cannot add 'dllimport' attribute}}
                                                                                        // expected-warning@-1{{definition of dllimport static field}}
                                                                                        // expected-note@-2{{attribute is here}}
-template<typename T> __declspec(dllimport) const  int  CTMR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) const  int  CTMR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMR<T>::StaticConstField' cannot add 'dllimport' attribute}}
                                                                                        // expected-warning@-1{{definition of dllimport static field}}
                                                                                        // expected-note@-2{{attribute is here}}
-template<typename T> __declspec(dllimport) constexpr int CTMR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllimport' attribute}}
+template<typename T> __declspec(dllimport) constexpr int CTMR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMR<T>::ConstexprField' cannot add 'dllimport' attribute}}
                                                                                        // expected-warning@-1{{definition of dllimport static field}}
                                                                                        // expected-note@-2{{attribute is here}}
 
@@ -1129,14 +1129,14 @@
 #endif // __has_feature(cxx_variable_templates)
 };
 
-template<typename T> template<typename U>        void ImportClsTmplMemTmpl<T>::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> template<typename U>        void ImportClsTmplMemTmpl<T>::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl<T>::normalDef<U>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 template<typename T> template<typename U>        void ImportClsTmplMemTmpl<T>::normalInlineDecl() {}
-template<typename T> template<typename U>        void ImportClsTmplMemTmpl<T>::staticDef() {} // expected-warning{{'ImportClsTmplMemTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+template<typename T> template<typename U>        void ImportClsTmplMemTmpl<T>::staticDef() {} // expected-warning{{'ImportClsTmplMemTmpl<T>::staticDef<U>' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 template<typename T> template<typename U>        void ImportClsTmplMemTmpl<T>::staticInlineDecl() {}
 
 #ifdef GNU
-// expected-warning@+3{{'ImportClsTmplMemTmpl::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}}
-// expected-warning@+3{{'ImportClsTmplMemTmpl::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+3{{'ImportClsTmplMemTmpl<T>::normalInlineDef<U>' redeclared inline; 'dllimport' attribute ignored}}
+// expected-warning@+3{{'ImportClsTmplMemTmpl<T>::staticInlineDef<U>' redeclared inline; 'dllimport' attribute ignored}}
 #endif
 template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::normalInlineDef() {}
 template<typename T> template<typename U> inline void ImportClsTmplMemTmpl<T>::staticInlineDef() {}
@@ -1170,29 +1170,29 @@
 #endif // __has_feature(cxx_variable_templates)
 };
 
-template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMTR<T>::normalDef<U>' cannot add 'dllimport' attribute}}
                                                                                                              // expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::normalInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllimport' attribute}}
-template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::normalInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR<T>::normalInlineDecl<U>' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMTR<T>::staticDef<U>' cannot add 'dllimport' attribute}}
                                                                                                              // expected-error@-1{{dllimport cannot be applied to non-inline function definition}}
-template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport)        void CTMTR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR<T>::staticInlineDecl<U>' cannot add 'dllimport' attribute}}
 
 #ifdef MS
-template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::normalInlineDef() {}   // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllimport' attribute}}
-template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::normalInlineDef() {}   // expected-error{{redeclaration of 'CTMTR<T>::normalInlineDef<U>' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMTR<T>::staticInlineDef<U>' cannot add 'dllimport' attribute}}
 #else
 template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::normalInlineDef() {}   // expected-warning{{'dllimport' attribute ignored on inline function}}
 template<typename T> template<typename U> __declspec(dllimport) inline void CTMTR<T>::staticInlineDef() {}   // expected-warning{{'dllimport' attribute ignored on inline function}}
 #endif
 
 #if __has_feature(cxx_variable_templates)
-template<typename T> template<typename U> __declspec(dllimport)        int  CTMTR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport)        int  CTMTR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMTR<T>::StaticField<U>' cannot add 'dllimport' attribute}}
                                                                                                              // expected-warning@-1{{definition of dllimport static field}}
                                                                                                              // expected-note@-2{{attribute is here}}
-template<typename T> template<typename U> __declspec(dllimport) const  int  CTMTR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport) const  int  CTMTR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMTR<T>::StaticConstField<U>' cannot add 'dllimport' attribute}}
                                                                                                              // expected-warning@-1{{definition of dllimport static field}}
                                                                                                              // expected-note@-2{{attribute is here}}
-template<typename T> template<typename U> __declspec(dllimport) constexpr int CTMTR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllimport' attribute}}
+template<typename T> template<typename U> __declspec(dllimport) constexpr int CTMTR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMTR<T>::ConstexprField<U>' cannot add 'dllimport' attribute}}
                                                                                                              // expected-warning@-1{{definition of dllimport static field}}
                                                                                                              // expected-note@-2{{attribute is here}}
 #endif // __has_feature(cxx_variable_templates)
Index: test/SemaCXX/dllexport.cpp
===================================================================
--- test/SemaCXX/dllexport.cpp
+++ test/SemaCXX/dllexport.cpp
@@ -113,15 +113,15 @@
 template<typename T>                              int VarTmplRedecl2 = 1;
 
 template<typename T>                       extern int VarTmplRedecl3; // expected-note{{previous declaration is here}}
-template<typename T> __declspec(dllexport) extern int VarTmplRedecl3; // expected-error{{redeclaration of 'VarTmplRedecl3' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) extern int VarTmplRedecl3; // expected-error{{redeclaration of 'VarTmplRedecl3<T>' cannot add 'dllexport' attribute}}
 
 // External linkage is required.
-template<typename T> __declspec(dllexport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllexport'}}
-template<typename T> __declspec(dllexport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllexport'}}
-namespace    { template<typename T> __declspec(dllexport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllexport'}}
+template<typename T> __declspec(dllexport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl<T>' must have external linkage when declared 'dllexport'}}
+template<typename T> __declspec(dllexport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl<T>' must have external linkage when declared 'dllexport'}}
+namespace    { template<typename T> __declspec(dllexport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl<T>' must have external linkage when declared 'dllexport'}}
 namespace ns { template<typename T> __declspec(dllexport) int ExternalVarTmpl = 1; }
 
-template<typename T> __declspec(dllexport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllexport'}}
+template<typename T> __declspec(dllexport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{'InternalAutoTypeVarTmpl<T>' must have external linkage when declared 'dllexport'}}
 template<typename T> __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External();
 template External ExternalAutoTypeVarTmpl<ExplicitInst_Exported>;
 
@@ -264,10 +264,10 @@
 template<typename T>                       void funcTmplRedecl2() {}
 
 template<typename T>                       void funcTmplRedecl3(); // expected-note{{previous declaration is here}}
-template<typename T> __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3<T>' cannot add 'dllexport' attribute}}
 
 template<typename T>                       void funcTmplRedecl4(); // expected-note{{previous declaration is here}}
-template<typename T> __declspec(dllexport) inline void funcTmplRedecl4() {} // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) inline void funcTmplRedecl4() {} // expected-error{{redeclaration of 'funcTmplRedecl4<T>' cannot add 'dllexport' attribute}}
 
 // Function template friends
 struct FuncTmplFriend {
@@ -278,13 +278,13 @@
 };
 template<typename T> __declspec(dllexport) void funcTmplFriend1() {}
 template<typename T>                       void funcTmplFriend2() {}
-template<typename T> __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) inline void funcTmplFriend4() {} // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3<T>' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) inline void funcTmplFriend4() {} // expected-error{{redeclaration of 'funcTmplFriend4<T>' cannot add 'dllexport' attribute}}
 
 // External linkage is required.
-template<typename T> __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllexport'}}
-template<typename T> __declspec(dllexport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllexport'}}
-namespace    { template<typename T> __declspec(dllexport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllexport'}}
+template<typename T> __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl<T>' must have external linkage when declared 'dllexport'}}
+template<typename T> __declspec(dllexport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl<T>' must have external linkage when declared 'dllexport'}}
+namespace    { template<typename T> __declspec(dllexport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl<T>' must have external linkage when declared 'dllexport'}}
 namespace ns { template<typename T> __declspec(dllexport) void externalFuncTmpl(); }
 
 
@@ -795,17 +795,17 @@
 #endif // __has_feature(cxx_variable_templates)
 };
 
-template<typename T> __declspec(dllexport)        void MemTmplRedecl::normalDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) inline void MemTmplRedecl::normalInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport)        void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport)        void MemTmplRedecl::staticDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) inline void MemTmplRedecl::staticInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport)        void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void MemTmplRedecl::normalDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::normalDef<T>' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) inline void MemTmplRedecl::normalInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef<T>' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl<T>' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void MemTmplRedecl::staticDef() {}        // expected-error{{redeclaration of 'MemTmplRedecl::staticDef<T>' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) inline void MemTmplRedecl::staticInlineDef() {}  // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef<T>' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl<T>' cannot add 'dllexport' attribute}}
 
 #if __has_feature(cxx_variable_templates)
-template<typename T> __declspec(dllexport)        int  MemTmplRedecl::StaticField = 1;      // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) const  int  MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField;     // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        int  MemTmplRedecl::StaticField = 1;      // expected-error{{redeclaration of 'MemTmplRedecl::StaticField<T>' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) const  int  MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField<T>' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField;     // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField<T>' cannot add 'dllexport' attribute}}
 #endif // __has_feature(cxx_variable_templates)
 
 
@@ -998,19 +998,19 @@
   constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}}
 };
 
-template<typename T> __declspec(dllexport)        void CTMR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) inline void CTMR<T>::normalInlineDef() {}   // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport)        void CTMR<T>::normalInlineDecl() {}  // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport)        void CTMR<T>::virtualDef() {}        // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) inline void CTMR<T>::virtualInlineDef() {}  // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport)        void CTMR<T>::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport)        void CTMR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) inline void CTMR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport)        void CTMR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void CTMR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMR<T>::normalDef' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) inline void CTMR<T>::normalInlineDef() {}   // expected-error{{redeclaration of 'CTMR<T>::normalInlineDef' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void CTMR<T>::normalInlineDecl() {}  // expected-error{{redeclaration of 'CTMR<T>::normalInlineDecl' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void CTMR<T>::virtualDef() {}        // expected-error{{redeclaration of 'CTMR<T>::virtualDef' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) inline void CTMR<T>::virtualInlineDef() {}  // expected-error{{redeclaration of 'CTMR<T>::virtualInlineDef' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void CTMR<T>::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR<T>::virtualInlineDecl' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void CTMR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMR<T>::staticDef' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) inline void CTMR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMR<T>::staticInlineDef' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        void CTMR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMR<T>::staticInlineDecl' cannot add 'dllexport' attribute}}
 
-template<typename T> __declspec(dllexport)        int  CTMR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) const  int  CTMR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllexport' attribute}}
-template<typename T> __declspec(dllexport) constexpr int CTMR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport)        int  CTMR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMR<T>::StaticField' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) const  int  CTMR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMR<T>::StaticConstField' cannot add 'dllexport' attribute}}
+template<typename T> __declspec(dllexport) constexpr int CTMR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMR<T>::ConstexprField' cannot add 'dllexport' attribute}}
 
 
 
@@ -1074,17 +1074,17 @@
 #endif // __has_feature(cxx_variable_templates)
 };
 
-template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllexport' attribute}}
-template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::normalInlineDef() {}   // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllexport' attribute}}
-template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::normalInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllexport' attribute}}
-template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllexport' attribute}}
-template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllexport' attribute}}
-template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::normalDef() {}         // expected-error{{redeclaration of 'CTMTR<T>::normalDef<U>' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::normalInlineDef() {}   // expected-error{{redeclaration of 'CTMTR<T>::normalInlineDef<U>' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::normalInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR<T>::normalInlineDecl<U>' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::staticDef() {}         // expected-error{{redeclaration of 'CTMTR<T>::staticDef<U>' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport) inline void CTMTR<T>::staticInlineDef() {}   // expected-error{{redeclaration of 'CTMTR<T>::staticInlineDef<U>' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport)        void CTMTR<T>::staticInlineDecl() {}  // expected-error{{redeclaration of 'CTMTR<T>::staticInlineDecl<U>' cannot add 'dllexport' attribute}}
 
 #if __has_feature(cxx_variable_templates)
-template<typename T> template<typename U> __declspec(dllexport)        int  CTMTR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllexport' attribute}}
-template<typename T> template<typename U> __declspec(dllexport) const  int  CTMTR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllexport' attribute}}
-template<typename T> template<typename U> __declspec(dllexport) constexpr int CTMTR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport)        int  CTMTR<T>::StaticField = 1;       // expected-error{{redeclaration of 'CTMTR<T>::StaticField<U>' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport) const  int  CTMTR<T>::StaticConstField = 1;  // expected-error{{redeclaration of 'CTMTR<T>::StaticConstField<U>' cannot add 'dllexport' attribute}}
+template<typename T> template<typename U> __declspec(dllexport) constexpr int CTMTR<T>::ConstexprField;      // expected-error{{redeclaration of 'CTMTR<T>::ConstexprField<U>' cannot add 'dllexport' attribute}}
 #endif // __has_feature(cxx_variable_templates)
 
 // FIXME: Precedence rules seem to be different for classes.
Index: test/SemaCXX/PR10177.cpp
===================================================================
--- test/SemaCXX/PR10177.cpp
+++ test/SemaCXX/PR10177.cpp
@@ -54,6 +54,7 @@
 
 namespace { template<typename> extern int n; }
 template<typename T> int g() { return n<int>; }
+namespace { extern template int n<int>; }
 
 #endif
 
Index: test/OpenMP/threadprivate_ast_print.cpp
===================================================================
--- test/OpenMP/threadprivate_ast_print.cpp
+++ test/OpenMP/threadprivate_ast_print.cpp
@@ -69,4 +69,5 @@
   return (foo<int>());
 }
 
+extern template int ST<int>::m;
 #endif
Index: test/OpenMP/teams_ast_print.cpp
===================================================================
--- test/OpenMP/teams_ast_print.cpp
+++ test/OpenMP/teams_ast_print.cpp
@@ -25,7 +25,7 @@
 // CHECK-NEXT: }
 // CHECK:      template <class T> struct S {
 // CHECK:        static T TS;
-// CHECK-NEXT:   #pragma omp threadprivate(S::TS)
+// CHECK-NEXT:   #pragma omp threadprivate(S<T>::TS)
 // CHECK:      };
 
 template <typename T, int C>
@@ -109,4 +109,6 @@
   return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
 }
 
+extern template int S<int>::TS;
+extern template long S<long>::TS;
 #endif
Index: test/OpenMP/task_ast_print.cpp
===================================================================
--- test/OpenMP/task_ast_print.cpp
+++ test/OpenMP/task_ast_print.cpp
@@ -76,7 +76,7 @@
 // CHECK-NEXT: }
 // CHECK:      template <class T> struct S {
 // CHECK:        static T TS;
-// CHECK-NEXT:   #pragma omp threadprivate(S::TS)
+// CHECK-NEXT:   #pragma omp threadprivate(S<T>::TS)
 // CHECK:      };
 
 template <typename T, int C>
@@ -149,4 +149,7 @@
   return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
 }
 
+extern template int S<int>::TS;
+extern template long S<long>::TS;
+
 #endif
Index: test/OpenMP/target_parallel_ast_print.cpp
===================================================================
--- test/OpenMP/target_parallel_ast_print.cpp
+++ test/OpenMP/target_parallel_ast_print.cpp
@@ -25,7 +25,7 @@
 // CHECK-NEXT: }
 // CHECK:      template <class T> struct S {
 // CHECK:        static T TS;
-// CHECK-NEXT:   #pragma omp threadprivate(S::TS)
+// CHECK-NEXT:   #pragma omp threadprivate(S<T>::TS)
 // CHECK:      };
 
 template <typename T, int C>
@@ -227,4 +227,7 @@
   return tmain<int, 5>(argc, &argc) + tmain<char, 1>(argv[0][0], argv[0]);
 }
 
+extern template int S<int>::TS;
+extern template char S<char>::TS;
+
 #endif
Index: test/OpenMP/parallel_sections_ast_print.cpp
===================================================================
--- test/OpenMP/parallel_sections_ast_print.cpp
+++ test/OpenMP/parallel_sections_ast_print.cpp
@@ -25,7 +25,7 @@
 // CHECK-NEXT: }
 // CHECK:      template <class T> struct S {
 // CHECK:        static T TS;
-// CHECK-NEXT:   #pragma omp threadprivate(S::TS)
+// CHECK-NEXT:   #pragma omp threadprivate(S<T>::TS)
 // CHECK:      };
 
 template <typename T, int C>
@@ -141,4 +141,7 @@
   return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x);
 }
 
+template<typename T>
+T S<T>::TS = 0;
+
 #endif
Index: test/OpenMP/parallel_ast_print.cpp
===================================================================
--- test/OpenMP/parallel_ast_print.cpp
+++ test/OpenMP/parallel_ast_print.cpp
@@ -132,7 +132,7 @@
 // CHECK-NEXT: }
 // CHECK:      template <class T> struct S {
 // CHECK:        static T TS;
-// CHECK-NEXT:   #pragma omp threadprivate(S::TS)
+// CHECK-NEXT:   #pragma omp threadprivate(S<T>::TS)
 // CHECK:      };
 
 template <typename T, int C>
@@ -227,4 +227,7 @@
   }
 }
 
+template<typename T>
+T S<T>::TS = 0;
+
 #endif
Index: test/Modules/merge-using-decls.cpp
===================================================================
--- test/Modules/merge-using-decls.cpp
+++ test/Modules/merge-using-decls.cpp
@@ -37,34 +37,34 @@
 // Here, we're instantiating the definition from 'A' and merging the definition
 // from 'B' into it.
 
-// expected-error@b.h:* {{'E::value' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
-// expected-error@b.h:* {{'E::v' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
+// expected-error@b.h:* {{'E<T>::value' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
+// expected-error@b.h:* {{'E<T>::v' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
 
-// expected-error@b.h:* {{'F::type' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
-// expected-error@b.h:* {{'F::t' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
-// expected-error@b.h:* {{'F::value' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
-// expected-error@b.h:* {{'F::v' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
+// expected-error@b.h:* {{'F<T>::type' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
+// expected-error@b.h:* {{'F<T>::t' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
+// expected-error@b.h:* {{'F<T>::value' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
+// expected-error@b.h:* {{'F<T>::v' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
 
 // expected-note@a.h:* +{{does not match}}
 #else
 // Here, we're instantiating the definition from 'B' and merging the definition
 // from 'A' into it.
 
-// expected-error@a.h:* {{'D::type' from module 'A' is not present in definition of 'D<T>' in module 'B'}}
-// expected-error@a.h:* {{'D::value' from module 'A' is not present in definition of 'D<T>' in module 'B'}}
+// expected-error@a.h:* {{'D<T>::type' from module 'A' is not present in definition of 'D<T>' in module 'B'}}
+// expected-error@a.h:* {{'D<T>::value' from module 'A' is not present in definition of 'D<T>' in module 'B'}}
 // expected-error@b.h:* 2{{'typename' keyword used on a non-type}}
 // expected-error@b.h:* 2{{dependent using declaration resolved to type without 'typename'}}
 
-// expected-error@a.h:* {{'E::type' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
-// expected-error@a.h:* {{'E::t' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
-// expected-error@a.h:* {{'E::value' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
-// expected-error@a.h:* {{'E::v' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
+// expected-error@a.h:* {{'E<T>::type' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
+// expected-error@a.h:* {{'E<T>::t' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
+// expected-error@a.h:* {{'E<T>::value' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
+// expected-error@a.h:* {{'E<T>::v' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
 // expected-note@b.h:* 2{{definition has no member}}
 
-// expected-error@a.h:* {{'F::type' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
-// expected-error@a.h:* {{'F::t' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
-// expected-error@a.h:* {{'F::value' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
-// expected-error@a.h:* {{'F::v' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
+// expected-error@a.h:* {{'F<T>::type' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
+// expected-error@a.h:* {{'F<T>::t' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
+// expected-error@a.h:* {{'F<T>::value' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
+// expected-error@a.h:* {{'F<T>::v' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
 
 // expected-note@b.h:* +{{does not match}}
 // expected-note@b.h:* +{{target of using}}
Index: test/CXX/temp/temp.decls/temp.mem/p1.cpp
===================================================================
--- test/CXX/temp/temp.decls/temp.mem/p1.cpp
+++ test/CXX/temp/temp.decls/temp.mem/p1.cpp
@@ -10,6 +10,7 @@
     }
   };
 };
+extern template bool A<bool>::cond;
 
 int foo() {
   A<bool>::cond = true;
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3530,7 +3530,8 @@
 void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                          FunctionDecl *Function,
                                          bool Recursive,
-                                         bool DefinitionRequired) {
+                                         bool DefinitionRequired,
+                                         bool AtEndOfTU) {
   if (Function->isInvalidDecl() || Function->isDefined())
     return;
 
@@ -3604,6 +3605,15 @@
       assert(!Recursive);
       PendingInstantiations.push_back(
         std::make_pair(Function, PointOfInstantiation));
+    } else if (Function->getTemplateSpecializationKind()
+                 == TSK_ImplicitInstantiation) {
+      if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+        Diag(PointOfInstantiation, diag::warn_func_template_missing)
+          << Function << PatternDecl;
+        if (getLangOpts().CPlusPlus11)
+          Diag(PointOfInstantiation, diag::note_inst_declaration_hint)
+            << Function;
+      }
     }
 
     return;
@@ -3951,7 +3961,7 @@
 
 void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
                                          VarDecl *Var, bool Recursive,
-                                         bool DefinitionRequired) {
+                                      bool DefinitionRequired, bool AtEndOfTU) {
   if (Var->isInvalidDecl())
     return;
 
@@ -4083,6 +4093,15 @@
                  == TSK_ExplicitInstantiationDefinition) {
       PendingInstantiations.push_back(
         std::make_pair(Var, PointOfInstantiation));
+    } else if (Var->getTemplateSpecializationKind()
+                 == TSK_ImplicitInstantiation) {
+      // Warn about missing definition at the end of translation unit.
+      if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+        Diag(PointOfInstantiation, diag::warn_var_template_missing)
+          << Var << PatternDecl;
+        if (getLangOpts().CPlusPlus11)
+          Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Var;
+      }
     }
 
     return;
@@ -4852,7 +4871,7 @@
       bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
                                 TSK_ExplicitInstantiationDefinition;
       InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
-                                    DefinitionRequired);
+                                    DefinitionRequired, true);
       continue;
     }
 
@@ -4893,7 +4912,7 @@
     // Instantiate static data member definitions or variable template
     // specializations.
     InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true,
-                                  DefinitionRequired);
+                                  DefinitionRequired, true);
   }
 }
 
Index: lib/Sema/SemaOverload.cpp
===================================================================
--- lib/Sema/SemaOverload.cpp
+++ lib/Sema/SemaOverload.cpp
@@ -9324,11 +9324,8 @@
 }
 
 static TemplateDecl *getDescribedTemplate(Decl *Templated) {
-  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated))
-    return FD->getDescribedFunctionTemplate();
-  else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated))
-    return RD->getDescribedClassTemplate();
-
+  if (TemplateDecl *TD = Templated->getDescribedTemplate())
+    return TD;
   llvm_unreachable("Unsupported: Getting the described template declaration"
                    " for bad deduction diagnosis");
 }
Index: lib/ASTMatchers/ASTMatchersInternal.cpp
===================================================================
--- lib/ASTMatchers/ASTMatchersInternal.cpp
+++ lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -469,13 +469,11 @@
     llvm::SmallString<128> NodeName = StringRef("::");
     llvm::raw_svector_ostream OS(NodeName);
 
-    if (SkipUnwritten) {
-      PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
+    PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
+    Policy.PrintTemplateParameters = false;
+    if (SkipUnwritten)
       Policy.SuppressUnwrittenScope = true;
-      Node.printQualifiedName(OS, Policy);
-    } else {
-      Node.printQualifiedName(OS);
-    }
+    Node.printQualifiedName(OS, Policy);
 
     const StringRef FullName = OS.str();
 
Index: lib/AST/DeclBase.cpp
===================================================================
--- lib/AST/DeclBase.cpp
+++ lib/AST/DeclBase.cpp
@@ -196,6 +196,17 @@
   return isa<TemplateDecl>(this);
 }
 
+TemplateDecl *Decl::getDescribedTemplate() const {
+  if (auto *FD = dyn_cast<FunctionDecl>(this))
+    return FD->getDescribedFunctionTemplate();
+  else if (auto *RD = dyn_cast<CXXRecordDecl>(this))
+    return RD->getDescribedClassTemplate();
+  else if (auto *VD = dyn_cast<VarDecl>(this))
+    return VD->getDescribedVarTemplate();
+
+  return nullptr;
+}
+
 const DeclContext *Decl::getParentFunctionOrMethod() const {
   for (const DeclContext *DC = getDeclContext();
        DC && !DC->isTranslationUnit() && !DC->isNamespace(); 
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1404,6 +1404,40 @@
   printQualifiedName(OS, getASTContext().getPrintingPolicy());
 }
 
+namespace {
+
+/// \brief Prints template parameters in diagnostic messages.
+///
+/// Allows a bit more readable reference to templates in the case of several
+/// template levels. For instance, a reference to the template function \c meth
+/// in the code:
+///
+/// \code
+/// template <class T, int Val> struct C1 {
+///   template<typename T1, template<typename TT> class TC> struct C2 {
+///     template <class T2> static void meth();
+///   };
+/// };
+/// \endcode
+///
+/// is printed as C1<T,Val>::C2<T1,TC>::meth<T2> rather than C1::C2::meth.
+///
+void printTemplateParameters(raw_ostream &OS, const TemplateDecl *Templ) {
+  OS << "<";
+  TemplateParameterList *TPL = Templ->getTemplateParameters();
+  for (unsigned I = 0, E = TPL->size(); I != E; ++I) {
+    if (I != 0)
+      OS << ",";
+    const NamedDecl *Param = TPL->getParam(I);
+    if (Param->isTemplateParameterPack())
+      OS << "...";
+    OS << Param->getDeclName();
+  }
+  OS << ">";
+}
+
+}
+
 void NamedDecl::printQualifiedName(raw_ostream &OS,
                                    const PrintingPolicy &P) const {
   const DeclContext *Ctx = getDeclContext();
@@ -1444,8 +1478,13 @@
     } else if (const auto *RD = dyn_cast<RecordDecl>(*I)) {
       if (!RD->getIdentifier())
         OS << "(anonymous " << RD->getKindName() << ')';
-      else
+      else {
         OS << *RD;
+        if (P.PrintTemplateParameters)
+          if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+            if (ClassTemplateDecl *Templ = CXXRD->getDescribedClassTemplate())
+              printTemplateParameters(OS, Templ);
+      }
     } else if (const auto *FD = dyn_cast<FunctionDecl>(*I)) {
       const FunctionProtoType *FT = nullptr;
       if (FD->hasWrittenPrototype())
@@ -1482,9 +1521,12 @@
     OS << "::";
   }
 
-  if (getDeclName())
-    OS << *this;
-  else
+  if (getDeclName()) {
+    printName(OS);
+    if (P.PrintTemplateParameters)
+      if (const TemplateDecl *TD = getDescribedTemplate())
+        printTemplateParameters(OS, TD);
+  } else
     OS << "(anonymous)";
 }
 
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -7171,7 +7171,8 @@
   void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                      FunctionDecl *Function,
                                      bool Recursive = false,
-                                     bool DefinitionRequired = false);
+                                     bool DefinitionRequired = false,
+                                     bool AtEndOfTU = false);
   VarTemplateSpecializationDecl *BuildVarTemplateInstantiation(
       VarTemplateDecl *VarTemplate, VarDecl *FromVar,
       const TemplateArgumentList &TemplateArgList,
@@ -7195,7 +7196,8 @@
       const MultiLevelTemplateArgumentList &TemplateArgs);
   void InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
                                      VarDecl *Var, bool Recursive = false,
-                                     bool DefinitionRequired = false);
+                                     bool DefinitionRequired = false,
+                                     bool AtEndOfTU = false);
   void InstantiateStaticDataMemberDefinition(
                                      SourceLocation PointOfInstantiation,
                                      VarDecl *Var,
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -3883,7 +3883,15 @@
   "in instantiation of template type alias %0 requested here">;
 def note_template_exception_spec_instantiation_here : Note<
   "in instantiation of exception specification for %0 requested here">;
-  
+def warn_var_template_missing : Warning<"instantiation of variable %q0 "
+  "required here, but %q1 is not defined">, InGroup<UndefinedVarTemplate>;
+def warn_func_template_missing : Warning<"instantiation of function %q0 "
+  "required here, but %q1 is not defined">, InGroup<UndefinedFuncTemplate>,
+  DefaultIgnore;
+def note_inst_declaration_hint : Note<"add an explicit instantiation "
+  "declaration to suppress this warning if %q0 is explicitly instantiated in "
+  "another translation unit">;
+
 def note_default_arg_instantiation_here : Note<
   "in instantiation of default argument for '%0' required here">;
 def note_default_function_arg_instantiation_here : Note<
Index: include/clang/Basic/DiagnosticGroups.td
===================================================================
--- include/clang/Basic/DiagnosticGroups.td
+++ include/clang/Basic/DiagnosticGroups.td
@@ -75,6 +75,8 @@
 def GNUDesignator : DiagGroup<"gnu-designator">;
 def GNUStringLiteralOperatorTemplate :
   DiagGroup<"gnu-string-literal-operator-template">;
+def UndefinedVarTemplate : DiagGroup<"undefined-var-template">;
+def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">;
 
 def DeleteIncomplete : DiagGroup<"delete-incomplete">;
 def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
Index: include/clang/AST/PrettyPrinter.h
===================================================================
--- include/clang/AST/PrettyPrinter.h
+++ include/clang/AST/PrettyPrinter.h
@@ -42,6 +42,7 @@
       ConstantArraySizeAsWritten(false), AnonymousTagLocations(true),
       SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false),
       SuppressTemplateArgsInCXXConstructors(false),
+      PrintTemplateParameters(true),
       Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false),
       Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar),
       IncludeNewlines(true), MSVCFormatting(false) { }
@@ -143,6 +144,10 @@
   /// constructors.
   unsigned SuppressTemplateArgsInCXXConstructors : 1;
 
+  /// \brief When true, template declaration name is printed with parameters,
+  /// e.g. 'C1<T>::C2<T1,N1>' instead of 'C1::C2'.
+  bool PrintTemplateParameters : 1;
+
   /// \brief Whether we can use 'bool' rather than '_Bool', even if the language
   /// doesn't actually have 'bool' (because, e.g., it is defined as a macro).
   unsigned Bool : 1;
Index: include/clang/AST/DeclBase.h
===================================================================
--- include/clang/AST/DeclBase.h
+++ include/clang/AST/DeclBase.h
@@ -52,6 +52,7 @@
 class RecordDecl;
 class Stmt;
 class StoredDeclsMap;
+class TemplateDecl;
 class TranslationUnitDecl;
 class UsingDirectiveDecl;
 }
@@ -905,6 +906,10 @@
            DeclKind == FunctionTemplate;
   }
 
+  /// \brief If this is a declaration that describes some template, this
+  /// method returns that template declaration.
+  TemplateDecl *getDescribedTemplate() const;
+
   /// \brief Returns the function itself, or the templated function if this is a
   /// function template.
   FunctionDecl *getAsFunction() LLVM_READONLY;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to