From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27898 invoked by alias); 12 Dec 2002 03:16:01 -0000 Mailing-List: contact gcc-prs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-prs-owner@gcc.gnu.org Received: (qmail 27870 invoked by uid 71); 12 Dec 2002 03:16:01 -0000 Resent-Date: 12 Dec 2002 03:16:01 -0000 Resent-Message-ID: <20021212031601.27869.qmail@sources.redhat.com> Resent-From: gcc-gnats@gcc.gnu.org (GNATS Filer) Resent-Cc: gcc-prs@gcc.gnu.org, gcc-bugs@gcc.gnu.org Resent-Reply-To: gcc-gnats@gcc.gnu.org, lgandhi@peerless.com Received: (qmail 27810 invoked by uid 61); 12 Dec 2002 03:15:52 -0000 Message-Id: <20021212031552.27809.qmail@sources.redhat.com> Date: Wed, 11 Dec 2002 19:16:00 -0000 From: lgandhi@peerless.com Reply-To: lgandhi@peerless.com To: gcc-gnats@gcc.gnu.org X-Send-Pr-Version: gnatsweb-2.9.3 (1.1.1.1.2.31) Subject: c++/8910: Incorrect code generation when returning class by value X-SW-Source: 2002-12/txt/msg00692.txt.bz2 List-Id: >Number: 8910 >Category: c++ >Synopsis: Incorrect code generation when returning class by value >Confidential: no >Severity: critical >Priority: medium >Responsible: unassigned >State: open >Class: wrong-code >Submitter-Id: net >Arrival-Date: Wed Dec 11 19:16:00 PST 2002 >Closed-Date: >Last-Modified: >Originator: Lakhbir Gandhi >Release: gcc version 2.95.4 20010321 (Peerless-JBurk) derived from gcc 2.95.3 with DaveK's modifications for VxWorksPPC. >Organization: >Environment: Compiler#1: gcc 2.95.3 with DaveK's modifications for VxWorksPPC. Compiler#2: cygwin 2.95.3-5 Host: PIII MS Windows 2000 666Mhz 768MB Shell: Cmd Compile command: c++ test.cpp -g -c -o test.o Disassembly command: objdump -d -r -S test.o >Description: Hello, I want to report a bug wherein if a method returns a class by value, incorrect code is generated. It manifests itself when copy constructors are not available, in my case I had my copy constructor declared 'explicit' to prevent the compiler from generating expensive temporary objects. Both the ppc & cygwin compilers produce the same result so I don't think DaveK's modifications have anything to do with it. The test code is as follows: (copy-paste into test.cpp) class A { }; class B { public : B(int init); B(A init); explicit B(const B & init); operator A(); }; class C { public : operator B(); }; C::operator B() { return B(12345); } The class setup is described so: class A is any class. class B contains conversion constructor and operator for class A. class B also has a conversion constructor from int. (I have used int as an example, but all other datatypes intrisic and user-defined cause the same behaviour) class C defines a conversion operator to class B. The copy constructor for class B is declared explicit to prevent the compiler from generating expensive temporary B objects. C's conversion operator returns a B object by value, not as a reference or pointer. The implementation of C::operator B() elects to return an object B which is initialized by the integer 12345. Because class B has a conversion constructor from int, all we should see in the assembly code generated is a call to B::B(int). However I get the following: MiscTest.ppc.o: file format elf32-powerpc Disassembly of section .text: 00000000 : }; C::operator B() { 0: 94 21 ff c0 stwu r1,-64(r1) 4: 7c 08 02 a6 mflr r0 8: 93 61 00 2c stw r27,44(r1) c: 93 81 00 30 stw r28,48(r1) 10: 93 a1 00 34 stw r29,52(r1) 14: 93 c1 00 38 stw r30,56(r1) 18: 93 e1 00 3c stw r31,60(r1) 1c: 90 01 00 44 stw r0,68(r1) 20: 7c 3f 0b 78 mr r31,r1 24: 7c 7d 1b 78 mr r29,r3 28: 7c 9c 23 78 mr r28,r4 return B(12345); 2c: 3b 7f 00 09 addi r27,r31,9 30: 38 1f 00 18 addi r0,r31,24 34: 7c 03 03 78 mr r3,r0 38: 38 80 30 39 li r4,12345 3c: 48 00 00 01 bl 3c 3c: R_PPC_REL24 B::B(int) 40: 7c 60 1b 78 mr r0,r3 44: 39 3f 00 18 addi r9,r31,24 48: 7f 63 db 78 mr r3,r27 4c: 7d 24 4b 78 mr r4,r9 50: 4c c6 31 82 crclr 4*cr1+eq 54: 48 00 00 01 bl 54 54: R_PPC_REL24 B::operator A(void) 58: 88 1f 00 09 lbz r0,9(r31) 5c: 39 20 00 00 li r9,0 60: 99 3f 00 08 stb r9,8(r31) 64: 7f a3 eb 78 mr r3,r29 68: 38 9f 00 08 addi r4,r31,8 6c: 48 00 00 01 bl 6c 6c: R_PPC_REL24 B::B(A) 70: 7c 60 1b 78 mr r0,r3 74: 48 00 00 0c b 80 78: 48 00 00 08 b 80 7c: 48 00 00 04 b 80 } 80: 7f a3 eb 78 mr r3,r29 84: 81 61 00 00 lwz r11,0(r1) 88: 80 0b 00 04 lwz r0,4(r11) 8c: 7c 08 03 a6 mtlr r0 90: 83 6b ff ec lwz r27,-20(r11) 94: 83 8b ff f0 lwz r28,-16(r11) 98: 83 ab ff f4 lwz r29,-12(r11) 9c: 83 cb ff f8 lwz r30,-8(r11) a0: 83 eb ff fc lwz r31,-4(r11) a4: 7d 61 5b 78 mr r1,r11 a8: 4e 80 00 20 blr At offset 3c above, the correct call to B::B(int) is generated. But at offset 54, there is a call to B::operator A !!!!! To add insult to injury, this returned A is used to call B::B(A) at offset 6c ! This causes C::operator B() to return the B object created above, which is initialized by an A instead of an int which was the intent. This is incorrect behavior on two accounts: 1) ISO/IEC 14882:1998 in section 12.3.4 specifies that "At most one user-defined conversion (constructor or conversion function) is implictely applied to a single value", and here we see two such conversions, from B to A and then back to B. 2) The B object created by B::B(A) at offset 6c is returned instead of the the B object created by B::B(int) at offset 3c. I have examined the rtl and it contains the incorrect return semantic described above, so rtl to asm conversion is not the issue. Either the bug is in gcc/cp/parse.y or tree generation is incorrect or the resolution of candidate functions is incorrect or has the wrong data or the code in gcc/cp/typeck.c between line 7449 and line 7453 in function c_expand_return does not implement the correct semantics. Please be aware this is just a conjecture. Now if I do not declare B::B(B&) explicit, the correct code gets generated at offset 30 as shown below. MiscTest.ppc.o: file format elf32-powerpc Disassembly of section .text: 00000000 : }; C::operator B() { 0: 94 21 ff e0 stwu r1,-32(r1) 4: 7c 08 02 a6 mflr r0 8: 93 81 00 10 stw r28,16(r1) c: 93 a1 00 14 stw r29,20(r1) 10: 93 c1 00 18 stw r30,24(r1) 14: 93 e1 00 1c stw r31,28(r1) 18: 90 01 00 24 stw r0,36(r1) 1c: 7c 3f 0b 78 mr r31,r1 20: 7c 7d 1b 78 mr r29,r3 24: 7c 9c 23 78 mr r28,r4 return B(12345); 28: 7f a3 eb 78 mr r3,r29 2c: 38 80 30 39 li r4,12345 30: 48 00 00 01 bl 30 30: R_PPC_REL24 B::B(int) 34: 7c 60 1b 78 mr r0,r3 38: 48 00 00 0c b 44 3c: 48 00 00 08 b 44 40: 48 00 00 04 b 44 } 44: 7f a3 eb 78 mr r3,r29 48: 81 61 00 00 lwz r11,0(r1) 4c: 80 0b 00 04 lwz r0,4(r11) 50: 7c 08 03 a6 mtlr r0 54: 83 8b ff f0 lwz r28,-16(r11) 58: 83 ab ff f4 lwz r29,-12(r11) 5c: 83 cb ff f8 lwz r30,-8(r11) 60: 83 eb ff fc lwz r31,-4(r11) 64: 7d 61 5b 78 mr r1,r11 68: 4e 80 00 20 blr This code should have been generated for the explicit copy constructor case because as you can see there is no mention of B::B(B&) here! I think it is a definite bug. I have tried commenting out the conversion operator B::operator A() and the conversion constructor B::B(A) one at a time, the compiler then generates the error messages shown below. Change#1: // B::B(A init); result#1: MiscTest.cpp: In method `C::operator B()': MiscTest.cpp:29: no matching function for call to `B::B (B)' MiscTest.cpp:11: candidates are: B::B(int) change#2: // B::operator A(); resullt#2: MiscTest.cpp: In method `C::operator B()': MiscTest.cpp:29: no matching function for call to `B::B (B)' MiscTest.cpp:11: candidates are: B::B(int) MiscTest.cpp:14: B::B(A) I am a newbie to gcc innards, so I may be way off the mark. Sorry I don't have more details yet, I just ran into this problem last friday. VisualC++ however does not display this behaviour and generates correct code. Regards, Lakhbir Gandhi Consulting Engineer Peerless Systems Imaging Products (PSIP) >How-To-Repeat: >Fix: >Release-Note: >Audit-Trail: >Unformatted: