Author: lattner Date: Sat Jul 9 22:47:27 2011 New Revision: 134861 URL: http://llvm.org/viewvc/llvm-project?rev=134861&view=rev Log: 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.
Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp cfe/trunk/test/CodeGen/struct.c cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp cfe/trunk/test/CodeGenObjC/arc-foreach.m cfe/trunk/test/CodeGenObjC/arc.m cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=134861&r1=134860&r2=134861&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original) +++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Sat Jul 9 22:47:27 2011 @@ -104,6 +104,7 @@ 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 @@ 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 @@ // 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 @@ 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 @@ 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()); Modified: cfe/trunk/test/CodeGen/struct.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/struct.c?rev=134861&r1=134860&r2=134861&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/struct.c (original) +++ cfe/trunk/test/CodeGen/struct.c Sat Jul 9 22:47:27 2011 @@ -181,3 +181,16 @@ rangepair rp; return (rp = f18_ext()).range1; } + + + +// Complex forward reference of struct. +struct f19S; +extern struct f19T { + struct f19S (*p)(void); +} t; +struct f19S { int i; }; +void f19(void) { + t.p(); +} + Modified: cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp?rev=134861&r1=134860&r2=134861&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp (original) +++ cfe/trunk/test/CodeGenCXX/anonymous-union-member-initializer.cpp Sat Jul 9 22:47:27 2011 @@ -86,7 +86,7 @@ // CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0 // CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to // CHECK-NEXT: [[CALLBACK:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 0 - // CHECK-NEXT: store void (i8*)* null, void (i8*)** [[CALLBACK]] + // CHECK-NEXT: store {{.*}}* null, {{.*}}** [[CALLBACK]] // CHECK-NEXT: [[UNION:%.*]] = getelementptr inbounds {{.*}} [[THIS]], i32 0, i32 0 // CHECK-NEXT: [[STRUCT:%.*]] = bitcast {{.*}}* [[UNION]] to // CHECK-NEXT: [[CVALUE:%.*]] = getelementptr inbounds {{.*}} [[STRUCT]], i32 0, i32 1 Modified: cfe/trunk/test/CodeGenObjC/arc-foreach.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc-foreach.m?rev=134861&r1=134860&r2=134861&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/arc-foreach.m (original) +++ cfe/trunk/test/CodeGenObjC/arc-foreach.m Sat Jul 9 22:47:27 2011 @@ -33,8 +33,8 @@ // CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[X]] // CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) // CHECK-LP64-NEXT: store i8* [[T2]], i8** [[T0]] -// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* -// CHECK-LP64-NEXT: call void @use_block(void ()* [[T1]]) +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] +// CHECK-LP64-NEXT: call void @use_block({{.*}}* [[T1]]) // CHECK-LP64-NEXT: [[T1:%.*]] = load i8** [[T0]] // CHECK-LP64-NEXT: call void @objc_release(i8* [[T1]]) @@ -66,7 +66,7 @@ // CHECK-LP64: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-LP64-NEXT: [[T1:%.*]] = call i8* @objc_loadWeak(i8** [[X]]) // CHECK-LP64-NEXT: call i8* @objc_initWeak(i8** [[T0]], i8* [[T1]]) -// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* -// CHECK-LP64-NEXT: call void @use_block(void ()* [[T1]]) +// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to +// CHECK-LP64-NEXT: call void @use_block({{.*}} [[T1]]) // CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[T0]]) // CHECK-LP64-NEXT: call void @objc_destroyWeak(i8** [[X]]) Modified: cfe/trunk/test/CodeGenObjC/arc.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/arc.m?rev=134861&r1=134860&r2=134861&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/arc.m (original) +++ cfe/trunk/test/CodeGenObjC/arc.m Sat Jul 9 22:47:27 2011 @@ -1225,8 +1225,8 @@ // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-NEXT: [[T0:%.*]] = load i8** [[VAR]] // CHECK-NEXT: store i8* [[T0]], i8** [[CAPTURE]] - // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* - // CHECK-NEXT: call void @test39_helper(void ()* [[T0]]) + // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to + // CHECK-NEXT: call void @test39_helper({{.*}} [[T0]]) // CHECK-NEXT: ret void } @@ -1338,7 +1338,7 @@ // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) // CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[TEST42]]* // CHECK-NEXT: store [[TEST42]]* [[T4]], [[TEST42]]** [[T0]] -// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* +// CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to // CHECK-NEXT: call void @test42_helper( // CHECK-NEXT: [[T1:%.*]] = load [[TEST42]]** [[T0]] // CHECK-NEXT: [[T2:%.*]] = bitcast [[TEST42]]* [[T1]] to i8* Modified: cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm?rev=134861&r1=134860&r2=134861&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm (original) +++ cfe/trunk/test/CodeGenObjCXX/arc-special-member-functions.mm Sat Jul 9 22:47:27 2011 @@ -94,9 +94,9 @@ // CHECK: define linkonce_odr {{%.*}}* @_ZN15ObjCBlockMemberaSERKS_( // CHECK: [[T0:%.*]] = call i8* @objc_retainBlock( // CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32 (i32)* -// CHECK-NEXT: [[T2:%.*]] = load i32 (i32)** [[SLOT:%.*]], -// CHECK-NEXT: store i32 (i32)* [[T1]], i32 (i32)** [[SLOT]] -// CHECK-NEXT: [[T3:%.*]] = bitcast i32 (i32)* [[T2]] to i8* +// CHECK-NEXT: [[T2:%.*]] = load {{.*}} [[SLOT:%.*]], +// CHECK: store +// CHECK-NEXT: [[T3:%.*]] = bitcast // CHECK-NEXT: call void @objc_release(i8* [[T3]]) // CHECK-NEXT: ret @@ -112,7 +112,7 @@ // Implicitly-generated default constructor for ObjCBlockMember // CHECK: define linkonce_odr void @_ZN15ObjCBlockMemberC2Ev -// CHECK: store i32 (i32)* null, +// CHECK: store {{.*}} null, // CHECK-NEXT: ret void // Implicitly-generated copy constructor for ObjCArrayMember _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits