I'm pretty sure this is the patch we need.

----- Forwarded message from Jakub Jelinek <[EMAIL PROTECTED]> -----

Date: Wed, 1 Oct 2003 20:35:19 +0200
From: Jakub Jelinek <[EMAIL PROTECTED]>
Subject: [3.3.2 PATCH] Backport invalid C++ tree sharing fix + testcase
To: Mark Mitchell <[EMAIL PROTECTED]>
Cc: [EMAIL PROTECTED]
Reply-To: Jakub Jelinek <[EMAIL PROTECTED]>

Hi!

The following testcase is miscompiled on IA-32 (foo has an endless loop)
in 3.3.x.
It is a regression from 3.2.x and fixed again on the trunk.
I tracked it down to:
http://gcc.gnu.org/ml/gcc-patches/2003-07/msg01063.html
Below is backport of the patch to gcc-3_3-branch.
Ok to commit?

2003-07-09  Mark Mitchell  <[EMAIL PROTECTED]>

        * cp-tree.h (break_out_calls): Remove declaration.
        * tree.c (break_out_calls): Remove.
        * typeck.c (build_modify_expr): Avoid invalid sharing of trees.

2003-10-01  Jakub Jelinek  <[EMAIL PROTECTED]>

        * g++.dg/opt/cond1.C: New test.

--- gcc/testsuite/g++.dg/opt/cond1.C.jj 2003-09-15 15:40:47.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/cond1.C    2003-10-01 14:39:32.000000000 +0200
@@ -0,0 +1,24 @@
+// { dg-do run }
+// { dg-options "-O2" }
+
+struct D { int x; };
+struct W
+{
+  W () {}
+  D & operator * () { return d; }
+  D d;
+};
+
+int
+foo (int y)
+{
+  W m;
+  (*m).x = (y > 1 ? y : 0);
+  return (*m).x;
+}
+
+int
+main ()
+{
+  return (foo (6) != 6);
+}
--- gcc/cp/cp-tree.h.jj 2003-10-01 12:08:54.000000000 +0200
+++ gcc/cp/cp-tree.h    2003-10-01 22:23:33.000000000 +0200
@@ -4317,7 +4317,6 @@ extern tree build_min                             PARAMS 
((enum t
 extern tree build_min_nt                       PARAMS ((enum tree_code, ...));
 extern tree build_cplus_new                    PARAMS ((tree, tree));
 extern tree get_target_expr                    PARAMS ((tree));
-extern tree break_out_calls                    PARAMS ((tree));
 extern tree build_cplus_method_type            PARAMS ((tree, tree, tree));
 extern tree build_cplus_staticfn_type          PARAMS ((tree, tree, tree));
 extern tree build_cplus_array_type             PARAMS ((tree, tree));
--- gcc/cp/typeck.c.jj  2003-09-16 17:25:55.000000000 +0200
+++ gcc/cp/typeck.c     2003-10-01 22:23:06.000000000 +0200
@@ -5502,44 +5502,8 @@ build_modify_expr (lhs, modifycode, rhs)
   if (newrhs == error_mark_node)
     return error_mark_node;
 
-  if (TREE_CODE (newrhs) == COND_EXPR)
-    {
-      tree lhs1;
-      tree cond = TREE_OPERAND (newrhs, 0);
-
-      if (TREE_SIDE_EFFECTS (lhs))
-       cond = build_compound_expr (tree_cons
-                                   (NULL_TREE, lhs,
-                                    build_tree_list (NULL_TREE, cond)));
-
-      /* Cannot have two identical lhs on this one tree (result) as preexpand
-        calls will rip them out and fill in RTL for them, but when the
-        rtl is generated, the calls will only be in the first side of the
-        condition, not on both, or before the conditional jump! (mrs) */
-      lhs1 = break_out_calls (lhs);
-
-      if (lhs == lhs1)
-       /* If there's no change, the COND_EXPR behaves like any other rhs.  */
-       result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
-                       lhstype, lhs, newrhs);
-      else
-       {
-         tree result_type = TREE_TYPE (newrhs);
-         /* We have to convert each arm to the proper type because the
-            types may have been munged by constant folding.  */
-         result
-           = build (COND_EXPR, result_type, cond,
-                    build_modify_expr (lhs, modifycode,
-                                       cp_convert (result_type,
-                                                   TREE_OPERAND (newrhs, 1))),
-                    build_modify_expr (lhs1, modifycode,
-                                       cp_convert (result_type,
-                                                   TREE_OPERAND (newrhs, 2))));
-       }
-    }
-  else
-    result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
-                   lhstype, lhs, newrhs);
+  result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
+                 lhstype, lhs, newrhs);
 
   TREE_SIDE_EFFECTS (result) = 1;
 
