r185018 - Rewrite record layout for ms_struct structs.

Eli Friedman eli.friedman at gmail.com
Wed Jun 26 13:50:35 PDT 2013


Author: efriedma
Date: Wed Jun 26 15:50:34 2013
New Revision: 185018

URL: http://llvm.org/viewvc/llvm-project?rev=185018&view=rev
Log:
Rewrite record layout for ms_struct structs.

The old implementation of ms_struct in RecordLayoutBuilder was a
complete mess: it depended on complicated conditionals which didn't
really reflect the underlying logic, and placed a burden on users of
the resulting RecordLayout. This commit rips out almost all of the
old code, and replaces it with simple checks in
RecordLayoutBuilder::LayoutBitField.

This commit also fixes <rdar://problem/14252115>, a bug where class
inheritance would cause us to lay out bitfields incorrectly.

Added:
    cfe/trunk/test/SemaCXX/ms_struct.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
    cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp
    cfe/trunk/test/CodeGen/tbaa-struct.cpp
    cfe/trunk/test/CodeGen/tbaa.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed Jun 26 15:50:34 2013
@@ -634,31 +634,6 @@ public:
 
   void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl);
   
-  /// \brief Return \c true if \p FD is a zero-length bitfield which follows
-  /// the non-bitfield \p LastFD.
-  bool ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, 
-                                      const FieldDecl *LastFD) const;
-
-  /// \brief Return \c true if \p FD is a zero-length bitfield which follows
-  /// the bitfield \p LastFD.
-  bool ZeroBitfieldFollowsBitfield(const FieldDecl *FD,
-                                   const FieldDecl *LastFD) const;
-  
-  /// \brief Return \c true if \p FD is a bitfield which follows the bitfield
-  /// \p LastFD.
-  bool BitfieldFollowsBitfield(const FieldDecl *FD,
-                               const FieldDecl *LastFD) const;
-  
-  /// \brief Return \c true if \p FD is not a bitfield which follows the
-  /// bitfield \p LastFD.
-  bool NonBitfieldFollowsBitfield(const FieldDecl *FD,
-                                  const FieldDecl *LastFD) const;
-  
-  /// \brief Return \c true if \p FD is a bitfield which follows the
-  /// non-bitfield \p LastFD.
-  bool BitfieldFollowsNonBitfield(const FieldDecl *FD,
-                                  const FieldDecl *LastFD) const;
-
   // Access to the set of methods overridden by the given C++ method.
   typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator;
   overridden_cxx_method_iterator

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Jun 26 15:50:34 2013
@@ -1132,38 +1132,6 @@ void ASTContext::setInstantiatedFromUnna
   InstantiatedFromUnnamedFieldDecl[Inst] = Tmpl;
 }
 
-bool ASTContext::ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, 
-                                    const FieldDecl *LastFD) const {
-  return (FD->isBitField() && LastFD && !LastFD->isBitField() &&
-          FD->getBitWidthValue(*this) == 0);
-}
-
-bool ASTContext::ZeroBitfieldFollowsBitfield(const FieldDecl *FD,
-                                             const FieldDecl *LastFD) const {
-  return (FD->isBitField() && LastFD && LastFD->isBitField() &&
-          FD->getBitWidthValue(*this) == 0 &&
-          LastFD->getBitWidthValue(*this) != 0);
-}
-
-bool ASTContext::BitfieldFollowsBitfield(const FieldDecl *FD,
-                                         const FieldDecl *LastFD) const {
-  return (FD->isBitField() && LastFD && LastFD->isBitField() &&
-          FD->getBitWidthValue(*this) &&
-          LastFD->getBitWidthValue(*this));
-}
-
-bool ASTContext::NonBitfieldFollowsBitfield(const FieldDecl *FD,
-                                         const FieldDecl *LastFD) const {
-  return (!FD->isBitField() && LastFD && LastFD->isBitField() &&
-          LastFD->getBitWidthValue(*this));
-}
-
-bool ASTContext::BitfieldFollowsNonBitfield(const FieldDecl *FD,
-                                             const FieldDecl *LastFD) const {
-  return (FD->isBitField() && LastFD && !LastFD->isBitField() &&
-          FD->getBitWidthValue(*this));
-}
-
 ASTContext::overridden_cxx_method_iterator
 ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const {
   llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Jun 26 15:50:34 2013
@@ -2917,23 +2917,11 @@ unsigned FieldDecl::getFieldIndex() cons
 
   unsigned Index = 0;
   const RecordDecl *RD = getParent();
-  const FieldDecl *LastFD = 0;
-  bool IsMsStruct = RD->isMsStruct(getASTContext());
 
   for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
-       I != E; ++I, ++Index) {
+       I != E; ++I, ++Index)
     I->CachedFieldIndex = Index + 1;
 
