Bug 15580

Summary: wrong code generation in c++ assignment operator
Product: gcc Reporter: unicorn <unicorn>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: gcc-bugs
Priority: P2 Keywords: wrong-code
Version: 3.3   
Target Milestone: 3.3.3   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:

Description unicorn@re.com.ua 2004-05-21 23:45:54 UTC
`this' calculated incorrectly for the assignment operator of the virtual base.

Environment:
gcc 3.3.x

How-To-Repeat:

[8<---test.cc---]
struct A { int a; };
struct B : virtual A { };
struct C : virtual A { };
struct D : B, C { };

int
main()
{
    D d;
    d = d;
    d.a = 5;
}
[--->8]

g++ test.cc
./a.out

no optimization should be used, otherwise `d.a' reference will be cached
from assignment operation. in any doubt this is an optimizer error here
is a modified version of the same test.cc which will crash in any of -Oxx
switches:
[...]

void test(D d);

int
main()
{
    D d;
    d = d;
    test(d);
}

void test(D d)
{
}

>Workaround:
downgrade to 3.2.x
Comment 1 unicorn@re.com.ua 2004-05-21 23:45:54 UTC
Fix:
downgrade to 3.2.x
- or -
here is a patch for gcc version 3.3.3 [FreeBSD] 20031106:

Index: method.c
===================================================================
RCS file: /home/ncvs/src/contrib/gcc/cp/method.c,v
retrieving revision 1.1.1.10
diff -u -r1.1.1.10 method.c
--- method.c    22 Aug 2003 02:56:03 -0000      1.1.1.10
+++ method.c    21 May 2004 04:52:33 -0000
@@ -665,15 +665,17 @@
       for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i)
        {
          tree binfo;
+         tree dst;
          tree converted_parm;
 
          binfo = BINFO_BASETYPE (TYPE_BINFO (current_class_type), i);
          /* We must convert PARM directly to the base class
             explicitly since the base class may be ambiguous.  */
          converted_parm = build_base_path (PLUS_EXPR, parm, binfo, 1);
+         dst = build_base_path (PLUS_EXPR, current_class_ref, binfo, 1);
          /* Call the base class assignment operator.  */
          finish_expr_stmt 
-           (build_special_member_call (current_class_ref, 
+           (build_special_member_call (dst, 
                                        ansi_assopname (NOP_EXPR),
                                        build_tree_list (NULL_TREE, 
                                                         converted_parm),
Comment 2 Andrew Pinski 2004-05-21 23:58:03 UTC
I cannot reproduce this at all on 3.3.3, 3.4.0 or 3.2.3.
Comment 3 Winged Unicorn 2004-05-22 00:38:58 UTC
(In reply to comment #2)
> I cannot reproduce this at all on 3.3.3, 3.4.0 or 3.2.3.

3.2.x hasn't this bug. 
(proposed patch was created after comparition of do_build_assign_ref 
routines of 3.2.3 and 3.3.3)

I did't test this on 3.4, but I'm completely sure 3.3.3 has this bug.
It may not show because of optimization or someth else.

try this:
#include <iostream>

struct A { 
    const A &operator = (const A &r) {
        std::cout << this << std::endl;
    }
};
struct B : virtual A { };
struct C : virtual A { };
struct D : B, C { };

int
main()
{
     D d0, d1;
     d0 = d1;
}

On 3.2 this will produce two equal address (as it has to be for virtual
inheritance), but 3.3 will show a different one.
Comment 4 Andrew Pinski 2004-05-22 00:51:02 UTC
I cannot produce it at all:
tin:~/src/gnu/gcctest>g++ pr15580.cc <-- the mainline
tin:~/src/gnu/gcctest>./a.out
0xbffec920
0xbffec920
tin:~/src/gnu/gcctest>~/ia32_linux_gcc3_4/bin/g++ pr15580.cc <-- released 3.4.0
tin:~/src/gnu/gcctest>./a.out
0xbffec920
0xbffec920
tin:~/src/gnu/gcctest>~/ia32_linux_gcc3_3/bin/g++ pr15580.cc -static <-- release of 3.3.3
./a.
tin:~/src/gnu/gcctest>./a.out 
0xbffec920
0xbffec920
tin:~/src/gnu/gcctest>~/ia32_linux_gcc3_3_1/bin/g++ pr15580.cc -static <-- a prelease of 3.3.1
tin:~/src/gnu/gcctest>./a.out 
0xbffec920
0xbffec920

So either it was fixed in a later version of 3.3.3 which is most likely, since you are using an old prelease 
of 3.3.3, can you try the released version?
Comment 5 Winged Unicorn 2004-05-22 01:47:55 UTC
(In reply to comment #4)
> So either it was fixed in a later version of 3.3.3 which is most likely, since
you are using an old prelease 
> of 3.3.3, can you try the released version?
Thank you.
I gues, this is a problem. freebsd still uses outdated gcc 3.3.3 as a system
compiller. I manage to submit a fbsd PR with a reference to this one.
Comment 6 Alfred Minarik 2004-05-22 05:03:49 UTC
I´m able to reproduce this on

$ uname -a
CYGWIN_NT-5.0 w2k 1.5.9(0.112/4/2) 2004-03-18 23:05 i686 unknown unknown Cygwin

$ gcc --version
gcc (GCC) 3.3.1 (cygming special)
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ pr15580.cc

$ ./a.exe
0x22f058
0x22f05c

Alfred
Comment 7 Alfred Minarik 2004-05-22 05:20:07 UTC
(In reply to comment #6)
> I´m able to reproduce this on
> $ uname -a
> CYGWIN_NT-5.0 w2k 1.5.9(0.112/4/2) 2004-03-18 23:05 i686 unknown unknown 
Cygwin
> $ gcc --version
> gcc (GCC) 3.3.1 (cygming special)
> Copyright (C) 2003 Free Software Foundation, Inc.
> This is free software; see the source for copying conditions.  There is NO
> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> $ g++ pr15580.cc
> $ ./a.exe
> 0x22f058
> 0x22f05c
> Alfred

but seems fixed in 3.4.0

$ uname -a
CYGWIN_NT-5.0 w2k 1.5.9(0.112/4/2) 2004-03-18 23:05 i686 unknown unknown 

$ gcc --version
gcc (GCC) 3.4.0
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ pr15580.cc

$ ./a.exe
0x22f058
0x22f058

Alfred
Comment 8 Giovanni Bajo 2004-05-22 09:10:49 UTC
So closing as already fixed at least in 3.3.3.
Comment 9 Winged Unicorn 2004-05-22 15:06:03 UTC
It was fixed in gcc-3_3-branch at 2004-01-21 05:04:06.
here is original PR: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13009