r280815 - [MS] Fix 'this' type when calling virtual methods with inalloca

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 7 08:15:52 PDT 2016


Author: rnk
Date: Wed Sep  7 10:15:51 2016
New Revision: 280815

URL: http://llvm.org/viewvc/llvm-project?rev=280815&view=rev
Log:
[MS] Fix 'this' type when calling virtual methods with inalloca

If the virtual method comes from a secondary vtable, then the type of
the 'this' parameter should be i8*, and not a pointer to the complete
class. In the MS ABI, the 'this' parameter on entry points to the vptr
containing the virtual method that was called, so we use i8* instead of
the normal type. We had a mismatch where the CGFunctionInfo of the call
didn't match the CGFunctionInfo of the declaration, and this resulted in
some assertions, but now both sides agree the type of 'this' is i8*.

Fixes one issue raised in PR30293

Modified:
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=280815&r1=280814&r2=280815&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Sep  7 10:15:51 2016
@@ -33,6 +33,7 @@ commonEmitCXXMemberOrOperatorCall(CodeGe
          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(CodeGe
   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) {

Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp?rev=280815&r1=280814&r2=280815&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp Wed Sep  7 10:15:51 2016
@@ -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) { fn
 // 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 at C@pr30293@@QAEXXZ"(%"struct.pr30293::C"* %this)
+// WIN32: call x86_thiscallcc %struct.SmallWithDtor* @"\01??0SmallWithDtor@@QAE at XZ"
+// WIN32: call void @"\01?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca %{{[^,)]*}})
+// WIN32: declare void @"\01?h at C@pr30293@@UAAXUSmallWithDtor@@@Z"(<{ i8*, %struct.SmallWithDtor }>* inalloca)
+
+// WIN64-LABEL: define void @"\01?g at C@pr30293@@QEAAXXZ"(%"struct.pr30293::C"* %this)
+// WIN64: declare void @"\01?h at C@pr30293@@UEAAXUSmallWithDtor@@@Z"(i8*, i32)
+}




More information about the cfe-commits mailing list