-    if (IsMsStruct) {
-      // Zero-length bitfields following non-bitfield members are ignored.
-      if (getASTContext().ZeroBitfieldFollowsNonBitfield(*I, LastFD)) {
-        --Index;
-        continue;
-      }
-      LastFD = *I;
-    }
-  }
-
   assert(CachedFieldIndex && "failed to find field in parent");
   return CachedFieldIndex - 1;
 }

Modified: cfe/trunk/lib/AST/RecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/RecordLayoutBuilder.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/lib/AST/RecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/AST/RecordLayoutBuilder.cpp Wed Jun 26 15:50:34 2013
@@ -573,10 +573,14 @@ protected:
   
   unsigned IsMsStruct : 1;
 
-  /// UnfilledBitsInLastByte - If the last field laid out was a bitfield,
-  /// this contains the number of bits in the last byte that can be used for
-  /// an adjacent bitfield if necessary.
-  unsigned char UnfilledBitsInLastByte;
+  /// UnfilledBitsInLastUnit - If the last field laid out was a bitfield,
+  /// this contains the number of bits in the last unit that can be used for
+  /// an adjacent bitfield if necessary.  The unit in question is usually
+  /// a byte, but larger units are used if IsMsStruct.
+  unsigned char UnfilledBitsInLastUnit;
+  /// LastBitfieldTypeSize - If IsMsStruct, represents the size of the type
+  /// of the previous field if it was a bitfield.
+  unsigned char LastBitfieldTypeSize;
 
   /// MaxFieldAlignment - The maximum allowed field alignment. This is set by
   /// #pragma pack.
@@ -646,7 +650,8 @@ protected:
       Alignment(CharUnits::One()), UnpackedAlignment(CharUnits::One()),
       ExternalLayout(false), InferAlignment(false), 
       Packed(false), IsUnion(false), IsMac68kAlign(false), IsMsStruct(false),
-      UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()), 
+      UnfilledBitsInLastUnit(0), LastBitfieldTypeSize(0),
+      MaxFieldAlignment(CharUnits::Zero()), 
       DataSize(0), NonVirtualSize(CharUnits::Zero()), 
       NonVirtualAlignment(CharUnits::One()), 
       ZeroLengthBitfield(0), PrimaryBase(0), 
