MS ABI: Consider alignment attributes on typedefs for layout

The MS ABI has a notion of 'required alignment' for fields; this
alignment supercedes pragma pack directives.

MSVC takes into account alignment attributes on typedefs when
determining whether or not a field has a certain required alignment.

Do the same in clang by tracking whether or not we saw such an attribute
when calculating the type's bitwidth and alignment.

This fixes PR20418.

Reviewers: rnk

Differential Revision: http://reviews.llvm.org/D4714

llvm-svn: 214274
diff --git a/clang/test/Layout/ms-x86-pack-and-align.cpp b/clang/test/Layout/ms-x86-pack-and-align.cpp
index 5e1aae1..73dcc7f 100644
--- a/clang/test/Layout/ms-x86-pack-and-align.cpp
+++ b/clang/test/Layout/ms-x86-pack-and-align.cpp
@@ -652,7 +652,94 @@
 // CHECK-X64-NEXT:      | [sizeof=12, align=1
 // CHECK-X64-NEXT:      |  nvsize=8, nvalign=1]
 
+struct __declspec(align(4)) PA {
+  int c;
+};
 
+typedef __declspec(align(8)) PA PB;
+
+#pragma pack(push, 1)
+struct PC {
+  char a;
+  PB x;
+};
+#pragma pack(pop)
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK:         0 | struct PC
+// CHECK-NEXT:    0 |   char a
+// CHECK-NEXT:    8 |   struct PA x
+// CHECK-NEXT:    8 |     int c
+// CHECK-NEXT:      |   [sizeof=4, align=4
+// CHECK-NEXT:      |    nvsize=4, nvalign=4]
+// CHECK-NEXT:      | [sizeof=16, align=8
+// CHECK-NEXT:      |  nvsize=12, nvalign=8]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64:         0 | struct PC
+// CHECK-X64-NEXT:    0 |   char a
+// CHECK-X64-NEXT:    8 |   struct PA x
+// CHECK-X64-NEXT:    8 |     int c
+// CHECK-X64-NEXT:      |   [sizeof=4, align=4
+// CHECK-X64-NEXT:      |    nvsize=4, nvalign=4]
+// CHECK-X64-NEXT:      | [sizeof=16, align=8
+// CHECK-X64-NEXT:      |  nvsize=12, nvalign=8]
+
+typedef int __declspec(align(2)) QA;
+#pragma pack(push, 1)
+struct QB {
+  char a;
+  QA b;
+};
+#pragma pack(pop)
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT:    0 | struct QB
+// CHECK-NEXT:    0 |   char a
+// CHECK-NEXT:    2 |   QA b
+// CHECK-NEXT:      | [sizeof=6, align=2
+// CHECK-NEXT:      |  nvsize=6, nvalign=2]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT:    0 | struct QB
+// CHECK-X64-NEXT:    0 |   char a
+// CHECK-X64-NEXT:    2 |   QA b
+// CHECK-X64-NEXT:      | [sizeof=6, align=2
+// CHECK-X64-NEXT:      |  nvsize=6, nvalign=2]
+
+struct QC {
+  char a;
+  QA b;
+};
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT:    0 | struct QC
+// CHECK-NEXT:    0 |   char a
+// CHECK-NEXT:    4 |   QA b
+// CHECK-NEXT:      | [sizeof=8, align=4
+// CHECK-NEXT:      |  nvsize=8, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT:    0 | struct QC
+// CHECK-X64-NEXT:    0 |   char a
+// CHECK-X64-NEXT:    4 |   QA b
+// CHECK-X64-NEXT:      | [sizeof=8, align=4
+// CHECK-X64-NEXT:      |  nvsize=8, nvalign=4]
+
+struct QD {
+  char a;
+  QA b : 3;
+};
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT:    0 | struct QD
+// CHECK-NEXT:    0 |   char a
+// CHECK-NEXT:    4 |   QA b
+// CHECK-NEXT:      | [sizeof=8, align=4
+// CHECK-NEXT:      |  nvsize=8, nvalign=4]
+// CHECK-X64: *** Dumping AST Record Layout
+// CHECK-X64-NEXT:    0 | struct QD
+// CHECK-X64-NEXT:    0 |   char a
+// CHECK-X64-NEXT:    4 |   QA b
+// CHECK-X64-NEXT:      | [sizeof=8, align=4
+// CHECK-X64-NEXT:      |  nvsize=8, nvalign=4]
 
 int a[
 sizeof(X)+
@@ -680,4 +767,8 @@
 sizeof(RE)+
 sizeof(ND)+
 sizeof(OD)+
+sizeof(PC)+
+sizeof(QB)+
+sizeof(QC)+
+sizeof(QD)+
 0];