r236962 - [MS ABI] Form member pointers from virtual funcs overriding vbases

David Majnemer david.majnemer at gmail.com
Sun May 10 14:48:09 PDT 2015


Author: majnemer
Date: Sun May 10 16:48:08 2015
New Revision: 236962

URL: http://llvm.org/viewvc/llvm-project?rev=236962&view=rev
Log:
[MS ABI] Form member pointers from virtual funcs overriding vbases

We didn't supporting taking the address of virtual member functions
which overrode a method in a virtual base.  We simply need to encode the
virtual base index in the member pointer.

This fixes PR23452.

N.B.  There is no data member pointer side to this change because taking
the address of a virtual bases' data member gives you a member pointer
whose type is derived from the virtual bases' type, not the most derived
type.

Added:
    cfe/trunk/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp
Modified:
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=236962&r1=236961&r2=236962&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Sun May 10 16:48:08 2015
@@ -496,7 +496,8 @@ private:
   llvm::Constant *EmitFullMemberPointer(llvm::Constant *FirstField,
                                         bool IsMemberFunction,
                                         const CXXRecordDecl *RD,
-                                        CharUnits NonVirtualBaseAdjustment);
+                                        CharUnits NonVirtualBaseAdjustment,
+                                        unsigned VBTableIndex);
 
   llvm::Constant *BuildMemberPointer(const CXXRecordDecl *RD,
                                      const CXXMethodDecl *MD,
@@ -2332,8 +2333,8 @@ llvm::Constant *
 MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField,
                                        bool IsMemberFunction,
                                        const CXXRecordDecl *RD,
-                                       CharUnits NonVirtualBaseAdjustment)
-{
+                                       CharUnits NonVirtualBaseAdjustment,
+                                       unsigned VBTableIndex) {
   MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel();
 
   // Single inheritance class member pointer are represented as scalars instead
@@ -2357,7 +2358,7 @@ MicrosoftCXXABI::EmitFullMemberPointer(l
 
   // The rest of the fields are adjusted by conversions to a more derived class.
   if (MSInheritanceAttr::hasVBTableOffsetField(Inheritance))
-    fields.push_back(getZeroInt());
+    fields.push_back(llvm::ConstantInt::get(CGM.IntTy, VBTableIndex));
 
   return llvm::ConstantStruct::getAnon(fields);
 }
@@ -2369,7 +2370,7 @@ MicrosoftCXXABI::EmitMemberDataPointer(c
   llvm::Constant *FirstField =
     llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity());
   return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD,
-                               CharUnits::Zero());
+                               CharUnits::Zero(), /*VBTableIndex=*/0);
 }
 
 llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
@@ -2405,6 +2406,7 @@ MicrosoftCXXABI::BuildMemberPointer(cons
   RD = RD->getMostRecentDecl();
   CodeGenTypes &Types = CGM.getTypes();
 
+  unsigned VBTableIndex = 0;
   llvm::Constant *FirstField;
   const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
   if (!MD->isVirtual()) {
@@ -2421,8 +2423,6 @@ MicrosoftCXXABI::BuildMemberPointer(cons
     FirstField = CGM.GetAddrOfFunction(MD, Ty);
     FirstField = llvm::ConstantExpr::getBitCast(FirstField, CGM.VoidPtrTy);
   } else {
-    MicrosoftVTableContext::MethodVFTableLocation ML =
-        CGM.getMicrosoftVTableContext().getMethodVFTableLocation(MD);
     if (!CGM.getTypes().isFuncTypeConvertible(
             MD->getType()->castAs<FunctionType>())) {
       CGM.ErrorUnsupported(MD, "pointer to virtual member function with "
@@ -2431,21 +2431,22 @@ MicrosoftCXXABI::BuildMemberPointer(cons
     } else if (FPT->getCallConv() == CC_X86FastCall) {
       CGM.ErrorUnsupported(MD, "pointer to fastcall virtual member function");
       FirstField = llvm::Constant::getNullValue(CGM.VoidPtrTy);
-    } else if (ML.VBase) {
-      CGM.ErrorUnsupported(MD, "pointer to virtual member function overriding "
-                               "member function in virtual base class");
-      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.
   return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/true, RD,
-                               NonVirtualBaseAdjustment);
+                               NonVirtualBaseAdjustment, VBTableIndex);
 }
 
 /// Member pointers are the same if they're either bitwise identical *or* both

Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp?rev=236962&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-vmemptr-vbase.cpp Sun May 10 16:48:08 2015
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm -triple=i386-pc-win32 -fms-extensions -fms-compatibility -std=c++11 %s -o - | FileCheck %s
+
+namespace PR23452 {
+struct A {
+    virtual void f();
+};
+struct B : virtual A {
+    virtual void f();
+};
+void (B::*MemPtr)(void) = &B::f;
+// CHECK-DAG: @"\01?MemPtr at PR23452@@3P8B at 1@AEXXZQ21@" = global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01??_9B at PR23452@@$BA at AE" to i8*), i32 0, i32 4 }
+}





More information about the cfe-commits mailing list