]> granicus.if.org Git - clang/commitdiff
Fix another obscure corner layout case.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 10 Dec 2010 00:11:00 +0000 (00:11 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Fri, 10 Dec 2010 00:11:00 +0000 (00:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121436 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGRecordLayoutBuilder.cpp
test/CodeGenCXX/pragma-pack.cpp [new file with mode: 0644]

index 4beaa82e5d6d8ff9da05c04a791117d8d36ba376..5571e43f7859fc253afcb1d40570be60ac1a3110 100644 (file)
@@ -125,7 +125,7 @@ private:
                              const ASTRecordLayout &Layout);
 
   /// ComputeNonVirtualBaseType - Compute the non-virtual base field types.
-  void ComputeNonVirtualBaseType(const CXXRecordDecl *RD);
+  bool ComputeNonVirtualBaseType(const CXXRecordDecl *RD);
   
   /// LayoutField - layout a single field. Returns false if the operation failed
   /// because the current struct is not packed.
@@ -612,7 +612,7 @@ CGRecordLayoutBuilder::LayoutNonVirtualBases(const CXXRecordDecl *RD,
   }
 }
 
-void 
+bool
 CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) {
   const ASTRecordLayout &Layout = Types.getContext().getASTRecordLayout(RD);
 
@@ -624,26 +624,27 @@ CGRecordLayoutBuilder::ComputeNonVirtualBaseType(const CXXRecordDecl *RD) {
   // First check if we can use the same fields as for the complete class.
   if (AlignedNonVirtualTypeSize == Layout.getSize() / 8) {
     NonVirtualBaseTypeIsSameAsCompleteType = true;
-    return;
+    return true;
   }
 
-  NonVirtualBaseFieldTypes = FieldTypes;
-
   // Check if we need padding.
   uint64_t AlignedNextFieldOffset =
     llvm::RoundUpToAlignment(NextFieldOffsetInBytes, 
                              getAlignmentAsLLVMStruct());
 
-  assert(AlignedNextFieldOffset <= AlignedNonVirtualTypeSize && 
-         "Size mismatch!");
+  if (AlignedNextFieldOffset > AlignedNonVirtualTypeSize)
+    return false; // Needs packing.
+
+  NonVirtualBaseFieldTypes = FieldTypes;
 
   if (AlignedNonVirtualTypeSize == AlignedNextFieldOffset) {
     // We don't need any padding.
-    return;
+    return true;
   }
 
   uint64_t NumBytes = AlignedNonVirtualTypeSize - AlignedNextFieldOffset;
   NonVirtualBaseFieldTypes.push_back(getByteArrayType(NumBytes));
+  return true;
 }
 
 bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
@@ -670,7 +671,10 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
   if (RD) {
     // We've laid out the non-virtual bases and the fields, now compute the
     // non-virtual base field types.
-    ComputeNonVirtualBaseType(RD);
+    if (!ComputeNonVirtualBaseType(RD)) {
+      assert(!Packed && "Could not layout even with a packed LLVM struct!");
+      return false;
+    }
 
     // And lay out the virtual bases.
     RD->getIndirectPrimaryBases(IndirectPrimaryBases);
diff --git a/test/CodeGenCXX/pragma-pack.cpp b/test/CodeGenCXX/pragma-pack.cpp
new file mode 100644 (file)
index 0000000..c0ddb1d
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -triple=i686-apple-darwin10 -emit-llvm -o - | FileCheck %s
+
+struct Base {
+  virtual ~Base();
+  int x;
+};
+
+#pragma pack(1)
+struct Sub : virtual Base {
+  char c;
+};
+
+// CHECK: %struct.Sub = type <{ i32 (...)**, i8, [8 x i8] }>
+void f(Sub*) { }