------- Additional Comments From aoliva at gcc dot gnu dot org  2005-04-04 
13:32 -------
Subject: Re: [Committed] PR c++/19199: Preserve COND_EXPR lvalueness in fold

On Apr  4, 2005, Roger Sayle <[EMAIL PROTECTED]> wrote:

>       (fold_cond_expr_with_comparison): Preserve lvalue-ness for the
>       C++ front-end prior to lowering into gimple form.

>       * expr2.C: Fixed.

Err...  Why did you choose to drop the portion of the patch below,
that would have avoided the ugliness of comparing langhooks.name, but
still retained it in the ChangeLog entry?

Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.554
diff -u -p -d -u -p -d -u -p -r1.554 fold-const.c
--- fold-const.c        4 Apr 2005 08:50:25 -0000       1.554
+++ fold-const.c        4 Apr 2005 13:25:47 -0000
@@ -4173,7 +4173,15 @@ fold_cond_expr_with_comparison (tree typ
   tree arg00 = TREE_OPERAND (arg0, 0);
   tree arg01 = TREE_OPERAND (arg0, 1);
   tree arg1_type = TREE_TYPE (arg1);
-  tree tem;
+  tree tem = NULL;
+  /* If the COND_EXPR can possibly be an lvalue, we don't want to
+     perform transformations that return a simplified result that will
+     be recognized as lvalue, but that will not match the expected
+     result.  We may still return other expressions that would be
+     incorrect, but those are going to be rvalues, and the caller is
+     supposed to discard them.  */
+  bool lvalue = !pedantic_lvalues
+    && maybe_lvalue_p (arg1) && maybe_lvalue_p (arg2);
 
   STRIP_NOPS (arg1);
   STRIP_NOPS (arg2);
@@ -4215,10 +4223,12 @@ fold_cond_expr_with_comparison (tree typ
       case EQ_EXPR:
       case UNEQ_EXPR:
        tem = fold_convert (arg1_type, arg1);
-       return pedantic_non_lvalue (fold_convert (type, negate_expr (tem)));
+       tem = pedantic_non_lvalue (fold_convert (type, negate_expr (tem)));
+       break;
       case NE_EXPR:
       case LTGT_EXPR:
-       return pedantic_non_lvalue (fold_convert (type, arg1));
+       tem = pedantic_non_lvalue (fold_convert (type, arg1));
+       break;
       case UNGE_EXPR:
       case UNGT_EXPR:
        if (flag_trapping_math)
@@ -4230,7 +4240,8 @@ fold_cond_expr_with_comparison (tree typ
          arg1 = fold_convert (lang_hooks.types.signed_type
                               (TREE_TYPE (arg1)), arg1);
        tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
-       return pedantic_non_lvalue (fold_convert (type, tem));
+       tem = pedantic_non_lvalue (fold_convert (type, tem));
+       break;
       case UNLE_EXPR:
       case UNLT_EXPR:
        if (flag_trapping_math)
@@ -4241,12 +4252,18 @@ fold_cond_expr_with_comparison (tree typ
          arg1 = fold_convert (lang_hooks.types.signed_type
                               (TREE_TYPE (arg1)), arg1);
        tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
-       return negate_expr (fold_convert (type, tem));
+       tem = negate_expr (fold_convert (type, tem));
+       break;
       default:
        gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
        break;
       }
 
+  if (tem && (! lvalue || maybe_lvalue_p (tem)))
+    return tem;
+  else
+    tem = NULL;
+
   /* A != 0 ? A : 0 is simply A, unless A is -0.  Likewise
      A == 0 ? A : 0 is always 0 unless A is -0.  Note that
      both transformations are correct when A is NaN: A != 0
@@ -4255,11 +4272,16 @@ fold_cond_expr_with_comparison (tree typ
   if (integer_zerop (arg01) && integer_zerop (arg2))
     {
       if (comp_code == NE_EXPR)
-       return pedantic_non_lvalue (fold_convert (type, arg1));
+       tem = pedantic_non_lvalue (fold_convert (type, arg1));
       else if (comp_code == EQ_EXPR)
-       return fold_convert (type, integer_zero_node);
+       tem = fold_convert (type, integer_zero_node);
     }
 
+  if (tem && (! lvalue || maybe_lvalue_p (tem)))
+    return tem;
+  else
+    tem = NULL;
+
   /* Try some transformations of A op B ? A : B.
 
      A == B? A : B    same as B
@@ -4309,9 +4331,15 @@ fold_cond_expr_with_comparison (tree typ
       switch (comp_code)
        {
        case EQ_EXPR:
-         return pedantic_non_lvalue (fold_convert (type, arg2));
+         if (lvalue)
+           break;
+         tem = pedantic_non_lvalue (fold_convert (type, arg2));
+         break;
        case NE_EXPR:
-         return pedantic_non_lvalue (fold_convert (type, arg1));
+         if (lvalue)
+           break;
+         tem = pedantic_non_lvalue (fold_convert (type, arg1));
+         break;
        case LE_EXPR:
        case LT_EXPR:
        case UNLE_EXPR:
@@ -4327,7 +4355,7 @@ fold_cond_expr_with_comparison (tree typ
              tem = (comp_code == LE_EXPR || comp_code == UNLE_EXPR)
                    ? fold_build2 (MIN_EXPR, comp_type, comp_op0, comp_op1)
                    : fold_build2 (MIN_EXPR, comp_type, comp_op1, comp_op0);
-             return pedantic_non_lvalue (fold_convert (type, tem));
+             tem = pedantic_non_lvalue (fold_convert (type, tem));
            }
          break;
        case GE_EXPR:
@@ -4341,16 +4369,16 @@ fold_cond_expr_with_comparison (tree typ
              tem = (comp_code == GE_EXPR || comp_code == UNGE_EXPR)
                    ? fold_build2 (MAX_EXPR, comp_type, comp_op0, comp_op1)
                    : fold_build2 (MAX_EXPR, comp_type, comp_op1, comp_op0);
-             return pedantic_non_lvalue (fold_convert (type, tem));
+             tem = pedantic_non_lvalue (fold_convert (type, tem));
            }
          break;
        case UNEQ_EXPR:
-         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
-           return pedantic_non_lvalue (fold_convert (type, arg2));
+         if (! lvalue && !HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+           tem = pedantic_non_lvalue (fold_convert (type, arg2));
          break;
        case LTGT_EXPR:
-         if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
-           return pedantic_non_lvalue (fold_convert (type, arg1));
+         if (! lvalue && !HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+           tem = pedantic_non_lvalue (fold_convert (type, arg1));
          break;
        default:
          gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
@@ -4358,6 +4386,11 @@ fold_cond_expr_with_comparison (tree typ
        }
     }
 
+  if (tem && (! lvalue || maybe_lvalue_p (tem)))
+    return tem;
+  else
+    tem = NULL;
+
   /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
      we might still be able to simplify this.  For example,
      if C1 is one less or one more than C2, this might have started
@@ -4372,7 +4405,7 @@ fold_cond_expr_with_comparison (tree typ
       case EQ_EXPR:
        /* We can replace A with C1 in this case.  */
        arg1 = fold_convert (type, arg01);
-       return fold_build3 (COND_EXPR, type, arg0, arg1, arg2);
+       tem = fold_build3 (COND_EXPR, type, arg0, arg1, arg2);
 
       case LT_EXPR:
        /* If C1 is C2 + 1, this is min(A, C2).  */
@@ -4382,8 +4415,8 @@ fold_cond_expr_with_comparison (tree typ
                                const_binop (PLUS_EXPR, arg2,
                                             integer_one_node, 0),
                                OEP_ONLY_CONST))
-         return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
-                                                  type, arg1, arg2));
+         tem = pedantic_non_lvalue (fold_build2 (MIN_EXPR,
+                                                 type, arg1, arg2));
        break;
 
       case LE_EXPR:
