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.
-// [email protected]:* {{'E::value' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
-// [email protected]:* {{'E::v' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
+// [email protected]:* {{'E<T>::value' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
+// [email protected]:* {{'E<T>::v' from module 'B' is not present in definition of 'E<T>' in module 'A'}}
-// [email protected]:* {{'F::type' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
-// [email protected]:* {{'F::t' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
-// [email protected]:* {{'F::value' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
-// [email protected]:* {{'F::v' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
+// [email protected]:* {{'F<T>::type' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
+// [email protected]:* {{'F<T>::t' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
+// [email protected]:* {{'F<T>::value' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
+// [email protected]:* {{'F<T>::v' from module 'B' is not present in definition of 'F<T>' in module 'A'}}
// [email protected]:* +{{does not match}}
#else
// Here, we're instantiating the definition from 'B' and merging the definition
// from 'A' into it.
-// [email protected]:* {{'D::type' from module 'A' is not present in definition of 'D<T>' in module 'B'}}
-// [email protected]:* {{'D::value' from module 'A' is not present in definition of 'D<T>' in module 'B'}}
+// [email protected]:* {{'D<T>::type' from module 'A' is not present in definition of 'D<T>' in module 'B'}}
+// [email protected]:* {{'D<T>::value' from module 'A' is not present in definition of 'D<T>' in module 'B'}}
// [email protected]:* 2{{'typename' keyword used on a non-type}}
// [email protected]:* 2{{dependent using declaration resolved to type without 'typename'}}
-// [email protected]:* {{'E::type' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
-// [email protected]:* {{'E::t' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
-// [email protected]:* {{'E::value' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
-// [email protected]:* {{'E::v' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
+// [email protected]:* {{'E<T>::type' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
+// [email protected]:* {{'E<T>::t' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
+// [email protected]:* {{'E<T>::value' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
+// [email protected]:* {{'E<T>::v' from module 'A' is not present in definition of 'E<T>' in module 'B'}}
// [email protected]:* 2{{definition has no member}}
-// [email protected]:* {{'F::type' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
-// [email protected]:* {{'F::t' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
-// [email protected]:* {{'F::value' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
-// [email protected]:* {{'F::v' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
+// [email protected]:* {{'F<T>::type' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
+// [email protected]:* {{'F<T>::t' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
+// [email protected]:* {{'F<T>::value' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
+// [email protected]:* {{'F<T>::v' from module 'A' is not present in definition of 'F<T>' in module 'B'}}
// [email protected]:* +{{does not match}}
// [email protected]:* +{{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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits