[cfe-commits] r105151 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp lib/CodeGen/CGCall.cpp lib/CodeGen/CGExprAgg.cpp lib/CodeGen/CGExprConstant.cpp lib/CodeGen/CodeGenModule.h lib/CodeGen/CodeGenTypes.cpp lib/CodeGen/CodeGenTypes.h test/CodeGenCXX/incomplete-member-function-pointer.cpp

Eli Friedman eli.friedman at gmail.com
Sat May 29 23:03:20 PDT 2010


Author: efriedma
Date: Sun May 30 01:03:20 2010
New Revision: 105151

URL: http://llvm.org/viewvc/llvm-project?rev=105151&view=rev
Log:
Fix for PR7040: Don't try to compute the LLVM type for a function where it
isn't possible to compute.

This patch is mostly refactoring; the key change is the addition of the code
starting with the comment, "Check whether the function has a computable LLVM
signature."  The solution here is essentially the same as the way the
vtable code handles such functions.


Added:
    cfe/trunk/test/CodeGenCXX/incomplete-member-function-pointer.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGCXX.cpp
    cfe/trunk/lib/CodeGen/CGCall.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
    cfe/trunk/lib/CodeGen/CodeGenTypes.h

Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=105151&r1=105150&r2=105151&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Sun May 30 01:03:20 2010
@@ -304,6 +304,44 @@
   getMangleContext().mangleCXXDtor(D, Type, Name.getBuffer());
 }
 
+llvm::Constant *
+CodeGenModule::GetCXXMemberFunctionPointerValue(const CXXMethodDecl *MD) {
+  assert(MD->isInstance() && "Member function must not be static!");
+    
+  MD = MD->getCanonicalDecl();
+
+  const llvm::Type *PtrDiffTy = Types.ConvertType(Context.getPointerDiffType());
+
+  // Get the function pointer (or index if this is a virtual function).
+  if (MD->isVirtual()) {
+    uint64_t Index = VTables.getMethodVTableIndex(MD);
+
+    // FIXME: We shouldn't use / 8 here.
+    uint64_t PointerWidthInBytes = Context.Target.getPointerWidth(0) / 8;
+
+    // Itanium C++ ABI 2.3:
+    //   For a non-virtual function, this field is a simple function pointer. 
+    //   For a virtual function, it is 1 plus the virtual table offset 
+    //   (in bytes) of the function, represented as a ptrdiff_t. 
+    return llvm::ConstantInt::get(PtrDiffTy, (Index * PointerWidthInBytes) + 1);
+  }
+
+  const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
+  const llvm::Type *Ty;
+  // Check whether the function has a computable LLVM signature.
+  if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
+    // The function has a computable LLVM signature; use the correct type.
+    Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic());
+  } else {
+    // Use an arbitrary non-function type to tell GetAddrOfFunction that the
+    // function type is incomplete.
+    Ty = PtrDiffTy;
+  }
+
+  llvm::Constant *FuncPtr = GetAddrOfFunction(MD, Ty);
+  return llvm::ConstantExpr::getPtrToInt(FuncPtr, PtrDiffTy);
+}
+
 static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VTableIndex, 
                                      llvm::Value *This, const llvm::Type *Ty) {
   Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo();

Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=105151&r1=105150&r2=105151&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Sun May 30 01:03:20 2010
@@ -515,27 +515,11 @@
   return llvm::FunctionType::get(ResultType, ArgTys, IsVariadic);
 }
 
-static bool HasIncompleteReturnTypeOrArgumentTypes(const FunctionProtoType *T) {
-  if (const TagType *TT = T->getResultType()->getAs<TagType>()) {
-    if (!TT->getDecl()->isDefinition())
-      return true;
-  }
-
-  for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) {
-    if (const TagType *TT = T->getArgType(i)->getAs<TagType>()) {
-      if (!TT->getDecl()->isDefinition())
-        return true;
-    }
-  }
-
-  return false;
-}
-
 const llvm::Type *
 CodeGenTypes::GetFunctionTypeForVTable(const CXXMethodDecl *MD) {
   const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
   
-  if (!HasIncompleteReturnTypeOrArgumentTypes(FPT))
+  if (!VerifyFuncTypeComplete(FPT))
     return GetFunctionType(getFunctionInfo(MD), FPT->isVariadic());
 
   return llvm::OpaqueType::get(getLLVMContext());

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=105151&r1=105150&r2=105151&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Sun May 30 01:03:20 2010
@@ -396,35 +396,11 @@
   const llvm::Type *PtrDiffTy = 
     CGF.ConvertType(CGF.getContext().getPointerDiffType());
 
-
   llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "dst.ptr");
