This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Decouple EXPR_STMT from statement expressions in C


Rearranges statement expressions in the C front end yet again.  We no
longer generate EXPR_STMT from C at all.  The primary blocker for this
had been a couple of warnings that needed to get generated elsewhere.

Now I generate these in two places.  One where the expressions are
emitted in the first place (if not inside a stmt expr).  Two when
finalizing the stmt expr, I walk over all sub-expressions not involved
in the actual return value.  This later walk is keyed by the warning
switches, so we don't do the extra traversal normally.

With Jason's recent change to how void initializers in TARGET_EXPRs
work, it's now easier to generate a TARGET_EXPR for a stmt expr than
anything else.  So I do.

The cleanup here is enough that tree-ssa/20030714-1.c started testing
something other than what it had before.  The first two if statements
had their && operator collapse to a BIT_FIELD_REF, which ruined what
we'd been planning on testing for in dom.


r~


        * 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.

Index: gcc/c-common.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.c,v
retrieving revision 1.517
diff -u -p -c -r1.517 c-common.c
*** gcc/c-common.c	19 Jun 2004 19:34:18 -0000	1.517
--- gcc/c-common.c	21 Jun 2004 09:03:46 -0000
*************** static int warning_candidate_p (tree);
*** 1247,1253 ****
  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 *
