re PR c++/19199 (Wrong warning about returning a reference to a temporary)
authorRoger Sayle <sayle@gcc.gnu.org>
Mon, 4 Apr 2005 05:02:10 +0000 (05:02 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Mon, 4 Apr 2005 05:02:10 +0000 (05:02 +0000)
2005-04-03  Roger Sayle  <roger@eyesopen.com>
    Alexandre Oliva  <aoliva@redhat.com>

PR c++/19199
* fold-const.c (non_lvalue): Split tests into...
(maybe_lvalue_p): New function.
(fold_cond_expr_with_comparison): Preserve lvalue-ness for the
C++ front-end prior to lowering into gimple form.

* g++.dg/expr/lval2.C: New.

* expr2.C: Fixed.

From-SVN: r97522

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/expr/lval2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.oliva/ChangeLog
gcc/testsuite/g++.old-deja/g++.oliva/expr2.C

index 330c4b2fadafad65d55d593801976210d41e618b..8c8faf304fd78f78ce7d5ba008376e135088115a 100644 (file)
@@ -1,3 +1,12 @@
+2005-04-03  Roger Sayle  <roger@eyesopen.com>
+           Alexandre Oliva  <aoliva@redhat.com>
+
+       PR c++/19199
+       * fold-const.c (non_lvalue): Split tests into...
+       (maybe_lvalue_p): New function.
+       (fold_cond_expr_with_comparison): Preserve lvalue-ness for the
+       C++ front-end prior to lowering into gimple form.
+
 2005-04-03  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * builtins.def (BUILT_IN_STPNCPY, BUILT_IN_STRCASECMP,
index c2242574c36f869e4a2d1a2a47702f063e3ffcc1..0b9a71f09f7b3152db890566b66cd179f59e40e5 100644 (file)
@@ -2003,16 +2003,13 @@ fold_convert (tree type, tree arg)
     }
 }
 \f
+/* Return false if expr can be assumed not to be an value, true
+   otherwise.  */
 /* Return an expr equal to X but certainly not valid as an lvalue.  */
 
-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))
   {
@@ -2052,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);
 }
 
@@ -4273,7 +4286,13 @@ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg1, tree arg2)
      a number and A is not.  The conditions in the original
      expressions will be false, so all four give B.  The min()
      and max() versions would give a NaN instead.  */
-  if (operand_equal_for_comparison_p (arg01, arg2, arg00))
+  if (operand_equal_for_comparison_p (arg01, arg2, arg00)
+      /* Avoid these transformations if the COND_EXPR may be used
+        as an lvalue in the C++ front-end.  PR c++/19199.  */
+      && (in_gimple_form
+         || strcmp (lang_hooks.name, "GNU C++") != 0
+         || ! maybe_lvalue_p (arg1)
+         || ! maybe_lvalue_p (arg2)))
     {
       tree comp_op0 = arg00;
       tree comp_op1 = arg01;
index 57946bdbe1dce7da0cb18f11d5b88e1e06b7dfb1..207e82429193a4ee0f3257b19d58637fa31f4ee7 100644 (file)
@@ -1,3 +1,8 @@
+2005-04-03  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR c++/19199
+       * g++.dg/expr/lval2.C: New.
+
 2005-04-03  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * gcc.dg/nonnull-3.c: Also test __builtin_stpncpy,
diff --git a/gcc/testsuite/g++.dg/expr/lval2.C b/gcc/testsuite/g++.dg/expr/lval2.C
new file mode 100644 (file)
index 0000000..5d062f1
--- /dev/null
@@ -0,0 +1,27 @@
+// 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;
+}
+
index cb7d567f659fca658282c61f56db218b17c8c99d..448ea13a6818f7cf127eb52ea93bf2b061dd1115 100644 (file)
@@ -1,3 +1,8 @@
+2005-04-03  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR c++/19199
+       * expr2.C: Fixed.
+
 2003-06-04  J"orn Rennecke <joern.rennecke@superh.com>
 
        * template1.C (bar): Remove xfail marker.
index dd364accfa4660e6ee5fd920654ef0a570e092de..1e63c645b6c16f05da4b258c4202b0c7e70837c8 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
 
 // Copyright (C) 2000 Free Software Foundation