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
This commit is contained in:
Roger Sayle 2005-04-04 05:02:10 +00:00
parent af842ce062
commit 283da5df2d
6 changed files with 75 additions and 10 deletions

View 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,

View File

@ -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;

View 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,

View File

@ -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;
}

View 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.

View File

@ -1,4 +1,4 @@
// { dg-do run { xfail *-*-* } }
// { dg-do run }
// Copyright (C) 2000 Free Software Foundation