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.carl...@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.carl...@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.
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;