From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 08AFF385843D; Tue, 13 Sep 2022 10:07:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 08AFF385843D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663063672; bh=n3lvzb5VCs+hNdmEcwwB9fSCaOoYzrX1Ub3EHNZkTMw=; h=From:To:Subject:Date:From; b=GiGTope2x2ojwhbd58sfUZRAt2xllN1ovI17Fui+Kb65LbfNF8wcgMyiEVSYBQE+b IHp84Cte0dJ7cbXLhsdhIFiGH9BawwKYSfAdMkdYdouNQcS0OqSKqD169BBXZ64Mbj g0ZBTvPs38u07lmc4K78jjQPqH1HUYciE4LI6qec= From: "aeiken at motortech dot de" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/106924] New: Nested class: virtual function returns wrong pointer of covariant type Date: Tue, 13 Sep 2022 10:07:51 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 10.3.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: aeiken at motortech dot de X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone attachments.created Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D106924 Bug ID: 106924 Summary: Nested class: virtual function returns wrong pointer of covariant type Product: gcc Version: 10.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: aeiken at motortech dot de Target Milestone: --- Created attachment 53570 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=3D53570&action=3Dedit test.ii file generated with g++ -save-temps test.cpp The following was found with gcc-arm-none-eabi-10.3-2021.07, tests with oth= er versions for linux (Ubuntu 20.04.3 LTS) did also not work (e.g. g++ 9.4.0 on Ubuntu). Take a look at the example code in test.cpp: A class (ABFabNested) is nested inside a class (class DerivedAB with multip= le inheritances (class BaseA and BaseB)). Because of the class layout, the adresses of DerivedAB and BaseB are differ= ent. The nested class itself is derived from a Base class (FabForB) which has a virtual function(getPtr), which return a pointer to class BaseA. The nested class overrides this virtual function, but returns a pointer to class DerivedAB. This is allowed, because DerivedAB and BaseB are covariant= s. If you have an instance of a pointer to FabForB, which points to an instanc= e of ABFabNested, getPtr returns the address of DerivedAB, not BaseA. If you implement the same class (here ABFab) outside of DerivedAB (not nest= ed) and repeat the step before, getPtr returns the address of BaseA, which is w= hat I expected. test.cpp was compiled with the 9.4.0 version of the g++ without any paramet= ers: g++ a.out Output of a.out: TEST fab: addr e89f6030 base e89f6040 TEST addr e89f6040=20 TEST fab nested: addr e89f6010 base e89f6020 TEST nested addr e89f6010 g++ --version g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0 Copyright (C) 2019 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. The test was repeated with other g++ versions (also newer version) with the same result. test.cpp: #include class BaseA { public: virtual BaseA* getPtr(){return this;} virtual ~BaseA(){} }; class BaseB { public: int i =3D 0; virtual int geti(){return i;}; virtual ~BaseB(){} }; class FabForB { public: virtual BaseA* getPtr()=3D0; virtual ~FabForB(){} }; class DerivedAB: public BaseB, public BaseA { public: virtual DerivedAB* getPtr(){printf("TEST D this %x\n", this);return thi= s;} virtual int geti(){return 5;}; class ABFabNested: public FabForB { public: virtual DerivedAB* getPtr() { static DerivedAB staticD; BaseA* basePtr =3D &staticD; printf("TEST fab nested: addr %x base %x\n", &staticD, basePtr); return &staticD; } virtual int geti(){return 5;}; }; }; class ABFab: public FabForB { public: virtual DerivedAB* getPtr() { static DerivedAB staticD; BaseA* basePtr =3D &staticD; printf("TEST fab: addr %x base %x\n", &staticD, basePtr); return &staticD; } virtual int geti(){return 5;}; }; int main() { ABFab fab; DerivedAB::ABFabNested fabNested; FabForB* fabPtr =3D &fab; FabForB* fabNestedPtr =3D &fabNested; printf("TEST addr %x \n", fabPtr->getPtr()); printf("TEST nested addr %x \n", fabNestedPtr->getPtr());=20=20 return 0; }=