PR c++/25979
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Feb 2006 09:54:36 +0000 (09:54 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Feb 2006 09:54:36 +0000 (09:54 +0000)
        * tree.def: Elaborate on difference from MODIFY_EXPR.
        * doc/c-tree.texi (INIT_EXPR): Likewise.
        * gimplify.c (internal_get_tmp_var): Use INIT_EXPR.
        (gimplify_decl_expr, gimplify_init_ctor_eval): Likewise.
        (gimplify_target_expr): Likewise.
        (gimplify_cond_expr): Remove target handling.
        (gimplify_modify_expr): Don't clobber INIT_EXPR code here.
        (gimplify_expr): Clobber it here.
        (gimplify_modify_expr_rhs): Push assignment into COND_EXPR here.
        Do return slot optimization if we have an INIT_EXPR.

        PR tree-opt/24365
        * tree-inline.c (declare_return_variable): Also clear
        DECL_COMPLEX_GIMPLE_REG_P as needed in the modify_dest case.

        PR c++/16405
        * gimplify.c (gimplify_modify_expr_rhs): Re-enable *& handling.

        PR middle-end/22439
        * gimplify.c (gimplify_one_sizepos): Fix typo.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110789 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/cp-gimplify.c
gcc/cp/typeck2.c
gcc/doc/c-tree.texi
gcc/gimplify.c
gcc/testsuite/g++.dg/opt/temp1.C
gcc/tree-inline.c
gcc/tree.def

index 9aef9b8..83b801f 100644 (file)
@@ -1,3 +1,27 @@
+2006-02-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/25979
+       * tree.def: Elaborate on difference from MODIFY_EXPR.
+       * doc/c-tree.texi (INIT_EXPR): Likewise.
+       * gimplify.c (internal_get_tmp_var): Use INIT_EXPR.
+       (gimplify_decl_expr, gimplify_init_ctor_eval): Likewise.
+       (gimplify_target_expr): Likewise.
+       (gimplify_cond_expr): Remove target handling.
+       (gimplify_modify_expr): Don't clobber INIT_EXPR code here.
+       (gimplify_expr): Clobber it here.
+       (gimplify_modify_expr_rhs): Push assignment into COND_EXPR here.
+       Do return slot optimization if we have an INIT_EXPR.
+
+       PR tree-opt/24365
+       * tree-inline.c (declare_return_variable): Also clear 
+       DECL_COMPLEX_GIMPLE_REG_P as needed in the modify_dest case.
+
+       PR c++/16405
+       * gimplify.c (gimplify_modify_expr_rhs): Re-enable *& handling.
+
+       PR middle-end/22439
+       * gimplify.c (gimplify_one_sizepos): Fix typo.
+
 2006-02-08  Jeff Law  <law@redhat.com>
 
        PR tree-optimization/21417
index 947e080..74071c9 100644 (file)
@@ -1,3 +1,10 @@
+2006-02-08  Jason Merrill  <jason@redhat.com>
+
+       PR c++/25979
+       * cp-gimplify.c (cp_gimplify_expr): Don't call
+       cp_gimplify_init_expr for MODIFY_EXPRs.
+       * typeck2.c (split_nonconstant_init_1): Use INIT_EXPR.
+
 2006-02-08  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/26071
index 38838e7..a9fb7bf 100644 (file)
@@ -477,8 +477,10 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p)
       ret = GS_OK;
       break;
 
+      /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
+        LHS of an assignment might also be involved in the RHS, as in bug
+        25979.  */
     case INIT_EXPR:
-    case MODIFY_EXPR:
       cp_gimplify_init_expr (expr_p, pre_p, post_p);
       ret = GS_OK;
       break;
index fe5b3df..49c58f8 100644 (file)
@@ -502,7 +502,7 @@ split_nonconstant_init_1 (tree dest, tree init)
                sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
                              NULL_TREE);
 
-             code = build2 (MODIFY_EXPR, inner_type, sub, value);
+             code = build2 (INIT_EXPR, inner_type, sub, value);
              code = build_stmt (EXPR_STMT, code);
              add_stmt (code);
              continue;
index 5045b72..62e7738 100644 (file)
@@ -2350,7 +2350,10 @@ just like that for @samp{i = i + 3}.
 
 @item INIT_EXPR
 These nodes are just like @code{MODIFY_EXPR}, but are used only when a
-variable is initialized, rather than assigned to subsequently.
+variable is initialized, rather than assigned to subsequently.  This
+means that we can assume that the target of the initialization is not
+used in computing its own value; any reference to the lhs in computing
+the rhs is undefined.
 
 @item COMPONENT_REF
 These nodes represent non-static data member accesses.  The first
index da800bb..7105698 100644 (file)
@@ -606,7 +606,7 @@ internal_get_tmp_var (tree val, tree *pre_p, tree *post_p, bool is_formal)
   if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
     DECL_COMPLEX_GIMPLE_REG_P (t) = 1;
 
-  mod = build2 (MODIFY_EXPR, TREE_TYPE (t), t, val);
+  mod = build2 (INIT_EXPR, TREE_TYPE (t), t, val);
 
   if (EXPR_HAS_LOCATION (val))
     SET_EXPR_LOCUS (mod, EXPR_LOCUS (val));
