re PR c++/63201 (Full specialization of a member variable template of a class templat...
authorJason Merrill <jason@redhat.com>
Fri, 12 Sep 2014 14:39:25 +0000 (10:39 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 12 Sep 2014 14:39:25 +0000 (10:39 -0400)
PR c++/63201
* decl.c (start_decl): Handle specialization of member variable
template.
* pt.c (check_explicit_specialization): Adjust error.

From-SVN: r215226

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1y/var-templ11.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.robertl/eb103.C

index afefed4e62348480e7d1c979f11e9c147d10d2ed..3e9cb8968240f5082e15ae15eaf51342683343f7 100644 (file)
@@ -1,3 +1,10 @@
+2014-09-11  Jason Merrill  <jason@redhat.com>
+
+       PR c++/63201
+       * decl.c (start_decl): Handle specialization of member variable
+       template.
+       * pt.c (check_explicit_specialization): Adjust error.
+
 2014-09-11  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/61489
index 6e195bb803d5859d53743fca705e4e7143a998ef..59dada7d3db290387ffb501852bb029e7d049745 100644 (file)
@@ -4659,20 +4659,24 @@ start_decl (const cp_declarator *declarator,
          if (field == NULL_TREE
              || !(VAR_P (field) || variable_template_p (field)))
            error ("%q+#D is not a static data member of %q#T", decl, context);
-         else
+         else if (variable_template_p (field) && !this_tmpl)
            {
-             if (variable_template_p (field))
+             if (DECL_LANG_SPECIFIC (decl)
+                 && DECL_TEMPLATE_SPECIALIZATION (decl))
+               /* OK, specialization was already checked.  */;
+             else
                {
-                 if (!this_tmpl)
-                   {
-                     error_at (DECL_SOURCE_LOCATION (decl),
-                               "non-member-template declaration of %qD", decl);
-                     inform (DECL_SOURCE_LOCATION (field), "does not match "
-                             "member template declaration here");
-                     return error_mark_node;
-                   }
-                 field = DECL_TEMPLATE_RESULT (field);
+                 error_at (DECL_SOURCE_LOCATION (decl),
+                           "non-member-template declaration of %qD", decl);
+                 inform (DECL_SOURCE_LOCATION (field), "does not match "
+                         "member template declaration here");
+                 return error_mark_node;
                }
+           }
+         else
+           {
+             if (variable_template_p (field))
+               field = DECL_TEMPLATE_RESULT (field);
 
              if (DECL_CONTEXT (field) != context)
                {
index 7f7ab93089034bd01a2b464710364d46c0777712..008879b28d5da49fcf6dfcdc6ca25c9a6feb12e2 100644 (file)
@@ -2471,7 +2471,7 @@ check_explicit_specialization (tree declarator,
             template <class T> void f<int>(); */
 
          if (uses_template_parms (declarator))
-           error ("function template partial specialization %qD "
+           error ("non-type partial specialization %qD "
                   "is not allowed", declarator);
          else
            error ("template-id %qD in declaration of primary template",
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ11.C b/gcc/testsuite/g++.dg/cpp1y/var-templ11.C
new file mode 100644 (file)
index 0000000..5d6e0d0
--- /dev/null
@@ -0,0 +1,67 @@
+// PR c++/63201
+// { dg-do compile { target c++14 } }
+
+template <class T>
+struct Y
+{
+  template <class U> static U x;
+};
+
+template <class T>
+template <class U>
+U Y<T>::x = U();
+
+template <>
+template <class U>
+U Y<int>::x = 42;
+
+template <>
+template <class U>
+// odd diagnostic
+U Y<float>::x<U> = 42; // { dg-error "partial specialization" }
+
+template <>
+template <>
+int Y<float>::x<int> = 42; // { dg-bogus "non-member-template declaration" }
+
+template <class T>
+struct Z
+{
+  template <class U> struct ZZ
+  {
+    template <class V> static V x;
+  };
+};
+
+template <class T>
+template <class U>
+template <class V>
+V Z<T>::ZZ<U>::x = V();
+
+template <>
+template <>
+template <class V>
+V Z<int>::ZZ<int>::x = V();
+
+template <>
+template <class U>
+struct Z<float>::ZZ
+{
+  template <class V> static V x;
+};
+
+template <>
+template <class U>
+template <class V>
+V Z<float>::ZZ<U>::x = V();
+
+template <>
+template <>
+template <>
+int Z<float>::ZZ<int>::x<int> = 42; // { dg-bogus "non-member-template declaration" }
+
+int main()
+{
+  int y = Y<int>::x<int>;
+  int z = Z<float>::ZZ<int>::x<int>;
+}
index c272d9403323bcb1338722118fe81c852a258034..ffc51ee44112590216a334c57e4d5fc3c5981454 100644 (file)
@@ -4,7 +4,7 @@
 template <int nlimb, int i>
 inline unsigned f (unsigned* ptr);
 template <int nlimb>
-inline unsigned f<nlimb,nlimb> (unsigned* ptr) // { dg-error "function template partial specialization" }
+inline unsigned f<nlimb,nlimb> (unsigned* ptr) // { dg-error "partial specialization" }
 {
   return 1;
 }