This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ PATCH to support non-constexpr variable templates


On 08/25/2014 05:24 AM, Ville Voutilainen wrote:
Well, it's a bit premature to add tests when the implementation itself is not
quite complete, I guess. :) Having ICEs makes it hard to add tests, too. :P

But tests are how you verify that the implementation is complete.

Anyway, here's a fix for your recent test.

commit e79c51a68ae5ace45a191bf95350a68c7ce386d3
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Aug 25 00:17:55 2014 -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.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e83192a..80696dd 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 74a10fb..5b1313e 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a40f9d2..3e6d777 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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;
 	      }
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr60626.C b/gcc/testsuite/g++.dg/cpp1y/pr60626.C
index 686db73..3114644 100644
--- a/gcc/testsuite/g++.dg/cpp1y/pr60626.C
+++ b/gcc/testsuite/g++.dg/cpp1y/pr60626.C
@@ -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
index 0000000..8e3d34a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ8.C
@@ -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
index 0000000..2ffb007
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ9.C
@@ -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" }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]