[cfe-commits] Vtordisp for MS ABI.
John McCall
rjmccall at apple.com
Tue Jun 5 00:44:03 PDT 2012
On May 30, 2012, at 4:46 AM, r4start wrote:
> On 30/05/2012 07:06, John McCall wrote:
>> Is this the rule used by MSVC? For example, does a vtordisp still get emitted even if a ctor "obviously" doesn't call any virtual functions, like if it's defined in the class definition and obviously empty? Please test both an empty ctor and an empty dtor.
>>
> I think MSVC doesn`t analyze ctor or dtor body.
Excellent. That's very good.
>> Please also add testcases verifying that we do the right thing in further-derived classes that provide ctors. For example:
>> struct A { virtual void foo(); };
>> struct B : virtual A { virtual void foo(); }; // no vtordisp
>> struct Test1 : B { Test1(); };
>> struct Test2 : virtual B { Test2(); };
>> struct Test3 : B { Test3(); virtual void foo(); };
>> struct Test4 : virtual B { Test4(); virtual void foo(); };
>>
> Test3 and Test4 have vtordisps for virtual base A. At now clang(with my patch, I test this on my working copy) add vtordisp only in Test4 for B, not for A.
> I add new patch. Problem was in undecidedVBases.erase(overriddenBase). In Test3 overriddenBase == B but undecidedVBases contains A.
Mmm, I'm not sure about this fix. I suspect that the rule here is that a class C requires a vtordisp for a virtual base B if:
1) it has a user-defined constructor or destructor and
2) it declares a method which overrides a method declared by that virtual base or one of its non-virtual bases, directly or no.
This all prompts some more interesting questions which I'd appreciate you running. Given the following:
struct A { virtual void foo(); };
struct B : A {};
struct C : virtual B { virtual void foo(); };
This tests that the rule applies to "virtual subobjects". I think we know this already.
struct Test1 : C { Test1(); virtual void foo(); }; // this should need a vtordisp for B
I'm very suspicious of your "first declaration" test; this should be sufficient as a counter-example, but the problem is deeper. It's more that we have to look everywhere in the hierarchy to see what's overridden by the method.
struct Test2a : C { virtual void foo(); };
struct Test2 : Test2 { Test2(); virtual void foo(); }; // this should need a vtordisp for B
This is just testing whether we can "break up" our class. Basically, should criterion (2) above be "C declares a method..." or "C's construction vtable declares a method..."? For correctness, I think the answer *should* be the latter, but I don't know whether MSVC actually does that, because it requires the emission of Test3's vtable to create a thunk for Test3a::foo(), which might be problematic.
struct Test3a : C { virtual void foo(); };
struct Test3 : Test3a { Test3(); };
John.
More information about the cfe-commits
mailing list