diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-09-06 12:00:10 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2010-09-06 12:00:10 +0000 |
commit | 2fdb5b5955d5c3d8ec58e1e2c9f31f1a532e4587 (patch) | |
tree | c382fec304528e6f812e3b8ec28e99db5baa21b7 /clang/lib/CodeGen/CGObjCMac.cpp | |
parent | 33dfc07b00b5eecdc153fe0a363dd4977bfa1b84 (diff) | |
download | bcm5719-llvm-2fdb5b5955d5c3d8ec58e1e2c9f31f1a532e4587.tar.gz bcm5719-llvm-2fdb5b5955d5c3d8ec58e1e2c9f31f1a532e4587.zip |
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).
llvm-svn: 113154
Diffstat (limited to 'clang/lib/CodeGen/CGObjCMac.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 54d0ff21ea4..9bd1d661e7d 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/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) |