Patchwork [C++] PR 54485

login
register
mail settings
Submitter Paolo Carlini
Date Aug. 25, 2013, 10:52 a.m.
Message ID <5219E1E8.2020707@oracle.com>
Download mbox | patch
Permalink /patch/269694/
State New
Headers show

Comments

Paolo Carlini - Aug. 25, 2013, 10:52 a.m.
Hi,

this bug, filed by Diego, is about 8.3.6/6, where member functions of 
class templates, at variance with plain classes, do not admit default 
arguments on the out-of-class redeclaration.

Tested x86_64-linux.

Thanks,
Paolo.

//////////////////////////
/cp
2013-08-25  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54485
	* decl.c (duplicate_decls): Enforce 8.3.6/6 about default arguments
	for member functions of class templates.

/testsuite
2013-08-25  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54485
	* g++.dg/other/default8.C: New.
	* g++.dg/tc1/dr217.C: Remove xfail.
	* g++.dg/other/default5.C: Adjust.
	* g++.old-deja/g++.mike/p1989.C: Likewise.
Jason Merrill - Nov. 23, 2013, 9:08 p.m.
I believe that our current practice is to have one error and then use 
inform for follow-on messages.  OK with that change.

Jason
Paolo Carlini - Nov. 25, 2013, 10:30 a.m.
On 11/23/2013 10:08 PM, Jason Merrill wrote:
> I believe that our current practice is to have one error and then use 
> inform for follow-on messages.  OK with that change.
Thanks. The multiple permerror and error aren't in the new code, my 
patch just shuffles those around. I would be glad to work on that issue 
too, but I think that the whole function should be audited, thus I would 
rather go first with my patch as-is and then go back to that. Agreed?

Paolo.
Jason Merrill - Nov. 25, 2013, 9:31 p.m.
On 11/25/2013 05:30 AM, Paolo Carlini wrote:
> On 11/23/2013 10:08 PM, Jason Merrill wrote:
>> I believe that our current practice is to have one error and then use
>> inform for follow-on messages.  OK with that change.
> Thanks. The multiple permerror and error aren't in the new code, my
> patch just shuffles those around. I would be glad to work on that issue
> too, but I think that the whole function should be audited, thus I would
> rather go first with my patch as-is and then go back to that. Agreed?

OK.

Jason

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 201977)
+++ cp/decl.c	(working copy)
@@ -1686,25 +1686,47 @@  duplicate_decls (tree newdecl, tree olddecl, bool
 	  if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
 	    t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
 
-	  for (; t1 && t1 != void_list_node;
-	       t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
-	    if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
-	      {
-		if (1 == simple_cst_equal (TREE_PURPOSE (t1),
-					   TREE_PURPOSE (t2)))
+	  if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE
+	      && CLASSTYPE_TEMPLATE_INFO (CP_DECL_CONTEXT (newdecl)))
+	    {
+	      /* C++11 8.3.6/6.
+		 Default arguments for a member function of a class template
+		 shall be specified on the initial declaration of the member
+		 function within the class template.  */
+	      for (; t2 && t2 != void_list_node; t2 = TREE_CHAIN (t2))
+		if (TREE_PURPOSE (t2))
 		  {
-		    permerror (input_location, "default argument given for parameter %d of %q#D",
-			       i, newdecl);
-		    permerror (input_location, "after previous specification in %q+#D", olddecl);
+		    permerror (input_location,
+			       "redeclaration of %q#D may not have default "
+			       "arguments", newdecl);
+		    break;
 		  }
-		else
+	    }
+	  else
+	    {
+	      for (; t1 && t1 != void_list_node;
+		   t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
+		if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
 		  {
-		    error ("default argument given for parameter %d of %q#D",
-			   i, newdecl);
-		    error ("after previous specification in %q+#D",
-				 olddecl);
+		    if (1 == simple_cst_equal (TREE_PURPOSE (t1),
+					       TREE_PURPOSE (t2)))
+		      {
+			permerror (input_location,
+				   "default argument given for parameter %d "
+				   "of %q#D", i, newdecl);
+			permerror (input_location,
+				   "after previous specification in %q+#D",
+				   olddecl);
+		      }
+		    else
+		      {
+			error ("default argument given for parameter %d "
+			       "of %q#D", i, newdecl);
+			error ("after previous specification in %q+#D",
+			       olddecl);
+		      }
 		  }
-	      }
+	    }
 	}
     }
 
Index: testsuite/g++.dg/other/default5.C
===================================================================
--- testsuite/g++.dg/other/default5.C	(revision 201977)
+++ testsuite/g++.dg/other/default5.C	(working copy)
@@ -43,5 +43,5 @@  template<int> struct B
   void F2(int, int, int = 0);
 };
 
-template<int N> void B<N>::F1(int, int = 0, int) {}
-template<int N> void B<N>::F2(int = 0, int, int) {}  // { dg-error "default" }
+template<int N> void B<N>::F1(int, int = 0, int) {}  // { dg-error "default arguments" }
+template<int N> void B<N>::F2(int = 0, int, int) {}  // { dg-error "default arguments|parameter 2" }
Index: testsuite/g++.dg/other/default8.C
===================================================================
--- testsuite/g++.dg/other/default8.C	(revision 0)
+++ testsuite/g++.dg/other/default8.C	(working copy)
@@ -0,0 +1,43 @@ 
+// PR c++54485
+
+template<typename T>
+class K1
+{
+  int fn(int, int);
+  int gn(int, int);
+};
+
+template<typename T>
+int K1<T>::fn (int a, int b = 3)      // { dg-error "default arguments" }
+{
+  return a - b;
+}
+
+template<typename T>
+int K1<T>::gn (int a = 1, int b = 3)  // { dg-error "default arguments" }
+{
+  return a - b;
+}
+
+template<typename T>
+class K2
+{
+  template<typename U>
+  int fn(int, int);
+  template<typename U>
+  int gn(int, int);
+};
+
+template<typename T>
+template<typename U>
+int K2<T>::fn (int a, int b = 3)  // { dg-error "default arguments" }
+{
+  return a - b;
+}
+
+template<typename T>
+template<typename U>
+int K2<T>::gn (int a = 1, int b = 3)  // { dg-error "default arguments" }
+{
+  return a - b;
+}
Index: testsuite/g++.dg/tc1/dr217.C
===================================================================
--- testsuite/g++.dg/tc1/dr217.C	(revision 201977)
+++ testsuite/g++.dg/tc1/dr217.C	(working copy)
@@ -10,5 +10,5 @@  struct S
 };
 
 template <class T>
-void S<T>::foo (int = 0)  // { dg-error "" "default arguments for parameters of member functions of class templates can be specified in the initial declaration only" { xfail *-*-* } }
+void S<T>::foo (int = 0)  // { dg-error "" "default arguments for parameters of member functions of class templates can be specified in the initial declaration only" }
 { }
Index: testsuite/g++.old-deja/g++.mike/p1989.C
===================================================================
--- testsuite/g++.old-deja/g++.mike/p1989.C	(revision 201977)
+++ testsuite/g++.old-deja/g++.mike/p1989.C	(working copy)
@@ -108,7 +108,7 @@  List_DL<T>::prepend(const T& item)
 
 template<class T>
 void
-List_DL<T>::insert(const T& item, Pix x, bool before = TRUE)
+List_DL<T>::insert(const T& item, Pix x, bool before = TRUE)  // { dg-error "default arguments" }
 {
     link<T> *l = (link<T> *) x;