aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-08-01 20:04:57 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-08-01 20:04:57 +0000
commit9beafc83cabd13b4ad5783209db8f32998363e08 (patch)
treedd3912200eeffd0b29ac6d29d2a8302828c500fc /gcc
parent8218f92fdf6d1b1c6cf64a03967b7ae8e9b83361 (diff)
downloadgcc-9beafc83cabd13b4ad5783209db8f32998363e08.zip
gcc-9beafc83cabd13b4ad5783209db8f32998363e08.tar.gz
gcc-9beafc83cabd13b4ad5783209db8f32998363e08.tar.bz2
re PR c++/28523 (Throw of a derived class casted to its base class using a C-style cast)
PR c++/28523 * tree.c (stabilize_expr): Tweak documentation. Add assertion. (stabilize_call): Tweak documentation. (stabilize_init): Only call stabilize_call for calls. PR c++/28523 * g++.dg/eh/cast1.C: New test. From-SVN: r115862
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/tree.c85
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/eh/cast1.C10
4 files changed, 70 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a93e420..1e327c2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+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-08-01 Steve Ellcey <sje@cup.hp.com>
PR c++/28432
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 0d42502..53d37be 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;
- }
+ TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
+ 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) == 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;
- /* The TARGET_EXPR might be initializing via bitwise copy from
- another variable; leave that alone. */
- if (TREE_SIDE_EFFECTS (t))
- stabilize_call (t, initp);
+ 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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4afaae1..1e1effc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-07-31 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/28523
+ * g++.dg/eh/cast1.C: New test.
+
2006-08-01 Thomas Koenig <Thomas.Koenig@online.de>
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 0000000..964dd69
--- /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;
+}