@@ -1728,123 +1733,16 @@ void RecordLayoutBuilder::Layout(const O
 void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
   // Layout each field, for now, just sequentially, respecting alignment.  In
   // the future, this will need to be tweakable by targets.
-  const FieldDecl *LastFD = 0;
   ZeroLengthBitfield = 0;
-  unsigned RemainingInAlignment = 0;
   for (RecordDecl::field_iterator Field = D->field_begin(),
        FieldEnd = D->field_end(); Field != FieldEnd; ++Field) {
-    if (IsMsStruct) {
-      FieldDecl *FD = *Field;
-      if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD))
-        ZeroLengthBitfield = FD;
-      // Zero-length bitfields following non-bitfield members are
-      // ignored:
-      else if (Context.ZeroBitfieldFollowsNonBitfield(FD, LastFD))
-        continue;
-      // FIXME. streamline these conditions into a simple one.
-      else if (Context.BitfieldFollowsBitfield(FD, LastFD) ||
-               Context.BitfieldFollowsNonBitfield(FD, LastFD) ||
-               Context.NonBitfieldFollowsBitfield(FD, LastFD)) {
-        // 1) Adjacent bit fields are packed into the same 1-, 2-, or
-        // 4-byte allocation unit if the integral types are the same
-        // size and if the next bit field fits into the current
-        // allocation unit without crossing the boundary imposed by the
-        // common alignment requirements of the bit fields.
-        // 2) Establish a new alignment for a bitfield following
-        // a non-bitfield if size of their types differ.
-        // 3) Establish a new alignment for a non-bitfield following
-        // a bitfield if size of their types differ.
-        std::pair<uint64_t, unsigned> FieldInfo = 
-          Context.getTypeInfo(FD->getType());
-        uint64_t TypeSize = FieldInfo.first;
-        unsigned FieldAlign = FieldInfo.second;
-        // This check is needed for 'long long' in -m32 mode.
-        if (TypeSize > FieldAlign &&
-            (Context.hasSameType(FD->getType(), 
-                                Context.UnsignedLongLongTy) 
-             ||Context.hasSameType(FD->getType(), 
-                                   Context.LongLongTy)))
-          FieldAlign = TypeSize;
-        FieldInfo = Context.getTypeInfo(LastFD->getType());
-        uint64_t TypeSizeLastFD = FieldInfo.first;
-        unsigned FieldAlignLastFD = FieldInfo.second;
-        // This check is needed for 'long long' in -m32 mode.
-        if (TypeSizeLastFD > FieldAlignLastFD &&
-            (Context.hasSameType(LastFD->getType(), 
-                                Context.UnsignedLongLongTy)
-             || Context.hasSameType(LastFD->getType(), 
-                                    Context.LongLongTy)))
-          FieldAlignLastFD = TypeSizeLastFD;
-        
-        if (TypeSizeLastFD != TypeSize) {
-          if (RemainingInAlignment &&
-              LastFD && LastFD->isBitField() &&
-              LastFD->getBitWidthValue(Context)) {
-            // If previous field was a bitfield with some remaining unfilled
-            // bits, pad the field so current field starts on its type boundary.
-            uint64_t FieldOffset = 
-            getDataSizeInBits() - UnfilledBitsInLastByte;
-            uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset;
-            setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
-                                                 Context.getTargetInfo().getCharAlign()));
-            setSize(std::max(getSizeInBits(), getDataSizeInBits()));
-            RemainingInAlignment = 0;
-          }
-          
-          uint64_t UnpaddedFieldOffset = 
-            getDataSizeInBits() - UnfilledBitsInLastByte;
-          FieldAlign = std::max(FieldAlign, FieldAlignLastFD);
-          
-          // The maximum field alignment overrides the aligned attribute.
-          if (!MaxFieldAlignment.isZero()) {
-            unsigned MaxFieldAlignmentInBits = 
-              Context.toBits(MaxFieldAlignment);
-            FieldAlign = std::min(FieldAlign, MaxFieldAlignmentInBits);
-          }
-          
-          uint64_t NewSizeInBits = 
-            llvm::RoundUpToAlignment(UnpaddedFieldOffset, FieldAlign);
-          setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
-                                               Context.getTargetInfo().getCharAlign()));
-          UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
-          setSize(std::max(getSizeInBits(), getDataSizeInBits()));
-        }
-        if (FD->isBitField()) {
-          uint64_t FieldSize = FD->getBitWidthValue(Context);
-          assert (FieldSize > 0 && "LayoutFields - ms_struct layout");
-          if (RemainingInAlignment < FieldSize)
-            RemainingInAlignment = TypeSize - FieldSize;
-          else
-            RemainingInAlignment -= FieldSize;
-        }
-      }
-      else if (FD->isBitField()) {
-        uint64_t FieldSize = FD->getBitWidthValue(Context);
-        std::pair<uint64_t, unsigned> FieldInfo = 
-          Context.getTypeInfo(FD->getType());
-        uint64_t TypeSize = FieldInfo.first;
-        RemainingInAlignment = TypeSize - FieldSize;
-      }
-      LastFD = FD;
-    }
-    else if (!Context.getTargetInfo().useBitFieldTypeAlignment() &&
-             Context.getTargetInfo().useZeroLengthBitfieldAlignment()) {             
+    if (!Context.getTargetInfo().useBitFieldTypeAlignment() &&
+        Context.getTargetInfo().useZeroLengthBitfieldAlignment()) {
       if (Field->isBitField() && Field->getBitWidthValue(Context) == 0)
         ZeroLengthBitfield = *Field;
     }
     LayoutField(*Field);
   }
-  if (IsMsStruct && RemainingInAlignment &&
-      LastFD && LastFD->isBitField() && LastFD->getBitWidthValue(Context)) {
-    // If we ended a bitfield before the full length of the type then
-    // pad the struct out to the full length of the last type.
-    uint64_t FieldOffset = 
-      getDataSizeInBits() - UnfilledBitsInLastByte;
-    uint64_t NewSizeInBits = RemainingInAlignment + FieldOffset;
-    setDataSize(llvm::RoundUpToAlignment(NewSizeInBits,
-                                         Context.getTargetInfo().getCharAlign()));
-    setSize(std::max(getSizeInBits(), getDataSizeInBits()));
-  }
 }
 
 void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize,
