The following source generates warning C4407 in VC and the compiler does indeed produce the incorrect code.
struct A1 {
int a1;
};
struct A2 {
int a2;
};
struct B: A1, A2 {
void f() {
std::cout << this << '\n';
}
};
int main() {
B b = B();
void (B::*pb)() = &B::f;
void (A2::*pa)() = (void (A2::*)())pb; // performs static_cast actually
std::cout << (std::uintptr_t&)pb << '\n';
std::cout << (std::uintptr_t&)pa << '\n';
B* pB = &b;
A2* pA = pB;
std::cout << pB << '\n';
std::cout << pA << '\n';
(pB->*pb)();
(pA->*pa)();
}
The code produced is incorrect because pointer pA
is not adjusted when invoking pa
, leading to a wrong this
pointer value in f
. However, the code compiles fine in GCC and clang without any warning (except for the strict-aliasing one). Pointer pA
is properly adjusted in the code produced by GCC and clang. So, I'm wondering what does the standard say about this? Is the cast in the above code fine according to the standard? Or is it a non-standard extension of GCC and clang?
As per the comments -- this is actually a non-standard extension of MSVC -- GCC and CLang are both handling this correctly by default. Anyone else who sees this should use the /vmg
switch on their compiler command line to disable the MSVC extension that allows for 'compacted' PMFs in simple inheritance hierarchies. Unfortunately, the documentation for that switch is quite cryptic -- its relative /vmv
is documented in a way that provides more insight as to what's really going on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With