summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/c-common.c25
-rw-r--r--gcc/c-common.h3
-rw-r--r--gcc/c-semantics.c25
-rw-r--r--gcc/expr.c6
-rw-r--r--gcc/stmt.c67
-rw-r--r--gcc/tree-inline.c6
-rw-r--r--gcc/tree.h12
8 files changed, 124 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1b5008b0cba..a9eaf973d7f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,24 @@
+2002-01-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * c-common.h (genrtl_expr_stmt_value): Declare.
+ * c-semantics.c (genrtl_goto_stmt): Redirect to...
+ (genrtl_goto_stmt_value): ... this new function. Pass new
+ argument down to expand_expr_stmt_value, taking
+ TREE_ADDRESSABLE into account.
+ * c-common.c (c_expand_expr): Mark the last EXPR_STMT of a
+ STMT_EXPR as addressable, i.e., one whose result we want.
+ * expr.c (expand_expr): Don't save expression statement value
+ of labeled_blocks or loop_exprs.
+ * stmt.c (expand_expr_stmt): Redirect to...
+ (expand_expr_stmt_value): ... this new function. Use new
+ argument to tell whether to save expression value.
+ (expand_end_stmt_expr): Reset last_expr_type and
+ last_expr_value if we don't have either.
+ * tree-inline.c (declare_return_variable): Mark its use
+ statement as addressable.
+ * tree.h: Document new use of TREE_ADDRESSABLE.
+ (expand_expr_stmt_value): Declare.
+
2002-01-01 Joseph S. Myers <jsm28@cam.ac.uk>
* configure.in: Prepend ${srcdir}/config/${cpu_type}/ instead of
diff --git a/gcc/c-common.c b/gcc/c-common.c
index d671e3bdf72..39ae17d9a8d 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -1,6 +1,6 @@
/* Subroutines shared by all languages that are variants of C.
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -3418,6 +3418,27 @@ c_expand_expr (exp, target, tmode, modifier)
STMT_EXPR. */
push_temp_slots ();
rtl_expr = expand_start_stmt_expr ();
+
+ /* If we want the result of this expression, find the last
+ EXPR_STMT in the COMPOUND_STMT and mark it as addressable. */
+ if (target != const0_rtx
+ && TREE_CODE (STMT_EXPR_STMT (exp)) == COMPOUND_STMT
+ && TREE_CODE (COMPOUND_BODY (STMT_EXPR_STMT (exp))) == SCOPE_STMT)
+ {
+ tree expr = COMPOUND_BODY (STMT_EXPR_STMT (exp));
+ tree last = TREE_CHAIN (expr);
+
+ while (TREE_CHAIN (last))
+ {
+ expr = last;
+ last = TREE_CHAIN (last);
+ }
+
+ if (TREE_CODE (last) == SCOPE_STMT
+ && TREE_CODE (expr) == EXPR_STMT)
+ TREE_ADDRESSABLE (expr) = 1;
+ }
+
expand_stmt (STMT_EXPR_STMT (exp));
expand_end_stmt_expr (rtl_expr);
result = expand_expr (rtl_expr, target, tmode, modifier);
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 61b8f84428b..4c49b9fcddf 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -1,6 +1,6 @@
/* Definitions for c-common.c.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -717,6 +717,7 @@ extern void add_c_tree_codes PARAMS ((void));
extern void genrtl_do_pushlevel PARAMS ((void));
extern void genrtl_goto_stmt PARAMS ((tree));
extern void genrtl_expr_stmt PARAMS ((tree));
+extern void genrtl_expr_stmt_value PARAMS ((tree, int));
extern void genrtl_decl_stmt PARAMS ((tree));
extern void genrtl_if_stmt PARAMS ((tree));
extern void genrtl_while_stmt PARAMS ((tree));
diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c
index 86e2e8999bb..ef9ba333751 100644
--- a/gcc/c-semantics.c
+++ b/gcc/c-semantics.c
@@ -1,7 +1,7 @@
/* This file contains the definitions and documentation for the common
tree codes used in the GNU C and C++ compilers (see c-common.def
for the standard codes).
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Benjamin Chelf (chelf@codesourcery.com).
This file is part of GCC.
@@ -305,12 +305,27 @@ genrtl_goto_stmt (destination)
expand_computed_goto (destination);
}
-/* Generate the RTL for EXPR, which is an EXPR_STMT. */
+/* Generate the RTL for EXPR, which is an EXPR_STMT. Provided just
+ for backward compatibility. genrtl_expr_stmt_value() should be
+ used for new code. */
-void
+void
genrtl_expr_stmt (expr)
tree expr;
{
+ genrtl_expr_stmt_value (expr, -1);
+}
+
+/* Generate the RTL for EXPR, which is an EXPR_STMT. WANT_VALUE tells
+ whether to (1) save the value of the expression, (0) discard it or
+ (-1) use expr_stmts_for_value to tell. The use of -1 is
+ deprecated, and retained only for backward compatibility. */
+
+void
+genrtl_expr_stmt_value (expr, want_value)
+ tree expr;
+ int want_value;
+{
if (expr != NULL_TREE)
{
emit_line_note (input_filename, lineno);
@@ -319,7 +334,7 @@ genrtl_expr_stmt (expr)
expand_start_target_temps ();
if (expr != error_mark_node)
- expand_expr_stmt (expr);
+ expand_expr_stmt_value (expr, want_value);
if (stmts_are_full_exprs_p ())
expand_end_target_temps ();
@@ -748,7 +763,7 @@ expand_stmt (t)
break;
case EXPR_STMT:
- genrtl_expr_stmt (EXPR_STMT_EXPR (t));
+ genrtl_expr_stmt_value (EXPR_STMT_EXPR (t), TREE_ADDRESSABLE (t));
break;
case DECL_STMT:
diff --git a/gcc/expr.c b/gcc/expr.c
index 60c3431f73a..1388b6ff835 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1,6 +1,6 @@
/* Convert tree expression to rtl instructions, for GNU compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001 Free Software Foundation, Inc.
+ 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -6453,7 +6453,7 @@ expand_expr (exp, target, tmode, modifier)
case LABELED_BLOCK_EXPR:
if (LABELED_BLOCK_BODY (exp))
- expand_expr_stmt (LABELED_BLOCK_BODY (exp));
+ expand_expr_stmt_value (LABELED_BLOCK_BODY (exp), 0);
/* Should perhaps use expand_label, but this is simpler and safer. */
do_pending_stack_adjust ();
emit_label (label_rtx (LABELED_BLOCK_LABEL (exp)));
@@ -6468,7 +6468,7 @@ expand_expr (exp, target, tmode, modifier)
case LOOP_EXPR:
push_temp_slots ();
expand_start_loop (1);
- expand_expr_stmt (TREE_OPERAND (exp, 0));
+ expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0);
expand_end_loop ();
pop_temp_slots ();
diff --git a/gcc/stmt.c b/gcc/stmt.c
index c87612aa3c3..16a3882ffd0 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -1,6 +1,6 @@
/* Expands front end tree to back end RTL for GNU C-Compiler
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -2182,16 +2182,37 @@ resolve_operand_name_1 (p, outputs, inputs)
}
/* Generate RTL to evaluate the expression EXP
- and remember it in case this is the VALUE in a ({... VALUE; }) constr. */
+ and remember it in case this is the VALUE in a ({... VALUE; }) constr.
+ Provided just for backward-compatibility. expand_expr_stmt_value()
+ should be used for new code. */
void
expand_expr_stmt (exp)
tree exp;
{
+ expand_expr_stmt_value (exp, -1);
+}
+
+/* Generate RTL to evaluate the expression EXP. WANT_VALUE tells
+ whether to (1) save the value of the expression, (0) discard it or
+ (-1) use expr_stmts_for_value to tell. The use of -1 is
+ deprecated, and retained only for backward compatibility. */
+
+void
+expand_expr_stmt_value (exp, want_value)
+ tree exp;
+ int want_value;
+{
+ rtx value;
+ tree type;
+
+ if (want_value == -1)
+ want_value = expr_stmts_for_value != 0;
+
/* If -W, warn about statements with no side effects,
except for an explicit cast to void (e.g. for assert()), and
except inside a ({...}) where they may be useful. */
- if (expr_stmts_for_value == 0 && exp != error_mark_node)
+ if (! want_value && exp != error_mark_node)
{
if (! TREE_SIDE_EFFECTS (exp))
{
@@ -2207,34 +2228,31 @@ expand_expr_stmt (exp)
/* If EXP is of function type and we are expanding statements for
value, convert it to pointer-to-function. */
- if (expr_stmts_for_value && TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE)
+ if (want_value && TREE_CODE (TREE_TYPE (exp)) == FUNCTION_TYPE)
exp = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (exp)), exp);
/* The call to `expand_expr' could cause last_expr_type and
last_expr_value to get reset. Therefore, we set last_expr_value
and last_expr_type *after* calling expand_expr. */
- last_expr_value = expand_expr (exp,
- (expr_stmts_for_value
- ? NULL_RTX : const0_rtx),
- VOIDmode, 0);
- last_expr_type = TREE_TYPE (exp);
+ value = expand_expr (exp, want_value ? NULL_RTX : const0_rtx,
+ VOIDmode, 0);
+ type = TREE_TYPE (exp);
/* If all we do is reference a volatile value in memory,
copy it to a register to be sure it is actually touched. */
- if (last_expr_value != 0 && GET_CODE (last_expr_value) == MEM
- && TREE_THIS_VOLATILE (exp))
+ if (value && GET_CODE (value) == MEM && TREE_THIS_VOLATILE (exp))
{
- if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode)
+ if (TYPE_MODE (type) == VOIDmode)
;
- else if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
- copy_to_reg (last_expr_value);
+ else if (TYPE_MODE (type) != BLKmode)
+ value = copy_to_reg (value);
else
{
rtx lab = gen_label_rtx ();
/* Compare the value with itself to reference it. */
- emit_cmp_and_jump_insns (last_expr_value, last_expr_value, EQ,
- expand_expr (TYPE_SIZE (last_expr_type),
+ emit_cmp_and_jump_insns (value, value, EQ,
+ expand_expr (TYPE_SIZE (type),
NULL_RTX, VOIDmode, 0),
BLKmode, 0, lab);
emit_label (lab);
@@ -2243,13 +2261,19 @@ expand_expr_stmt (exp)
/* If this expression is part of a ({...}) and is in memory, we may have
to preserve temporaries. */
- preserve_temp_slots (last_expr_value);
+ preserve_temp_slots (value);
/* Free any temporaries used to evaluate this expression. Any temporary
used as a result of this expression will already have been preserved
above. */
free_temp_slots ();
+ if (want_value)
+ {
+ last_expr_value = value;
+ last_expr_type = type;
+ }
+
emit_queue ();
}
@@ -2386,6 +2410,7 @@ expand_start_stmt_expr ()
start_sequence_for_rtl_expr (t);
NO_DEFER_POP;
expr_stmts_for_value++;
+ last_expr_value = NULL_RTX;
return t;
}
@@ -2407,15 +2432,11 @@ expand_end_stmt_expr (t)
{
OK_DEFER_POP;
- if (last_expr_type == 0)
+ if (! last_expr_value || ! last_expr_type)
{
- last_expr_type = void_type_node;
last_expr_value = const0_rtx;
+ last_expr_type = void_type_node;
}
- else if (last_expr_value == 0)
- /* There are some cases where this can happen, such as when the
- statement is void type. */
- last_expr_value = const0_rtx;
else if (GET_CODE (last_expr_value) != REG && ! CONSTANT_P (last_expr_value))
/* Remove any possible QUEUED. */
last_expr_value = protect_from_queue (last_expr_value, 0);
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 6cd1fbb5e15..02ba7161b46 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1,5 +1,5 @@
/* Control and data flow functions for trees.
- Copyright 2001 Free Software Foundation, Inc.
+ Copyright 2001, 2002 Free Software Foundation, Inc.
Contributed by Alexandre Oliva <aoliva@redhat.com>
This file is part of GNU CC.
@@ -624,7 +624,9 @@ declare_return_variable (id, use_stmt)
*use_stmt = build_stmt (EXPR_STMT,
build1 (NOP_EXPR, TREE_TYPE (TREE_TYPE (fn)),
var));
-
+
+ TREE_ADDRESSABLE (*use_stmt) = 1;
+
/* Build the declaration statement if FN does not return an
aggregate. */
if (need_return_decl)
diff --git a/gcc/tree.h b/gcc/tree.h
index eee6663cb75..051aa2c5bf3 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1,6 +1,6 @@
/* Front-end tree definitions for GNU compiler.
- Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@@ -161,7 +161,9 @@ struct tree_common
TREE_ADDRESSABLE in
VAR_DECL, FUNCTION_DECL, FIELD_DECL, CONSTRUCTOR, LABEL_DECL,
- ..._TYPE, IDENTIFIER_NODE
+ ..._TYPE, IDENTIFIER_NODE.
+ In a STMT_EXPR, it means we want the result of the enclosed
+ expression.
static_flag:
@@ -258,8 +260,7 @@ struct tree_common
expressions, VAR_DECL, PARM_DECL, FIELD_DECL, FUNCTION_DECL,
IDENTIFIER_NODE
TYPE_BOUNDED in
- ..._TYPE
-*/
+ ..._TYPE */
/* Define accessors for the fields that all tree nodes have
(though some fields are not used for all kinds of nodes). */
@@ -2719,6 +2720,7 @@ extern void expand_fixups PARAMS ((rtx));
extern tree expand_start_stmt_expr PARAMS ((void));
extern tree expand_end_stmt_expr PARAMS ((tree));
extern void expand_expr_stmt PARAMS ((tree));
+extern void expand_expr_stmt_value PARAMS ((tree, int));
extern int warn_if_unused_value PARAMS ((tree));
extern void expand_decl_init PARAMS ((tree));
extern void clear_last_expr PARAMS ((void));