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; +} _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits