]> granicus.if.org Git - clang/commitdiff
LastFieldBitfield in CGObjCCommonMac::BuildAggrIvarLayout keeps bitfields or unnamed...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 6 Sep 2010 12:00:10 +0000 (12:00 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Mon, 6 Sep 2010 12:00:10 +0000 (12:00 +0000)
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

lib/CodeGen/CGObjCMac.cpp
test/CodeGenObjC/ivars.m

index 54d0ff21ea44a4123d944002e4d7b585eeb6a862..9bd1d661e7d7b4b9eca3cf5e3b512ac7c12ec362 100644 (file)
@@ -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)
index fe178aba14bdc474e5cf7f6d4717f94b6d810e70..98c39b7a844b3db4e3bb6d7ad26c3ad3b023789d 100644 (file)
@@ -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 {
 void foo(ITF *P) {
   P->boolfield = 1;
 }
+
+// rdar://8368320
+@interface R {
+  struct {
+    union {
+      int x;
+      char c;
+    };
+  } _union;
+}
+@end
+
+@implementation R
+@end