This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 28523
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 1 Aug 2006 13:18:43 -0700
- Subject: C++ PATCH: PR 28523
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/28523, an ICE-on-valid. We were calling
stabilize_call with something that was not a call, which caused an
assertion to trip. I find the comments in build_throw (the caller of
stabilize_call) difficult to understand, but the bottom line is that
using stabilize_init in this situation is just an optimization. So,
we don't want stabilize_init to crash when handed something it can't
pre-evaluate; we just want it to indicate that it couldn't
pre-evaluate it. I tried to clean up the comments around stabilize_*;
the previous comments didn't really explain what these functions did
and didn't document the return values in all cases.
Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.1 branch.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
2006-07-31 Mark Mitchell <mark@codesourcery.com>
PR c++/28523
* tree.c (stabilize_expr): Tweak documentation. Add assertion.
(stabilize_call): Tweak documentation.
(stabilize_init): Only call stabilize_call for calls.
2006-07-31 Mark Mitchell <mark@codesourcery.com>
PR c++/28523
* g++.dg/eh/cast1.C: New test.
Index: gcc/cp/tree.c
===================================================================
--- gcc/cp/tree.c (revision 115850)
+++ gcc/cp/tree.c (working copy)
@@ -2229,9 +2229,11 @@ decl_linkage (tree decl)
return lk_internal;
}
-/* EXP is an expression that we want to pre-evaluate. Returns via INITP an
- expression to perform the pre-evaluation, and returns directly an
- expression to use the precalculated result. */
+/* EXP is an expression that we want to pre-evaluate. Returns (in
+ *INITP) an expression that will perform the pre-evaluation. The
+ value returned by this function is a side-effect free expression
+ equivalent to the pre-evaluated expression. Callers must ensure
+ that *INITP is evaluated before EXP. */
tree
stabilize_expr (tree exp, tree* initp)
@@ -2239,9 +2241,7 @@ stabilize_expr (tree exp, tree* initp)
tree init_expr;
if (!TREE_SIDE_EFFECTS (exp))
- {
- init_expr = NULL_TREE;
- }
+ init_expr = NULL_TREE;
else if (!real_lvalue_p (exp)
|| !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
{
@@ -2255,8 +2255,9 @@ stabilize_expr (tree exp, tree* initp)
exp = TARGET_EXPR_SLOT (init_expr);
exp = build_indirect_ref (exp, 0);
}
-
*initp = init_expr;
+
+ gcc_assert (!TREE_SIDE_EFFECTS (exp));
return exp;
}
@@ -2273,8 +2274,10 @@ add_stmt_to_compound (tree orig, tree ne
return build2 (COMPOUND_EXPR, void_type_node, orig, new);
}
-/* Like stabilize_expr, but for a call whose args we want to
- pre-evaluate. */
+/* Like stabilize_expr, but for a call whose arguments we want to
+ pre-evaluate. CALL is modified in place to use the pre-evaluated
+ arguments, while, upon return, *INITP contains an expression to
+ compute the arguments. */
void
stabilize_call (tree call, tree *initp)
@@ -2299,50 +2302,58 @@ stabilize_call (tree call, tree *initp)
*initp = inits;
}
-/* Like stabilize_expr, but for an initialization. If we are initializing
- an object of class type, we don't want to introduce an extra temporary,
- so we look past the TARGET_EXPR and stabilize the arguments of the call
- instead. */
+/* Like stabilize_expr, but for an initialization.
+
+ If the initialization is for an object of class type, this function
+ takes care not to introduce additional temporaries.
+
+ Returns TRUE iff the expression was successfully pre-evaluated,
+ i.e., if INIT is now side-effect free, except for, possible, a
+ single call to a constructor. */
bool
stabilize_init (tree init, tree *initp)
{
tree t = init;
+ *initp = NULL_TREE;
+
if (t == error_mark_node)
return true;
if (TREE_CODE (t) == INIT_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
- TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
- else
{
- if (TREE_CODE (t) == INIT_EXPR)
- t = TREE_OPERAND (t, 1);
- if (TREE_CODE (t) == TARGET_EXPR)
- t = TARGET_EXPR_INITIAL (t);
- if (TREE_CODE (t) == COMPOUND_EXPR)
- t = expr_last (t);
- if (TREE_CODE (t) == CONSTRUCTOR
- && EMPTY_CONSTRUCTOR_P (t))
- {
- /* Default-initialization. */
- *initp = NULL_TREE;
- return true;
- }
-
- /* If the initializer is a COND_EXPR, we can't preevaluate
- anything. */
- if (TREE_CODE (t) == COND_EXPR)
- return false;
-
- /* The TARGET_EXPR might be initializing via bitwise copy from
- another variable; leave that alone. */
- if (TREE_SIDE_EFFECTS (t))
- stabilize_call (t, initp);
+ TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
+ return true;
+ }
+
+ if (TREE_CODE (t) == INIT_EXPR)
+ t = TREE_OPERAND (t, 1);
+ if (TREE_CODE (t) == TARGET_EXPR)
+ t = TARGET_EXPR_INITIAL (t);
+ if (TREE_CODE (t) == COMPOUND_EXPR)
+ t = expr_last (t);
+ if (TREE_CODE (t) == CONSTRUCTOR
+ && EMPTY_CONSTRUCTOR_P (t))
+ /* Default-initialization. */
+ return true;
+
+ /* If the initializer is a COND_EXPR, we can't preevaluate
+ anything. */
+ if (TREE_CODE (t) == COND_EXPR)
+ return false;
+
+ if (TREE_CODE (t) == CALL_EXPR
+ || TREE_CODE (t) == AGGR_INIT_EXPR)
+ {
+ stabilize_call (t, initp);
+ return true;
}
- return true;
+ /* The initialization is being performed via a bitwise copy -- and
+ the item copied may have side effects. */
+ return TREE_SIDE_EFFECTS (init);
}
/* Like "fold", but should be used whenever we might be processing the
Index: gcc/testsuite/g++.dg/eh/cast1.C
===================================================================
--- gcc/testsuite/g++.dg/eh/cast1.C (revision 0)
+++ gcc/testsuite/g++.dg/eh/cast1.C (revision 0)
@@ -0,0 +1,10 @@
+// PR c++/28523
+
+class A {};
+class B : public A {};
+
+int main()
+{
+ throw (A) B();
+ return 0;
+}