diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index a90610f5927b7a9064f6a59148515e3af0106430..c6f46c3969b071b3b30bb703ce86f9f0379a003f 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -274,7 +274,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( if (MD->isVirtual()) { This = CGM.getCXXABI().adjustThisArgumentForVirtualFunctionCall( - *this, MD, This, UseVirtualCall); + *this, CalleeDecl, This, UseVirtualCall); } return EmitCXXMemberOrOperatorCall(MD, Callee, ReturnValue, This.getPointer(), diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 8897a384430c8f3a5715d976e360e3072338ce50..f4a6e30119b7d3b158b6da93a41453849426aab2 100644 --- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -481,3 +481,21 @@ C::C() : B() {} // CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[B_i8]], i32 4 // CHECK: call void @llvm.memset.p0i8.i32(i8* %[[FIELD]], i8 0, i32 4, i32 4, i1 false) } + +namespace pr27621 { +// Devirtualization through a static_cast used to make us compute the 'this' +// adjustment for B::g instead of C::g. When we directly call C::g, 'this' is a +// B*, and the prologue of C::g will adjust it to a C*. +struct A { virtual void f(); }; +struct B { virtual void g(); }; +struct C final : A, B { + virtual void h(); + void g() override; +}; +void callit(C *p) { + static_cast<B*>(p)->g(); +} +// CHECK-LABEL: define void @"\01?callit@pr27621@@YAXPAUC@1@@Z"(%"struct.pr27621::C"* %{{.*}}) +// CHECK: %[[B_i8:.*]] = getelementptr i8, i8* %1, i32 4 +// CHECK: call x86_thiscallcc void @"\01?g@C@pr27621@@UAEXXZ"(i8* %[[B_i8]]) +}