https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81051
Matthew House changed:
What|Removed |Added
CC||mattlloydhouse at gmail dot com
--- Comment #4 from Matthew House ---
Both of these example programs result in undefined behavior.
The cited subclause, C++14 12.7 [class.dtor] p3, does not apply, since the call
expression neither forms a pointer to a member nor accesses the value of a
member. Instead, the relevant subclause is C++14 12.6.2 [class.base.init] p14.
The example for that subclause demonstrates that a member function inherited
from an initialized base class may not be called directly from the derived
object until all base class subobjects are initialized.
In the first program, this->Func() calls the inherited member function Func of
Derived, but the initializer for B has not completed yet, so the behavior is
undefined. The same applies to the p->Func() call in the second program.
However, this segfault persists if this->Func() or p->Func() is replaced with
((A*)this)->Func() or ((A*)p)->Func() in either example. The conversion doesn't
result in UB, since the construction of Derived has started, and the function
call doesn't result in UB, since the A subobject is already initialized. Thus,
the behavior of GCC is still erroneous in this case.
struct A
{
int Func () { return x++; }
int x = 5;
};
struct B { B (int) {} };
struct Derived : virtual A, B
{
friend int f (Derived *p) { return ((A *) p)->Func (); }
Derived () : A (), B (f (this)) {}
};
int main()
{
Derived d;
}