@@ -1878,10 +1776,11 @@ void RecordLayoutBuilder::LayoutWideBitF
   CharUnits TypeAlign = Context.getTypeAlignInChars(Type);
 
   // We're not going to use any of the unfilled bits in the last byte.
-  UnfilledBitsInLastByte = 0;
+  UnfilledBitsInLastUnit = 0;
+  LastBitfieldTypeSize = 0;
 
   uint64_t FieldOffset;
-  uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
+  uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
 
   if (IsUnion) {
     setDataSize(std::max(getDataSizeInBits(), FieldSize));
@@ -1896,7 +1795,7 @@ void RecordLayoutBuilder::LayoutWideBitF
 
     setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 
                                          Context.getTargetInfo().getCharAlign()));
-    UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
+    UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
   }
 
   // Place this field at the current location.
@@ -1914,47 +1813,37 @@ void RecordLayoutBuilder::LayoutWideBitF
 
 void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) {
   bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
-  uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
-  uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset;
   uint64_t FieldSize = D->getBitWidthValue(Context);
-
   std::pair<uint64_t, unsigned> FieldInfo = Context.getTypeInfo(D->getType());
   uint64_t TypeSize = FieldInfo.first;
   unsigned FieldAlign = FieldInfo.second;
-  
-  // This check is needed for 'long long' in -m32 mode.
-  if (IsMsStruct && (TypeSize > FieldAlign) && 
-      (Context.hasSameType(D->getType(), 
-                           Context.UnsignedLongLongTy) 
-       || Context.hasSameType(D->getType(), Context.LongLongTy)))
+
+  if (IsMsStruct) {
+    // The field alignment for integer types in ms_struct structs is
+    // always the size.
     FieldAlign = TypeSize;
+    // Ignore zero-length bitfields after non-bitfields in ms_struct structs.
+    if (!FieldSize && !LastBitfieldTypeSize)
+      FieldAlign = 1;
+    // If a bitfield is followed by a bitfield of a different size, don't
+    // pack the bits together in ms_struct structs.
+    if (LastBitfieldTypeSize != TypeSize) {
+      UnfilledBitsInLastUnit = 0;
+      LastBitfieldTypeSize = 0;
+    }
+  }
+
+  uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
+  uint64_t FieldOffset = IsUnion ? 0 : UnpaddedFieldOffset;
 
   if (ZeroLengthBitfield) {
-    std::pair<uint64_t, unsigned> FieldInfo;
-    unsigned ZeroLengthBitfieldAlignment;
-    if (IsMsStruct) {
-      // If a zero-length bitfield is inserted after a bitfield,
-      // and the alignment of the zero-length bitfield is
-      // greater than the member that follows it, `bar', `bar' 
-      // will be aligned as the type of the zero-length bitfield.
-      if (ZeroLengthBitfield != D) {
-        FieldInfo = Context.getTypeInfo(ZeroLengthBitfield->getType());
-        ZeroLengthBitfieldAlignment = FieldInfo.second;
-        // Ignore alignment of subsequent zero-length bitfields.
-        if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0))
-          FieldAlign = ZeroLengthBitfieldAlignment;
-        if (FieldSize)
-          ZeroLengthBitfield = 0;
-      }
-    } else {
-      // The alignment of a zero-length bitfield affects the alignment
-      // of the next member.  The alignment is the max of the zero 
-      // length bitfield's alignment and a target specific fixed value.
-      unsigned ZeroLengthBitfieldBoundary =
-        Context.getTargetInfo().getZeroLengthBitfieldBoundary();
-      if (ZeroLengthBitfieldBoundary > FieldAlign)
-        FieldAlign = ZeroLengthBitfieldBoundary;
-    }
+    // The alignment of a zero-length bitfield affects the alignment
+    // of the next member.  The alignment is the max of the zero 
+    // length bitfield's alignment and a target specific fixed value.
+    unsigned ZeroLengthBitfieldBoundary =
+      Context.getTargetInfo().getZeroLengthBitfieldBoundary();
+    if (ZeroLengthBitfieldBoundary > FieldAlign)
+      FieldAlign = ZeroLengthBitfieldBoundary;
   }
 
   if (FieldSize > TypeSize) {
@@ -1982,6 +1871,13 @@ void RecordLayoutBuilder::LayoutBitField
     UnpackedFieldAlign = std::min(UnpackedFieldAlign, MaxFieldAlignmentInBits);
   }
 