-  llvm::Value *FuncPtr;
-  
-  if (MD->isVirtual()) {
-    int64_t Index = CGF.CGM.getVTables().getMethodVTableIndex(MD);
-    
-    // FIXME: We shouldn't use / 8 here.
-    uint64_t PointerWidthInBytes = 
-      CGF.CGM.getContext().Target.getPointerWidth(0) / 8;
-
-    // Itanium C++ ABI 2.3:
-    //   For a non-virtual function, this field is a simple function pointer. 
-    //   For a virtual function, it is 1 plus the virtual table offset 
-    //   (in bytes) of the function, represented as a ptrdiff_t. 
-    FuncPtr = llvm::ConstantInt::get(PtrDiffTy,
-                                     (Index * PointerWidthInBytes) + 1);
-  } else {
-    const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
-    const llvm::Type *Ty =
-      CGF.CGM.getTypes().GetFunctionType(CGF.CGM.getTypes().getFunctionInfo(MD),
-                                         FPT->isVariadic());
-    llvm::Constant *Fn = CGF.CGM.GetAddrOfFunction(MD, Ty);
-    FuncPtr = llvm::ConstantExpr::getPtrToInt(Fn, PtrDiffTy);
-  }
+  llvm::Value *FuncPtr = CGF.CGM.GetCXXMemberFunctionPointerValue(MD);
   Builder.CreateStore(FuncPtr, DstPtr, VolatileDest);
 
   llvm::Value *AdjPtr = Builder.CreateStructGEP(DestPtr, 1, "dst.adj");
-  
   // The adjustment will always be 0.
   Builder.CreateStore(llvm::ConstantInt::get(PtrDiffTy, 0), AdjPtr,
                       VolatileDest);

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=105151&r1=105150&r2=105151&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Sun May 30 01:03:20 2010
@@ -443,30 +443,8 @@
       CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
     
     llvm::Constant *Values[2];
-    
-    // Get the function pointer (or index if this is a virtual function).
-    if (MD->isVirtual()) {
-      uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD);
-
-      // FIXME: We shouldn't use / 8 here.
-      uint64_t PointerWidthInBytes = 
-        CGM.getContext().Target.getPointerWidth(0) / 8;
-      
-      // Itanium C++ ABI 2.3:
-      //   For a non-virtual function, this field is a simple function pointer. 
-      //   For a virtual function, it is 1 plus the virtual table offset 
-      //   (in bytes) of the function, represented as a ptrdiff_t. 
-      Values[0] = llvm::ConstantInt::get(PtrDiffTy, 
-                                         (Index * PointerWidthInBytes) + 1);
-    } else {
-      const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
-      const llvm::Type *Ty =
-        CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD),
-                                       FPT->isVariadic());
-
-      llvm::Constant *FuncPtr = CGM.GetAddrOfFunction(MD, Ty);
-      Values[0] = llvm::ConstantExpr::getPtrToInt(FuncPtr, PtrDiffTy);
-    } 
+
+    Values[0] = CGM.GetCXXMemberFunctionPointerValue(MD);
     
     // The adjustment will always be 0.
     Values[1] = llvm::ConstantInt::get(PtrDiffTy, 0);

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=105151&r1=105150&r2=105151&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sun May 30 01:03:20 2010
@@ -315,6 +315,10 @@
   llvm::GlobalValue *GetAddrOfCXXDestructor(const CXXDestructorDecl *D,
                                             CXXDtorType Type);
 
+  // GetCXXMemberFunctionPointerValue - Given a method declaration, return the
+  // integer used in a member function pointer to refer to that value.
+  llvm::Constant *GetCXXMemberFunctionPointerValue(const CXXMethodDecl *MD);
+
   /// getBuiltinLibFunction - Given a builtin id for a function like
   /// "__builtin_fabsf", return a Function* for "fabsf".
   llvm::Value *getBuiltinLibFunction(const FunctionDecl *FD,

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=105151&r1=105150&r2=105151&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Sun May 30 01:03:20 2010
@@ -108,7 +108,7 @@
 
 // Code to verify a given function type is complete, i.e. the return type
 // and all of the argument types are complete.
-static const TagType *VerifyFuncTypeComplete(const Type* T) {
+const TagType *CodeGenTypes::VerifyFuncTypeComplete(const Type* T) {
   const FunctionType *FT = cast<FunctionType>(T);
   if (const TagType* TT = FT->getResultType()->getAs<TagType>())
     if (!TT->getDecl()->isDefinition())

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=105151&r1=105150&r2=105151&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Sun May 30 01:03:20 2010
@@ -122,6 +122,10 @@
 
   const llvm::FunctionType *GetFunctionType(GlobalDecl GD);
 
+  /// VerifyFuncTypeComplete - Utility to check whether a function type can
+  /// be converted to an LLVM type (i.e. doesn't depend on an incomplete tag
+  /// type).
+  static const TagType *VerifyFuncTypeComplete(const Type* T);
 
   /// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
   /// given a CXXMethodDecl. If the method to has an incomplete return type, 

Added: cfe/trunk/test/CodeGenCXX/incomplete-member-function-pointer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/incomplete-member-function-pointer.cpp?rev=105151&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/incomplete-member-function-pointer.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/incomplete-member-function-pointer.cpp Sun May 30 01:03:20 2010
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 %s -emit-llvm-only
+// PR7040
+struct fake_tuple;
+struct connection {
+    void bar(fake_tuple);
+};
+void (connection::*a)(fake_tuple) = &connection::bar;
+void f() {
+  void (connection::*b)(fake_tuple) = &connection::bar;
+}





More information about the cfe-commits mailing list