diff mbox

[C++] PR 15339

Message ID 53DC0F66.7050209@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Aug. 1, 2014, 10:06 p.m. UTC
Hi,

thus this is what I have tested for c++/15339. By the way, I figured out 
why yesterday I got stupidly confused about DECL_TEMPLATE_INFO: at this 
point, for a member function template, newdecl does *not* have 
DECL_TEMPLATE_INFO set, only olddecl does. Consistently, I adjusted all 
the code in the condition to work on olddecl. Tested x86_64-linux.

Thanks,
Paolo.

//////////////////
/cp
2014-08-01  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/15339
	* decl.c (duplicate_decls): Handle default arguments in function
	templates.

/testsuite
2014-08-01  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/15339
	* g++.dg/other/default9.C: New.
	* g++.dg/other/default3.C: Remove xfail.
diff mbox

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 213505)
+++ cp/decl.c	(working copy)
@@ -1704,19 +1704,23 @@  duplicate_decls (tree newdecl, tree olddecl, bool
 
       if (DECL_LANG_SPECIFIC (olddecl) && DECL_USE_TEMPLATE (olddecl))
 	;
-      else if (TREE_CODE (olddecl) == FUNCTION_DECL)
+      else if (DECL_DECLARES_FUNCTION_P (olddecl))
 	{
 	  tree t1 = FUNCTION_FIRST_USER_PARMTYPE (olddecl);
 	  tree t2 = FUNCTION_FIRST_USER_PARMTYPE (newdecl);
 	  int i = 1;
 
-	  if (DECL_FUNCTION_MEMBER_P (newdecl)
-	      && CLASSTYPE_TEMPLATE_INFO (CP_DECL_CONTEXT (newdecl)))
+	  if (DECL_FUNCTION_TEMPLATE_P (olddecl)
+	      || (DECL_FUNCTION_MEMBER_P (olddecl)
+		  && (/* grokfndecl passes member function templates too
+			 as FUNCTION_DECLs.  */
+		      DECL_TEMPLATE_INFO (olddecl)
+		      /* 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.  */
+		      || CLASSTYPE_TEMPLATE_INFO (CP_DECL_CONTEXT (olddecl)))))
 	    {
-	      /* 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))
 		  {
Index: testsuite/g++.dg/other/default3.C
===================================================================
--- testsuite/g++.dg/other/default3.C	(revision 213504)
+++ testsuite/g++.dg/other/default3.C	(working copy)
@@ -25,7 +25,7 @@  template<typename> void g3(int, int);
 template<typename> void g3(int = 0, int);    // { dg-error "default" }
 
 template<typename> void g4(int, int);
-template<typename> void g4(int = 0, int) {}  // { dg-error "default" "" { xfail *-*-* } }
+template<typename> void g4(int = 0, int) {}  // { dg-error "default" }
 
 template<typename> void g5();
 template<typename> void g5(int = 0, int);    // { dg-error "default" }
Index: testsuite/g++.dg/other/default9.C
===================================================================
--- testsuite/g++.dg/other/default9.C	(revision 0)
+++ testsuite/g++.dg/other/default9.C	(working copy)
@@ -0,0 +1,18 @@ 
+// PR c++/15339
+
+template<typename> void fun(int); 
+template<typename> void fun(int = 0);  // { dg-error "default arguments" }
+
+class A
+{
+  template<typename> void fun(int);
+};
+
+template<typename> void A::fun(int = 0) { } // { dg-error "default arguments" }
+
+class B
+{
+  void fun(int);
+};
+
+void B::fun(int = 0) { }