+  // ms_struct bitfields always have to start at a round alignment.
+  if (IsMsStruct && !LastBitfieldTypeSize) {
+    FieldOffset = llvm::RoundUpToAlignment(FieldOffset, FieldAlign);
+    UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset,
+                                                   UnpackedFieldAlign);
+  }
+
   // Check if we need to add padding to give the field the correct alignment.
   if (FieldSize == 0 || 
       (MaxFieldAlignment.isZero() &&
@@ -1996,11 +1892,12 @@ void RecordLayoutBuilder::LayoutBitField
 
   // Padding members don't affect overall alignment, unless zero length bitfield
   // alignment is enabled.
-  if (!D->getIdentifier() && !Context.getTargetInfo().useZeroLengthBitfieldAlignment())
+  if (!D->getIdentifier() &&
+      !Context.getTargetInfo().useZeroLengthBitfieldAlignment() &&
+      !IsMsStruct)
     FieldAlign = UnpackedFieldAlign = 1;
 
-  if (!IsMsStruct)
-    ZeroLengthBitfield = 0;
+  ZeroLengthBitfield = 0;
 
   if (ExternalLayout)
     FieldOffset = updateExternalFieldOffset(D, FieldOffset);
@@ -2017,11 +1914,29 @@ void RecordLayoutBuilder::LayoutBitField
     // FIXME: I think FieldSize should be TypeSize here.
     setDataSize(std::max(getDataSizeInBits(), FieldSize));
   } else {
-    uint64_t NewSizeInBits = FieldOffset + FieldSize;
-
-    setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, 
-                                         Context.getTargetInfo().getCharAlign()));
-    UnfilledBitsInLastByte = getDataSizeInBits() - NewSizeInBits;
+    if (IsMsStruct && FieldSize) {
+      // Under ms_struct, a bitfield always takes up space equal to the size
+      // of the type.  We can't just change the alignment computation on the
+      // other codepath because of the way this interacts with #pragma pack:
+      // in a packed struct, we need to allocate misaligned space in the
+      // struct to hold the bitfield.
+      if (!UnfilledBitsInLastUnit) {
+        setDataSize(FieldOffset + TypeSize);
+        UnfilledBitsInLastUnit = TypeSize - FieldSize;
+      } else if (UnfilledBitsInLastUnit < FieldSize) {
+        setDataSize(getDataSizeInBits() + TypeSize);
+        UnfilledBitsInLastUnit = TypeSize - FieldSize;
+      } else {
+        UnfilledBitsInLastUnit -= FieldSize;
+      }
+      LastBitfieldTypeSize = TypeSize;
+    } else {
+      uint64_t NewSizeInBits = FieldOffset + FieldSize;
+      uint64_t BitfieldAlignment = Context.getTargetInfo().getCharAlign();
+      setDataSize(llvm::RoundUpToAlignment(NewSizeInBits, BitfieldAlignment));
+      UnfilledBitsInLastUnit = getDataSizeInBits() - NewSizeInBits;
+      LastBitfieldTypeSize = 0;
+    }
   }
 
   // Update the size.
@@ -2038,10 +1953,11 @@ void RecordLayoutBuilder::LayoutField(co
     return;
   }
 
-  uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastByte;
+  uint64_t UnpaddedFieldOffset = getDataSizeInBits() - UnfilledBitsInLastUnit;
 
   // Reset the unfilled bits.
-  UnfilledBitsInLastByte = 0;
+  UnfilledBitsInLastUnit = 0;
+  LastBitfieldTypeSize = 0;
 
   bool FieldPacked = Packed || D->hasAttr<PackedAttr>();
   CharUnits FieldOffset = 
