This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]