]> granicus.if.org Git - clang/commitdiff
Fix PR2101 - Codegen crash during bitfield initialization.
authorDevang Patel <dpatel@apple.com>
Tue, 6 May 2008 19:57:59 +0000 (19:57 +0000)
committerDevang Patel <dpatel@apple.com>
Tue, 6 May 2008 19:57:59 +0000 (19:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50769 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenTypes.cpp
test/CodeGen/bitfield-init.c [new file with mode: 0644]

index a7f6670cb6eb2ba1d991ae4cf19cd8d286b05b4b..751cd3a07778b1c91013ead1cc47fc4d42ed4543 100644 (file)
@@ -521,7 +521,28 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) {
   unsigned StructAlign = RL.getAlignment();
   if (llvmSize % StructAlign) {
     unsigned StructPadding = StructAlign - (llvmSize % StructAlign);
-    addPaddingFields(llvmSize + StructPadding);
+    bool needStructPadding = true;
+    if (!LLVMFields.empty()) {
+      const llvm::Type *LastFieldType = LLVMFields.back();
+      const llvm::Type *LastFieldDeclType = 
+        CGT.ConvertTypeRecursive(FieldDecls.back()->getType());
+      if (LastFieldType != LastFieldDeclType) {
+        unsigned LastFieldTypeSize = 
+          CGT.getTargetData().getABITypeSizeInBits(LastFieldType);
+        unsigned LastFieldDeclTypeSize = 
+          CGT.getTargetData().getABITypeSizeInBits(LastFieldDeclType);
+        if (LastFieldDeclTypeSize > LastFieldTypeSize
+            && StructPadding == (LastFieldDeclTypeSize - LastFieldTypeSize)) {
+          // Replace last LLVMField with a LastFieldDeclType field will 
+          // to avoid extra padding fields.
+          LLVMFields.pop_back();
+          LLVMFields.push_back(LastFieldDeclType);
+          needStructPadding = false;
+        }
+      }
+    }
+    if (needStructPadding)
+      addPaddingFields(llvmSize + StructPadding);
   }
 
   STy = llvm::StructType::get(LLVMFields);
@@ -533,8 +554,13 @@ void RecordOrganizer::addPaddingFields(unsigned WaterMark) {
   assert(WaterMark >= llvmSize && "Invalid padding Field");
   unsigned RequiredBits = WaterMark - llvmSize;
   unsigned RequiredBytes = (RequiredBits + 7) / 8;
-  for (unsigned i = 0; i != RequiredBytes; ++i)
-    addLLVMField(llvm::Type::Int8Ty, true);
+  if (RequiredBytes == 1)
+    // This is a bitfield that is using few bits from this byte.
+    // It is not a padding field.
+    addLLVMField(llvm::Type::Int8Ty, false);
+  else
+    for (unsigned i = 0; i != RequiredBytes; ++i)
+      addLLVMField(llvm::Type::Int8Ty, true);
 }
 
 /// addLLVMField - Add llvm struct field that corresponds to llvm type Ty.
diff --git a/test/CodeGen/bitfield-init.c b/test/CodeGen/bitfield-init.c
new file mode 100644 (file)
index 0000000..6e89e11
--- /dev/null
@@ -0,0 +1,4 @@
+// RUN: clang %s -emit-llvm 
+typedef struct { unsigned int i: 1; } c;
+const c d = { 1 };
+