@@ -4394,8 +4427,8 @@ fold_cond_expr_with_comparison (tree typ
                                const_binop (MINUS_EXPR, arg2,
                                             integer_one_node, 0),
                                OEP_ONLY_CONST))
-         return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
-                                                  type, arg1, arg2));
+         tem = pedantic_non_lvalue (fold_build2 (MIN_EXPR,
+                                                 type, arg1, arg2));
        break;
 
       case GT_EXPR:
@@ -4406,8 +4439,8 @@ fold_cond_expr_with_comparison (tree typ
                                const_binop (MINUS_EXPR, arg2,
                                             integer_one_node, 0),
                                OEP_ONLY_CONST))
-         return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
-                                                  type, arg1, arg2));
+         tem = pedantic_non_lvalue (fold_build2 (MAX_EXPR,
+                                                 type, arg1, arg2));
        break;
 
       case GE_EXPR:
@@ -4418,8 +4451,8 @@ fold_cond_expr_with_comparison (tree typ
                                const_binop (PLUS_EXPR, arg2,
                                             integer_one_node, 0),
                                OEP_ONLY_CONST))
-         return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
-                                                  type, arg1, arg2));
+         tem = pedantic_non_lvalue (fold_build2 (MAX_EXPR,
+                                                 type, arg1, arg2));
        break;
       case NE_EXPR:
        break;
@@ -4427,6 +4460,11 @@ fold_cond_expr_with_comparison (tree typ
        gcc_unreachable ();
       }
 
+  if (tem && (! lvalue || maybe_lvalue_p (tem)))
+    return tem;
+  else
+    tem = NULL;
+
   return NULL_TREE;
 }
 


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19199

Reply via email to