From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21101 invoked by alias); 4 Mar 2005 19:08:55 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 20880 invoked by alias); 4 Mar 2005 19:08:46 -0000 Date: Fri, 04 Mar 2005 19:08:00 -0000 Message-ID: <20050304190846.20879.qmail@sourceware.org> From: "aoliva at redhat dot com" To: gcc-bugs@gcc.gnu.org In-Reply-To: <20041230105911.19199.lars@trolltech.com> References: <20041230105911.19199.lars@trolltech.com> Reply-To: gcc-bugzilla@gcc.gnu.org Subject: [Bug c++/19199] [3.3/3.4/4.0/4.1 Regression] Wrong warning about returning a reference to a temporary X-Bugzilla-Reason: CC X-SW-Source: 2005-03/txt/msg00569.txt.bz2 List-Id: ------- Additional Comments From aoliva at gcc dot gnu dot org 2005-03-04 19:08 ------- Subject: [PR c++/19199] don't turn cond_expr lvalue into min_expr rvalue (continued from PR c++/20280) On Mar 4, 2005, Mark Mitchell 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: > > > > into: > > > 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 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 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 + +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; +} -- 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} -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19199