From: Argyrios Kyrtzidis Date: Mon, 6 Sep 2010 12:00:10 +0000 (+0000) Subject: LastFieldBitfield in CGObjCCommonMac::BuildAggrIvarLayout keeps bitfields or unnamed... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0dc7509ed7f775f74106fbac37473da39b6c8e3a;p=clang LastFieldBitfield in CGObjCCommonMac::BuildAggrIvarLayout keeps bitfields or unnamed fields but later the code assumes that it's always a bitfield. This can lead to a crash (reported at rdar://8368320). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113154 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 54d0ff21ea..9bd1d661e7 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -3586,10 +3586,10 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, uint64_t MaxSkippedUnionIvarSize = 0; FieldDecl *MaxField = 0; FieldDecl *MaxSkippedField = 0; - FieldDecl *LastFieldBitfield = 0; + FieldDecl *LastFieldBitfieldOrUnnamed = 0; uint64_t MaxFieldOffset = 0; uint64_t MaxSkippedFieldOffset = 0; - uint64_t LastBitfieldOffset = 0; + uint64_t LastBitfieldOrUnnamedOffset = 0; if (RecFields.empty()) return; @@ -3609,12 +3609,12 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, // Skip over unnamed or bitfields if (!Field->getIdentifier() || Field->isBitField()) { - LastFieldBitfield = Field; - LastBitfieldOffset = FieldOffset; + LastFieldBitfieldOrUnnamed = Field; + LastBitfieldOrUnnamedOffset = FieldOffset; continue; } - LastFieldBitfield = 0; + LastFieldBitfieldOrUnnamed = 0; QualType FQT = Field->getType(); if (FQT->isRecordType() || FQT->isUnionType()) { if (FQT->isUnionType()) @@ -3703,16 +3703,25 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, } } - if (LastFieldBitfield) { - // Last field was a bitfield. Must update skip info. - Expr *BitWidth = LastFieldBitfield->getBitWidth(); - uint64_t BitFieldSize = - BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); - GC_IVAR skivar; - skivar.ivar_bytepos = BytePos + LastBitfieldOffset; - skivar.ivar_size = (BitFieldSize / ByteSizeInBits) - + ((BitFieldSize % ByteSizeInBits) != 0); - SkipIvars.push_back(skivar); + if (LastFieldBitfieldOrUnnamed) { + if (LastFieldBitfieldOrUnnamed->isBitField()) { + // Last field was a bitfield. Must update skip info. + Expr *BitWidth = LastFieldBitfieldOrUnnamed->getBitWidth(); + uint64_t BitFieldSize = + BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue(); + GC_IVAR skivar; + skivar.ivar_bytepos = BytePos + LastBitfieldOrUnnamedOffset; + skivar.ivar_size = (BitFieldSize / ByteSizeInBits) + + ((BitFieldSize % ByteSizeInBits) != 0); + SkipIvars.push_back(skivar); + } else { + assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); + // Last field was unnamed. Must update skip info. + unsigned FieldSize + = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType()); + SkipIvars.push_back(GC_IVAR(BytePos + LastBitfieldOrUnnamedOffset, + FieldSize / ByteSizeInBits)); + } } if (MaxField) diff --git a/test/CodeGenObjC/ivars.m b/test/CodeGenObjC/ivars.m index fe178aba14..98c39b7a84 100644 --- a/test/CodeGenObjC/ivars.m +++ b/test/CodeGenObjC/ivars.m @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -emit-llvm -o - %s // RUN: %clang_cc1 -triple i386-apple-darwin9 -emit-llvm -o - %s +// RUN: %clang_cc1 -fobjc-gc -emit-llvm -o - %s // rdar://6800926 @interface ITF { @@ -12,3 +13,17 @@ void foo(ITF *P) { P->boolfield = 1; } + +// rdar://8368320 +@interface R { + struct { + union { + int x; + char c; + }; + } _union; +} +@end + +@implementation R +@end