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]

C++ PATCH: PR 30108


This patch fixes PR c++/30108, a rejects-valid regression involving
default arguments (but, I admit, no GNU extensions!).  When we parse a
default argument, we store it with the function declaration.  Then,
when callers need the default argument, we convert the default
argument as appropriate in the context of the caller.  

In this case, the default argument as a pointer-to-function-member
cast to a different pointer-to-function-member type, so the
representation is (NOP_EXPR (PTRMEM_CST)).  Because no further
conversions were required, this tree was used -- without a copy -- in
the caller.  Then, when gimplified, this because (NOP_EXPR (VAR_DECL))
because the PTRMEM_CST is lowered to a value of structure type.  Then,
when used in another caller, the compiler aborted noticing the
VAR_DECL is from the wrong function.  

So, the bottom line is that we have to copy default arguments.  As an
optimization, I've exempted constants from the copy, since -- as far
as I know -- we will never modify a constant in place.  Since we
didn't copy constants before, this patch copies strictly more default
arguments.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.  I will
backport to 4.2 shortly.

--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

2007-03-12  Mark Mitchell  <mark@codesourcery.com>

	PR c++/30108
	* call.c (convert_default_arg): Copy non-constant arguments.

2007-03-12  Mark Mitchell  <mark@codesourcery.com>

	PR c++/30108
	* g++.dg/other/default6.C: New test.

Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 122822)
+++ gcc/cp/call.c	(working copy)
@@ -4664,10 +4664,14 @@ convert_default_arg (tree type, tree arg
     }
   else
     {
-      /* This could get clobbered by the following call.  */
-      if (TREE_HAS_CONSTRUCTOR (arg))
+      /* We must make a copy of ARG, in case subsequent processing
+	 alters any part of it.  For example, during gimplification a
+	 cast of the form (T) &X::f (where "f" is a member function)
+	 will lead to replacing the PTRMEM_CST for &X::f with a
+	 VAR_DECL.  We can avoid the copy for constants, since they
+	 are never modified in place.  */
+      if (!CONSTANT_CLASS_P (arg))
 	arg = copy_node (arg);
-
       arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
 					"default argument", fn, parmnum);
       arg = convert_for_arg_passing (type, arg);
Index: gcc/testsuite/g++.dg/other/default6.C
===================================================================
--- gcc/testsuite/g++.dg/other/default6.C	(revision 0)
+++ gcc/testsuite/g++.dg/other/default6.C	(revision 0)
@@ -0,0 +1,18 @@
+// PR c++/30108
+
+class BaseRobot {
+  typedef void (BaseRobot::*PseudoState)(void);
+  typedef PseudoState STATE;
+  STATE initial ();
+  int ready ();
+  STATE stpOtherTask ();
+  STATE commonEventProcessing (STATE pIdleTarget=(STATE)&BaseRobot::ready);
+};
+BaseRobot::STATE BaseRobot::initial ()
+{
+  return commonEventProcessing ();
+}
+BaseRobot::STATE BaseRobot::stpOtherTask ()
+{
+  return commonEventProcessing ();
+}


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