decl.c (start_decl): Look through member variable template.
authorJason Merrill <jason@redhat.com>
Mon, 25 Aug 2014 12:48:22 +0000 (08:48 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 25 Aug 2014 12:48:22 +0000 (08:48 -0400)
* decl.c (start_decl): Look through member variable template.
* pt.c (tsubst_decl) [VAR_DECL]: Handle member variable templates.
* decl2.c (grokfield): Set DECL_CONTEXT earlier on
variables.

From-SVN: r214420

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1y/pr60626.C
gcc/testsuite/g++.dg/cpp1y/var-templ8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/var-templ9.C [new file with mode: 0644]

index 18a281b0a586e03bf3705efd75885e40303d46fb..d9bf9058f7e6b4b74e3cbc294f431a30448c0520 100644 (file)
@@ -1,3 +1,10 @@
+2014-08-25  Jason Merrill  <jason@redhat.com>
+
+       * decl.c (start_decl): Look through member variable template.
+       * pt.c (tsubst_decl) [VAR_DECL]: Handle member variable templates.
+       * decl2.c (grokfield): Set DECL_CONTEXT earlier on
+       variables.
+
 2014-08-25  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/34938
index e83192ad749be608a21c3668aec25f197cb50711..80696ddb21651b4d34b7c8807c87aed880169471 100644 (file)
@@ -4650,13 +4650,37 @@ start_decl (const cp_declarator *declarator,
 
   if (TYPE_P (context) && COMPLETE_TYPE_P (complete_type (context)))
     {
+      bool this_tmpl = (processing_template_decl
+                       > template_class_depth (context));
       if (VAR_P (decl))
        {
          tree field = lookup_field (context, DECL_NAME (decl), 0, false);
-         if (field == NULL_TREE || !VAR_P (field))
-           error ("%q#D is not a static member of %q#T", decl, context);
+         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
            {
+             if (variable_template_p (field))
+               {
+                 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);
+               }
+             else if (this_tmpl)
+               {
+                 error_at (DECL_SOURCE_LOCATION (decl),
+                           "member template declaration of %qD", decl);
+                 inform (DECL_SOURCE_LOCATION (field), "does not match "
+                         "non-member-template declaration here");
+                 return error_mark_node;
+               }
+
              if (DECL_CONTEXT (field) != context)
                {
                  if (!same_type_p (DECL_CONTEXT (field), context))
@@ -4683,8 +4707,7 @@ start_decl (const cp_declarator *declarator,
       else
        {
          tree field = check_classfn (context, decl,
-                                     (processing_template_decl
-                                      > template_class_depth (context))
+                                     this_tmpl
                                      ? current_template_parms
                                      : NULL_TREE);
          if (field && field != error_mark_node
index 74a10fb74fbdef4943ccec9be6d64848c95ec214..5b1313efa2623625cc8a31fc8348d1df5704cfbe 100644 (file)
@@ -994,6 +994,10 @@ grokfield (const cp_declarator *declarator,
       && DECL_CONTEXT (value) != current_class_type)
     return value;
 
+  /* Need to set this before push_template_decl.  */
+  if (TREE_CODE (value) == VAR_DECL)
+    DECL_CONTEXT (value) = current_class_type;
+
   if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value))
     {
       value = push_template_decl (value);
index a40f9d2ad7c653306e63e4045bb273941ad320ce..3e6d777e72de0ba5d61a967d130f6abf539e648d 100644 (file)
@@ -11127,13 +11127,12 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
                   same_type_p, because DECL_CONTEXT is always
                   canonical...  */
                if (ctx == DECL_CONTEXT (t)
-                   && (TREE_CODE (t) != TYPE_DECL
-                       /* ... unless T is a member template; in which
-                          case our caller can be willing to create a
-                          specialization of that template represented
-                          by T.  */
-                       || !(DECL_TI_TEMPLATE (t)
-                            && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t)))))
+                   /* ... unless T is a member template; in which
+                      case our caller can be willing to create a
+                      specialization of that template represented
+                      by T.  */
+                   && !(DECL_TI_TEMPLATE (t)
+                        && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
                  spec = t;
              }
 
index 686db7306b932a69691b0414a9737047a3756d8a..311464472daef6d4d314c265681e1a5a5e8fc9b5 100644 (file)
@@ -4,4 +4,4 @@
 
 struct A {};
 
-void (*A::p)(auto) = 0;  // { dg-error "static member|template" }
+void (*A::p)(auto) = 0;  // { dg-error "static data member|template" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ8.C b/gcc/testsuite/g++.dg/cpp1y/var-templ8.C
new file mode 100644 (file)
index 0000000..8e3d34a
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++14 } }
+// { dg-final { scan-assembler "_ZN1X1xIiEE" } }
+
+struct X
+{
+  template <class T> static T x;
+};
+
+template <class T>
+T X::x = T();
+
+int main()
+{
+  int x = X::x<int>;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ9.C b/gcc/testsuite/g++.dg/cpp1y/var-templ9.C
new file mode 100644 (file)
index 0000000..2ffb007
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++14 } }
+
+struct X
+{
+  template <class T> static int x;
+};
+
+int X::x = 42;                 // { dg-error "template" }
+
+struct Y
+{
+  static int y;
+};
+
+template <class T> int Y::y = 42; // { dg-error "template" }