[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