@@ -2464,11 +2464,18 @@ class VFTableBuilder {
2464
2464
// / or used for vcalls in the most derived class.
2465
2465
bool Shadowed;
2466
2466
2467
- MethodInfo (uint64_t VBTableIndex, uint64_t VFTableIndex)
2467
+ // / UsesExtraSlot - Indicates if this vftable slot was created because
2468
+ // / any of the overridden slots required a return adjusting thunk.
2469
+ bool UsesExtraSlot;
2470
+
2471
+ MethodInfo (uint64_t VBTableIndex, uint64_t VFTableIndex,
2472
+ bool UsesExtraSlot = false )
2468
2473
: VBTableIndex(VBTableIndex), VFTableIndex(VFTableIndex),
2469
- Shadowed (false ) {}
2474
+ Shadowed (false ), UsesExtraSlot(UsesExtraSlot) {}
2470
2475
2471
- MethodInfo () : VBTableIndex(0 ), VFTableIndex(0 ), Shadowed(false ) {}
2476
+ MethodInfo ()
2477
+ : VBTableIndex(0 ), VFTableIndex(0 ), Shadowed(false ),
2478
+ UsesExtraSlot(false ) {}
2472
2479
};
2473
2480
2474
2481
typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
@@ -2525,8 +2532,6 @@ class VFTableBuilder {
2525
2532
}
2526
2533
}
2527
2534
2528
- bool NeedsReturnAdjustingThunk (const CXXMethodDecl *MD);
2529
-
2530
2535
// / AddMethods - Add the methods of this base subobject and the relevant
2531
2536
// / subbases to the vftable we're currently laying out.
2532
2537
void AddMethods (BaseSubobject Base, unsigned BaseDepth,
@@ -2789,24 +2794,6 @@ static void GroupNewVirtualOverloads(
2789
2794
VirtualMethods.append (Groups[I].rbegin (), Groups[I].rend ());
2790
2795
}
2791
2796
2792
- // / We need a return adjusting thunk for this method if its return type is
2793
- // / not trivially convertible to the return type of any of its overridden
2794
- // / methods.
2795
- bool VFTableBuilder::NeedsReturnAdjustingThunk (const CXXMethodDecl *MD) {
2796
- OverriddenMethodsSetTy OverriddenMethods;
2797
- ComputeAllOverriddenMethods (MD, OverriddenMethods);
2798
- for (OverriddenMethodsSetTy::iterator I = OverriddenMethods.begin (),
2799
- E = OverriddenMethods.end ();
2800
- I != E; ++I) {
2801
- const CXXMethodDecl *OverriddenMD = *I;
2802
- BaseOffset Adjustment =
2803
- ComputeReturnAdjustmentBaseOffset (Context, MD, OverriddenMD);
2804
- if (!Adjustment.isEmpty ())
2805
- return true ;
2806
- }
2807
- return false ;
2808
- }
2809
-
2810
2797
static bool isDirectVBase (const CXXRecordDecl *Base, const CXXRecordDecl *RD) {
2811
2798
for (const auto &B : RD->bases ()) {
2812
2799
if (B.isVirtual () && B.getType ()->getAsCXXRecordDecl () == Base)
@@ -2873,7 +2860,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2873
2860
FindNearestOverriddenMethod (MD, VisitedBases);
2874
2861
2875
2862
ThisAdjustment ThisAdjustmentOffset;
2876
- bool ReturnAdjustingThunk = false ;
2863
+ bool ReturnAdjustingThunk = false , ForceReturnAdjustmentMangling = false ;
2877
2864
CharUnits ThisOffset = ComputeThisOffset (Overrider);
2878
2865
ThisAdjustmentOffset.NonVirtual =
2879
2866
(ThisOffset - WhichVFPtr.FullOffsetInMDC ).getQuantity ();
@@ -2892,7 +2879,16 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2892
2879
2893
2880
MethodInfo &OverriddenMethodInfo = OverriddenMDIterator->second ;
2894
2881
2895
- if (!NeedsReturnAdjustingThunk (MD)) {
2882
+ // Let's check if the overrider requires any return adjustments.
2883
+ // We must create a new slot if the MD's return type is not trivially
2884
+ // convertible to the OverriddenMD's one.
2885
+ // Once a chain of method overrides adds a return adjusting vftable slot,
2886
+ // all subsequent overrides will also use an extra method slot.
2887
+ ReturnAdjustingThunk = !ComputeReturnAdjustmentBaseOffset (
2888
+ Context, MD, OverriddenMD).isEmpty () ||
2889
+ OverriddenMethodInfo.UsesExtraSlot ;
2890
+
2891
+ if (!ReturnAdjustingThunk) {
2896
2892
// No return adjustment needed - just replace the overridden method info
2897
2893
// with the current info.
2898
2894
MethodInfo MI (OverriddenMethodInfo.VBTableIndex ,
@@ -2911,7 +2907,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2911
2907
2912
2908
// Force a special name mangling for a return-adjusting thunk
2913
2909
// unless the method is the final overrider without this adjustment.
2914
- ReturnAdjustingThunk =
2910
+ ForceReturnAdjustmentMangling =
2915
2911
!(MD == OverriderMD && ThisAdjustmentOffset.isEmpty ());
2916
2912
} else if (Base.getBaseOffset () != WhichVFPtr.FullOffsetInMDC ||
2917
2913
MD->size_overridden_methods ()) {
@@ -2926,7 +2922,8 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2926
2922
unsigned VBIndex =
2927
2923
LastVBase ? VTables.getVBTableIndex (MostDerivedClass, LastVBase) : 0 ;
2928
2924
MethodInfo MI (VBIndex,
2929
- HasRTTIComponent ? Components.size () - 1 : Components.size ());
2925
+ HasRTTIComponent ? Components.size () - 1 : Components.size (),
2926
+ ReturnAdjustingThunk);
2930
2927
2931
2928
assert (!MethodInfoMap.count (MD) &&
2932
2929
" Should not have method info for this method yet!" );
@@ -2941,7 +2938,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2941
2938
ComputeReturnAdjustmentBaseOffset (Context, OverriderMD, MD);
2942
2939
}
2943
2940
if (!ReturnAdjustmentOffset.isEmpty ()) {
2944
- ReturnAdjustingThunk = true ;
2941
+ ForceReturnAdjustmentMangling = true ;
2945
2942
ReturnAdjustment.NonVirtual =
2946
2943
ReturnAdjustmentOffset.NonVirtualOffset .getQuantity ();
2947
2944
if (ReturnAdjustmentOffset.VirtualBase ) {
@@ -2955,8 +2952,9 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
2955
2952
}
2956
2953
}
2957
2954
2958
- AddMethod (OverriderMD, ThunkInfo (ThisAdjustmentOffset, ReturnAdjustment,
2959
- ReturnAdjustingThunk ? MD : nullptr ));
2955
+ AddMethod (OverriderMD,
2956
+ ThunkInfo (ThisAdjustmentOffset, ReturnAdjustment,
2957
+ ForceReturnAdjustmentMangling ? MD : nullptr ));
2960
2958
}
2961
2959
}
2962
2960
0 commit comments