From 283da5df2d76ce3909d70ea9dd6b77143eb7c04a Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Mon, 4 Apr 2005 05:02:10 +0000 Subject: [PATCH] re PR c++/19199 (Wrong warning about returning a reference to a temporary) 2005-04-03 Roger Sayle Alexandre Oliva 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 | 9 +++++ gcc/fold-const.c | 37 ++++++++++++++----- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/expr/lval2.C | 27 ++++++++++++++ .../g++.old-deja/g++.oliva/ChangeLog | 5 +++ gcc/testsuite/g++.old-deja/g++.oliva/expr2.C | 2 +- 6 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/expr/lval2.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 330c4b2fada..8c8faf304fd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2005-04-03 Roger Sayle + Alexandre Oliva + + 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 * builtins.def (BUILT_IN_STPNCPY, BUILT_IN_STRCASECMP, diff --git a/gcc/fold-const.c b/gcc/fold-const.c index c2242574c36..0b9a71f09f7 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 57946bdbe1d..207e8242919 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-04-03 Alexandre Oliva + + PR c++/19199 + * g++.dg/expr/lval2.C: New. + 2005-04-03 Kaveh R. Ghazi * 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 00000000000..5d062f1c628 --- /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 + +enum Foo { A, B }; + +template 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 cb7d567f659..448ea13a681 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 + + PR c++/19199 + * expr2.C: Fixed. + 2003-06-04 J"orn Rennecke * 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 dd364accfa4..1e63c645b6c 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 -- 2.30.2