c-common.c (verify_sequence_points): Export.
* c-common.c (verify_sequence_points): Export. (c_expand_expr_stmt): Move to c-typeck.c. * c-common.h (c_expand_expr_stmt): Remove. (verify_sequence_points): Declare. * c-mudflap.c (mflang_flush_calls): Use c_finish_expr_stmt. * c-parse.in (for_init_stmt, stmt): Likewise. * c-tree.h (c_finish_expr_stmt): Declare. (c_tree_expr_nonnegative_p): Remove. * c-typeck.c (c_tree_expr_nonnegative_p): Remove. (build_conditional_expr, build_binary_op): Use tree_expr_nonnegative_p. (emit_side_effect_warnings): New. (c_finish_expr_stmt): Rename from c_expand_expr_stmt. Use it. (c_finish_stmt_expr): Work without EXPR_STMT. Handle eh regions. Use emit_side_effect_warnings. (push_cleanup): Copy STATEMENT_LIST_STMT_EXPR. * fold-const.c (tree_expr_nonnegative_p): Handle TARGET_EXPR. * gimplify.c (gimplify_modify_expr): Don't discard TARGET_EXPR with void initializer. (gimplify_target_expr): Handle void BIND_EXPR initializer. * tree-inline.c (estimate_num_insns_1): Fix type lookup for INIT_EXPR and MODIFY_EXPR. * objc/objc-act.c (build_module_descriptor): Use add_stmt instead of c_expand_expr_stmt. cp/ * semantics.c (finish_expr_stmt): Call verify_sequence_points. testsuite/ * gcc.dg/tree-ssa/20030714-1.c: Rename variables to avoid merging && to BIT_FIELD_REF. From-SVN: r83429
This commit is contained in:
parent
2c486ea78c
commit
3a5b9284da
15 changed files with 238 additions and 114 deletions
|
@ -1,3 +1,29 @@
|
|||
2004-06-21 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* c-common.c (verify_sequence_points): Export.
|
||||
(c_expand_expr_stmt): Move to c-typeck.c.
|
||||
* c-common.h (c_expand_expr_stmt): Remove.
|
||||
(verify_sequence_points): Declare.
|
||||
* c-mudflap.c (mflang_flush_calls): Use c_finish_expr_stmt.
|
||||
* c-parse.in (for_init_stmt, stmt): Likewise.
|
||||
* c-tree.h (c_finish_expr_stmt): Declare.
|
||||
(c_tree_expr_nonnegative_p): Remove.
|
||||
* c-typeck.c (c_tree_expr_nonnegative_p): Remove.
|
||||
(build_conditional_expr, build_binary_op): Use tree_expr_nonnegative_p.
|
||||
(emit_side_effect_warnings): New.
|
||||
(c_finish_expr_stmt): Rename from c_expand_expr_stmt. Use it.
|
||||
(c_finish_stmt_expr): Work without EXPR_STMT. Handle eh regions.
|
||||
Use emit_side_effect_warnings.
|
||||
(push_cleanup): Copy STATEMENT_LIST_STMT_EXPR.
|
||||
* fold-const.c (tree_expr_nonnegative_p): Handle TARGET_EXPR.
|
||||
* gimplify.c (gimplify_modify_expr): Don't discard TARGET_EXPR
|
||||
with void initializer.
|
||||
(gimplify_target_expr): Handle void BIND_EXPR initializer.
|
||||
* tree-inline.c (estimate_num_insns_1): Fix type lookup for
|
||||
INIT_EXPR and MODIFY_EXPR.
|
||||
* objc/objc-act.c (build_module_descriptor): Use add_stmt
|
||||
instead of c_expand_expr_stmt.
|
||||
|
||||
2004-06-21 Paolo Bonzini <bonzini@gnu.org>
|
||||
|
||||
* fold-const.c (fold_cond_expr_with_comparison):
|
||||
|
|
|
@ -1247,7 +1247,6 @@ static int warning_candidate_p (tree);
|
|||
static void warn_for_collisions (struct tlist *);
|
||||
static void warn_for_collisions_1 (tree, tree, struct tlist *, int);
|
||||
static struct tlist *new_tlist (struct tlist *, tree, tree);
|
||||
static void verify_sequence_points (tree);
|
||||
|
||||
/* Create a new struct tlist and fill in its fields. */
|
||||
static struct tlist *
|
||||
|
@ -1586,7 +1585,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
|
|||
/* Try to warn for undefined behavior in EXPR due to missing sequence
|
||||
points. */
|
||||
|
||||
static void
|
||||
void
|
||||
verify_sequence_points (tree expr)
|
||||
{
|
||||
struct tlist *before_sp = 0, *after_sp = 0;
|
||||
|
@ -1603,32 +1602,6 @@ verify_sequence_points (tree expr)
|
|||
warn_for_collisions (after_sp);
|
||||
obstack_free (&tlist_obstack, tlist_firstobj);
|
||||
}
|
||||
|
||||
tree
|
||||
c_expand_expr_stmt (tree expr)
|
||||
{
|
||||
/* Do default conversion if safe and possibly important,
|
||||
in case within ({...}). */
|
||||
if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
|
||||
&& (flag_isoc99 || lvalue_p (expr)))
|
||||
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
|
||||
expr = default_conversion (expr);
|
||||
|
||||
if (warn_sequence_point)
|
||||
verify_sequence_points (expr);
|
||||
|
||||
if (TREE_TYPE (expr) != error_mark_node
|
||||
&& !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr))
|
||||
&& TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
|
||||
error ("expression statement has incomplete type");
|
||||
|
||||
/* As tempting as it might be, we can't diagnose statement with no
|
||||
effect yet. We have to wait until after statement expressions
|
||||
have been parsed, and that process modifies the trees we are
|
||||
creating here. */
|
||||
|
||||
return add_stmt (build_stmt (EXPR_STMT, expr));
|
||||
}
|
||||
|
||||
/* Validate the expression after `case' and apply default promotions. */
|
||||
|
||||
|
|
|
@ -859,7 +859,6 @@ extern void binary_op_error (enum tree_code);
|
|||
#define my_friendly_assert(EXP, N) (void) \
|
||||
(((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0)
|
||||
|
||||
extern tree c_expand_expr_stmt (tree);
|
||||
/* Validate the expression after `case' and apply default promotions. */
|
||||
extern tree check_case_value (tree);
|
||||
extern tree fix_string_type (tree);
|
||||
|
@ -1097,6 +1096,8 @@ extern tree c_walk_subtrees (tree*, int*, walk_tree_fn, void*, void*);
|
|||
|
||||
extern void c_warn_unused_result (tree *);
|
||||
|
||||
extern void verify_sequence_points (tree);
|
||||
|
||||
/* In c-gimplify.c */
|
||||
extern void c_genericize (tree);
|
||||
extern int c_gimplify_expr (tree *, tree *, tree *);
|
||||
|
|
|
@ -85,7 +85,7 @@ mflang_flush_calls (tree enqueued_call_stmt_chain)
|
|||
mf_mark (current_function_decl);
|
||||
|
||||
cs = c_begin_compound_stmt (true);
|
||||
c_expand_expr_stmt (enqueued_call_stmt_chain);
|
||||
c_finish_expr_stmt (enqueued_call_stmt_chain);
|
||||
add_stmt (c_end_compound_stmt (cs, true));
|
||||
|
||||
finish_function ();
|
||||
|
|
|
@ -2210,7 +2210,7 @@ select_or_iter_stmt:
|
|||
|
||||
for_init_stmt:
|
||||
xexpr ';'
|
||||
{ add_stmt (build_stmt (EXPR_STMT, $1)); }
|
||||
{ c_finish_expr_stmt ($1); }
|
||||
| decl
|
||||
{ check_for_loop_decls (); }
|
||||
;
|
||||
|
@ -2226,7 +2226,7 @@ stmt:
|
|||
compstmt
|
||||
{ stmt_count++; add_stmt ($1); }
|
||||
| expr ';'
|
||||
{ stmt_count++; c_expand_expr_stmt ($1); }
|
||||
{ stmt_count++; c_finish_expr_stmt ($1); }
|
||||
| c99_block_start select_or_iter_stmt
|
||||
{ add_stmt (c_end_compound_stmt ($1, flag_isoc99)); }
|
||||
| BREAK ';'
|
||||
|
|
|
@ -227,7 +227,6 @@ extern tree build_indirect_ref (tree, const char *);
|
|||
extern tree build_array_ref (tree, tree);
|
||||
extern tree build_external_ref (tree, int);
|
||||
extern tree parser_build_binary_op (enum tree_code, tree, tree);
|
||||
extern int c_tree_expr_nonnegative_p (tree);
|
||||
extern void readonly_error (tree, const char *);
|
||||
extern tree build_conditional_expr (tree, tree, tree);
|
||||
extern tree build_compound_expr (tree);
|
||||
|
@ -272,6 +271,7 @@ extern void c_finish_for_stmt_incr (tree, tree);
|
|||
extern void c_finish_for_stmt (tree, tree);
|
||||
extern tree c_begin_stmt_expr (void);
|
||||
extern tree c_finish_stmt_expr (tree);
|
||||
extern void c_finish_expr_stmt (tree);
|
||||
extern tree build_offsetof (tree, tree);
|
||||
|
||||
/* Set to 0 at beginning of a function definition, set to 1 if
|
||||
|
|
183
gcc/c-typeck.c
183
gcc/c-typeck.c
|
@ -46,6 +46,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
|||
#include "ggc.h"
|
||||
#include "target.h"
|
||||
#include "tree-iterator.h"
|
||||
#include "tree-gimple.h"
|
||||
|
||||
|
||||
/* Nonzero if we've already printed a "missing braces around initializer"
|
||||
|
@ -2201,17 +2202,6 @@ parser_build_binary_op (enum tree_code code, tree arg1, tree arg2)
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if `t' is known to be non-negative. */
|
||||
|
||||
int
|
||||
c_tree_expr_nonnegative_p (tree t)
|
||||
{
|
||||
if (TREE_CODE (t) == STMT_EXPR)
|
||||
t = expr_last (STMT_EXPR_STMT (t));
|
||||
return tree_expr_nonnegative_p (t);
|
||||
}
|
||||
|
||||
/* Return a tree for the difference of pointers OP0 and OP1.
|
||||
The resulting tree has type int. */
|
||||
|
||||
|
@ -2810,8 +2800,8 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
|
|||
/* Do not warn if the signed quantity is an unsuffixed
|
||||
integer literal (or some static constant expression
|
||||
involving such literals) and it is non-negative. */
|
||||
else if ((unsigned_op2 && c_tree_expr_nonnegative_p (op1))
|
||||
|| (unsigned_op1 && c_tree_expr_nonnegative_p (op2)))
|
||||
else if ((unsigned_op2 && tree_expr_nonnegative_p (op1))
|
||||
|| (unsigned_op1 && tree_expr_nonnegative_p (op2)))
|
||||
/* OK */;
|
||||
else
|
||||
warning ("signed and unsigned type in conditional expression");
|
||||
|
@ -6657,7 +6647,61 @@ c_finish_for_stmt (tree body, tree for_stmt)
|
|||
FOR_BODY (for_stmt) = body;
|
||||
}
|
||||
|
||||
/* Create a statement expression. */
|
||||
/* A helper routine for c_finish_expr_stmt and c_finish_stmt_expr. */
|
||||
|
||||
static void
|
||||
emit_side_effect_warnings (tree expr)
|
||||
{
|
||||
if (!TREE_SIDE_EFFECTS (expr))
|
||||
{
|
||||
if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
|
||||
warning ("%Hstatement with no effect",
|
||||
EXPR_LOCUS (expr) ? EXPR_LOCUS (expr) : &input_location);
|
||||
}
|
||||
else if (warn_unused_value)
|
||||
warn_if_unused_value (expr, input_location);
|
||||
}
|
||||
|
||||
/* Emit an expression as a statement. */
|
||||
|
||||
void
|
||||
c_finish_expr_stmt (tree expr)
|
||||
{
|
||||
if (!expr)
|
||||
return;
|
||||
|
||||
/* Do default conversion if safe and possibly important,
|
||||
in case within ({...}). */
|
||||
if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
|
||||
&& (flag_isoc99 || lvalue_p (expr)))
|
||||
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
|
||||
expr = default_conversion (expr);
|
||||
|
||||
if (warn_sequence_point)
|
||||
verify_sequence_points (expr);
|
||||
|
||||
if (TREE_TYPE (expr) != error_mark_node
|
||||
&& !COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (expr))
|
||||
&& TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
|
||||
error ("expression statement has incomplete type");
|
||||
|
||||
/* If we're not processing a statement expression, warn about unused values.
|
||||
Warnings for statement expressions will be emitted later, once we figure
|
||||
out which is the result. */
|
||||
if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
|
||||
&& (extra_warnings || warn_unused_value))
|
||||
emit_side_effect_warnings (expr);
|
||||
|
||||
/* If the expression is not of a type to which we cannot assign a line
|
||||
number, wrap the thing in a no-op NOP_EXPR. */
|
||||
if (DECL_P (expr) || TREE_CODE_CLASS (TREE_CODE (expr)) == 'c')
|
||||
expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
|
||||
|
||||
add_stmt (expr);
|
||||
}
|
||||
|
||||
/* Do the opposite and emit a statement as an expression. To begin,
|
||||
create a new binding level and return it. */
|
||||
|
||||
tree
|
||||
c_begin_stmt_expr (void)
|
||||
|
@ -6679,63 +6723,77 @@ c_begin_stmt_expr (void)
|
|||
tree
|
||||
c_finish_stmt_expr (tree body)
|
||||
{
|
||||
tree ret, last, type;
|
||||
tree last, type, tmp, val;
|
||||
tree *last_p;
|
||||
|
||||
body = c_end_compound_stmt (body, true);
|
||||
|
||||
/* Locate the last statement in BODY. */
|
||||
last = body, last_p = &body;
|
||||
if (TREE_CODE (last) == BIND_EXPR)
|
||||
{
|
||||
last_p = &BIND_EXPR_BODY (last);
|
||||
last = BIND_EXPR_BODY (last);
|
||||
}
|
||||
/* Locate the last statement in BODY. See c_end_compound_stmt
|
||||
about always returning a BIND_EXPR. */
|
||||
last_p = &BIND_EXPR_BODY (body);
|
||||
last = BIND_EXPR_BODY (body);
|
||||
|
||||
continue_searching:
|
||||
if (TREE_CODE (last) == STATEMENT_LIST)
|
||||
{
|
||||
tree_stmt_iterator i = tsi_last (last);
|
||||
if (tsi_end_p (i))
|
||||
tree_stmt_iterator i;
|
||||
|
||||
/* This can happen with degenerate cases like ({ }). No value. */
|
||||
if (!TREE_SIDE_EFFECTS (last))
|
||||
return body;
|
||||
|
||||
/* If we're supposed to generate side effects warnings, process
|
||||
all of the statements except the last. */
|
||||
if (extra_warnings || warn_unused_value)
|
||||
{
|
||||
type = void_type_node;
|
||||
/* ??? Warn */
|
||||
goto no_expr;
|
||||
for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
|
||||
emit_side_effect_warnings (tsi_stmt (i));
|
||||
}
|
||||
else
|
||||
{
|
||||
last_p = tsi_stmt_ptr (i);
|
||||
last = *last_p;
|
||||
}
|
||||
i = tsi_last (last);
|
||||
last_p = tsi_stmt_ptr (i);
|
||||
last = *last_p;
|
||||
}
|
||||
|
||||
/* If the last statement is an EXPR_STMT, then unwrap it. Otherwise
|
||||
voidify_wrapper_expr will stuff it inside a MODIFY_EXPR and we'll
|
||||
fail gimplification. */
|
||||
/* ??? Should we go ahead and perform voidify_wrapper_expr here?
|
||||
We've got about all the information we need here. All we'd have
|
||||
to do even for proper type safety is to create, in effect,
|
||||
( ({ ...; tmp = last; }), tmp )
|
||||
I.e. a COMPOUND_EXPR with the rhs being the compiler temporary.
|
||||
Not going to try this now, since it's not clear what should
|
||||
happen (wrt bindings) with new temporaries at this stage. It's
|
||||
easier once we begin gimplification. */
|
||||
if (TREE_CODE (last) == EXPR_STMT)
|
||||
*last_p = last = EXPR_STMT_EXPR (last);
|
||||
/* If the end of the list is exception related, then the list was split
|
||||
by a call to push_cleanup. Continue searching. */
|
||||
if (TREE_CODE (last) == TRY_FINALLY_EXPR
|
||||
|| TREE_CODE (last) == TRY_CATCH_EXPR)
|
||||
{
|
||||
last_p = &TREE_OPERAND (last, 0);
|
||||
last = *last_p;
|
||||
goto continue_searching;
|
||||
}
|
||||
|
||||
/* In the case that the BIND_EXPR is not necessary, return the
|
||||
expression out from inside it. */
|
||||
if (last == BIND_EXPR_BODY (body) && BIND_EXPR_VARS (body) == NULL)
|
||||
return last;
|
||||
|
||||
/* Extract the type of said expression. */
|
||||
type = TREE_TYPE (last);
|
||||
if (!type)
|
||||
type = void_type_node;
|
||||
|
||||
no_expr:
|
||||
/* If what's left is compound, make sure we've got a BIND_EXPR, and
|
||||
that it has the proper type. */
|
||||
ret = body;
|
||||
if (TREE_CODE (ret) == STATEMENT_LIST)
|
||||
ret = build (BIND_EXPR, type, NULL, ret, NULL);
|
||||
else if (TREE_CODE (ret) == BIND_EXPR)
|
||||
TREE_TYPE (ret) = type;
|
||||
/* If we're not returning a value at all, then the BIND_EXPR that
|
||||
we already have is a fine expression to return. */
|
||||
if (!type || VOID_TYPE_P (type))
|
||||
return body;
|
||||
|
||||
return ret;
|
||||
/* Now that we've located the expression containing the value, it seems
|
||||
silly to make voidify_wrapper_expr repeat the process. Create a
|
||||
temporary of the appropriate type and stick it in a TARGET_EXPR. */
|
||||
tmp = create_tmp_var_raw (type, NULL);
|
||||
|
||||
/* Unwrap a no-op NOP_EXPR as added by c_finish_expr_stmt. This avoids
|
||||
tree_expr_nonnegative_p giving up immediately. */
|
||||
val = last;
|
||||
if (TREE_CODE (val) == NOP_EXPR
|
||||
&& TREE_TYPE (val) == TREE_TYPE (TREE_OPERAND (val, 0)))
|
||||
val = TREE_OPERAND (val, 0);
|
||||
|
||||
*last_p = build (MODIFY_EXPR, void_type_node, tmp, val);
|
||||
SET_EXPR_LOCUS (*last_p, EXPR_LOCUS (last));
|
||||
|
||||
return build (TARGET_EXPR, type, tmp, body, NULL_TREE, NULL_TREE);
|
||||
}
|
||||
|
||||
/* Begin and end compound statements. This is as simple as pushing
|
||||
|
@ -6791,10 +6849,17 @@ c_end_compound_stmt (tree stmt, bool do_scope)
|
|||
void
|
||||
push_cleanup (tree decl ATTRIBUTE_UNUSED, tree cleanup, bool eh_only)
|
||||
{
|
||||
enum tree_code code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
|
||||
tree stmt = build_stmt (code, NULL, cleanup);
|
||||
enum tree_code code;
|
||||
tree stmt, list;
|
||||
bool stmt_expr;
|
||||
|
||||
code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
|
||||
stmt = build_stmt (code, NULL, cleanup);
|
||||
add_stmt (stmt);
|
||||
TREE_OPERAND (stmt, 0) = push_stmt_list ();
|
||||
stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list);
|
||||
list = push_stmt_list ();
|
||||
TREE_OPERAND (stmt, 0) = list;
|
||||
STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
|
||||
}
|
||||
|
||||
/* Build a binary-operation expression without default conversions.
|
||||
|
@ -7412,7 +7477,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
constant expression involving such literals or a
|
||||
conditional expression involving such literals)
|
||||
and it is non-negative. */
|
||||
if (c_tree_expr_nonnegative_p (sop))
|
||||
if (tree_expr_nonnegative_p (sop))
|
||||
/* OK */;
|
||||
/* Do not warn if the comparison is an equality operation,
|
||||
the unsigned quantity is an integral constant, and it
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2004-06-21 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* semantics.c (finish_expr_stmt): Call verify_sequence_points.
|
||||
|
||||
2004-06-20 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* cp-tree.h (add_decl_stmt): Declare.
|
||||
|
|
|
@ -493,7 +493,11 @@ finish_expr_stmt (tree expr)
|
|||
if (expr != NULL_TREE)
|
||||
{
|
||||
if (!processing_template_decl)
|
||||
expr = convert_to_void (expr, "statement");
|
||||
{
|
||||
if (warn_sequence_point)
|
||||
verify_sequence_points (expr);
|
||||
expr = convert_to_void (expr, "statement");
|
||||
}
|
||||
else if (!type_dependent_expression_p (expr))
|
||||
convert_to_void (build_non_dependent_expr (expr), "statement");
|
||||
|
||||
|
|
|
@ -9267,6 +9267,37 @@ tree_expr_nonnegative_p (tree t)
|
|||
case RTL_EXPR:
|
||||
return rtl_expr_nonnegative_p (RTL_EXPR_RTL (t));
|
||||
|
||||
case TARGET_EXPR:
|
||||
{
|
||||
tree temp = TARGET_EXPR_SLOT (t);
|
||||
t = TARGET_EXPR_INITIAL (t);
|
||||
|
||||
/* If the initializer is non-void, then it's a normal expression
|
||||
that will be assigned to the slot. */
|
||||
if (!VOID_TYPE_P (t))
|
||||
return tree_expr_nonnegative_p (t);
|
||||
|
||||
/* Otherwise, the initializer sets the slot in some way. One common
|
||||
way is an assignment statement at the end of the initializer. */
|
||||
while (1)
|
||||
{
|
||||
if (TREE_CODE (t) == BIND_EXPR)
|
||||
t = expr_last (BIND_EXPR_BODY (t));
|
||||
else if (TREE_CODE (t) == TRY_FINALLY_EXPR
|
||||
|| TREE_CODE (t) == TRY_CATCH_EXPR)
|
||||
t = expr_last (TREE_OPERAND (t, 0));
|
||||
else if (TREE_CODE (t) == STATEMENT_LIST)
|
||||
t = expr_last (t);
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (TREE_CODE (t) == MODIFY_EXPR
|
||||
&& TREE_OPERAND (t, 0) == temp)
|
||||
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case CALL_EXPR:
|
||||
{
|
||||
tree fndecl = get_callee_fndecl (t);
|
||||
|
|
|
@ -2472,13 +2472,19 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
|
|||
return ret;
|
||||
|
||||
/* If we are initializing something from a TARGET_EXPR, strip the
|
||||
TARGET_EXPR and initialize it directly. */
|
||||
TARGET_EXPR and initialize it directly, if possible. This can't
|
||||
be done if the initializer is void, since that implies that the
|
||||
temporary is set in some non-trivial way. */
|
||||
/* What about code that pulls out the temp and uses it elsewhere? I
|
||||
think that such code never uses the TARGET_EXPR as an initializer. If
|
||||
I'm wrong, we'll abort because the temp won't have any RTL. In that
|
||||
case, I guess we'll need to replace references somehow. */
|
||||
if (TREE_CODE (*from_p) == TARGET_EXPR)
|
||||
*from_p = TARGET_EXPR_INITIAL (*from_p);
|
||||
{
|
||||
tree init = TARGET_EXPR_INITIAL (*from_p);
|
||||
if (!VOID_TYPE_P (TREE_TYPE (init)))
|
||||
*from_p = init;
|
||||
}
|
||||
|
||||
/* If we're assigning from a ?: expression with ADDRESSABLE type, push
|
||||
the assignment down into the branches, since we can't generate a
|
||||
|
@ -3021,22 +3027,29 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p)
|
|||
|
||||
if (init)
|
||||
{
|
||||
/* TARGET_EXPR temps aren't part of the enclosing block, so add it to the
|
||||
temps list. */
|
||||
/* TARGET_EXPR temps aren't part of the enclosing block, so add it
|
||||
to the temps list. */
|
||||
gimple_add_tmp_var (temp);
|
||||
|
||||
/* Build up the initialization and add it to pre_p. Special handling
|
||||
for BIND_EXPR can result in fewer temporaries created. */
|
||||
if (TREE_CODE (init) == BIND_EXPR)
|
||||
gimplify_bind_expr (&init, temp, pre_p);
|
||||
if (init != temp)
|
||||
/* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
|
||||
expression is supposed to initialize the slot. */
|
||||
if (VOID_TYPE_P (TREE_TYPE (init)))
|
||||
ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none);
|
||||
else
|
||||
{
|
||||
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;
|
||||
/* Special handling for BIND_EXPR can result in fewer temps. */
|
||||
ret = GS_OK;
|
||||
if (TREE_CODE (init) == BIND_EXPR)
|
||||
gimplify_bind_expr (&init, temp, pre_p);
|
||||
if (init != temp)
|
||||
{
|
||||
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;
|
||||
append_to_statement_list (init, pre_p);
|
||||
|
||||
/* If needed, push the cleanup for the temp. */
|
||||
|
|
|
@ -1918,7 +1918,7 @@ build_module_descriptor (void)
|
|||
build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
|
||||
decelerator = build_function_call (execclass_decl, parms);
|
||||
|
||||
c_expand_expr_stmt (decelerator);
|
||||
add_stmt (decelerator);
|
||||
add_stmt (c_end_compound_stmt (compound, true));
|
||||
|
||||
finish_function ();
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2004-06-21 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* gcc.dg/tree-ssa/20030714-1.c: Rename variables to avoid
|
||||
merging && to BIT_FIELD_REF.
|
||||
|
||||
2004-06-21 Richard Sandiford <rsandifo@redhat.com>
|
||||
|
||||
* g++.dg/opt/placeholder1.C: New test.
|
||||
|
|
|
@ -19,12 +19,12 @@ find_base_value (src)
|
|||
rtx src;
|
||||
{
|
||||
rtx temp;
|
||||
rtx src_0;
|
||||
rtx src_1;
|
||||
rtx src_0, src_2;
|
||||
rtx src_1, src_3;
|
||||
|
||||
if ((src_0->code == REG) && (({src_0;})->frame_related))
|
||||
if ((src_0->code == REG) && (({src_2;})->frame_related))
|
||||
return find_base_value (src_0);
|
||||
if ((src_1->code == REG) && (({ src_1;})->frame_related))
|
||||
if ((src_1->code == REG) && (({ src_3;})->frame_related))
|
||||
return find_base_value (src_1);
|
||||
if (src_0->code == REG)
|
||||
find_base_value (src_0);
|
||||
|
@ -41,4 +41,3 @@ find_base_value (src)
|
|||
|
||||
/* There should be three loads of ->code. */
|
||||
/* { dg-final { scan-tree-dump-times "->code" 3 "dom3"} } */
|
||||
|
||||
|
|
|
@ -1251,11 +1251,14 @@ estimate_num_insns_1 (tree *tp, int *walk_subtrees, void *data)
|
|||
case STRING_CST:
|
||||
*walk_subtrees = 0;
|
||||
return NULL;
|
||||
|
||||
/* Recognize assignments of large structures and constructors of
|
||||
big arrays. */
|
||||
case INIT_EXPR:
|
||||
case TARGET_EXPR:
|
||||
case MODIFY_EXPR:
|
||||
x = TREE_OPERAND (x, 0);
|
||||
/* FALLTHRU */
|
||||
case TARGET_EXPR:
|
||||
case CONSTRUCTOR:
|
||||
{
|
||||
HOST_WIDE_INT size;
|
||||
|
|
Loading…
Add table
Reference in a new issue