This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 30108
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 12 Mar 2007 09:38:59 -0700
- Subject: C++ PATCH: PR 30108
- Reply-to: mark at codesourcery dot com
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 ();
+}