Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does VC conform to the standard with respect to warning C4407?

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?

like image 828
Lingxi Avatar asked Nov 01 '22 10:11

Lingxi


1 Answers

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.

like image 197
LThode Avatar answered Nov 04 '22 12:11

LThode