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" }

Reply via email to