--- gcc/cp/tree.c.jj    2003-05-16 00:06:44.000000000 +0200
+++ gcc/cp/tree.c       2003-10-01 22:24:46.000000000 +0200
@@ -375,97 +375,6 @@ get_target_expr (init)
 {
   return build_target_expr_with_type (init, TREE_TYPE (init));
 }
-
-/* Recursively perform a preorder search EXP for CALL_EXPRs, making
-   copies where they are found.  Returns a deep copy all nodes transitively
-   containing CALL_EXPRs.  */
-
-tree
-break_out_calls (exp)
-     tree exp;
-{
-  register tree t1, t2 = NULL_TREE;
-  register enum tree_code code;
-  register int changed = 0;
-  register int i;
-
-  if (exp == NULL_TREE)
-    return exp;
-
-  code = TREE_CODE (exp);
-
-  if (code == CALL_EXPR)
-    return copy_node (exp);
-
-  /* Don't try and defeat a save_expr, as it should only be done once.  */
-    if (code == SAVE_EXPR)
-       return exp;
-
-  switch (TREE_CODE_CLASS (code))
-    {
-    default:
-      abort ();
-
-    case 'c':  /* a constant */
-    case 't':  /* a type node */
-    case 'x':  /* something random, like an identifier or an ERROR_MARK.  */
-      return exp;
-
-    case 'd':  /* A decl node */
-#if 0                               /* This is bogus.  jason 9/21/94 */
-
-      t1 = break_out_calls (DECL_INITIAL (exp));
-      if (t1 != DECL_INITIAL (exp))
-       {
-         exp = copy_node (exp);
-         DECL_INITIAL (exp) = t1;
-       }
-#endif
-      return exp;
-
-    case 'b':  /* A block node */
-      {
-       /* Don't know how to handle these correctly yet.   Must do a
-          break_out_calls on all DECL_INITIAL values for local variables,
-          and also break_out_calls on all sub-blocks and sub-statements.  */
-       abort ();
-      }
-      return exp;
-
-    case 'e':  /* an expression */
-    case 'r':  /* a reference */
-    case 's':  /* an expression with side effects */
-      for (i = TREE_CODE_LENGTH (code) - 1; i >= 0; i--)
-       {
-         t1 = break_out_calls (TREE_OPERAND (exp, i));
-         if (t1 != TREE_OPERAND (exp, i))
-           {
-             exp = copy_node (exp);
-             TREE_OPERAND (exp, i) = t1;
-           }
-       }
-      return exp;
-
-    case '<':  /* a comparison expression */
-    case '2':  /* a binary arithmetic expression */
-      t2 = break_out_calls (TREE_OPERAND (exp, 1));
-      if (t2 != TREE_OPERAND (exp, 1))
-       changed = 1;
-    case '1':  /* a unary arithmetic expression */
-      t1 = break_out_calls (TREE_OPERAND (exp, 0));
-      if (t1 != TREE_OPERAND (exp, 0))
-       changed = 1;
-      if (changed)
-       {
-         if (TREE_CODE_LENGTH (code) == 1)
-           return build1 (code, TREE_TYPE (exp), t1);
-         else
-           return build (code, TREE_TYPE (exp), t1, t2);
-       }
-      return exp;
-    }
-
-}
 
 /* Construct, lay out and return the type of methods belonging to class
    BASETYPE and whose arguments are described by ARGTYPES and whose values

        Jakub


----- End forwarded message -----

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


Reply via email to