diff options
author | Chris Lattner <sabre@nondot.org> | 2011-07-10 03:47:27 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2011-07-10 03:47:27 +0000 |
commit | f0a8679b6e6635117533b89894646f1450cea25b (patch) | |
tree | 0524a1b5ef9d8052c6bc846d6614c8c187fa05c6 /lib/CodeGen | |
parent | 12569fb55db2a8181711ac134b7479155db4f838 (diff) |
Fix the clang bootstrap and Jay's testcase from llvm-dev by being completely
conservative when converting a functiontype to IR when in a "pointer within
a struct" context. This has the unfortunate sideeffect of compiling all
function pointers inside of structs into "{}*" which, though correct, is
ugly. This has the positive side effect of being correct, and it is pretty
straight-forward to improve on this.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134861 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index f304df917b..59c632f0d7 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -104,6 +104,7 @@ bool CodeGenTypes::isFuncTypeArgumentConvertible(QualType Ty){ 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; @@ -158,8 +159,14 @@ void CodeGenTypes::UpdateCompletedType(const TagDecl *TD) { return; } + // If we completed a RecordDecl that we previously used and converted to an + // anonymous type, then go ahead and complete it now. const RecordDecl *RD = cast<RecordDecl>(TD); - if (!RD->isDependentType()) + if (RD->isDependentType()) return; + + // Only complete it if we converted it already. If we haven't converted it + // yet, we'll just do it lazily. + // if (RecordDeclTypes.count(Context.getTagDeclType(RD).getTypePtr())) ConvertRecordDeclType(RD); } @@ -333,13 +340,20 @@ 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 (!isFuncTypeConvertible(cast<FunctionType>(Ty))) { + if (RecursionState == RS_StructPointer || + !isFuncTypeConvertible(cast<FunctionType>(Ty))) { // This function's type depends on an incomplete tag type. // Return a placeholder type. ResultType = llvm::StructType::get(getLLVMContext()); break; } + // While we're converting the argument types for a function, we don't want + // to recursively convert any pointed-to structs. Converting directly-used + // structs is ok though. + RecursionStateTy SavedRecursionState = RecursionState; + RecursionState = RS_Struct; + // The function type can be built; call the appropriate routines to // build it. const CGFunctionInfo *FI; @@ -354,8 +368,15 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { CanQual<FunctionNoProtoType>::CreateUnsafe(QualType(FNPT, 0))); isVariadic = true; } - + ResultType = GetFunctionType(*FI, isVariadic); + + // Restore our recursion state. + RecursionState = SavedRecursionState; + + if (RecursionState == RS_Normal) + while (!DeferredRecords.empty()) + ConvertRecordDeclType(DeferredRecords.pop_back_val()); break; } @@ -463,10 +484,16 @@ llvm::StructType *CodeGenTypes::ConvertRecordDeclType(const RecordDecl *RD) { CGRecordLayout *Layout = ComputeRecordLayout(RD, Ty); CGRecordLayouts[Key] = Layout; + // If this struct blocked a FunctionType conversion, then recompute whatever + // was derived from that. + // FIXME: This is hugely overconservative. + TypeCache.clear(); + // Restore our recursion state. If we're done converting the outer-most // record, then convert any deferred structs as well. RecursionState = SavedRecursionState; + if (RecursionState == RS_Normal) while (!DeferredRecords.empty()) ConvertRecordDeclType(DeferredRecords.pop_back_val()); |