[Bug c++/19199] [3.3/3.4/4.0/4.1 Regression] Wrong warning about returning a reference to a temporary

aoliva at redhat dot com gcc-bugzilla@gcc.gnu.org
Mon Apr 4 13:32:00 GMT 2005


------- 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 <roger@eyesopen.com> 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



More information about the Gcc-bugs mailing list