summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/VTableBuilder.cpp
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2013-12-27 19:43:59 +0000
committerReid Kleckner <reid@kleckner.net>2013-12-27 19:43:59 +0000
commit604c8b45e407da523f105144d4f4294696b37150 (patch)
tree56b4197458efd47c8d57cfeb8dd66ec308412430 /clang/lib/AST/VTableBuilder.cpp
parentac2002973cb68fba3e808eab2920036086d1a214 (diff)
downloadbcm5719-llvm-604c8b45e407da523f105144d4f4294696b37150.tar.gz
bcm5719-llvm-604c8b45e407da523f105144d4f4294696b37150.zip
[ms-cxxabi] Emit fewer trivial return adjusting thunks
Most importantly, this makes our vtable layout match MSVC's. Previously we would emit a return adjusting thunk whenever the return types differed, even if the adjustment would have been trivial. MSVC does emit some trivial return adjusting thunks, but only if there was already an overridden method that required a return adjustment. llvm-svn: 198080
Diffstat (limited to 'clang/lib/AST/VTableBuilder.cpp')
-rw-r--r--clang/lib/AST/VTableBuilder.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index 408fbad17a2..b14ddbfe02e 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -2541,6 +2541,8 @@ private:
}
}
+ bool VFTableBuilder::NeedsReturnAdjustingThunk(const CXXMethodDecl *MD);
+
/// AddMethods - Add the methods of this base subobject and the relevant
/// subbases to the vftable we're currently laying out.
void AddMethods(BaseSubobject Base, unsigned BaseDepth,
@@ -2800,6 +2802,24 @@ static void GroupNewVirtualOverloads(
VirtualMethods.append(Groups[I].rbegin(), Groups[I].rend());
}
+/// We need a return adjusting thunk for this method if its return type is
+/// not trivially convertible to the return type of any of its overridden
+/// methods.
+bool VFTableBuilder::NeedsReturnAdjustingThunk(const CXXMethodDecl *MD) {
+ OverriddenMethodsSetTy OverriddenMethods;
+ ComputeAllOverriddenMethods(MD, OverriddenMethods);
+ for (OverriddenMethodsSetTy::iterator I = OverriddenMethods.begin(),
+ E = OverriddenMethods.end();
+ I != E; ++I) {
+ const CXXMethodDecl *OverriddenMD = *I;
+ BaseOffset Adjustment =
+ ComputeReturnAdjustmentBaseOffset(Context, MD, OverriddenMD);
+ if (!Adjustment.isEmpty())
+ return true;
+ }
+ return false;
+}
+
void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
const CXXRecordDecl *LastVBase,
BasesSetVectorTy &VisitedBases) {
@@ -2885,8 +2905,7 @@ void VFTableBuilder::AddMethods(BaseSubobject Base, unsigned BaseDepth,
AddThunk(MD, VTableThunks[OverriddenMethodInfo.VFTableIndex]);
}
- if (Context.hasSameType(MD->getResultType(),
- OverriddenMD->getResultType())) {
+ if (!NeedsReturnAdjustingThunk(MD)) {
// No return adjustment needed - just replace the overridden method info
// with the current info.
MethodInfo MI(OverriddenMethodInfo.VBTableIndex,
@@ -3049,6 +3068,8 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
case VTableComponent::CK_FunctionPointer: {
const CXXMethodDecl *MD = Component.getFunctionDecl();
+ // FIXME: Figure out how to print the real thunk type, since they can
+ // differ in the return type.
std::string Str = PredefinedExpr::ComputeName(
PredefinedExpr::PrettyFunctionNoVirtual, MD);
Out << Str;
OpenPOWER on IntegriCloud