Hi,
On 28/02/2018 17:24, Jason Merrill wrote:
What do you think, should we do something similar?
Sounds good.
(by the way, yesterday
got a bit confused because in other vaguely related cases clang also has
this kind of two-part error message and we don't. Eg, I cooked up:
template <class T>
class Foo
{
template <class U>
class Bar;
};
template<class T>
template<class U>
class Foo<T>::Bar<U>;
And the same would be good for this example.
Great. I'm finishing testing the below, looks Ok?
Thanks,
Paolo.
///////////////////////
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 258059)
+++ cp/pt.c (working copy)
@@ -2873,7 +2873,18 @@ check_explicit_specialization (tree declarator,
/* Partial specialization of variable template. */
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
specialization = 1;
- goto ok;
+ if (template_count && DECL_CLASS_SCOPE_P (decl)
+ && template_class_depth (DECL_CONTEXT (decl)) > 0)
+ {
+ error ("variable template partial specialization %qD does "
+ "not specialize any template arguments; to define the "
+ "primary template, remove the template argument list",
+ declarator);
+ inform (DECL_SOURCE_LOCATION (TREE_OPERAND (declarator, 0)),
+ "primary template here");
+ }
+ else
+ goto ok;
}
else if (cxx_dialect < cxx14)
error ("non-type partial specialization %qD "
@@ -4832,11 +4843,14 @@ process_partial_specialization (tree decl)
get_constraints (maintmpl))))
{
if (!flag_concepts)
- error ("partial specialization %q+D does not specialize "
- "any template arguments", decl);
+ error ("partial specialization %q+D does not specialize any "
+ "template arguments; to define the primary template, "
+ "remove the template argument list", decl);
else
error ("partial specialization %q+D does not specialize any "
- "template arguments and is not more constrained than", decl);
+ "template arguments and is not more constrained than "
+ "the primary template; to define the primary template, "
+ "remove the template argument list", decl);
inform (DECL_SOURCE_LOCATION (maintmpl), "primary template here");
}
Index: testsuite/g++.dg/cpp1y/var-templ58.C
===================================================================
--- testsuite/g++.dg/cpp1y/var-templ58.C (nonexistent)
+++ testsuite/g++.dg/cpp1y/var-templ58.C (working copy)
@@ -0,0 +1,13 @@
+// PR c++/71569
+// { dg-do compile { target c++14 } }
+
+template <class T>
+class Foo
+{
+ template <class U>
+ static bool Bar; // { dg-message "primary template" }
+};
+
+template<class T>
+template<class U>
+bool Foo<T>::Bar<U>; // { dg-error "variable template partial" }
Index: testsuite/g++.dg/template/partial-specialization9.C
===================================================================
--- testsuite/g++.dg/template/partial-specialization9.C (nonexistent)
+++ testsuite/g++.dg/template/partial-specialization9.C (working copy)
@@ -0,0 +1,12 @@
+// PR c++/71569
+
+template <class T>
+class Foo
+{
+ template <class U>
+ class Bar; // { dg-message "primary template" }
+};
+
+template<class T>
+template<class U>
+class Foo<T>::Bar<U> {}; // { dg-error "partial specialization" }