diff options
Diffstat (limited to 'lib/CodeGen/CodeGenTypes.cpp')
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 9375410477..ed44aec492 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -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()); |