diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index eec2aceb88a282f029fe932b4e9882c2480c0c50..e607c3c153e0543ebb4ac4d4ec5204847f359a24 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -33,6 +33,7 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD, isa<CXXOperatorCallExpr>(CE)); assert(MD->isInstance() && "Trying to emit a member or operator call expr on a static method!"); + ASTContext &C = CGF.getContext(); // C++11 [class.mfct.non-static]p2: // If a non-static member function of a class X is called for an object that @@ -40,13 +41,16 @@ commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, const CXXMethodDecl *MD, SourceLocation CallLoc; if (CE) CallLoc = CE->getExprLoc(); - CGF.EmitTypeCheck( - isa<CXXConstructorDecl>(MD) ? CodeGenFunction::TCK_ConstructorCall - : CodeGenFunction::TCK_MemberCall, - CallLoc, This, CGF.getContext().getRecordType(MD->getParent())); + CGF.EmitTypeCheck(isa<CXXConstructorDecl>(MD) + ? CodeGenFunction::TCK_ConstructorCall + : CodeGenFunction::TCK_MemberCall, + CallLoc, This, C.getRecordType(MD->getParent())); // Push the this ptr. - Args.add(RValue::get(This), MD->getThisType(CGF.getContext())); + const CXXRecordDecl *RD = + CGF.CGM.getCXXABI().getThisArgumentTypeForMethod(MD); + Args.add(RValue::get(This), + RD ? C.getPointerType(C.getTypeDeclType(RD)) : C.VoidPtrTy); // If there is an implicit parameter (e.g. VTT), emit it. if (ImplicitParam) { diff --git a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp index 5b5d62525e2660bd8171e9c942bedd8294d3ee2c..7eea41c8712e3b131b861c12eb1e1aee0ff62628 100644 --- a/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp +++ b/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp @@ -1,7 +1,7 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA %s -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-linux | FileCheck -check-prefix LINUX %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN32 %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=thumb-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WOA %s +// RUN: %clang_cc1 -std=c++11 -emit-llvm %s -o - -triple=x86_64-pc-win32 -mconstructor-aliases -fno-rtti | FileCheck -check-prefix WIN64 %s struct Empty {}; @@ -401,3 +401,30 @@ void fn2(FnPtr1 a, SmallWithDtor b) { fn1(a, b); }; // WIN32: %[[addr:[^ ]*]] = bitcast {}** %[[gep2]] to void [[dst_ty]]* // WIN32: store void [[dst_ty]] %[[a2]], void [[dst_ty]]* %[[addr]], align 4 // WIN32: call void @"\01?fn1@@YAXP6AXUForwardDeclare1@@@ZUSmallWithDtor@@@Z"([[argmem_ty]]* inalloca %[[argmem]]) + +namespace pr30293 { +// Virtual methods living in a secondary vtable take i8* as their 'this' +// parameter because the 'this' parameter on entry points to the secondary +// vptr. We used to have a bug where we didn't apply this rule consistently, +// and it would cause assertion failures when used with inalloca. +struct A { + virtual void f(); +}; +struct B { + virtual void __cdecl h(SmallWithDtor); +}; +struct C final : A, B { + void g(); + void __cdecl h(SmallWithDtor); + void f(); +}; +void C::g() { return h(SmallWithDtor()); } + +// WIN32-LABEL: define x86_thiscallcc void @"\01?g@C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* %this) +// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE@XZ" +// WIN32: call void @"\01?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}}) +// WIN32: declare void @"\01?h@C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca) + +// WIN64-LABEL: define void @"\01?g@C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this) +// WIN64: declare void @"\01?h@C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32) +}