diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a93e420ff86..1e327c22e76 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2006-07-31 Mark Mitchell + + PR c++/28523 + * tree.c (stabilize_expr): Tweak documentation. Add assertion. + (stabilize_call): Tweak documentation. + (stabilize_init): Only call stabilize_call for calls. + 2006-08-01 Steve Ellcey PR c++/28432 diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 0d42502da76..53d37beca68 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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 new) 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; } - 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; + } + + /* 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4afaae11cb2..1e1effcfbc6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2006-07-31 Mark Mitchell + + PR c++/28523 + * g++.dg/eh/cast1.C: New test. + 2006-08-01 Thomas Koenig PR libfortran/28452 diff --git a/gcc/testsuite/g++.dg/eh/cast1.C b/gcc/testsuite/g++.dg/eh/cast1.C new file mode 100644 index 00000000000..964dd698d30 --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/cast1.C @@ -0,0 +1,10 @@ +// PR c++/28523 + +class A {}; +class B : public A {}; + +int main() +{ + throw (A) B(); + return 0; +}