@@ -1204,7 +1204,7 @@ gimplify_decl_expr (tree *stmt_p)
          if (!TREE_STATIC (decl))
            {
              DECL_INITIAL (decl) = NULL_TREE;
-             init = build2 (MODIFY_EXPR, void_type_node, decl, init);
+             init = build2 (INIT_EXPR, void_type_node, decl, init);
              gimplify_and_add (init, stmt_p);
            }
          else
@@ -2341,14 +2341,10 @@ gimple_boolify (tree expr)
     TARGET is the tree for T1 above.
 
     PRE_P points to the list where side effects that must happen before
-       *EXPR_P should be stored.
-
-   POST_P points to the list where side effects that must happen after
-     *EXPR_P should be stored.  */
+      *EXPR_P should be stored.  */
 
 static enum gimplify_status
-gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target,
-                   fallback_t fallback)
+gimplify_cond_expr (tree *expr_p, tree *pre_p, fallback_t fallback)
 {
   tree expr = *expr_p;
   tree tmp, tmp2, type;
@@ -2362,16 +2358,7 @@ gimplify_cond_expr (tree *expr_p, tree *pre_p, tree *post_p, tree target,
     {
       tree result;
 
-      if (target)
-       {
-         ret = gimplify_expr (&target, pre_p, post_p,
-                              is_gimple_min_lval, fb_lvalue);
-         if (ret != GS_ERROR)
-           ret = GS_OK;
-         result = tmp = target;
-         tmp2 = unshare_expr (target);
-       }
-      else if ((fallback & fb_lvalue) == 0)
+      if ((fallback & fb_lvalue) == 0)
        {
          result = tmp2 = tmp = create_tmp_var (TREE_TYPE (expr), "iftmp");
          ret = GS_ALL_DONE;
@@ -2836,7 +2823,7 @@ gimplify_init_ctor_eval (tree object, VEC(constructor_elt,gc) *elts,
                                 pre_p, cleared);
       else
        {
-         init = build2 (MODIFY_EXPR, TREE_TYPE (cref), cref, value);
+         init = build2 (INIT_EXPR, TREE_TYPE (cref), cref, value);
          gimplify_and_add (init, pre_p);
        }
     }
@@ -3190,7 +3177,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
   while (ret != GS_UNHANDLED)
     switch (TREE_CODE (*from_p))
       {
-#if 0
       case INDIRECT_REF:
        {
          /* If we have code like 
@@ -3212,7 +3198,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
            ret = GS_UNHANDLED;
          break;
        }
-#endif
 
       case TARGET_EXPR:
        {
@@ -3257,9 +3242,36 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
           copy in other cases as well.  */
        if (!is_gimple_reg_type (TREE_TYPE (*from_p)))
          {
-           *expr_p = *from_p;
-           return gimplify_cond_expr (expr_p, pre_p, post_p, *to_p,
-                                      fb_rvalue);
+           /* This code should mirror the code in gimplify_cond_expr. */
+           enum tree_code code = TREE_CODE (*expr_p);
+           tree cond = *from_p;
+           tree result = *to_p;
+
+           ret = gimplify_expr (&result, pre_p, post_p,
+                                is_gimple_min_lval, fb_lvalue);
+           if (ret != GS_ERROR)
+             ret = GS_OK;
+
+           if (TREE_TYPE (TREE_OPERAND (cond, 1)) != void_type_node)
+             TREE_OPERAND (cond, 1)
+               = build2 (code, void_type_node, result,
+                         TREE_OPERAND (cond, 1));
+           if (TREE_TYPE (TREE_OPERAND (cond, 2)) != void_type_node)
+             TREE_OPERAND (cond, 2)
+               = build2 (code, void_type_node, unshare_expr (result),
+                         TREE_OPERAND (cond, 2));
+
+           TREE_TYPE (cond) = void_type_node;
+           recalculate_side_effects (cond);
+
+           if (want_value)
+             {
+               gimplify_and_add (cond, pre_p);
+               *expr_p = unshare_expr (result);
+             }
+           else
+             *expr_p = cond;
+           return ret;
          }
        else
          ret = GS_UNHANDLED;
@@ -3273,11 +3285,26 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
          {
            bool use_target;
 
-           if (TREE_CODE (*to_p) == RESULT_DECL
-               && DECL_NAME (*to_p) == NULL_TREE
-               && needs_to_live_in_memory (*to_p))
+           if (!(rhs_predicate_for (*to_p))(*from_p))
+             /* If we need a temporary, *to_p isn't accurate.  */
+             use_target = false;
+           else if (TREE_CODE (*to_p) == RESULT_DECL
+                    && DECL_NAME (*to_p) == NULL_TREE
+                    && needs_to_live_in_memory (*to_p))
              /* It's OK to use the return slot directly unless it's an NRV. */
              use_target = true;
+           else if (is_gimple_reg_type (TREE_TYPE (*to_p)))
+             /* Don't force regs into memory.  */
+             use_target = false;
+           else if (TREE_CODE (*to_p) == VAR_DECL
+                    && DECL_GIMPLE_FORMAL_TEMP_P (*to_p))
+             /* Don't use the original target if it's a formal temp; we
+                don't want to take their addresses.  */
+             use_target = false;
+           else if (TREE_CODE (*expr_p) == INIT_EXPR)
+             /* It's OK to use the target directly if it's being
+                initialized. */
+             use_target = true;
            else if (!is_gimple_non_addressable (*to_p))
              /* Don't use the original target if it's already addressable;
                 if its address escapes, and the called function uses the
@@ -3286,14 +3313,6 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
                 When optimizing, the return_slot pass marks more functions
                 as safe after we have escape info.  */
              use_target = false;
-           else if (TREE_CODE (*to_p) != PARM_DECL 
-                    && DECL_GIMPLE_FORMAL_TEMP_P (*to_p))
-             /* Don't use the original target if it's a formal temp; we
-                don't want to take their addresses.  */
-             use_target = false;
-           else if (is_gimple_reg_type (TREE_TYPE (*to_p)))
-             /* Also don't force regs into memory.  */
-             use_target = false;
            else
              use_target = true;
 
@@ -3379,10 +3398,6 @@ gimplify_modify_expr (tree *expr_p, tree *pre_p, tree *post_p, bool want_value)
   gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR
              || TREE_CODE (*expr_p) == INIT_EXPR);
 
-  /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer useful.  */
-  if (TREE_CODE (*expr_p) == INIT_EXPR)
-    TREE_SET_CODE (*expr_p, MODIFY_EXPR);
-  
   /* For zero sized types only gimplify the left hand side and right hand side
      as statements and throw away the assignment.  */
   if (zero_sized_type (TREE_TYPE (*from_p)))
@@ -4072,7 +4087,7 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p)
            gimplify_bind_expr (&init, temp, pre_p);
          if (init != temp)
            {
-             init = build2 (MODIFY_EXPR, void_type_node, temp, init);
+             init = build2 (INIT_EXPR, void_type_node, temp, init);
              ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt,
                                   fb_none);
            }
@@ -5216,8 +5231,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
          break;
 
        case COND_EXPR:
-         ret = gimplify_cond_expr (expr_p, pre_p, post_p, NULL_TREE,
-                                   fallback);
+         ret = gimplify_cond_expr (expr_p, pre_p, fallback);
          /* C99 code may assign to an array in a structure value of a
             conditional expression, and this has undefined behavior
             only on execution, so create a temporary if an lvalue is
@@ -5253,6 +5267,11 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
        case INIT_EXPR:
          ret = gimplify_modify_expr (expr_p, pre_p, post_p,
                                      fallback != fb_none);
+
+         /* The distinction between MODIFY_EXPR and INIT_EXPR is no longer
+            useful.  */
+         if (*expr_p && TREE_CODE (*expr_p) == INIT_EXPR)
+           TREE_SET_CODE (*expr_p, MODIFY_EXPR);
          break;
 
        case TRUTH_ANDIF_EXPR:
@@ -5889,7 +5908,7 @@ gimplify_one_sizepos (tree *expr_p, tree *stmt_p)
 
       *expr_p = create_tmp_var (type, NULL);
       tmp = build1 (NOP_EXPR, type, expr);
-      tmp = build2 (MODIFY_EXPR, type, *expr_p, expr);
+      tmp = build2 (MODIFY_EXPR, type, *expr_p, tmp);
       if (EXPR_HAS_LOCATION (expr))
        SET_EXPR_LOCUS (tmp, EXPR_LOCUS (expr));
       else
index 6b0e2f3..b822dc4 100644 (file)
@@ -1,6 +1,6 @@
 // PR c++/16405
 // { dg-options "-O2" } 
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
 
 // There should be exactly one temporary generated for the code in "f"
 // below when optimizing -- for the result of "b + c".  We have no
index 07085b1..f9ce09b 100644 (file)
@@ -1222,6 +1222,9 @@ declare_return_variable (copy_body_data *id, tree return_slot_addr,
            use_it = false;
          else if (is_global_var (base_m))
            use_it = false;
+         else if (TREE_CODE (TREE_TYPE (base_m)) == COMPLEX_TYPE
+                  && !DECL_COMPLEX_GIMPLE_REG_P (result))
+           DECL_COMPLEX_GIMPLE_REG_P (base_m) = 0;
          else if (!TREE_ADDRESSABLE (base_m))
            use_it = true;
        }
index bc227e2..14c15a7 100644 (file)
@@ -465,7 +465,8 @@ DEFTREECODE (COMPOUND_EXPR, "compound_expr", tcc_expression, 2)
 DEFTREECODE (MODIFY_EXPR, "modify_expr", tcc_expression, 2)
 
 /* Initialization expression.  Operand 0 is the variable to initialize;
-   Operand 1 is the initializer.  */
+   Operand 1 is the initializer.  This differs from MODIFY_EXPR in that any
+   reference to the referent of operand 0 within operand 1 is undefined.  */
 DEFTREECODE (INIT_EXPR, "init_expr", tcc_expression, 2)
 
 /* For TARGET_EXPR, operand 0 is the target of an initialization,