[cfe-commits] r166824 - in /cfe/trunk: lib/AST/RecordLayoutBuilder.cpp test/CodeGenCXX/override-layout.cpp

Douglas Gregor dgregor at apple.com
Fri Oct 26 15:31:15 PDT 2012


Author: dgregor
Date: Fri Oct 26 17:31:14 2012
New Revision: 166824

URL: http://llvm.org/viewvc/llvm-project?rev=166824&view=rev
Log:
When an externally-supplied record layout has a size that clearly
doesn't include padding up to the alignment of the record, take this
as a cue that the alignment of the record should (conservatively) be
set to 1. This is similar to other the other cues we use to determine
that the record has a lower alignment, e.g., that the
externally-supplied layout places fields at lower offsets than we
would. Fixes <rdar://problem/12582052>; test case in LLDB.

Modified:
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/test/CodeGenCXX/override-layout.cpp

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=166824&r1=166823&r2=166824&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Fri Oct 26 17:31:14 2012
@@ -1557,6 +1557,13 @@
     bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset);
     (void)Allowed;
     assert(Allowed && "Base subobject externally placed at overlapping offset");
+
+    if (InferAlignment && Offset < getDataSize().RoundUpToAlignment(BaseAlign)){
+      // The externally-supplied base offset is before the base offset we
+      // computed. Assume that the structure is packed.
+      Alignment = CharUnits::One();
+      InferAlignment = false;
+    }
   }
   
   if (!Base->Class->isEmpty()) {
@@ -1616,7 +1623,6 @@
       if (ExternalLayout) {
         if (ExternalAlign > 0) {
           Alignment = Context.toCharUnitsFromBits(ExternalAlign);
-          UnpackedAlignment = Alignment;
         } else {
           // The external source didn't have alignment information; infer it.
           InferAlignment = true;
@@ -2166,11 +2172,6 @@
 }
 
 void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
-  if (ExternalLayout) {
-    setSize(ExternalSize);
-    return;
-  }
-  
   // In C++, records cannot be of size 0.
   if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) {
     if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
@@ -2184,20 +2185,37 @@
       setSize(CharUnits::One());
   }
 
+  // Finally, round the size of the record up to the alignment of the
+  // record itself.
+  uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte;
+  uint64_t UnpackedSizeInBits =
+  llvm::RoundUpToAlignment(getSizeInBits(),
+                           Context.toBits(UnpackedAlignment));
+  CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits);
+  uint64_t RoundedSize
+    = llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment));
+
+  if (ExternalLayout) {
+    // If we're inferring alignment, and the external size is smaller than
+    // our size after we've rounded up to alignment, conservatively set the
+    // alignment to 1.
+    if (InferAlignment && ExternalSize < RoundedSize) {
+      Alignment = CharUnits::One();
+      InferAlignment = false;
+    }
+    setSize(ExternalSize);
+    return;
+  }
+
+
   // MSVC doesn't round up to the alignment of the record with virtual bases.
   if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
     if (isMicrosoftCXXABI() && RD->getNumVBases())
       return;
   }
 
-  // Finally, round the size of the record up to the alignment of the
-  // record itself.
-  uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte;
-  uint64_t UnpackedSizeInBits = 
-    llvm::RoundUpToAlignment(getSizeInBits(), 
-                             Context.toBits(UnpackedAlignment));
-  CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits);
-  setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment)));
+  // Set the size to the final size.
+  setSize(RoundedSize);
 
   unsigned CharBitNum = Context.getTargetInfo().getCharWidth();
   if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
@@ -2255,7 +2273,7 @@
   if (InferAlignment && ExternalFieldOffset < ComputedOffset) {
     // The externally-supplied field offset is before the field offset we
     // computed. Assume that the structure is packed.
-    Alignment = CharUnits::fromQuantity(1);
+    Alignment = CharUnits::One();
     InferAlignment = false;
   }
   

Modified: cfe/trunk/test/CodeGenCXX/override-layout.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/override-layout.cpp?rev=166824&r1=166823&r2=166824&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/override-layout.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/override-layout.cpp Fri Oct 26 17:31:14 2012
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fdump-record-layouts-simple %s 2> %t.layouts
 // RUN: %clang_cc1 -fdump-record-layouts-simple %s > %t.before 2>&1
 // RUN: %clang_cc1 -DPACKED= -DALIGNED16= -fdump-record-layouts-simple -foverride-record-layout=%t.layouts %s > %t.after 2>&1
-// RUN: diff %t.before %t.after
+// RUN: diff -u %t.before %t.after
 // RUN: FileCheck %s < %t.after
 
 // If not explicitly disabled, set PACKED to the packed attribute.
@@ -54,11 +54,24 @@
   X4();
 };
 
+// CHECK: Type: struct X5
+struct PACKED X5 {
+  union {
+    long a;
+    long b;
+  };
+  short l;
+  short r;
+};
+
 void use_structs() {
   X0 x0s[sizeof(X0)];
   X1 x1s[sizeof(X1)];
   X2 x2s[sizeof(X2)];
   X3 x3s[sizeof(X3)];
   X4 x4s[sizeof(X4)];
+  X5 x5s[sizeof(X5)];
   x4s[1].a = 1;
+  x5s[1].a = 17;
 }
+





More information about the cfe-commits mailing list