PATCH: Fix bug 787: g++ calls function multiple times for multiple pre-increment

Erik Rozendaal dlr@acm.org
Sat Jul 7 16:57:00 GMT 2001


This patch avoids duplicating the argument to a pre- or post-increment
when used as an lvalue and when the argument has side-effects.  This
fixes bug 787.

Added a test case as well (and make check-c++ works).

Erik


2001-07-01  Erik Rozendaal  <dlr@acm.org>

     * cp/typeck.c (unary_complex_lvalue): Do not duplicate the
     argument to modify, pre-, or post-increment when used as an
     lvalue and when the argument has side-effects.



Index: gcc/cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.356
diff -c -3 -p -r1.356 typeck.c
*** typeck.c    2001/07/07 01:07:22    1.356
--- typeck.c    2001/07/07 23:34:02
*************** unary_complex_lvalue (code, arg)
*** 4808,4819 ****
         || TREE_CODE (arg) == MIN_EXPR || TREE_CODE (arg) == MAX_EXPR)
       return rationalize_conditional_expr (code, arg);

     if (TREE_CODE (arg) == MODIFY_EXPR
         || TREE_CODE (arg) == PREINCREMENT_EXPR
         || TREE_CODE (arg) == PREDECREMENT_EXPR)
!     return unary_complex_lvalue
!       (code, build (COMPOUND_EXPR, TREE_TYPE (TREE_OPERAND (arg, 0)),
!             arg, TREE_OPERAND (arg, 0)));

     if (code != ADDR_EXPR)
       return 0;
--- 4808,4828 ----
         || TREE_CODE (arg) == MIN_EXPR || TREE_CODE (arg) == MAX_EXPR)
       return rationalize_conditional_expr (code, arg);

+   /* Handle (a = b), (++a), and (--a) used as an "lvalue".  */
     if (TREE_CODE (arg) == MODIFY_EXPR
         || TREE_CODE (arg) == PREINCREMENT_EXPR
         || TREE_CODE (arg) == PREDECREMENT_EXPR)
!     {
!       tree lvalue = TREE_OPERAND (arg, 0);
!       if (TREE_SIDE_EFFECTS (lvalue))
!         {
!           lvalue = stabilize_reference (lvalue);
!           arg = build (TREE_CODE (arg), TREE_TYPE (arg),
!                        lvalue, TREE_OPERAND (arg, 1));
!         }
!       return unary_complex_lvalue
!         (code, build (COMPOUND_EXPR, TREE_TYPE (lvalue), arg, lvalue));
!     }

     if (code != ADDR_EXPR)
       return 0;
Index: gcc/testsuite/g++.dg/init-ref-lhs.C
===================================================================
RCS file: init-ref-lhs.C
diff -N -c -3 -p init-ref-lhs.C
*** /dev/null    Fri Mar 23 20:37:44 2001
--- init-ref-lhs.C    Sat Jul  7 14:50:42 2001
***************
*** 0 ****
--- 1,44 ----
+ /* Test case for GNATS bug 787.  */
+ /* { dg-do run } */
+
+ #include <stdio.h>
+ #include <stdlib.h>
+
+ static int calls;
+
+ int &foo (int &arg)
+ {
+   calls++;
+   arg=0;
+   return arg;
+ }
+
+ int &identity (int &x)
+ {
+   return x;
+ }
+
+ int main()
+ {
+   int a;
+
+   calls = 0;
+   int &b = ++foo (a);
+   if (calls > 1)
+     abort ();
+   if (&a != &b)
+     abort ();
+   if (a != 1)
+     abort ();
+
+   calls = 0;
+   int &c = ++identity (++foo (a));
+   if (calls > 1)
+     abort ();
+   if (&a != &c)
+     abort ();
+   if (a != 2)
+     abort ();
+
+   exit (0);
+ }



More information about the Gcc-patches mailing list