+2004-06-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/16015
+ * gimplify.c (gimplify_target_expr): Handle void initializer.
+ * expr.c (expand_expr_real_1) [TARGET_EXPR]: Likewise.
+ * doc/c-tree.texi (Expression trees): Update TARGET_EXPR
+ and AGGR_INIT_EXPR.
+
2004-06-17 Roger Sayle <roger@eyesopen.com>
* fold-const.c (fold_relational_const): Use constant_boolean_node.
+2004-06-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/16015
+ * semantics.c (simplify_aggr_init_expr): Don't return the slot.
+ (finish_stmt_expr_expr): Update type after conversions.
+ (finish_stmt_expr): Wrap initializer in CLEANUP_POINT_EXPR.
+ Handle void initializer.
+ * tree.c (build_cplus_new): Make AGGR_INIT_EXPRs void.
+
2004-06-17 Geoffrey Keating <geoffk@apple.com>
* class.c (build_clone): Don't call defer_fn, let mark_used do it.
finish_stmt_expr_expr (tree expr, tree stmt_expr)
{
tree result = NULL_TREE;
- tree type = void_type_node;
if (expr)
{
- type = TREE_TYPE (expr);
-
if (!processing_template_decl && !VOID_TYPE_P (TREE_TYPE (expr)))
{
+ tree type = TREE_TYPE (expr);
+
if (TREE_CODE (type) == ARRAY_TYPE
|| TREE_CODE (type) == FUNCTION_TYPE)
expr = decay_conversion (expr);
expr = convert_from_reference (expr);
expr = require_complete_type (expr);
+ type = TREE_TYPE (expr);
+
/* Build a TARGET_EXPR for this aggregate. finish_stmt_expr
will then pull it apart so the lifetime of the target is
within the scope of the expression containing this statement
the target's init_expr as the final expression and then put
the statement expression itself as the target's init
expr. Finally, return the target expression. */
- tree last_expr = EXPR_STMT_EXPR (result_stmt);
-
- my_friendly_assert (TREE_CODE (last_expr) == TARGET_EXPR, 20030729);
- *result_stmt_p = TREE_OPERAND (last_expr, 1);
-
- if (TREE_CODE (result) == BIND_EXPR)
+ tree init, target_expr = EXPR_STMT_EXPR (result_stmt);
+ my_friendly_assert (TREE_CODE (target_expr) == TARGET_EXPR, 20030729);
+
+ /* The initializer will be void if the initialization is done by
+ AGGR_INIT_EXPR; propagate that out to the statement-expression as
+ a whole. */
+ init = TREE_OPERAND (target_expr, 1);
+ type = TREE_TYPE (init);
+
+ if (stmts_are_full_exprs_p ())
+ init = fold (build1 (CLEANUP_POINT_EXPR, type, init));
+ *result_stmt_p = init;
+
+ if (VOID_TYPE_P (type))
+ /* No frobbing needed. */;
+ else if (TREE_CODE (result) == BIND_EXPR)
{
+ /* The BIND_EXPR created in finish_compound_stmt is void; if we're
+ returning a value directly, give it the appropriate type. */
if (VOID_TYPE_P (TREE_TYPE (result)))
- TREE_TYPE (result) = TREE_TYPE (last_expr);
- else if (same_type_p (TREE_TYPE (result), TREE_TYPE (last_expr)))
+ TREE_TYPE (result) = type;
+ else if (same_type_p (TREE_TYPE (result), type))
;
else
abort ();
}
else if (TREE_CODE (result) == STATEMENT_LIST)
- result = build (BIND_EXPR, TREE_TYPE (last_expr), NULL, result, NULL);
+ /* We need to wrap a STATEMENT_LIST in a BIND_EXPR so it can have a
+ type other than void. FIXME why can't we just return a value
+ from STATEMENT_LIST? */
+ result = build3 (BIND_EXPR, type, NULL, result, NULL);
- TREE_OPERAND (last_expr, 1) = result;
- result = last_expr;
+ TREE_OPERAND (target_expr, 1) = result;
+ result = target_expr;
}
return result;
tree fn = TREE_OPERAND (aggr_init_expr, 0);
tree args = TREE_OPERAND (aggr_init_expr, 1);
tree slot = TREE_OPERAND (aggr_init_expr, 2);
- tree type = TREE_TYPE (aggr_init_expr);
+ tree type = TREE_TYPE (slot);
tree call_expr;
enum style_t { ctor, arg, pcc } style;
args = TREE_CHAIN (args);
cxx_mark_addressable (slot);
- addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (slot)), slot);
+ addr = build1 (ADDR_EXPR, build_pointer_type (type), slot);
if (style == arg)
{
/* The return type might have different cv-quals from the slot. */
pop_deferring_access_checks ();
}
- /* We want to use the value of the initialized location as the
- result. */
- call_expr = build (COMPOUND_EXPR, type, call_expr, slot);
-
*tp = call_expr;
}
type, don't mess with AGGR_INIT_EXPR. */
if (is_ctor || TREE_ADDRESSABLE (type))
{
- rval = build (AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
+ rval = build (AGGR_INIT_EXPR, void_type_node, fn,
+ TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
}
@item TARGET_EXPR
A @code{TARGET_EXPR} represents a temporary object. The first operand
is a @code{VAR_DECL} for the temporary variable. The second operand is
-the initializer for the temporary. The initializer is evaluated, and
-copied (bitwise) into the temporary.
+the initializer for the temporary. The initializer is evaluated and,
+if non-void, copied (bitwise) into the temporary. If the initializer
+is void, that means that it will perform the initialization itself.
Often, a @code{TARGET_EXPR} occurs on the right-hand side of an
assignment, or as the second operand to a comma-expression which is
@item AGGR_INIT_EXPR
An @code{AGGR_INIT_EXPR} represents the initialization as the return
value of a function call, or as the result of a constructor. An
-@code{AGGR_INIT_EXPR} will only appear as the second operand of a
-@code{TARGET_EXPR}. The first operand to the @code{AGGR_INIT_EXPR} is
-the address of a function to call, just as in a @code{CALL_EXPR}. The
-second operand are the arguments to pass that function, as a
-@code{TREE_LIST}, again in a manner similar to that of a
-@code{CALL_EXPR}. The value of the expression is that returned by the
-function.
+@code{AGGR_INIT_EXPR} will only appear as a full-expression, or as the
+second operand of a @code{TARGET_EXPR}. The first operand to the
+@code{AGGR_INIT_EXPR} is the address of a function to call, just as in
+a @code{CALL_EXPR}. The second operand are the arguments to pass that
+function, as a @code{TREE_LIST}, again in a manner similar to that of
+a @code{CALL_EXPR}.
If @code{AGGR_INIT_VIA_CTOR_P} holds of the @code{AGGR_INIT_EXPR}, then
the initialization is via a constructor call. The address of the third
operand of the @code{AGGR_INIT_EXPR}, which is always a @code{VAR_DECL},
is taken, and this value replaces the first argument in the argument
-list. In this case, the value of the expression is the @code{VAR_DECL}
-given by the third operand to the @code{AGGR_INIT_EXPR}; constructors do
-not return a value.
+list.
+
+In either case, the expression is void.
@item VTABLE_REF
A @code{VTABLE_REF} indicates that the interior expression computes
/* Mark it as expanded. */
TREE_OPERAND (exp, 1) = NULL_TREE;
- store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
+ if (VOID_TYPE_P (TREE_TYPE (exp1)))
+ /* If the initializer is void, just expand it; it will initialize
+ the object directly. */
+ expand_expr (exp1, const0_rtx, VOIDmode, 0);
+ else
+ store_expr (exp1, target, modifier == EXPAND_STACK_PARM ? 2 : 0);
expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp));
gimplify_bind_expr (&init, temp, pre_p);
if (init != temp)
{
- init = build (MODIFY_EXPR, void_type_node, temp, init);
+ if (! VOID_TYPE_P (TREE_TYPE (init)))
+ init = build (MODIFY_EXPR, void_type_node, temp, init);
ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none);
if (ret == GS_ERROR)
return GS_ERROR;
-// { dg-do run { xfail *-*-* } }
-// { dg-options "" }
-
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 30 Jul 2003 <nathan@codesourcery.com>
-// make statement expressions work properly
+// make sure statement expressions work properly
+
+// { dg-do run }
+// { dg-options "" }
extern "C" int printf (char const *, ...);
extern "C" void abort ();
({A<14> a; a; });
Check (0, 0, 0, "end");
}
-
DEFTREECODE (INIT_EXPR, "init_expr", 'e', 2)
/* For TARGET_EXPR, operand 0 is the target of an initialization,
- operand 1 is the initializer for the target,
- and operand 2 is the cleanup for this node, if any.
- and operand 3 is the saved initializer after this node has been
- expanded once, this is so we can re-expand the tree later. */
+ operand 1 is the initializer for the target, which may be void
+ if simplify expanding it initializes the target.
+ operand 2 is the cleanup for this node, if any.
+ operand 3 is the saved initializer after this node has been
+ expanded once; this is so we can re-expand the tree later. */
DEFTREECODE (TARGET_EXPR, "target_expr", 'e', 4)
/* Conditional expression ( ... ? ... : ... in C).