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]

[PR c++/19199] don't turn cond_expr lvalue into min_expr rvalue (continued from PR c++/20280)


On Mar  4, 2005, Mark Mitchell <mark@codesourcery.com> wrote:

> Actually, looking at this more closely, I think that something is
> forgetting to call rationalize_conditional_expr, which is normally
> called from unary_complex_lvalue.  When the conditional expression is
> used in the lvalue context, something should be calling that.
> Normally, that happens because something calls build_unary_op
> (ADDR_EXPR, ...) on the COND_EXPR.

> It may be that I changed something to call build_addr (instead of
> build_unary_op) in a case where that's not safe.  Can you confirm or
> deny that hypothesis?

I'm not sure you're still talking about PR 20280, or about PR 19199,
that is marked as a blocker because it appears to be the same problem,
but AFAICT really isn't.

Here's a patch that fixes PR c++/19199, by avoiding the transformation
from:

<cond <lt <nop(int) <parm a> > <nop(int) <parm b> > >
      <parm a> <parm b> >

into:

<nop(enum) <min <nop(int) <parm a> > <nop(int) <parm b> > >

since the latter is clearly not an lvalue, and
rationalize_conditional_expr doesn't manage to turn it back into one
(I don't think it should).  I realize we might miss some optimization
opportunities because of this change in C, because the optimization
would be valid there, but I suppose we could arrange for cond_expr
operands in C to be forced into rvalues.

Still testing on x86_64-linux-gnu.  Ok to install if it passes?

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR c++/19199
	* fold-const.c (non_lvalue): Split tests into...
	(maybe_lvalue_p): New function.
	(fold_ternary): Use it to avoid turning a COND_EXPR lvalue into
	an MIN_EXPR rvalue.

Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.523
diff -u -p -r1.523 fold-const.c
--- gcc/fold-const.c 4 Mar 2005 06:24:09 -0000 1.523
+++ gcc/fold-const.c 4 Mar 2005 19:04:26 -0000
@@ -2004,16 +2004,12 @@ fold_convert (tree type, tree arg)
     }
 }
 
-/* Return an expr equal to X but certainly not valid as an lvalue.  */
+/* Return false if expr can be assumed to not be an lvalue, true
+   otherwise.  */
 
-tree
-non_lvalue (tree x)
+static bool
+maybe_lvalue_p (tree x)
 {
-  /* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to
-     us.  */
-  if (in_gimple_form)
-    return x;
-
   /* We only need to wrap lvalue tree codes.  */
   switch (TREE_CODE (x))
   {
@@ -2053,8 +2049,24 @@ non_lvalue (tree x)
     /* Assume the worst for front-end tree codes.  */
     if ((int)TREE_CODE (x) >= NUM_TREE_CODES)
       break;
-    return x;
+    return false;
   }
+
+  return true;
+}
+
+/* Return an expr equal to X but certainly not valid as an lvalue.  */
+
+tree
+non_lvalue (tree x)
+{
+  /* While we are in GIMPLE, NON_LVALUE_EXPR doesn't mean anything to
+     us.  */
+  if (in_gimple_form)
+    return x;
+
+  if (! maybe_lvalue_p (x))
+    return x;
   return build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
 }
 
@@ -7095,10 +7107,17 @@ fold_ternary (tree expr)
 	 of B and C.  Signed zeros prevent all of these transformations,
 	 for reasons given above each one.
 
+	 We don't want to use operand_equal_for_comparison_p here,
+	 because it might turn an lvalue COND_EXPR into an rvalue one,
+	 see PR c++/19199.
+
          Also try swapping the arguments and inverting the conditional.  */
       if (COMPARISON_CLASS_P (arg0)
-	  && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
-					     arg1, TREE_OPERAND (arg0, 1))
+	  && ((maybe_lvalue_p (arg1)
+	       && maybe_lvalue_p (TREE_OPERAND (t, 2)))
+	      ? operand_equal_p (TREE_OPERAND (arg0, 0), arg1, OEP_ONLY_CONST)
+	      : operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
+						arg1, TREE_OPERAND (arg0, 1)))
 	  && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
 	{
 	  tem = fold_cond_expr_with_comparison (type, arg0,
@@ -7109,9 +7128,13 @@ fold_ternary (tree expr)
 	}
 
       if (COMPARISON_CLASS_P (arg0)
-	  && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
-					     TREE_OPERAND (t, 2),
-					     TREE_OPERAND (arg0, 1))
+	  && ((maybe_lvalue_p (arg1)
+	       && maybe_lvalue_p (TREE_OPERAND (t, 2)))
+	      ? operand_equal_p (TREE_OPERAND (arg0, 0),
+				 TREE_OPERAND (t, 2), OEP_ONLY_CONST)
+	      : operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
+						TREE_OPERAND (t, 2),
+						TREE_OPERAND (arg0, 1)))
 	  && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
 	{
 	  tem = invert_truthvalue (arg0);
Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR c++/19199
	* g++.dg/expr/lval2.C: New.

Index: gcc/testsuite/g++.dg/expr/lval2.C
===================================================================
RCS file: gcc/testsuite/g++.dg/expr/lval2.C
diff -N gcc/testsuite/g++.dg/expr/lval2.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/g++.dg/expr/lval2.C 4 Mar 2005 19:04:42 -0000
@@ -0,0 +1,26 @@
+// PR c++/19199
+
+// { dg-do run }
+
+// We used to turn the COND_EXPR lvalue into a MIN_EXPR rvalue, and
+// then return a reference to a temporary in qMin.
+
+#include <assert.h>
+
+enum Foo { A, B };
+
+template<typename T> T &qMin(T &a, T &b) 
+{
+  return a < b ? a : b;
+}
+
+int main (int,  char **)
+{
+  Foo f = A;
+  Foo g = B;
+  Foo &h = qMin(f, g);
+  assert (&h == &f || &h == &g);
+  const Foo &i = qMin((const Foo&)f, (const Foo&)g);
+  assert (&i == &f || &i == &g);
+  return 0;
+}
-- 
Alexandre Oliva             http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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