Rename CGT::VerifyFuncTypeComplete to isFuncTypeConvertible since

it is a predicate, not an action.  Change the return type to be a bool,
not the incomplete member.  Enhace it to detect the recursive compilation
case, allowing us to compile Eli's testcase on llvmdev:

struct T {
 struct T (*p)(void);
} t;

into:

%struct.T = type { {}* }

@t = common global %struct.T zeroinitializer, align 8




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134853 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2011-07-10 00:18:59 +00:00
Родитель 064fa99dbe
Коммит f742eb0196
6 изменённых файлов: 73 добавлений и 28 удалений

Просмотреть файл

@ -704,16 +704,15 @@ const llvm::Type *CodeGenTypes::GetFunctionTypeForVTable(GlobalDecl GD) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();
if (!VerifyFuncTypeComplete(FPT)) {
const CGFunctionInfo *Info;
if (isa<CXXDestructorDecl>(MD))
Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
else
Info = &getFunctionInfo(MD);
return GetFunctionType(*Info, FPT->isVariadic());
}
return llvm::StructType::get(getLLVMContext());
if (!isFuncTypeConvertible(FPT))
return llvm::StructType::get(getLLVMContext());
const CGFunctionInfo *Info;
if (isa<CXXDestructorDecl>(MD))
Info = &getFunctionInfo(cast<CXXDestructorDecl>(MD), GD.getDtorType());
else
Info = &getFunctionInfo(MD);
return GetFunctionType(*Info, FPT->isVariadic());
}
void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,

Просмотреть файл

@ -2937,7 +2937,8 @@ void CodeGenVTables::MaybeEmitThunkAvailableExternally(GlobalDecl GD,
// We can't emit thunks for member functions with incomplete types.
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
if (CGM.getTypes().VerifyFuncTypeComplete(MD->getType().getTypePtr()))
if (!CGM.getTypes().isFuncTypeConvertible(
cast<FunctionType>(MD->getType().getTypePtr())))
return;
EmitThunk(GD, Thunk, /*UseAvailableExternallyLinkage=*/true);

Просмотреть файл

@ -93,19 +93,55 @@ llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T){
}
// Code to verify a given function type is complete, i.e. the return type
// and all of the argument types are complete.
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())
return TT;
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(T))
/// isFuncTypeArgumentConvertible - Return true if the specified type in a
/// function argument or result position can be converted to an IR type at this
/// point. This boils down to being whether it is complete, as well as whether
/// we've temporarily deferred expanding the type because we're in a recursive
/// context.
bool CodeGenTypes::isFuncTypeArgumentConvertible(QualType Ty){
// If this isn't a tagged type, we can convert it!
const TagType *TT = Ty->getAs<TagType>();
if (TT == 0) return true;
// If it's a tagged type, but is a forward decl, we can't convert it.
if (!TT->getDecl()->isDefinition())
return false;
// If we're not under a pointer under a struct, then we can convert it if
// needed.
if (RecursionState != RS_StructPointer)
return true;
// If this is an enum, then it is safe to convert.
const RecordType *RT = dyn_cast<RecordType>(TT);
if (RT == 0) return true;
// Otherwise, we have to be careful. If it is a struct that we're in the
// process of expanding, then we can't convert the function type. That's ok
// though because we must be in a pointer context under the struct, so we can
// just convert it to a dummy type.
//
// We decide this by checking whether ConvertRecordDeclType returns us an
// opaque type for a struct that we know is defined.
return !ConvertRecordDeclType(RT->getDecl())->isOpaque();
}
/// Code to verify a given function type is complete, i.e. the return type
/// and all of the argument types are complete. Also check to see if we are in
/// a RS_StructPointer context, and if so whether any struct types have been
/// pended. If so, we don't want to ask the ABI lowering code to handle a type
/// that cannot be converted to an IR type.
bool CodeGenTypes::isFuncTypeConvertible(const FunctionType *FT) {
if (!isFuncTypeArgumentConvertible(FT->getResultType()))
return false;
if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT))
for (unsigned i = 0, e = FPT->getNumArgs(); i != e; i++)
if (const TagType *TT = FPT->getArgType(i)->getAs<TagType>())
if (!TT->getDecl()->isDefinition())
return TT;
return 0;
if (!isFuncTypeArgumentConvertible(FPT->getArgType(i)))
return false;
return true;
}
/// UpdateCompletedType - When we find the full definition for a TagDecl,
@ -296,7 +332,7 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
// First, check whether we can build the full function type. If the
// function type depends on an incomplete type (e.g. a struct or enum), we
// cannot lower the function type.
if (VerifyFuncTypeComplete(Ty)) {
if (!isFuncTypeConvertible(cast<FunctionType>(Ty))) {
// This function's type depends on an incomplete tag type.
// Return a placeholder type.
ResultType = llvm::StructType::get(getLLVMContext());

Просмотреть файл

@ -137,11 +137,12 @@ public:
llvm::FunctionType *GetFunctionType(GlobalDecl GD);
/// VerifyFuncTypeComplete - Utility to check whether a function type can
/// isFuncTypeConvertible - 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);
bool isFuncTypeConvertible(const FunctionType *FT);
bool isFuncTypeArgumentConvertible(QualType Ty);
/// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable,
/// given a CXXMethodDecl. If the method to has an incomplete return type,
/// and/or incomplete argument types, this will return the opaque type.

Просмотреть файл

@ -537,7 +537,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
const llvm::Type *Ty;
// Check whether the function has a computable LLVM signature.
if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) {
if (Types.isFuncTypeConvertible(FPT)) {
// The function has a computable LLVM signature; use the correct type.
Ty = Types.GetFunctionType(Types.getFunctionInfo(MD),
FPT->isVariadic());

Просмотреть файл

@ -115,3 +115,11 @@ void test11(struct test11S *P) {
// CHECK: store i32 4
// CHECK: ret void
}
// Verify that we can convert a recursive struct with a memory that returns
// an instance of the struct we're converting.
struct test12 {
struct test12 (*p)(void);
} test12g;