[cfe-commits] r95307 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/member-function-pointer-calls.cpp

Anders Carlsson andersca at mac.com
Thu Feb 4 09:08:48 PST 2010


Author: andersca
Date: Thu Feb  4 11:08:48 2010
New Revision: 95307

URL: http://llvm.org/viewvc/llvm-project?rev=95307&view=rev
Log:
Fix another pointer-to-member function miscompile, this time when trying to call a virtual member function.

Added:
    cfe/trunk/test/CodeGenCXX/member-function-pointer-calls.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=95307&r1=95306&r2=95307&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Thu Feb  4 11:08:48 2010
@@ -159,8 +159,7 @@
     CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT),
                                    FPT->isVariadic());
 
-  const llvm::Type *Int8PtrTy = 
-    llvm::Type::getInt8Ty(VMContext)->getPointerTo();
+  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
 
   // Get the member function pointer.
   llvm::Value *MemFnPtr = 
@@ -206,19 +205,20 @@
   Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual);
   EmitBlock(FnVirtual);
   
-  const llvm::Type *VTableTy = 
-    FTy->getPointerTo()->getPointerTo()->getPointerTo();
+  const llvm::Type *VtableTy = 
+    FTy->getPointerTo()->getPointerTo();
 
-  llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy);
-  VTable = Builder.CreateLoad(VTable);
+  llvm::Value *Vtable = Builder.CreateBitCast(This, VtableTy->getPointerTo());
+  Vtable = Builder.CreateLoad(Vtable);
   
-  VTable = Builder.CreateGEP(VTable, FnAsInt, "fn");
+  Vtable = Builder.CreateBitCast(Vtable, Int8PtrTy);
+  llvm::Value *VtableOffset = 
+    Builder.CreateSub(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1));
   
-  // Since the function pointer is 1 plus the virtual table offset, we
-  // subtract 1 by using a GEP.
-  VTable = Builder.CreateConstGEP1_64(VTable, (uint64_t)-1);
+  Vtable = Builder.CreateGEP(Vtable, VtableOffset, "fn");
+  Vtable = Builder.CreateBitCast(Vtable, VtableTy);
   
-  llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn");
+  llvm::Value *VirtualFn = Builder.CreateLoad(Vtable, "virtualfn");
   
   EmitBranch(FnEnd);
   EmitBlock(FnNonVirtual);

Added: cfe/trunk/test/CodeGenCXX/member-function-pointer-calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/member-function-pointer-calls.cpp?rev=95307&view=auto

==============================================================================
--- cfe/trunk/test/CodeGenCXX/member-function-pointer-calls.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/member-function-pointer-calls.cpp Thu Feb  4 11:08:48 2010
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -O3 -o - | FileCheck %s
+struct A {
+  virtual int vf1() { return 1; }
+  virtual int vf2() { return 2; }
+};
+
+int f(A* a, int (A::*fp)()) {
+  return (a->*fp)();
+}
+
+// CHECK: define i32 @_Z2g1v()
+int g1() {
+  A a;
+  
+  // CHECK: call i32 @_ZN1A3vf1Ev
+  // CHECK-NEXT: ret i32
+  return f(&a, &A::vf1);
+}
+
+int g2() {
+  A a;
+  
+  // CHECK: call i32 @_ZN1A3vf2Ev
+  // CHECK-NEXT: ret i32
+  return f(&a, &A::vf2);
+}





More information about the cfe-commits mailing list