[cfe-dev] Microsoft vtordisp field support for clang.
John McCall
rjmccall at apple.com
Mon Feb 13 17:06:30 PST 2012
On Feb 13, 2012, at 4:29 AM, r4start wrote:
> On 11/02/2012 02:24, John McCall wrote:
>>
>> I guess we still need to record whether
>> a base actually requires this at all. I'd be more comfortable with storing this
>> as additional value information in VBaseOffsets; that will avoid bloating
>> the RecordLayout for the common case of a class with no virtual bases.
> Are you suggest something like this?
> struct VBaseInfo {
> CharUnits Offset;
> bool IsVtorDispPresent;
> };
> llvm::DenseMap<const CXXRecordDecl *, VBaseInfo> VBaseOffsets;
Yep, that's what I had in mind.
>> + CharUnits IntSize =
>> + CharUnits::fromQuantity(Context.getTargetInfo().getIntWidth() / 8);
>>
>> Is this really 'int'? Like, on Windows 64, is this still only 32-bits?
> Yes, this field on Windows x64 is still int.
Okay, that looks good, then.
>> +bool RecordLayoutBuilder::needsVtorDisp(const CXXRecordDecl *RD,
>> + const CXXRecordDecl *Base) const {
>>
>> This entire algorithm is grossly inefficient. I believe that all you want is:
>> 1) Create a set of classes, and fill it with the all virtual bases.
>> 2) For each virtual method in the entire class hierarchy, remove all the
>> classes declaring a method overridden by that method.
>> 3) A vtordisp field is required for every virtual base class which is no
>> longer in the set.
>> In addition, you can avoid the full hierarchy walk by immediately
>> removing virtual bases which are known by a direct base class to
>> require a vtordisp field.
>>
>> This algorithm has the side-effect of working when a function overrides
>> two different virtual functions from virtual bases at once.
> Please tell me if I am not right.
> You suggest remove this function with function like this "void RecordLayoutBuilder::FillVtorDispBases(const CXXRecordDecl *RD)".
>
> This function in pseudo code:
>
> Vbases = getAllVBasesForRD; // First step in your algorithm.
> VBasesVtorDisp;
>
> // Then goes step 2, but if we want traverse all virtual methods we must walk throw inheritance path.
> foreach (VBase in Vbases) {
> CXXBasePath &Path = getPathFromRDToVBase;
> bool needsVtorDisp = false;
>
> foreach(Class in Path) {
> // Here we will have another 'for' from Class->method_begin() to Class->method_end(),
> // and check that Class overrides virtual method from VBase.
> if ((Class.hasCtorDeclared || Class.hasDtorDeclared) && Class.overridesVirtualFunctionOfBase) {
> needsVtorDisp = true;
> break;
> }
> }
> if (needsVtorDisp)
> VBasesVtorDisp.push_back(VBase);
> }
> If I am right then I am not sure that this algorithm is better.
I don't think this needs to be path-dependent, or at least not path-dependent in any way beyond what's encapsulated in the usual override rules. Either the most-derived class directly overrides a method from a virtual base class, or one of its base classes does. That is, I think the algorithm just needs to be something like this:
var basesThatNeedVtorDisps : set<class>
for each (base in mostDerivedClass.directBases)
basesThatNeedVtorDisps.addAll(base.basesThatNeedVtorDisps)
for each (method in mostDerivedClass.virtualMethods)
for each (overriddenMethod in method.overriddenMethods)
if (mostDerivedClass.virtualBases.contains(overriddenMethod.declaringClass))
basesThatNeedVtorDisps.add(overriddenMethod.declaringClass);
The only tricky thing is that you might be overriding a method from a non-virtual base of a virtual base; I don't even know what that's supposed to do for these vtordisp fields, though. Could you check? The test case would be something like this:
class A { virtual void foo(); }
class B : public A { };
class C : public virtual B { C(); virtual void foo(); };
John.
More information about the cfe-dev
mailing list