[ms-abi] Handle __declspec(align) on bitfields "properly"

__declspec(align), when applied to bitfields affects their perferred 
alignment instead of their required alignment.  We don't know why.  
Also, #pragma pack(n) turns packing *off* if n is greater than the 
pointer size.  This is now observable because of the impact of 
declspec(align) on bitfields.

llvm-svn: 198907
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index ceb49ff..30293c2 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -2028,7 +2028,9 @@
 //   modes).
 // * There is no concept of non-virtual alignment or any distinction between
 //   data size and non-virtual size.
-
+// * __declspec(align) on bitfields has the effect of changing the bitfield's
+//   alignment instead of its required alignment.  This has implications on how
+//   it interacts with pragam pack.
 
 namespace {
 struct MicrosoftRecordLayoutBuilder {
@@ -2165,6 +2167,9 @@
 MicrosoftRecordLayoutBuilder::getAdjustedElementInfo(
     const FieldDecl *FD) {
   ElementInfo Info;
+  // Respect align attributes.
+  CharUnits FieldRequiredAlignment = 
+      Context.toCharUnitsFromBits(FD->getMaxAlignment());
   // Respect attributes applied to subobjects of the field.
   if (const RecordType *RT =
       FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) {
@@ -2183,6 +2188,8 @@
         Context.getTypeInfoInChars(FD->getType());
     Info.Size = FieldInfo.first;
     Info.Alignment = FieldInfo.second;
+    if (FD->isBitField() && FD->getMaxAlignment() != 0)
+      Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
     // Respect pragma pack.
     if (!MaxFieldAlignment.isZero())
       Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment);
@@ -2190,13 +2197,13 @@
   // Respect packed field attribute.
   if (FD->hasAttr<PackedAttr>())
     Info.Alignment = CharUnits::One();
-  // Respect align attributes.
-  CharUnits FieldRequiredAlignment = 
-      Context.toCharUnitsFromBits(FD->getMaxAlignment());
-  // Take required alignment into account.
-  Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
-  // Capture required alignment as a side-effect.
-  RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
+  // Take required alignment into account.  __declspec(align) on bitfields
+  // impacts the alignment rather than the required alignment.
+  if (!FD->isBitField()) {
+    Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment);
+    // Capture required alignment as a side-effect.
+    RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment);
+  }
   return Info;
 }
 
@@ -2233,10 +2240,14 @@
   MaxFieldAlignment = CharUnits::Zero();
   // Honor the default struct packing maximum alignment flag.
   if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct)
-    MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment);
-  // Honor the packing attribute.
-  if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>())
-    MaxFieldAlignment = Context.toCharUnitsFromBits(MFAA->getAlignment());
+      MaxFieldAlignment = CharUnits::fromQuantity(DefaultMaxFieldAlignment);
+  // Honor the packing attribute.  The MS-ABI ignores pragma pack if its larger
+  // than the pointer size.
+  if (const MaxFieldAlignmentAttr *MFAA = RD->getAttr<MaxFieldAlignmentAttr>()){
+    unsigned PackedAlignment = MFAA->getAlignment();
+    if (PackedAlignment <= Context.getTargetInfo().getPointerWidth(0))
+      MaxFieldAlignment = Context.toCharUnitsFromBits(PackedAlignment);
+  }
   // Packed attribute forces max field alignment to be 1.
   if (RD->hasAttr<PackedAttr>())
     MaxFieldAlignment = CharUnits::One();
@@ -2335,18 +2346,18 @@
     const CXXRecordDecl *BaseDecl,
     const ASTRecordLayout &BaseLayout,
     const ASTRecordLayout *&PreviousBaseLayout) {
-  // Insert padding between two bases if the left first one is zero sized or

-  // contains a zero sized subobject and the right is zero sized or one leads

-  // with a zero sized base.

-  if (PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() &&

-      BaseLayout.leadsWithZeroSizedBase())

-    Size++;

-  ElementInfo Info = getAdjustedElementInfo(BaseLayout);

-  CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);

-  Bases.insert(std::make_pair(BaseDecl, BaseOffset));

-  Size = BaseOffset + BaseLayout.getDataSize();

-  updateAlignment(Info.Alignment);

-  PreviousBaseLayout = &BaseLayout;

+  // Insert padding between two bases if the left first one is zero sized or
+  // contains a zero sized subobject and the right is zero sized or one leads
+  // with a zero sized base.
+  if (PreviousBaseLayout && PreviousBaseLayout->hasZeroSizedSubObject() &&
+      BaseLayout.leadsWithZeroSizedBase())
+    Size++;
+  ElementInfo Info = getAdjustedElementInfo(BaseLayout);
+  CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
+  Bases.insert(std::make_pair(BaseDecl, BaseOffset));
+  Size = BaseOffset + BaseLayout.getDataSize();
+  updateAlignment(Info.Alignment);
+  PreviousBaseLayout = &BaseLayout;
   VBPtrOffset = Size;
 }
 
@@ -2598,7 +2609,7 @@
       Size = Size.RoundUpToAlignment(VtorDispAlignment) + VtorDispSize;
     // Insert the virtual base.
     ElementInfo Info = getAdjustedElementInfo(BaseLayout);
-    CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);

+    CharUnits BaseOffset = Size.RoundUpToAlignment(Info.Alignment);
     VBases.insert(std::make_pair(BaseDecl,
         ASTRecordLayout::VBaseInfo(BaseOffset, HasVtordisp)));
     Size = BaseOffset + BaseLayout.getDataSize();