Created attachment 29128 [details] minimal program which does not work. The attached minimal c++11 source compiles with g++ -std=c++11 minimal.c++, but the program does not run as expected (indicated by a non-zero exit value). Using clang works. The same source with debug outputs shows that the virtual base constructor is called more than once upon initialization with bogus 'this' pointers. Not all classes agree on the offset to the virtual base. This causes silent member corruption (and ultimately crashes if some of the members are pointers). Replacing brace initializers for B1 and A2 with C++03 parentheses initializers makes the problem go away. Bug is also reproducible on trunk@195009 configured with ./configure --enable-languages=c,c++ --prefix=...
Created attachment 29129 [details] same source with more outputs. Example output of what i have on my system with this attachment : Base ctor is called at 0x7fffb7eeb474 Base ctor is called at 0x7fffb7eeb468 A1::Base is at 0x7fffb7eeb468 B1::Base is at 0x7fffb7eeb468 Base ctor is called at 0x7fffb7eeb470 A2::Base is at 0x7fffb7eeb470 C::Base is at 0x7fffb7eeb474 2 2 3 Standard output should read "1 2 3".
bool called = false; struct Base { Base() { if (called) throw 1; called = true; } }; struct B1 : virtual Base { B1() { } }; struct C : B1, virtual Base { C() : #ifdef FIX B1() #else B1{} #endif { } }; int main() { C c; }
*** Bug 70818 has been marked as a duplicate of this bug. ***
I'm not sure how helpful or relevant this is at this point but according to my testing the wrong code seems to have been emitted since r142404 committed in the gcc 4.4.0 release cycle: r142404 | jason | 2008-12-03 14:22:08 -0500 (Wed, 03 Dec 2008) | 6 lines PR c++/38380 * decl.c (grokdeclarator): Only set DECL_NONCONVERTING_P on explicit constructors. * pt.c (tsubst_copy_and_build) [CONSTRUCTOR]: Propagate CONSTRUCTOR_IS_DIRECT_INIT. Prior to that, GCC rejected the program with the following error: error: converting to ‘const B1’ from initializer list would use explicit constructor ‘B1::B1()’
Author: jason Date: Sun Jul 24 02:56:22 2016 New Revision: 238688 URL: https://gcc.gnu.org/viewcvs?rev=238688&root=gcc&view=rev Log: PR c++/55922 - list-value-initialization of base PR c++/63151 * init.c (expand_aggr_init_1): Handle list-initialization from {}. Added: trunk/gcc/testsuite/g++.dg/cpp0x/initlist-base2.C trunk/gcc/testsuite/g++.dg/cpp0x/initlist-base3.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/init.c
Author: jason Date: Sun Jul 24 03:05:46 2016 New Revision: 238694 URL: https://gcc.gnu.org/viewcvs?rev=238694&root=gcc&view=rev Log: PR c++/55922 - list-value-initialization of base PR c++/63151 * init.c (expand_aggr_init_1): Handle list-initialization from {}. Added: branches/gcc-6-branch/gcc/testsuite/g++.dg/cpp0x/initlist-base2.C branches/gcc-6-branch/gcc/testsuite/g++.dg/cpp0x/initlist-base3.C Modified: branches/gcc-6-branch/gcc/cp/ChangeLog branches/gcc-6-branch/gcc/cp/init.c
Fixed for 6.2/7 so far.
While your minimal test case seems to be fixed, my test case still fails on GCC 6.2.0 (Debian): The output is now: Base ctor is called at 0x7fff79b27a14 A1::Base is at 0x7fff79b27a14 B1::Base is at 0x7fff79b27a14 Base ctor is called at 0x7fff79b27a10 A2::Base is at 0x7fff79b27a10 C::Base is at 0x7fff79b27a14 2 2 3 There is one less base constructor call, so we are getting there.
*** Bug 80849 has been marked as a duplicate of this bug. ***
This still occurs in 6.3.0 In the duplicate https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80849 I showed that whether or not this occurs can sometimes (I say because my results don't seem consistent with everyone else's) depend on the number of arguments that are given to (all of) the constructors. I could not replicate the problem with my test case if the constructors were invoked with brace syntax and all had no or 1 argument, but I could when they had 2 or more arguments.
Author: jason Date: Mon Sep 18 18:33:52 2017 New Revision: 252937 URL: https://gcc.gnu.org/viewcvs?rev=252937&root=gcc&view=rev Log: PR c++/55922 - list-value-initialization of base PR c++/63151 * init.c (expand_aggr_init_1): Handle list-initialization from {}. Added: branches/gcc-5-branch/gcc/testsuite/g++.dg/cpp0x/initlist-base2.C branches/gcc-5-branch/gcc/testsuite/g++.dg/cpp0x/initlist-base3.C Modified: branches/gcc-5-branch/gcc/cp/ChangeLog branches/gcc-5-branch/gcc/cp/init.c
This is fixed in GCC 7.1 and later, but not in the gcc-6 branch.
The testcase in comment 1 originally made three calls to _ZN4BaseC2Ev until r238688 when it made two, and then only one call after r238689 (the fix for PR 66617). So it looks like the reason it's still wrong on gcc-6-branch is that r238689 isn't on the branch.
Can the bug be marked as resolved?
Fixed so closing.