diff options
author | Roger Sayle <sayle@gcc.gnu.org> | 2005-04-04 05:02:10 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2005-04-04 05:02:10 +0000 |
commit | 283da5df2d76ce3909d70ea9dd6b77143eb7c04a (patch) | |
tree | 7edc4f9f0dabe9c7e7d4bdddc9d08b31857564fb | |
parent | af842ce06249a2b2b9d09867af8e0076486b1acc (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/fold-const.c | 37 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/expr/lval2.C | 27 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.oliva/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.oliva/expr2.C | 2 |
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 |