@@ -2189,7 +2105,7 @@ void RecordLayoutBuilder::FinishLayout(c
 
   // Finally, round the size of the record up to the alignment of the
   // record itself.
-  uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte;
+  uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastUnit;
   uint64_t UnpackedSizeInBits =
   llvm::RoundUpToAlignment(getSizeInBits(),
                            Context.toBits(UnpackedAlignment));

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Wed Jun 26 15:50:34 2013
@@ -915,10 +915,6 @@ CollectRecordFields(const RecordDecl *re
     // Field number for non-static fields.
     unsigned fieldNo = 0;
 
-    // Bookkeeping for an ms struct, which ignores certain fields.
-    bool IsMsStruct = record->isMsStruct(CGM.getContext());
-    const FieldDecl *LastFD = 0;
-
     // Static and non-static members should appear in the same order as
     // the corresponding declarations in the source program.
     for (RecordDecl::decl_iterator I = record->decls_begin(),
@@ -926,13 +922,6 @@ CollectRecordFields(const RecordDecl *re
       if (const VarDecl *V = dyn_cast<VarDecl>(*I))
         CollectRecordStaticField(V, elements, RecordTy);
       else if (FieldDecl *field = dyn_cast<FieldDecl>(*I)) {
-        if (IsMsStruct) {
-          // Zero-length bitfields following non-bitfield members are
-          // completely ignored; we don't even count them.
-          if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD))
-            continue;
-          LastFD = field;
-        }
         CollectRecordNormalField(field, layout.getFieldOffset(fieldNo),
                                  tunit, elements, RecordTy);
 

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Wed Jun 26 15:50:34 2013
@@ -373,30 +373,16 @@ bool ConstStructBuilder::Build(InitListE
 
   unsigned FieldNo = 0;
   unsigned ElementNo = 0;
-  const FieldDecl *LastFD = 0;
-  bool IsMsStruct = RD->isMsStruct(CGM.getContext());
   
   for (RecordDecl::field_iterator Field = RD->field_begin(),
        FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
-    if (IsMsStruct) {
-      // Zero-length bitfields following non-bitfield members are
-      // ignored:
-      if (CGM.getContext().ZeroBitfieldFollowsNonBitfield(*Field, LastFD)) {
-        --FieldNo;
-        continue;
-      }
-      LastFD = *Field;
-    }
-    
     // If this is a union, skip all the fields that aren't being initialized.
     if (RD->isUnion() && ILE->getInitializedFieldInUnion() != *Field)
       continue;
 
     // Don't emit anonymous bitfields, they just affect layout.
-    if (Field->isUnnamedBitfield()) {
-      LastFD = *Field;
+    if (Field->isUnnamedBitfield())
       continue;
-    }
 
     // Get the initializer.  A struct can include fields without initializers,
     // we just use explicit null values for them.
@@ -472,31 +458,17 @@ void ConstStructBuilder::Build(const APV
   }
 
   unsigned FieldNo = 0;
-  const FieldDecl *LastFD = 0;
-  bool IsMsStruct = RD->isMsStruct(CGM.getContext());
   uint64_t OffsetBits = CGM.getContext().toBits(Offset);
 
   for (RecordDecl::field_iterator Field = RD->field_begin(),
        FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
-    if (IsMsStruct) {
-      // Zero-length bitfields following non-bitfield members are
-      // ignored:
-      if (CGM.getContext().ZeroBitfieldFollowsNonBitfield(*Field, LastFD)) {
-        --FieldNo;
-        continue;
-      }
-      LastFD = *Field;
-    }
-
     // If this is a union, skip all the fields that aren't being initialized.
     if (RD->isUnion() && Val.getUnionField() != *Field)
       continue;
 
     // Don't emit anonymous bitfields, they just affect layout.
-    if (Field->isUnnamedBitfield()) {
-      LastFD = *Field;
+    if (Field->isUnnamedBitfield())
       continue;
-    }
 
     // Emit the value of the initializer.
     const APValue &FieldValue =

Modified: cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRecordLayoutBuilder.cpp Wed Jun 26 15:50:34 2013
@@ -78,9 +78,6 @@ public:
 
   /// Packed - Whether the resulting LLVM struct will be packed or not.
   bool Packed;
-  
-  /// IsMsStruct - Whether ms_struct is in effect or not
-  bool IsMsStruct;
 
 private:
   CodeGenTypes &Types;
@@ -195,8 +192,7 @@ public:
   CGRecordLayoutBuilder(CodeGenTypes &Types)
     : BaseSubobjectType(0),
       IsZeroInitializable(true), IsZeroInitializableAsBase(true),
-      Packed(false), IsMsStruct(false),
-      Types(Types) { }
+      Packed(false), Types(Types) { }
 
   /// Layout - Will layout a RecordDecl.
   void Layout(const RecordDecl *D);
@@ -207,8 +203,6 @@ public:
 void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
   Alignment = Types.getContext().getASTRecordLayout(D).getAlignment();
   Packed = D->hasAttr<PackedAttr>();
-  
-  IsMsStruct = D->isMsStruct(Types.getContext());
 
   if (D->isUnion()) {
     LayoutUnion(D);
@@ -764,20 +758,10 @@ bool CGRecordLayoutBuilder::LayoutFields
       return false;
 
   unsigned FieldNo = 0;
-  const FieldDecl *LastFD = 0;
   
   for (RecordDecl::field_iterator FI = D->field_begin(), FE = D->field_end();
        FI != FE; ++FI, ++FieldNo) {
     FieldDecl *FD = *FI;
-    if (IsMsStruct) {
-      // Zero-length bitfields following non-bitfield members are
-      // ignored:
-      if (Types.getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD)) {
-        --FieldNo;
-        continue;
-      }
-      LastFD = FD;
-    }
 
     // If this field is a bitfield, layout all of the consecutive
     // non-zero-length bitfields and the last zero-length bitfield; these will
@@ -1028,8 +1012,6 @@ CGRecordLayout *CodeGenTypes::ComputeRec
 
   const ASTRecordLayout &AST_RL = getContext().getASTRecordLayout(D);
   RecordDecl::field_iterator it = D->field_begin();
-  const FieldDecl *LastFD = 0;
-  bool IsMsStruct = D->isMsStruct(getContext());
   for (unsigned i = 0, e = AST_RL.getFieldCount(); i != e; ++i, ++it) {
     const FieldDecl *FD = *it;
 
@@ -1039,25 +1021,12 @@ CGRecordLayout *CodeGenTypes::ComputeRec
       unsigned FieldNo = RL->getLLVMFieldNo(FD);
       assert(AST_RL.getFieldOffset(i) == SL->getElementOffsetInBits(FieldNo) &&
              "Invalid field offset!");
-      LastFD = FD;
       continue;
     }
-
-    if (IsMsStruct) {
-      // Zero-length bitfields following non-bitfield members are
-      // ignored:
-      if (getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD)) {
-        --i;
-        continue;
-      }
-      LastFD = FD;
-    }
     
     // Ignore unnamed bit-fields.
-    if (!FD->getDeclName()) {
-      LastFD = FD;
+    if (!FD->getDeclName())
       continue;
-    }
 
     // Don't inspect zero-length bitfields.
     if (FD->getBitWidthValue(getContext()) == 0)

Modified: cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTBAA.cpp Wed Jun 26 15:50:34 2013
@@ -203,18 +203,8 @@ CodeGenTBAA::CollectFields(uint64_t Base
     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
 
     unsigned idx = 0;
-    const FieldDecl *LastFD = 0;
-    bool IsMsStruct = RD->isMsStruct(Context);
     for (RecordDecl::field_iterator i = RD->field_begin(),
          e = RD->field_end(); i != e; ++i, ++idx) {
-      if (IsMsStruct) {
-        // Zero-length bitfields following non-bitfield members are ignored.
-        if (Context.ZeroBitfieldFollowsNonBitfield(*i, LastFD)) {
-          --idx;
-          continue;
-        }
-        LastFD = *i;
-      }
       uint64_t Offset = BaseOffset +
                         Layout.getFieldOffset(idx) / Context.getCharWidth();
       QualType FieldQTy = i->getType();
@@ -278,19 +268,8 @@ CodeGenTBAA::getTBAAStructTypeInfo(QualT
     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
     SmallVector <std::pair<llvm::MDNode*, uint64_t>, 4> Fields;
     unsigned idx = 0;
-    const FieldDecl *LastFD = 0;
-    bool IsMsStruct = RD->isMsStruct(Context);
     for (RecordDecl::field_iterator i = RD->field_begin(),
          e = RD->field_end(); i != e; ++i, ++idx) {
-      if (IsMsStruct) {
-        // Zero-length bitfields following non-bitfield members are ignored.
-        if (Context.ZeroBitfieldFollowsNonBitfield(*i, LastFD)) {
-          --idx;
-          continue;
-        }
-        LastFD = *i;
-      }
-
       QualType FieldQTy = i->getType();
       llvm::MDNode *FieldNode;
       if (isTBAAPathStruct(FieldQTy))

Modified: cfe/trunk/test/CodeGen/tbaa-struct.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/tbaa-struct.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/tbaa-struct.cpp (original)
+++ cfe/trunk/test/CodeGen/tbaa-struct.cpp Wed Jun 26 15:50:34 2013
@@ -70,5 +70,5 @@ void copy5(struct six *a, struct six *b)
 // CHECK: [[TS2]] = metadata !{i64 0, i64 1, metadata !{{.*}}, i64 4, i64 2, metadata !{{.*}}, i64 8, i64 4, metadata !{{.*}}, i64 12, i64 1, metadata !{{.*}}, i64 16, i64 4, metadata {{.*}}, i64 20, i64 4, metadata {{.*}}}
 // (offset, size) = (0,8) char; (0,2) char; (4,8) char
 // CHECK: [[TS3]] = metadata !{i64 0, i64 8, metadata !{{.*}}, i64 0, i64 2, metadata !{{.*}}, i64 4, i64 8, metadata !{{.*}}}
-// CHECK: [[TS4]] = metadata !{i64 0, i64 1, metadata [[CHAR]], i64 1, i64 1, metadata [[CHAR]], i64 2, i64 1, metadata [[CHAR]]}
+// CHECK: [[TS4]] = metadata !{i64 0, i64 1, metadata [[CHAR]], i64 1, i64 4, metadata [[INT]], i64 1, i64 1, metadata [[CHAR]], i64 2, i64 1, metadata [[CHAR]]}
 // CHECK: [[TS5]] = metadata !{i64 0, i64 1, metadata [[CHAR]], i64 4, i64 4, metadata [[INT]], i64 4, i64 1, metadata [[CHAR]], i64 5, i64 1, metadata [[CHAR]]}

Modified: cfe/trunk/test/CodeGen/tbaa.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/tbaa.cpp?rev=185018&r1=185017&r2=185018&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/tbaa.cpp (original)
+++ cfe/trunk/test/CodeGen/tbaa.cpp Wed Jun 26 15:50:34 2013
@@ -250,6 +250,6 @@ char g14(struct six *a, struct six *b) {
 // PATH: [[TAG_D_b_a_f32]] = metadata !{metadata [[TYPE_D:!.*]], metadata [[TYPE_INT]], i64 12}
 // PATH: [[TYPE_D]] = metadata !{metadata !"_ZTS7StructD", metadata [[TYPE_SHORT]], i64 0, metadata [[TYPE_B]], i64 4, metadata [[TYPE_INT]], i64 28, metadata [[TYPE_CHAR]], i64 32}
 // PATH: [[TAG_five_b]] = metadata !{metadata [[TYPE_five:!.*]], metadata [[TYPE_CHAR]], i64 1}
-// PATH: [[TYPE_five]] = metadata !{metadata !"_ZTS4five", metadata [[TYPE_CHAR]], i64 0, metadata [[TYPE_CHAR]], i64 1, metadata [[TYPE_CHAR]], i64 2}
+// PATH: [[TYPE_five]] = metadata !{metadata !"_ZTS4five", metadata [[TYPE_CHAR]], i64 0, metadata [[TYPE_INT]], i64 1, metadata [[TYPE_CHAR]], i64 1, metadata [[TYPE_CHAR]], i64 2}
 // PATH: [[TAG_six_b]] = metadata !{metadata [[TYPE_six:!.*]], metadata [[TYPE_CHAR]], i64 4}
 // PATH: [[TYPE_six]] = metadata !{metadata !"_ZTS3six", metadata [[TYPE_CHAR]], i64 0, metadata [[TYPE_INT]], i64 4, metadata [[TYPE_CHAR]], i64 4, metadata [[TYPE_CHAR]], i64 5}

Added: cfe/trunk/test/SemaCXX/ms_struct.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms_struct.cpp?rev=185018&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/ms_struct.cpp (added)
+++ cfe/trunk/test/SemaCXX/ms_struct.cpp Wed Jun 26 15:50:34 2013
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple i686-apple-darwin9 -std=c++11 %s
+// expected-no-diagnostics
+
+#pragma ms_struct on
+
+struct A {
+  unsigned long a:4;
+  unsigned char b;
+  A();
+};
+
+struct B : public A {
+  unsigned long c:16;
+	int d;
+  B();
+};
+
+static_assert(__builtin_offsetof(B, d) == 12,
+  "We can't allocate the bitfield into the padding under ms_struct");
\ No newline at end of file





More information about the cfe-commits mailing list