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]

[patch] Fix PR c++/28274: Extra default argument in redeclaration rejected


The following valid code snippet is rejected by the C++ frontend:

  void foo(int, int = 0);
  void foo(int = 0, int);

This was caused by my patch for PR 16829 to catch missing default
arguments. Alas, in case of a redeclaration the checks are performed
*before* the new declaration has been merged with the previous one(s).
Hence, the compiler misses the default arguments of the latter.

I decided to move the main check to duplicate_decls (decl.c) where the
merging actually takes place. (Placing the check after duplicate_decls
would have the disadvantage that the line number of the new declaration
is already gone, so that check_default_args reports the line number of
the old declaration, making it difficult to track down the invalid
declaration.) I moved the check to a place in duplicate_decls where
the arguments have been merged already, but where we still have the
line number of the new decl.

This makes the call to check_default_args in start_preparsed_function
completely unnecessary.
In pushdecl_maybe_friend (name-lookup.c) we only have to deal with the
case that duplicate_decls gets bypassed. This is done by moving the
test a little later.

Bootstrapped and regtested on x86_64-unknown-linux-gnu.
Ok for mainline, 4.1 branch, and 4.0 branch?

Regards,
Volker

:ADDPATCH C++:


2006-07-28  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>

	PR c++/28274
	* decl.c (duplicate_decls): Check check_default_args here.
	(start_preparsed_function): Do not call check_default_args.
	* name-lookup.c (pushdecl_maybe_friend): Only call
	check_default_args if duplicate_decls got bypassed.

===================================================================
--- gcc/gcc/cp/decl.c	(revision 115770)
+++ gcc/gcc/cp/decl.c	(working copy)
@@ -1691,6 +1691,9 @@ duplicate_decls (tree newdecl, tree olddecl
 	check_redeclaration_exception_specification (newdecl, olddecl);
       TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
 
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+	check_default_args (newdecl);
+
       /* Lay the type out, unless already done.  */
       if (! same_type_p (newtype, oldtype)
 	  && TREE_TYPE (newdecl) != error_mark_node
@@ -10425,8 +10429,6 @@ start_preparsed_function (tree decl1,
      you declare a function, these types can be incomplete, but they
      must be complete when you define the function.  */
   check_function_type (decl1, current_function_parms);
-  /* Make sure no default arg is missing.  */
-  check_default_args (decl1);
 
   /* Build the return declaration for the function.  */
   restype = TREE_TYPE (fntype);
===================================================================
--- gcc/gcc/cp/name-lookup.c	(revision 115770)
+++ gcc/gcc/cp/name-lookup.c	(working copy)
@@ -606,9 +606,6 @@ pushdecl_maybe_friend (tree x, bool is_friend)
     {
       int different_binding_level = 0;
 
-      if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
-       check_default_args (x);
-
       if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
 	name = TREE_OPERAND (name, 0);
 
@@ -751,6 +748,9 @@ pushdecl_maybe_friend (tree x, bool is_friend)
 	    }
 	}
 
+      if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
+	check_default_args (x);
+
       check_template_shadow (x);
 
       /* If this is a function conjured up by the backend, massage it
===================================================================

2006-07-28  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>

	PR c++/28274
	* g++.dg/other/default5.C: New test.

===================================================================
--- gcc/gcc/testsuite/g++.dg/other/default5.C	2005-08-29 00:25:44 +0200
+++ gcc/gcc/testsuite/g++.dg/other/default5.C	2006-07-27 22:42:20 +0200
@@ -0,0 +1,47 @@
+// PR c++/28274
+// { dg-do "compile" }
+
+void f1(int, int, int, int, int = 0);
+void f1(int, int, int, int = 0, int);
+void f1(int, int, int = 0, int, int);
+void f1(int = 0, int, int, int, int);    // { dg-error "default" }
+
+void f2(int, int, int, int, int = 0) {}
+void f2(int, int, int, int = 0, int);
+void f2(int, int, int = 0, int, int);
+void f2(int = 0, int, int, int, int);    // { dg-error "default" }
+
+void f3(int, int, int, int, int = 0);
+void f3(int, int, int, int = 0, int) {}
+void f3(int, int, int = 0, int, int);
+void f3(int = 0, int, int, int, int);    // { dg-error "default" }
+
+void f4(int, int, int, int, int = 0);
+void f4(int, int, int, int = 0, int);
+void f4(int, int, int = 0, int, int) {}
+void f4(int = 0, int, int, int, int);    // { dg-error "default" }
+
+void f5(int, int, int, int, int = 0);
+void f5(int, int, int, int = 0, int);
+void f5(int, int, int = 0, int, int);
+void f5(int = 0, int, int, int, int) {}  // { dg-error "default" }
+
+
+struct A
+{
+  void F1(int, int, int = 0);
+  void F2(int, int, int = 0);
+};
+
+void A::F1(int, int = 0, int) {}
+void A::F2(int = 0, int, int) {}  // { dg-error "default" }
+
+
+template<int> struct B
+{
+  void F1(int, int, int = 0);
+  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" }
===================================================================



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