This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Committed] PR c++/19199: Preserve COND_EXPR lvalueness in fold
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 3 Apr 2005 23:17:29 -0600 (MDT)
- Subject: [Committed] PR c++/19199: Preserve COND_EXPR lvalueness in fold
The following band-aid resolves PR c++/19199 which is wrong-code and
diagnostic regression in the C++ front-end affecting mainline, 4.0 and
3.4. Desperate times call for desparate measures, and whilst several
long-term solutions have been proposed for g++ 4.1, the patch below is
the best "4.0 timeframe" work-around that doesn't adversely affect
performance for GCC's non C++ front-ends, and even retains the ability
to synthesize MIN_EXPR and MAX_EXPR for C++ during the tree-ssa passes.
There are several clean-ups related to this patch that further simplify
handling of lvalue COND_EXPRs in fold_cond_expr_with_comparison, but
this patch is intentionally short and non-intrusive (if extremely ugly)
to make it backport friendly to the open release branches.
My apologies to Mark and Alex for letting this one slip whilst I was
on vacation without internet access last week. If we come up with a
better solution before 4.0, we can always revert the relevant bits
below.
The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages, and regression tested with a
top-level "make -k check", with no new failures. Committed to mainline
CVS. I'll backport it to the gcc-4_0-branch tomorrow following the
prerequisite bootstraps and regressions tests there. Alex's testsuite
changes are those described in the bugzilla PR.
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.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.552
diff -c -3 -p -r1.552 fold-const.c
*** fold-const.c 1 Apr 2005 14:36:33 -0000 1.552
--- fold-const.c 4 Apr 2005 01:38:33 -0000
*************** fold_convert (tree type, tree arg)
*** 2003,2018 ****
}
}
/* 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;
-
/* We only need to wrap lvalue tree codes. */
switch (TREE_CODE (x))
{
--- 2003,2015 ----
}
}
+ /* 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. */
! static bool
! maybe_lvalue_p (tree x)
{
/* We only need to wrap lvalue tree codes. */
switch (TREE_CODE (x))
{
*************** non_lvalue (tree x)
*** 2052,2059 ****
/* Assume the worst for front-end tree codes. */
if ((int)TREE_CODE (x) >= NUM_TREE_CODES)
break;
! return x;
}
return build1 (NON_LVALUE_EXPR, TREE_TYPE (x), x);
}
--- 2049,2072 ----
/* Assume the worst for front-end tree codes. */
if ((int)TREE_CODE (x) >= NUM_TREE_CODES)
break;
! 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);
}
*************** fold_cond_expr_with_comparison (tree typ
*** 4273,4279 ****
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))
{
tree comp_op0 = arg00;
tree comp_op1 = arg01;
--- 4286,4298 ----
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)
! /* 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;
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833