--- 1247,1252 ----
*************** verify_tree (tree x, struct tlist **pbef
*** 1586,1592 ****
  /* Try to warn for undefined behavior in EXPR due to missing sequence
     points.  */
  
! static void
  verify_sequence_points (tree expr)
  {
    struct tlist *before_sp = 0, *after_sp = 0;
--- 1585,1591 ----
  /* Try to warn for undefined behavior in EXPR due to missing sequence
     points.  */
  
! void
  verify_sequence_points (tree expr)
  {
    struct tlist *before_sp = 0, *after_sp = 0;
*************** verify_sequence_points (tree expr)
*** 1603,1634 ****
    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.  */
  
--- 1602,1607 ----
Index: gcc/c-common.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-common.h,v
retrieving revision 1.241
diff -u -p -c -r1.241 c-common.h
*** gcc/c-common.h	20 Jun 2004 10:09:56 -0000	1.241
--- gcc/c-common.h	21 Jun 2004 09:03:46 -0000
*************** extern void binary_op_error (enum tree_c
*** 859,865 ****
  #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);
--- 859,864 ----
*************** extern tree c_walk_subtrees (tree*, int*
*** 1097,1102 ****
--- 1096,1103 ----
  
  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 *);
Index: gcc/c-mudflap.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-mudflap.c,v
retrieving revision 2.2
diff -u -p -c -r2.2 c-mudflap.c
*** gcc/c-mudflap.c	16 Jun 2004 01:21:21 -0000	2.2
--- gcc/c-mudflap.c	21 Jun 2004 09:03:46 -0000
*************** mflang_flush_calls (tree enqueued_call_s
*** 85,91 ****
    mf_mark (current_function_decl);
  
    cs = c_begin_compound_stmt (true);
!   c_expand_expr_stmt (enqueued_call_stmt_chain);
    add_stmt (c_end_compound_stmt (cs, true));
  
    finish_function ();
--- 85,91 ----
    mf_mark (current_function_decl);
  
    cs = c_begin_compound_stmt (true);
!   c_finish_expr_stmt (enqueued_call_stmt_chain);
    add_stmt (c_end_compound_stmt (cs, true));
  
    finish_function ();
Index: gcc/c-parse.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-parse.in,v
retrieving revision 1.217
diff -u -p -c -r1.217 c-parse.in
*** gcc/c-parse.in	21 Jun 2004 01:50:17 -0000	1.217
--- gcc/c-parse.in	21 Jun 2004 09:03:46 -0000
*************** select_or_iter_stmt:
*** 2210,2216 ****
  
  for_init_stmt:
  	  xexpr ';'
! 		{ add_stmt (build_stmt (EXPR_STMT, $1)); }
  	| decl
  		{ check_for_loop_decls (); }
  	;
--- 2210,2216 ----
  
  for_init_stmt:
  	  xexpr ';'
! 		{ c_finish_expr_stmt ($1); }
  	| decl
  		{ check_for_loop_decls (); }
  	;
*************** stmt:
*** 2226,2232 ****
  	  compstmt
  		{ stmt_count++; add_stmt ($1); }
  	| expr ';'
! 		{ stmt_count++; c_expand_expr_stmt ($1); }
  	| c99_block_start select_or_iter_stmt
                  { add_stmt (c_end_compound_stmt ($1, flag_isoc99)); }
  	| BREAK ';'
--- 2226,2232 ----
  	  compstmt
  		{ stmt_count++; add_stmt ($1); }
  	| expr ';'
! 		{ stmt_count++; c_finish_expr_stmt ($1); }
  	| c99_block_start select_or_iter_stmt
                  { add_stmt (c_end_compound_stmt ($1, flag_isoc99)); }
  	| BREAK ';'
Index: gcc/c-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-tree.h,v
retrieving revision 1.153
diff -u -p -c -r1.153 c-tree.h
*** gcc/c-tree.h	18 Jun 2004 01:20:51 -0000	1.153
--- gcc/c-tree.h	21 Jun 2004 09:03:46 -0000
*************** extern tree build_indirect_ref (tree, co
*** 227,233 ****
  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);
--- 227,232 ----
*************** extern void c_finish_for_stmt_incr (tree
*** 272,277 ****
--- 271,277 ----
  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
Index: gcc/c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.322
diff -u -p -c -r1.322 c-typeck.c
*** gcc/c-typeck.c	20 Jun 2004 17:16:24 -0000	1.322
--- gcc/c-typeck.c	21 Jun 2004 09:03:47 -0000
*************** Software Foundation, 59 Temple Place - S
*** 46,51 ****
--- 46,52 ----
  #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"
*************** parser_build_binary_op (enum tree_code c
*** 2201,2217 ****
    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.  */
  
--- 2202,2207 ----
*************** build_conditional_expr (tree ifexp, tree
*** 2810,2817 ****
  	      /* 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)))
  		/* OK */;
  	      else
  		warning ("signed and unsigned type in conditional expression");
--- 2800,2807 ----
  	      /* 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 && tree_expr_nonnegative_p (op1))
! 		       || (unsigned_op1 && tree_expr_nonnegative_p (op2)))
  		/* OK */;
  	      else
  		warning ("signed and unsigned type in conditional expression");
*************** c_finish_for_stmt (tree body, tree for_s
*** 6657,6663 ****
    FOR_BODY (for_stmt) = body;
  }
  
! /* Create a statement expression.  */
  
  tree
  c_begin_stmt_expr (void)
--- 6647,6707 ----
    FOR_BODY (for_stmt) = body;
  }
  
! /* 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)
*************** c_begin_stmt_expr (void)
*** 6679,6741 ****
  tree
  c_finish_stmt_expr (tree body)
  {
!   tree ret, last, type;
    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);
!     }
    if (TREE_CODE (last) == STATEMENT_LIST)
      {
!       tree_stmt_iterator i = tsi_last (last);
!       if (tsi_end_p (i))
  	{
! 	  type = void_type_node;
! 	  /* ??? Warn */
! 	  goto no_expr;
  	}
        else
! 	{
! 	  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);
  
    /* 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;
  
!   return ret;
  }
  
  /* Begin and end compound statements.  This is as simple as pushing
--- 6723,6799 ----
  tree
  c_finish_stmt_expr (tree body)
  {
!   tree last, type, tmp, val;
    tree *last_p;
  
    body = c_end_compound_stmt (body, true);
  
!   /* 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;
! 
!       /* 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)
  	{
! 	  for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
! 	    emit_side_effect_warnings (tsi_stmt (i));
  	}
        else
! 	i = tsi_last (last);
!       last_p = tsi_stmt_ptr (i);
!       last = *last_p;
!     }
! 
!   /* 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 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;
! 
!   /* 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
*************** c_end_compound_stmt (tree stmt, bool do_
*** 6791,6800 ****
  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);
    add_stmt (stmt);
!   TREE_OPERAND (stmt, 0) = push_stmt_list ();
  }
  
  /* Build a binary-operation expression without default conversions.
--- 6849,6865 ----
  void
  push_cleanup (tree decl ATTRIBUTE_UNUSED, tree cleanup, bool eh_only)
  {
!   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);
!   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.
*************** build_binary_op (enum tree_code code, tr
*** 7412,7418 ****
  		     constant expression involving such literals or a
  		     conditional expression involving such literals)
  		     and it is non-negative.  */
! 		  if (c_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
--- 7477,7483 ----
  		     constant expression involving such literals or a
  		     conditional expression involving such literals)
  		     and it is non-negative.  */
! 		  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
Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.403
diff -u -p -c -r1.403 fold-const.c
*** gcc/fold-const.c	21 Jun 2004 08:34:07 -0000	1.403
--- gcc/fold-const.c	21 Jun 2004 09:03:48 -0000
*************** tree_expr_nonnegative_p (tree t)
*** 9267,9272 ****
--- 9267,9303 ----
      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);
Index: gcc/gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.19
diff -u -p -c -r2.19 gimplify.c
*** gcc/gimplify.c	19 Jun 2004 19:34:20 -0000	2.19
--- gcc/gimplify.c	21 Jun 2004 09:03:49 -0000
*************** gimplify_modify_expr (tree *expr_p, tree
*** 2472,2484 ****
      return ret;
  
    /* If we are initializing something from a TARGET_EXPR, strip the
!      TARGET_EXPR and initialize it directly.  */
    /* 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);
  
    /* If we're assigning from a ?: expression with ADDRESSABLE type, push
       the assignment down into the branches, since we can't generate a
--- 2472,2490 ----
      return ret;
  
    /* If we are initializing something from a TARGET_EXPR, strip the
!      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)
!     {
!       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
*************** gimplify_target_expr (tree *expr_p, tree
*** 3021,3042 ****
  
    if (init)
      {
!       /* 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 (! 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;
  	}
        append_to_statement_list (init, pre_p);
  
        /* If needed, push the cleanup for the temp.  */
--- 3027,3055 ----
  
    if (init)
      {
!       /* TARGET_EXPR temps aren't part of the enclosing block, so add it
! 	 to the temps list.  */
        gimple_add_tmp_var (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
  	{
!           /* 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.  */
Index: gcc/tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.109
diff -u -p -c -r1.109 tree-inline.c
*** gcc/tree-inline.c	17 Jun 2004 05:13:25 -0000	1.109
--- gcc/tree-inline.c	21 Jun 2004 09:03:49 -0000
*************** estimate_num_insns_1 (tree *tp, int *wal
*** 1251,1261 ****
      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:
      case CONSTRUCTOR:
        {
  	HOST_WIDE_INT size;
--- 1251,1264 ----
      case STRING_CST:
        *walk_subtrees = 0;
        return NULL;
+ 
      /* Recognize assignments of large structures and constructors of
         big arrays.  */
      case INIT_EXPR:
      case MODIFY_EXPR:
+       x = TREE_OPERAND (x, 0);
+       /* FALLTHRU */
+     case TARGET_EXPR:
      case CONSTRUCTOR:
        {
  	HOST_WIDE_INT size;
Index: gcc/cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.405
diff -u -p -c -r1.405 semantics.c
*** gcc/cp/semantics.c	20 Jun 2004 10:10:02 -0000	1.405
--- gcc/cp/semantics.c	21 Jun 2004 09:03:49 -0000
*************** finish_expr_stmt (tree expr)
*** 493,499 ****
    if (expr != NULL_TREE)
      {
        if (!processing_template_decl)
! 	expr = convert_to_void (expr, "statement");
        else if (!type_dependent_expression_p (expr))
  	convert_to_void (build_non_dependent_expr (expr), "statement");
  
--- 493,503 ----
    if (expr != NULL_TREE)
      {
        if (!processing_template_decl)
! 	{
! 	  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");
  
Index: gcc/objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.223
diff -u -p -c -r1.223 objc-act.c
*** gcc/objc/objc-act.c	21 Jun 2004 01:50:18 -0000	1.223
--- gcc/objc/objc-act.c	21 Jun 2004 09:03:50 -0000
*************** build_module_descriptor (void)
*** 1918,1924 ****
  			 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
      decelerator = build_function_call (execclass_decl, parms);
  
!     c_expand_expr_stmt (decelerator);
      add_stmt (c_end_compound_stmt (compound, true));
  
      finish_function ();
--- 1918,1924 ----
  			 build_unary_op (ADDR_EXPR, UOBJC_MODULES_decl, 0));
      decelerator = build_function_call (execclass_decl, parms);
  
!     add_stmt (decelerator);
      add_stmt (c_end_compound_stmt (compound, true));
  
      finish_function ();
Index: gcc/testsuite/gcc.dg/tree-ssa/20030714-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/tree-ssa/20030714-1.c,v
retrieving revision 1.3
diff -u -p -c -r1.3 20030714-1.c
*** gcc/testsuite/gcc.dg/tree-ssa/20030714-1.c	13 May 2004 17:20:10 -0000	1.3
--- gcc/testsuite/gcc.dg/tree-ssa/20030714-1.c	21 Jun 2004 09:03:50 -0000
*************** find_base_value (src)
*** 19,30 ****
       rtx src;
  {
    rtx temp;
!   rtx src_0;
!   rtx src_1;
  
!   if ((src_0->code == REG) && (({src_0;})->frame_related))
      return find_base_value (src_0);
!   if ((src_1->code == REG) && (({ src_1;})->frame_related))
      return find_base_value (src_1);
    if (src_0->code == REG)
      find_base_value (src_0);
--- 19,30 ----
       rtx src;
  {
    rtx temp;
!   rtx src_0, src_2;
!   rtx src_1, src_3;
  
!   if ((src_0->code == REG) && (({src_2;})->frame_related))
      return find_base_value (src_0);
!   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);
*************** find_base_value (src)
*** 41,44 ****
  
  /* There should be three loads of ->code.  */
  /* { dg-final { scan-tree-dump-times "->code" 3 "dom3"} } */
-                                                                                 
--- 41,43 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]