aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Sayle <sayle@gcc.gnu.org>2005-04-04 05:02:10 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2005-04-04 05:02:10 +0000
commit283da5df2d76ce3909d70ea9dd6b77143eb7c04a (patch)
tree7edc4f9f0dabe9c7e7d4bdddc9d08b31857564fb
parentaf842ce06249a2b2b9d09867af8e0076486b1acc (diff)
downloadgcc-283da5df2d76ce3909d70ea9dd6b77143eb7c04a.zip
gcc-283da5df2d76ce3909d70ea9dd6b77143eb7c04a.tar.gz
gcc-283da5df2d76ce3909d70ea9dd6b77143eb7c04a.tar.bz2
re PR c++/19199 (Wrong warning about returning a reference to a temporary)
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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/fold-const.c37
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/expr/lval2.C27
-rw-r--r--gcc/testsuite/g++.old-deja/g++.oliva/ChangeLog5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.oliva/expr2.C2
6 files changed, 75 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 330c4b2..8c8faf3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index c224257..0b9a71f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2003,16 +2003,13 @@ fold_convert (tree type, tree arg)
}
}
+/* 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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 57946bd..207e824 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..5d062f1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/lval2.C
@@ -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;
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/ChangeLog b/gcc/testsuite/g++.old-deja/g++.oliva/ChangeLog
index cb7d567..448ea13 100644
--- a/gcc/testsuite/g++.old-deja/g++.oliva/ChangeLog
+++ b/gcc/testsuite/g++.old-deja/g++.oliva/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.old-deja/g++.oliva/expr2.C b/gcc/testsuite/g++.old-deja/g++.oliva/expr2.C
index dd364ac..1e63c64 100644
--- a/gcc/testsuite/g++.old-deja/g++.oliva/expr2.C
+++ b/gcc/testsuite/g++.old-deja/g++.oliva/expr2.C
@@ -1,4 +1,4 @@
-// { dg-do run { xfail *-*-* } }
+// { dg-do run }
// Copyright (C) 2000 Free Software Foundation