Revert "[MS ABI] Allow fastcall member function pointers to get CodeGen'd"
authorManuel Klimek <klimek@google.com>
Thu, 11 Jun 2015 07:54:35 +0000 (07:54 +0000)
committerManuel Klimek <klimek@google.com>
Thu, 11 Jun 2015 07:54:35 +0000 (07:54 +0000)
Revert "[MS ABI] Allow memfn pointers with unconvertible types to be formed"

This reverts r239499 and r239503; the former breaks tests [1] and the
latter is based on the former.

[1]
http://lab.llvm.org:8080/green/job/clang-stage2-configure-Rlto_check/4473/testReport/Clang/CodeGenCXX/microsoft_abi_virtual_member_pointers_cpp/

llvm-svn: 239511

clang/lib/CodeGen/MicrosoftCXXABI.cpp
clang/test/CodeGenCXX/microsoft-abi-virtual-member-pointers.cpp
clang/test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp

index e19ad69..de30883 100644 (file)
@@ -2423,15 +2423,25 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD,
     FirstField = CGM.GetAddrOfFunction(MD, Ty);
     FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy);
   } else {
-    auto &VTableContext = CGM.getMicrosoftVTableContext();
-    MicrosoftVTableContext::MethodVFTableLocation ML =
-        VTableContext.getMethodVFTableLocation(MD);
-    llvm::Function *Thunk = EmitVirtualMemPtrThunk(MD, ML);
-    FirstField = llvm::ConstantExpr::getBitCast(Thunk, CGM.VoidPtrTy);
-    // Include the vfptr adjustment if the method is in a non-primary vftable.
-    NonVirtualBaseAdjustment += ML.VFPtrOffset;
-    if (ML.VBase)
-      VBTableIndex = VTableContext.getVBTableIndex(RD, ML.VBase) * 4;
+    if (!CGM.getTypes().isFuncTypeConvertible(
+            MD->getType()->castAs<FunctionType>())) {
+      CGM.ErrorUnsupported(MD, "pointer to virtual member function with "
+                               "incomplete return or parameter type");
+      FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
+    } else if (FPT->getCallConv() == CC_X86FastCall) {
+      CGM.ErrorUnsupported(MD, "pointer to fastcall virtual member function");
+      FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
+    } else {
+      auto &VTableContext = CGM.getMicrosoftVTableContext();
+      MicrosoftVTableContext::MethodVFTableLocation ML =
+          VTableContext.getMethodVFTableLocation(MD);
+      llvm::Function *Thunk = EmitVirtualMemPtrThunk(MD, ML);
+      FirstField = llvm::ConstantExpr::getBitCast(Thunk, CGM.VoidPtrTy);
+      // Include the vfptr adjustment if the method is in a non-primary vftable.
+      NonVirtualBaseAdjustment += ML.VFPtrOffset;
+      if (ML.VBase)
+        VBTableIndex = VTableContext.getVBTableIndex(RD, ML.VBase) * 4;
+    }
   }
 
   // The rest of the fields are common with data member pointers.
index eb5f90d..f6f7583 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32
-// RUN: %clang_cc1 -std=c++11 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK32
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK64
 
 struct S {
   int x, y, z;
@@ -13,15 +13,12 @@ struct U {
   U(const U &);
 };
 
-struct B;
-
 struct C {
   virtual void foo();
   virtual int bar(int, double);
   virtual S baz(int);
   virtual S qux(U);
   virtual void thud(...);
-  virtual void (B::*plugh())();
 };
 
 namespace {
@@ -50,8 +47,6 @@ void f() {
   void (C::*ptr6)(...);
   ptr6 = &C::thud;
 
-  auto ptr7 = &C::plugh;
-
 
 // CHECK32-LABEL: define void @"\01?f@@YAXXZ"()
 // CHECK32: store i8* bitcast (void (%struct.C*, ...)* @"\01??_9C@@$BA@AE" to i8*), i8** %ptr
@@ -172,18 +167,4 @@ void f() {
 // CHECK64: ret void
 // CHECK64: }
 
-// CHECK32: define linkonce_odr x86_thiscallcc void @"\01??_9C@@$BBE@AE"(%struct.C* %this, ...) {{.*}} comdat align 2 {
-// CHECK32: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %vtable, i64 5
-// CHECK32: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
-// CHECK32: musttail call x86_thiscallcc void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
-// CHECK32: ret void
-// CHECK32: }
-
-// CHECK64: define linkonce_odr void @"\01??_9C@@$BCI@AA"(%struct.C* %this, ...) {{.*}} comdat align 2 {
-// CHECK64: [[VPTR:%.*]] = getelementptr inbounds void (%struct.C*, ...)*, void (%struct.C*, ...)** %vtable, i64 5
-// CHECK64: [[CALLEE:%.*]] = load void (%struct.C*, ...)*, void (%struct.C*, ...)** [[VPTR]]
-// CHECK64: musttail call void (%struct.C*, ...) [[CALLEE]](%struct.C* %{{.*}}, ...)
-// CHECK64: ret void
-// CHECK64: }
-
 // CHECK32: #[[ATTR]] = {{{.*}}"thunk"{{.*}}}
index 61cd58a..6d42b85 100644 (file)
@@ -1,15 +1,11 @@
-// RUN: %clang_cc1 -fms-extensions -triple i686-pc-windows-msvc %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -fms-extensions -triple i686-pc-windows-msvc %s -emit-llvm-only -verify
+
+// We reject this because LLVM doesn't forward the second regparm through the
+// thunk.
 
 struct A {
-  virtual void __fastcall f(int a, int b);
+  virtual void __fastcall f(int a, int b); // expected-error {{cannot compile this pointer to fastcall virtual member function yet}}
 };
 void (__fastcall A::*doit())(int, int) {
   return &A::f;
 }
-
-// CHECK: define linkonce_odr x86_fastcallcc void @"\01??_9A@@$BA@AI"(%struct.A* inreg %this, ...) {{.*}} comdat align 2 {
-// CHECK: [[VPTR:%.*]] = getelementptr inbounds void (%struct.A*, ...)*, void (%struct.A*, ...)** %vtable, i64 0
-// CHECK: [[CALLEE:%.*]] = load void (%struct.A*, ...)*, void (%struct.A*, ...)** [[VPTR]]
-// CHECK: musttail call x86_fastcallcc void (%struct.A*, ...) [[CALLEE]](%struct.A* inreg %{{.*}}, ...)
-// CHECK: ret void
-// CHECK: }