summaryrefslogtreecommitdiff
path: root/test/Layout
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
commit45b533945f0851ec234ca846e1af5ee1e4df0b6e (patch)
tree0a5b74c0b9ca73aded34df95c91fcaf3815230d8 /test/Layout
parent7e86edd64bfae4e324224452e4ea879b3371a4bd (diff)
Notes
Diffstat (limited to 'test/Layout')
-rw-r--r--test/Layout/itanium-union-bitfield.cpp16
-rw-r--r--test/Layout/ms-vtordisp-local.cpp217
-rw-r--r--test/Layout/ms-x86-alias-avoidance-padding.cpp24
-rw-r--r--test/Layout/ms-x86-bitfields-vbases.cpp24
-rw-r--r--test/Layout/ms-x86-empty-layout.c56
-rw-r--r--test/Layout/ms-x86-empty-nonvirtual-bases.cpp38
-rw-r--r--test/Layout/ms-x86-empty-virtual-base.cpp4
-rw-r--r--test/Layout/ms-x86-pack-and-align.cpp80
-rw-r--r--test/Layout/ms_struct-bitfields.c48
9 files changed, 355 insertions, 152 deletions
diff --git a/test/Layout/itanium-union-bitfield.cpp b/test/Layout/itanium-union-bitfield.cpp
index b06fd36071e9..289a565359e9 100644
--- a/test/Layout/itanium-union-bitfield.cpp
+++ b/test/Layout/itanium-union-bitfield.cpp
@@ -16,14 +16,14 @@ union B {
B::B() {}
// CHECK:*** Dumping AST Record Layout
-// CHECK-NEXT: 0 | union A
-// CHECK-NEXT: 0 | int f1
-// CHECK-NEXT: | [sizeof=4, dsize=1, align=4
-// CHECK-NEXT: | nvsize=1, nvalign=4]
+// CHECK-NEXT: 0 | union A
+// CHECK-NEXT: 0:0-2 | int f1
+// CHECK-NEXT: | [sizeof=4, dsize=1, align=4
+// CHECK-NEXT: | nvsize=1, nvalign=4]
// CHECK:*** Dumping AST Record Layout
-// CHECK-NEXT: 0 | union B
-// CHECK-NEXT: 0 | char f1
-// CHECK-NEXT: | [sizeof=8, dsize=5, align=4
-// CHECK-NEXT: | nvsize=5, nvalign=4]
+// CHECK-NEXT: 0 | union B
+// CHECK-NEXT: 0:0-34 | char f1
+// CHECK-NEXT: | [sizeof=8, dsize=5, align=4
+// CHECK-NEXT: | nvsize=5, nvalign=4]
diff --git a/test/Layout/ms-vtordisp-local.cpp b/test/Layout/ms-vtordisp-local.cpp
new file mode 100644
index 000000000000..048f4e58297b
--- /dev/null
+++ b/test/Layout/ms-vtordisp-local.cpp
@@ -0,0 +1,217 @@
+// RUN: %clang_cc1 -fms-extensions -fexceptions -fcxx-exceptions -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only %s 2>&1 | FileCheck %s
+
+struct Base {
+ virtual ~Base() {}
+ virtual void BaseFunc() {}
+};
+
+#pragma vtordisp(0)
+
+struct Container {
+ static void f() try {
+ #pragma vtordisp(2)
+ struct HasVtorDisp : virtual Base {
+ virtual ~HasVtorDisp() {}
+ virtual void Func() {}
+ };
+
+ int x[sizeof(HasVtorDisp)];
+
+ // HasVtorDisp: vtordisp because of pragma right before it.
+ //
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK-NEXT: 0 | struct HasVtorDisp
+ // CHECK-NEXT: 0 | (HasVtorDisp vftable pointer)
+ // CHECK-NEXT: 8 | (HasVtorDisp vbtable pointer)
+ // CHECK-NEXT: 20 | (vtordisp for vbase Base)
+ // CHECK-NEXT: 24 | struct Base (virtual base)
+ // CHECK-NEXT: 24 | (Base vftable pointer)
+ // CHECK-NEXT: | [sizeof=32, align=8,
+ // CHECK-NEXT: | nvsize=16, nvalign=8]
+ } catch (...) {
+ }
+};
+
+struct NoVtorDisp1 : virtual Base {
+ virtual ~NoVtorDisp1() {}
+ virtual void Func() {}
+};
+
+int x1[sizeof(NoVtorDisp1)];
+
+// NoVtroDisp1: no vtordisp because of pragma disabling it.
+//
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct NoVtorDisp1
+// CHECK-NEXT: 0 | (NoVtorDisp1 vftable pointer)
+// CHECK-NEXT: 8 | (NoVtorDisp1 vbtable pointer)
+// CHECK-NEXT: 16 | struct Base (virtual base)
+// CHECK-NEXT: 16 | (Base vftable pointer)
+// CHECK-NEXT: | [sizeof=24, align=8,
+// CHECK-NEXT: | nvsize=16, nvalign=8]
+
+struct Container2 {
+ static void f1() {
+ // Local pragma #1 - must be disabled on exit from f1().
+ #pragma vtordisp(push, 2)
+ struct HasVtorDisp1 : virtual Base {
+ virtual ~HasVtorDisp1() {}
+ virtual void Func() {}
+ };
+
+ int x2[sizeof(HasVtorDisp1)];
+
+ // HasVtorDisp1: vtordisp because of pragma right before it.
+ //
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK-NEXT: 0 | struct HasVtorDisp1
+ // CHECK-NEXT: 0 | (HasVtorDisp1 vftable pointer)
+ // CHECK-NEXT: 8 | (HasVtorDisp1 vbtable pointer)
+ // CHECK-NEXT: 20 | (vtordisp for vbase Base)
+ // CHECK-NEXT: 24 | struct Base (virtual base)
+ // CHECK-NEXT: 24 | (Base vftable pointer)
+ // CHECK-NEXT: | [sizeof=32, align=8,
+ // CHECK-NEXT: | nvsize=16, nvalign=8]
+
+ struct InnerContainer {
+ static void g1() {
+ struct HasVtorDisp2 : virtual Base {
+ virtual ~HasVtorDisp2() {}
+ virtual void Func() {}
+ };
+
+ int x3[sizeof(HasVtorDisp2)];
+
+ // HasVtorDisp2: vtordisp because of vtordisp(2) in f1().
+ //
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK-NEXT: 0 | struct HasVtorDisp2
+ // CHECK-NEXT: 0 | (HasVtorDisp2 vftable pointer)
+ // CHECK-NEXT: 8 | (HasVtorDisp2 vbtable pointer)
+ // CHECK-NEXT: 20 | (vtordisp for vbase Base)
+ // CHECK-NEXT: 24 | struct Base (virtual base)
+ // CHECK-NEXT: 24 | (Base vftable pointer)
+ // CHECK-NEXT: | [sizeof=32, align=8,
+ // CHECK-NEXT: | nvsize=16, nvalign=8]
+
+ // Local pragma #2 - must be disabled on exit from g1().
+ #pragma vtordisp(push, 0)
+ struct NoVtorDisp2 : virtual Base {
+ virtual ~NoVtorDisp2() {}
+ virtual void Func() {}
+ };
+
+ int x4[sizeof(NoVtorDisp2)];
+
+ // NoVtroDisp2: no vtordisp because of vtordisp(0) in g1().
+ //
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK-NEXT: 0 | struct NoVtorDisp2
+ // CHECK-NEXT: 0 | (NoVtorDisp2 vftable pointer)
+ // CHECK-NEXT: 8 | (NoVtorDisp2 vbtable pointer)
+ // CHECK-NEXT: 16 | struct Base (virtual base)
+ // CHECK-NEXT: 16 | (Base vftable pointer)
+ // CHECK-NEXT: | [sizeof=24, align=8,
+ // CHECK-NEXT: | nvsize=16, nvalign=8]
+ }
+
+ static void g2() {
+ struct HasVtorDisp3 : virtual Base {
+ virtual ~HasVtorDisp3() {}
+ virtual void Func() {}
+ };
+
+ int x5[sizeof(HasVtorDisp3)];
+
+ // HasVtorDisp3: vtordisp because of vtordisp(2) in f1(),
+ // local vtordisp(0) in g1() is disabled.
+ //
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK-NEXT: 0 | struct HasVtorDisp3
+ // CHECK-NEXT: 0 | (HasVtorDisp3 vftable pointer)
+ // CHECK-NEXT: 8 | (HasVtorDisp3 vbtable pointer)
+ // CHECK-NEXT: 20 | (vtordisp for vbase Base)
+ // CHECK-NEXT: 24 | struct Base (virtual base)
+ // CHECK-NEXT: 24 | (Base vftable pointer)
+ // CHECK-NEXT: | [sizeof=32, align=8,
+ // CHECK-NEXT: | nvsize=16, nvalign=8]
+ }
+ };
+
+ struct HasVtorDisp4 : virtual Base {
+ virtual ~HasVtorDisp4() {}
+ virtual void Func() {}
+ };
+
+ int x6[sizeof(HasVtorDisp4)];
+
+ // HasVtorDisp4: vtordisp because of vtordisp(2) in f1(),
+ // local vtordisp(0) in g1() is disabled,
+ // g2() has no pragmas - stack is not affected.
+ //
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK-NEXT: 0 | struct HasVtorDisp4
+ // CHECK-NEXT: 0 | (HasVtorDisp4 vftable pointer)
+ // CHECK-NEXT: 8 | (HasVtorDisp4 vbtable pointer)
+ // CHECK-NEXT: 20 | (vtordisp for vbase Base)
+ // CHECK-NEXT: 24 | struct Base (virtual base)
+ // CHECK-NEXT: 24 | (Base vftable pointer)
+ // CHECK-NEXT: | [sizeof=32, align=8,
+ // CHECK-NEXT: | nvsize=16, nvalign=8]
+
+ InnerContainer::g1();
+ InnerContainer::g2();
+ }
+
+ static void f2() {
+ struct NoVtorDisp3 : virtual Base {
+ virtual ~NoVtorDisp3() {}
+ virtual void Func() {}
+ };
+
+ int x7[sizeof(NoVtorDisp3)];
+
+ // NoVtroDisp3: no vtordisp because of global pragma (0),
+ // local vtordisp(2) is disabled on exit from f1().
+ //
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK-NEXT: 0 | struct NoVtorDisp3
+ // CHECK-NEXT: 0 | (NoVtorDisp3 vftable pointer)
+ // CHECK-NEXT: 8 | (NoVtorDisp3 vbtable pointer)
+ // CHECK-NEXT: 16 | struct Base (virtual base)
+ // CHECK-NEXT: 16 | (Base vftable pointer)
+ // CHECK-NEXT: | [sizeof=24, align=8,
+ // CHECK-NEXT: | nvsize=16, nvalign=8]
+ }
+};
+
+struct Container3 {
+ #pragma vtordisp(2)
+ struct HasVtorDisp5 : virtual Base {
+ virtual ~HasVtorDisp5() {}
+ virtual void Func() {}
+ };
+
+ int x8[sizeof(HasVtorDisp5)];
+
+ // HasVtorDisp5: vtordisp because of pragma right before it.
+ //
+ // CHECK: *** Dumping AST Record Layout
+ // CHECK-NEXT: 0 | struct Container3::HasVtorDisp5
+ // CHECK-NEXT: 0 | (HasVtorDisp5 vftable pointer)
+ // CHECK-NEXT: 8 | (HasVtorDisp5 vbtable pointer)
+ // CHECK-NEXT: 20 | (vtordisp for vbase Base)
+ // CHECK-NEXT: 24 | struct Base (virtual base)
+ // CHECK-NEXT: 24 | (Base vftable pointer)
+ // CHECK-NEXT: | [sizeof=32, align=8,
+ // CHECK-NEXT: | nvsize=16, nvalign=8]
+};
+
+int main() {
+ Container::f();
+ Container2::f1();
+ Container2::f2();
+ Container3 cont3;
+ return 0;
+};
diff --git a/test/Layout/ms-x86-alias-avoidance-padding.cpp b/test/Layout/ms-x86-alias-avoidance-padding.cpp
index 1d77bf9e9061..203927b69a89 100644
--- a/test/Layout/ms-x86-alias-avoidance-padding.cpp
+++ b/test/Layout/ms-x86-alias-avoidance-padding.cpp
@@ -391,8 +391,6 @@ struct RZ3 : RX3, RY {};
// CHECK-NEXT: 0 | struct RA (base) (empty)
// CHECK-NEXT: 0 | struct RB a
// CHECK-NEXT: 0 | char c
-// CHECK-NEXT: | [sizeof=1, align=1
-// CHECK-NEXT: | nvsize=1, nvalign=1]
// CHECK-NEXT: 1 | struct RY (base) (empty)
// CHECK-NEXT: | [sizeof=1, align=1
// CHECK-NEXT: | nvsize=1, nvalign=1]
@@ -403,8 +401,6 @@ struct RZ3 : RX3, RY {};
// CHECK-X64-NEXT: 0 | struct RA (base) (empty)
// CHECK-X64-NEXT: 0 | struct RB a
// CHECK-X64-NEXT: 0 | char c
-// CHECK-X64-NEXT: | [sizeof=1, align=1
-// CHECK-X64-NEXT: | nvsize=1, nvalign=1]
// CHECK-X64-NEXT: 1 | struct RY (base) (empty)
// CHECK-X64-NEXT: | [sizeof=1, align=1
// CHECK-X64-NEXT: | nvsize=1, nvalign=1]
@@ -415,8 +411,6 @@ struct RZ4 : RX4, RY {};
// CHECK-NEXT: 0 | struct RZ4
// CHECK-NEXT: 0 | struct RX4 (base)
// CHECK-NEXT: 0 | struct RA a (empty)
-// CHECK-NEXT: | [sizeof=1, align=1
-// CHECK-NEXT: | nvsize=0, nvalign=1]
// CHECK-NEXT: 1 | char b
// CHECK-NEXT: 3 | struct RY (base) (empty)
// CHECK-NEXT: | [sizeof=3, align=1
@@ -426,8 +420,6 @@ struct RZ4 : RX4, RY {};
// CHECK-X64-NEXT: 0 | struct RZ4
// CHECK-X64-NEXT: 0 | struct RX4 (base)
// CHECK-X64-NEXT: 0 | struct RA a (empty)
-// CHECK-X64-NEXT: | [sizeof=1, align=1
-// CHECK-X64-NEXT: | nvsize=0, nvalign=1]
// CHECK-X64-NEXT: 1 | char b
// CHECK-X64-NEXT: 3 | struct RY (base) (empty)
// CHECK-X64-NEXT: | [sizeof=3, align=1
@@ -439,12 +431,8 @@ struct RZ5 : RX5, RY {};
// CHECK-NEXT: 0 | struct RZ5
// CHECK-NEXT: 0 | struct RX5 (base)
// CHECK-NEXT: 0 | struct RA a (empty)
-// CHECK-NEXT: | [sizeof=1, align=1
-// CHECK-NEXT: | nvsize=0, nvalign=1]
// CHECK-NEXT: 1 | struct RB b
// CHECK-NEXT: 1 | char c
-// CHECK-NEXT: | [sizeof=1, align=1
-// CHECK-NEXT: | nvsize=1, nvalign=1]
// CHECK-NEXT: 2 | struct RY (base) (empty)
// CHECK-NEXT: | [sizeof=2, align=1
// CHECK-NEXT: | nvsize=2, nvalign=1]
@@ -453,12 +441,8 @@ struct RZ5 : RX5, RY {};
// CHECK-X64-NEXT: 0 | struct RZ5
// CHECK-X64-NEXT: 0 | struct RX5 (base)
// CHECK-X64-NEXT: 0 | struct RA a (empty)
-// CHECK-X64-NEXT: | [sizeof=1, align=1
-// CHECK-X64-NEXT: | nvsize=0, nvalign=1]
// CHECK-X64-NEXT: 1 | struct RB b
// CHECK-X64-NEXT: 1 | char c
-// CHECK-X64-NEXT: | [sizeof=1, align=1
-// CHECK-X64-NEXT: | nvsize=1, nvalign=1]
// CHECK-X64-NEXT: 2 | struct RY (base) (empty)
// CHECK-X64-NEXT: | [sizeof=2, align=1
// CHECK-X64-NEXT: | nvsize=2, nvalign=1]
@@ -472,8 +456,6 @@ struct RZ6 : RX6, RY {};
// CHECK-NEXT: 0 | (RX6 vbtable pointer)
// CHECK-NEXT: 4 | struct RB a
// CHECK-NEXT: 4 | char c
-// CHECK-NEXT: | [sizeof=1, align=1
-// CHECK-NEXT: | nvsize=1, nvalign=1]
// CHECK-NEXT: 9 | struct RY (base) (empty)
// CHECK-NEXT: 12 | struct RV (virtual base) (empty)
// CHECK-NEXT: | [sizeof=12, align=4
@@ -486,8 +468,6 @@ struct RZ6 : RX6, RY {};
// CHECK-X64-NEXT: 0 | (RX6 vbtable pointer)
// CHECK-X64-NEXT: 8 | struct RB a
// CHECK-X64-NEXT: 8 | char c
-// CHECK-X64-NEXT: | [sizeof=1, align=1
-// CHECK-X64-NEXT: | nvsize=1, nvalign=1]
// CHECK-X64-NEXT: 17 | struct RY (base) (empty)
// CHECK-X64-NEXT: 24 | struct RV (virtual base) (empty)
// CHECK-X64-NEXT: | [sizeof=24, align=8
@@ -501,8 +481,6 @@ struct RZ7 : RX7, RY {};
// CHECK-NEXT: 0 | struct RX7 (base)
// CHECK-NEXT: 0 | (RX7 vbtable pointer)
// CHECK-NEXT: 4 | struct RA a (empty)
-// CHECK-NEXT: | [sizeof=1, align=1
-// CHECK-NEXT: | nvsize=0, nvalign=1]
// CHECK-NEXT: 8 | struct RY (base) (empty)
// CHECK-NEXT: 8 | struct RW (virtual base)
// CHECK-NEXT: 8 | char c
@@ -515,8 +493,6 @@ struct RZ7 : RX7, RY {};
// CHECK-X64-NEXT: 0 | struct RX7 (base)
// CHECK-X64-NEXT: 0 | (RX7 vbtable pointer)
// CHECK-X64-NEXT: 8 | struct RA a (empty)
-// CHECK-X64-NEXT: | [sizeof=1, align=1
-// CHECK-X64-NEXT: | nvsize=0, nvalign=1]
// CHECK-X64-NEXT: 16 | struct RY (base) (empty)
// CHECK-X64-NEXT: 16 | struct RW (virtual base)
// CHECK-X64-NEXT: 16 | char c
diff --git a/test/Layout/ms-x86-bitfields-vbases.cpp b/test/Layout/ms-x86-bitfields-vbases.cpp
index 5b54596bbb83..a78fdad7e2eb 100644
--- a/test/Layout/ms-x86-bitfields-vbases.cpp
+++ b/test/Layout/ms-x86-bitfields-vbases.cpp
@@ -12,7 +12,7 @@ struct A : virtual B0 { char a : 1; };
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct A
// CHECK-NEXT: 0 | (A vbtable pointer)
-// CHECK-NEXT: 4 | char a
+// CHECK-NEXT: 4:0-0 | char a
// CHECK-NEXT: 8 | struct B0 (virtual base)
// CHECK-NEXT: 8 | int a
// CHECK-NEXT: | [sizeof=12, align=4
@@ -21,7 +21,7 @@ struct A : virtual B0 { char a : 1; };
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct A
// CHECK-X64-NEXT: 0 | (A vbtable pointer)
-// CHECK-X64-NEXT: 8 | char a
+// CHECK-X64-NEXT: 8:0-0 | char a
// CHECK-X64-NEXT: 16 | struct B0 (virtual base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: | [sizeof=24, align=8
@@ -32,7 +32,7 @@ struct B : virtual B0 { short a : 1; };
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct B
// CHECK-NEXT: 0 | (B vbtable pointer)
-// CHECK-NEXT: 4 | short a
+// CHECK-NEXT: 4:0-0 | short a
// CHECK-NEXT: 8 | struct B0 (virtual base)
// CHECK-NEXT: 8 | int a
// CHECK-NEXT: | [sizeof=12, align=4
@@ -40,7 +40,7 @@ struct B : virtual B0 { short a : 1; };
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct B
// CHECK-X64-NEXT: 0 | (B vbtable pointer)
-// CHECK-X64-NEXT: 8 | short a
+// CHECK-X64-NEXT: 8:0-0 | short a
// CHECK-X64-NEXT: 16 | struct B0 (virtual base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: | [sizeof=24, align=8
@@ -51,8 +51,8 @@ struct C : virtual B0 { char a : 1; char : 0; };
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct C
// CHECK-NEXT: 0 | (C vbtable pointer)
-// CHECK-NEXT: 4 | char a
-// CHECK-NEXT: 5 | char
+// CHECK-NEXT: 4:0-0 | char a
+// CHECK-NEXT: 5:- | char
// CHECK-NEXT: 8 | struct B0 (virtual base)
// CHECK-NEXT: 8 | int a
// CHECK-NEXT: | [sizeof=12, align=4
@@ -60,8 +60,8 @@ struct C : virtual B0 { char a : 1; char : 0; };
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct C
// CHECK-X64-NEXT: 0 | (C vbtable pointer)
-// CHECK-X64-NEXT: 8 | char a
-// CHECK-X64-NEXT: 9 | char
+// CHECK-X64-NEXT: 8:0-0 | char a
+// CHECK-X64-NEXT: 9:- | char
// CHECK-X64-NEXT: 16 | struct B0 (virtual base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: | [sizeof=24, align=8
@@ -72,7 +72,7 @@ struct D : virtual B0 { char a : 1; char b; };
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct D
// CHECK-NEXT: 0 | (D vbtable pointer)
-// CHECK-NEXT: 4 | char a
+// CHECK-NEXT: 4:0-0 | char a
// CHECK-NEXT: 5 | char b
// CHECK-NEXT: 8 | struct B0 (virtual base)
// CHECK-NEXT: 8 | int a
@@ -81,7 +81,7 @@ struct D : virtual B0 { char a : 1; char b; };
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct D
// CHECK-X64-NEXT: 0 | (D vbtable pointer)
-// CHECK-X64-NEXT: 8 | char a
+// CHECK-X64-NEXT: 8:0-0 | char a
// CHECK-X64-NEXT: 9 | char b
// CHECK-X64-NEXT: 16 | struct B0 (virtual base)
// CHECK-X64-NEXT: 16 | int a
@@ -93,7 +93,7 @@ struct E : virtual B0, virtual B1 { long long : 1; };
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct E
// CHECK-NEXT: 0 | (E vbtable pointer)
-// CHECK-NEXT: 8 | long long
+// CHECK-NEXT: 8:0-0 | long long
// CHECK-NEXT: 16 | struct B0 (virtual base)
// CHECK-NEXT: 16 | int a
// CHECK-NEXT: 20 | struct B1 (virtual base)
@@ -104,7 +104,7 @@ struct E : virtual B0, virtual B1 { long long : 1; };
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct E
// CHECK-X64-NEXT: 0 | (E vbtable pointer)
-// CHECK-X64-NEXT: 8 | long long
+// CHECK-X64-NEXT: 8:0-0 | long long
// CHECK-X64-NEXT: 16 | struct B0 (virtual base)
// CHECK-X64-NEXT: 16 | int a
// CHECK-X64-NEXT: 20 | struct B1 (virtual base)
diff --git a/test/Layout/ms-x86-empty-layout.c b/test/Layout/ms-x86-empty-layout.c
index 3554baf3a8bc..5dbd8446597e 100644
--- a/test/Layout/ms-x86-empty-layout.c
+++ b/test/Layout/ms-x86-empty-layout.c
@@ -6,48 +6,36 @@
struct EmptyIntMemb {
int FlexArrayMemb[0];
};
-// CHECK: *** Dumping AST Record Layout
-// CHECK: Type: struct EmptyIntMemb
-// CHECK: Record:
-// CHECK: Layout: <ASTRecordLayout
-// CHECK: Size:32
-// CHECK: Alignment:32
-// CHECK: FieldOffsets: [0]>
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct EmptyIntMemb
+// CHECK-NEXT: 0 | int [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=4, align=4
struct EmptyLongLongMemb {
long long FlexArrayMemb[0];
};
// CHECK: *** Dumping AST Record Layout
-// CHECK: Type: struct EmptyLongLongMemb
-// CHECK: Record:
-// CHECK: Layout: <ASTRecordLayout
-// CHECK: Size:32
-// CHECK: Alignment:64
-// CHECK: FieldOffsets: [0]>
+// CHECK-NEXT: 0 | struct EmptyLongLongMemb
+// CHECK-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=4, align=8
struct EmptyAligned2LongLongMemb {
long long __declspec(align(2)) FlexArrayMemb[0];
};
// CHECK: *** Dumping AST Record Layout
-// CHECK: Type: struct EmptyAligned2LongLongMemb
-// CHECK: Record:
-// CHECK: Layout: <ASTRecordLayout
-// CHECK: Size:32
-// CHECK: Alignment:64
-// CHECK: FieldOffsets: [0]>
+// CHECK-NEXT: 0 | struct EmptyAligned2LongLongMemb
+// CHECK-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=4, align=8
struct EmptyAligned8LongLongMemb {
long long __declspec(align(8)) FlexArrayMemb[0];
};
// CHECK: *** Dumping AST Record Layout
-// CHECK: Type: struct EmptyAligned8LongLongMemb
-// CHECK: Record:
-// CHECK: Layout: <ASTRecordLayout
-// CHECK: Size:64
-// CHECK: Alignment:64
-// CHECK: FieldOffsets: [0]>
+// CHECK-NEXT: 0 | struct EmptyAligned8LongLongMemb
+// CHECK-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=8, align=8
#pragma pack(1)
struct __declspec(align(4)) EmptyPackedAligned4LongLongMemb {
@@ -56,12 +44,9 @@ struct __declspec(align(4)) EmptyPackedAligned4LongLongMemb {
#pragma pack()
// CHECK: *** Dumping AST Record Layout
-// CHECK: Type: struct EmptyPackedAligned4LongLongMemb
-// CHECK: Record:
-// CHECK: Layout: <ASTRecordLayout
-// CHECK: Size:32
-// CHECK: Alignment:32
-// CHECK: FieldOffsets: [0]>
+// CHECK-NEXT: 0 | struct EmptyPackedAligned4LongLongMemb
+// CHECK-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=4, align=4
#pragma pack(1)
struct EmptyPackedAligned8LongLongMemb {
@@ -70,12 +55,9 @@ struct EmptyPackedAligned8LongLongMemb {
#pragma pack()
// CHECK: *** Dumping AST Record Layout
-// CHECK: Type: struct EmptyPackedAligned8LongLongMemb
-// CHECK: Record:
-// CHECK: Layout: <ASTRecordLayout
-// CHECK: Size:64
-// CHECK: Alignment:64
-// CHECK: FieldOffsets: [0]>
+// CHECK-NEXT: 0 | struct EmptyPackedAligned8LongLongMemb
+// CHECK-NEXT: 0 | long long [0] FlexArrayMemb
+// CHECK-NEXT: | [sizeof=8, align=8
int a[
diff --git a/test/Layout/ms-x86-empty-nonvirtual-bases.cpp b/test/Layout/ms-x86-empty-nonvirtual-bases.cpp
index 3fca32444b77..07be1d836ec5 100644
--- a/test/Layout/ms-x86-empty-nonvirtual-bases.cpp
+++ b/test/Layout/ms-x86-empty-nonvirtual-bases.cpp
@@ -40,8 +40,6 @@ struct B : B0 {
// CHECK-NEXT: 0 | struct B
// CHECK-NEXT: 0 | struct B0 (base) (empty)
// CHECK-NEXT: 0 | struct B0 b0 (empty)
-// CHECK-NEXT: | [sizeof=8, align=8
-// CHECK-NEXT: | nvsize=0, nvalign=8]
// CHECK: 8 | int a
// CHECK-NEXT: | [sizeof=16, align=8
// CHECK-NEXT: | nvsize=16, nvalign=8]
@@ -82,23 +80,13 @@ struct D {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct D
// CHECK-NEXT: 0 | struct B0 b0 (empty)
-// CHECK-NEXT: | [sizeof=8, align=8
-// CHECK-NEXT: | nvsize=0, nvalign=8]
// CHECK: 8 | struct C0 c0
// CHECK-NEXT: 8 | int a
-// CHECK-NEXT: | [sizeof=4, align=4
-// CHECK-NEXT: | nvsize=4, nvalign=4]
// CHECK: 12 | struct C1 c1
// CHECK-NEXT: 12 | int a
-// CHECK-NEXT: | [sizeof=4, align=4
-// CHECK-NEXT: | nvsize=4, nvalign=4]
// CHECK: 16 | struct C2 c2
// CHECK-NEXT: 16 | int a
-// CHECK-NEXT: | [sizeof=4, align=4
-// CHECK-NEXT: | nvsize=4, nvalign=4]
// CHECK: 24 | struct B1 b1 (empty)
-// CHECK-NEXT: | [sizeof=8, align=8
-// CHECK-NEXT: | nvsize=0, nvalign=8]
// CHECK: 32 | int a
// CHECK-NEXT: | [sizeof=40, align=8
// CHECK-NEXT: | nvsize=40, nvalign=8]
@@ -171,6 +159,28 @@ struct __declspec(align(32)) H : B0, B1, B2, B3, B4 {
// CHECK-NEXT: | [sizeof=64, align=32
// CHECK-NEXT: | nvsize=40, nvalign=32]
+struct I {
+ int i0[0];
+};
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct I
+// CHECK-NEXT: 0 | int [0] i0
+// CHECK-NEXT: | [sizeof={{1|4}}, align=4,
+// CHECK-NEXT: | nvsize=0, nvalign=4]
+
+struct J : I {
+ int j;
+};
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct J
+// CHECK-NEXT: 0 | struct I (base)
+// CHECK-NEXT: 0 | int [0] i0
+// CHECK-NEXT: 0 | int j
+// CHECK-NEXT: | [sizeof=4, align=4,
+// CHECK-NEXT: | nvsize=4, nvalign=4]
+
int a[
sizeof(A)+
sizeof(B)+
@@ -179,4 +189,6 @@ sizeof(D)+
sizeof(E)+
sizeof(F)+
sizeof(G)+
-sizeof(H)];
+sizeof(H)+
+sizeof(I)+
+sizeof(J)];
diff --git a/test/Layout/ms-x86-empty-virtual-base.cpp b/test/Layout/ms-x86-empty-virtual-base.cpp
index 2d0e55a01cb9..b732415152ff 100644
--- a/test/Layout/ms-x86-empty-virtual-base.cpp
+++ b/test/Layout/ms-x86-empty-virtual-base.cpp
@@ -53,8 +53,6 @@ struct B : virtual B0 {
// CHECK-NEXT: 0 | struct B
// CHECK-NEXT: 0 | (B vbtable pointer)
// CHECK-NEXT: 8 | struct B0 b0 (empty)
-// CHECK-NEXT: | [sizeof=8, align=8
-// CHECK-NEXT: | nvsize=0, nvalign=8]
// CHECK: 16 | int a
// CHECK-NEXT: 24 | struct B0 (virtual base) (empty)
// CHECK-NEXT: | [sizeof=24, align=8
@@ -63,8 +61,6 @@ struct B : virtual B0 {
// CHECK-X64-NEXT: 0 | struct B
// CHECK-X64-NEXT: 0 | (B vbtable pointer)
// CHECK-X64-NEXT: 8 | struct B0 b0 (empty)
-// CHECK-X64-NEXT: | [sizeof=8, align=8
-// CHECK-X64-NEXT: | nvsize=0, nvalign=8]
// CHECK-X64: 16 | int a
// CHECK-X64-NEXT: 24 | struct B0 (virtual base) (empty)
// CHECK-X64-NEXT: | [sizeof=24, align=8
diff --git a/test/Layout/ms-x86-pack-and-align.cpp b/test/Layout/ms-x86-pack-and-align.cpp
index 9ded22ec8505..958ee1958148 100644
--- a/test/Layout/ms-x86-pack-and-align.cpp
+++ b/test/Layout/ms-x86-pack-and-align.cpp
@@ -40,8 +40,6 @@ struct X {
// CHECK-NEXT: 0 | struct X
// CHECK-NEXT: 0 | struct B a
// CHECK-NEXT: 0 | long long a
-// CHECK-NEXT: | [sizeof=8, align=8
-// CHECK-NEXT: | nvsize=8, nvalign=8]
// CHECK-NEXT: 8 | char b
// CHECK-NEXT: 10 | int c
// CHECK-NEXT: | [sizeof=16, align=4
@@ -51,8 +49,6 @@ struct X {
// CHECK-X64-NEXT: 0 | struct X
// CHECK-X64-NEXT: 0 | struct B a
// CHECK-X64-NEXT: 0 | long long a
-// CHECK-X64-NEXT: | [sizeof=8, align=8
-// CHECK-X64-NEXT: | nvsize=8, nvalign=8]
// CHECK-X64-NEXT: 8 | char b
// CHECK-X64-NEXT: 10 | int c
// CHECK-X64-NEXT: | [sizeof=16, align=4
@@ -193,12 +189,12 @@ struct YA {
};
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YA (empty)
-// CHECK-NEXT: 0 | char
+// CHECK-NEXT:0:0-0 | char
// CHECK-NEXT: | [sizeof=32, align=32
// CHECK-NEXT: | nvsize=32, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YA (empty)
-// CHECK-X64-NEXT: 0 | char
+// CHECK-X64-NEXT:0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=32, align=32
// CHECK-X64-NEXT: | nvsize=32, nvalign=32]
@@ -211,18 +207,14 @@ struct YB {
// CHECK-NEXT: 0 | struct YB
// CHECK-NEXT: 0 | char a
// CHECK-NEXT: 1 | struct YA b (empty)
-// CHECK-NEXT: 1 | char
-// CHECK-NEXT: | [sizeof=32, align=32
-// CHECK-NEXT: | nvsize=32, nvalign=32]
+// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=33, align=1
// CHECK-NEXT: | nvsize=33, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YB
// CHECK-X64-NEXT: 0 | char a
// CHECK-X64-NEXT: 1 | struct YA b (empty)
-// CHECK-X64-NEXT: 1 | char
-// CHECK-X64-NEXT: | [sizeof=32, align=32
-// CHECK-X64-NEXT: | nvsize=32, nvalign=32]
+// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=33, align=1
// CHECK-X64-NEXT: | nvsize=33, nvalign=1]
@@ -232,12 +224,12 @@ struct YC {
};
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YC (empty)
-// CHECK-NEXT: 0 | char
+// CHECK-NEXT:0:0-0 | char
// CHECK-NEXT: | [sizeof=32, align=32
// CHECK-NEXT: | nvsize=32, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YC (empty)
-// CHECK-X64-NEXT: 0 | char
+// CHECK-X64-NEXT: 0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=8, align=32
// CHECK-X64-NEXT: | nvsize=8, nvalign=32]
@@ -250,18 +242,14 @@ struct YD {
// CHECK-NEXT: 0 | struct YD
// CHECK-NEXT: 0 | char a
// CHECK-NEXT: 1 | struct YC b (empty)
-// CHECK-NEXT: 1 | char
-// CHECK-NEXT: | [sizeof=32, align=32
-// CHECK-NEXT: | nvsize=32, nvalign=32]
+// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=33, align=1
// CHECK-NEXT: | nvsize=33, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YD
// CHECK-X64-NEXT: 0 | char a
// CHECK-X64-NEXT: 1 | struct YC b (empty)
-// CHECK-X64-NEXT: 1 | char
-// CHECK-X64-NEXT: | [sizeof=8, align=32
-// CHECK-X64-NEXT: | nvsize=8, nvalign=32]
+// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=9, align=1
// CHECK-X64-NEXT: | nvsize=9, nvalign=1]
@@ -271,12 +259,12 @@ struct YE {
};
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct YE (empty)
-// CHECK-NEXT: 0 | char
+// CHECK-NEXT: 0:0-0 | char
// CHECK-NEXT: | [sizeof=4, align=32
// CHECK-NEXT: | nvsize=4, nvalign=32]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YE (empty)
-// CHECK-X64-NEXT: 0 | char
+// CHECK-X64-NEXT: 0:0-0 | char
// CHECK-X64-NEXT: | [sizeof=4, align=32
// CHECK-X64-NEXT: | nvsize=4, nvalign=32]
@@ -289,18 +277,14 @@ struct YF {
// CHECK-NEXT: 0 | struct YF
// CHECK-NEXT: 0 | char a
// CHECK-NEXT: 1 | struct YE b (empty)
-// CHECK-NEXT: 1 | char
-// CHECK-NEXT: | [sizeof=4, align=32
-// CHECK-NEXT: | nvsize=4, nvalign=32]
+// CHECK-NEXT:1:0-0 | char
// CHECK-NEXT: | [sizeof=5, align=1
// CHECK-NEXT: | nvsize=5, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct YF
// CHECK-X64-NEXT: 0 | char a
// CHECK-X64-NEXT: 1 | struct YE b (empty)
-// CHECK-X64-NEXT: 1 | char
-// CHECK-X64-NEXT: | [sizeof=4, align=32
-// CHECK-X64-NEXT: | nvsize=4, nvalign=32]
+// CHECK-X64-NEXT:1:0-0 | char
// CHECK-X64-NEXT: | [sizeof=5, align=1
// CHECK-X64-NEXT: | nvsize=5, nvalign=1]
@@ -459,20 +443,20 @@ struct RE {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct RB0
-// CHECK-NEXT: 0 | int b
+// CHECK-NEXT:0:0-2 | int b
// CHECK-NEXT: | [sizeof=8, align=1024
// CHECK-NEXT: | nvsize=4, nvalign=1024]
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct RB1
// CHECK-NEXT: 0 | (RB1 vftable pointer)
-// CHECK-NEXT: 1024 | int b
+// CHECK-NEXT: 1024:0-2 | int b
// CHECK-NEXT: | [sizeof=1032, align=1024
// CHECK-NEXT: | nvsize=1028, nvalign=1024]
// CHECK: *** Dumping AST Record Layout
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct RB2
// CHECK-NEXT: 0 | (RB2 vbtable pointer)
-// CHECK-NEXT: 1024 | int b
+// CHECK-NEXT: 1024:0-2 | int b
// CHECK-NEXT: 1028 | struct RA (virtual base) (empty)
// CHECK-NEXT: | [sizeof=1032, align=1024
// CHECK-NEXT: | nvsize=1028, nvalign=1024]
@@ -480,14 +464,14 @@ struct RE {
// CHECK-NEXT: 0 | struct RB3
// CHECK-NEXT: 0 | (RB3 vftable pointer)
// CHECK-NEXT: 1024 | (RB3 vbtable pointer)
-// CHECK-NEXT: 2048 | int b
+// CHECK-NEXT: 2048:0-2 | int b
// CHECK-NEXT: 2052 | struct RA (virtual base) (empty)
// CHECK-NEXT: | [sizeof=2056, align=1024
// CHECK-NEXT: | nvsize=2052, nvalign=1024]
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct RC
// CHECK-NEXT: 0 | char _
-// CHECK-NEXT: 1024 | int c
+// CHECK-NEXT: 1024:0-2 | int c
// CHECK-NEXT: | [sizeof=1028, align=1024
// CHECK-NEXT: | nvsize=1028, nvalign=1024]
// CHECK: *** Dumping AST Record Layout
@@ -495,27 +479,25 @@ struct RE {
// CHECK-NEXT: 0 | char _
// CHECK-NEXT: 1 | struct RC c
// CHECK-NEXT: 1 | char _
-// CHECK-NEXT: 1025 | int c
-// CHECK-NEXT: | [sizeof=1028, align=1024
-// CHECK-NEXT: | nvsize=1028, nvalign=1024]
+// CHECK-NEXT: 1025:0-2 | int c
// CHECK-NEXT: | [sizeof=1029, align=1
// CHECK-NEXT: | nvsize=1029, nvalign=1]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct RB0
-// CHECK-X64-NEXT: 0 | int b
+// CHECK-X64-NEXT: 0:0-2 | int b
// CHECK-X64-NEXT: | [sizeof=8, align=1024
// CHECK-X64-NEXT: | nvsize=4, nvalign=1024]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct RB1
// CHECK-X64-NEXT: 0 | (RB1 vftable pointer)
-// CHECK-X64-NEXT: 1024 | int b
+// CHECK-X64-NEXT: 1024:0-2 | int b
// CHECK-X64-NEXT: | [sizeof=1032, align=1024
// CHECK-X64-NEXT: | nvsize=1028, nvalign=1024]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct RB2
// CHECK-X64-NEXT: 0 | (RB2 vbtable pointer)
-// CHECK-X64-NEXT: 1024 | int b
+// CHECK-X64-NEXT: 1024:0-2 | int b
// CHECK-X64-NEXT: 1028 | struct RA (virtual base) (empty)
// CHECK-X64-NEXT: | [sizeof=1032, align=1024
// CHECK-X64-NEXT: | nvsize=1028, nvalign=1024]
@@ -523,14 +505,14 @@ struct RE {
// CHECK-X64-NEXT: 0 | struct RB3
// CHECK-X64-NEXT: 0 | (RB3 vftable pointer)
// CHECK-X64-NEXT: 1024 | (RB3 vbtable pointer)
-// CHECK-X64-NEXT: 2048 | int b
+// CHECK-X64-NEXT: 2048:0-2 | int b
// CHECK-X64-NEXT: 2052 | struct RA (virtual base) (empty)
// CHECK-X64-NEXT: | [sizeof=2056, align=1024
// CHECK-X64-NEXT: | nvsize=2052, nvalign=1024]
// CHECK-X64: *** Dumping AST Record Layout
// CHECK-X64-NEXT: 0 | struct RC
// CHECK-X64-NEXT: 0 | char _
-// CHECK-X64-NEXT: 1024 | int c
+// CHECK-X64-NEXT: 1024:0-2 | int c
// CHECK-X64-NEXT: | [sizeof=1028, align=1024
// CHECK-X64-NEXT: | nvsize=1028, nvalign=1024]
// CHECK-X64: *** Dumping AST Record Layout
@@ -538,9 +520,7 @@ struct RE {
// CHECK-X64-NEXT: 0 | char _
// CHECK-X64-NEXT: 1 | struct RC c
// CHECK-X64-NEXT: 1 | char _
-// CHECK-X64-NEXT: 1025 | int c
-// CHECK-X64-NEXT: | [sizeof=1028, align=1024
-// CHECK-X64-NEXT: | nvsize=1028, nvalign=1024]
+// CHECK-X64-NEXT: 1025:0-2 | int c
// CHECK-X64-NEXT: | [sizeof=1029, align=1
// CHECK-X64-NEXT: | nvsize=1029, nvalign=1]
@@ -670,8 +650,6 @@ 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
@@ -679,8 +657,6 @@ 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]
@@ -698,8 +674,6 @@ struct PE {
// 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
@@ -707,8 +681,6 @@ struct PE {
// 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]
@@ -759,13 +731,13 @@ struct QD {
// CHECK: *** Dumping AST Record Layout
// CHECK-NEXT: 0 | struct QD
// CHECK-NEXT: 0 | char a
-// CHECK-NEXT: 4 | QA b
+// CHECK-NEXT:4:0-2 | 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:4:0-2 | QA b
// CHECK-X64-NEXT: | [sizeof=8, align=4
// CHECK-X64-NEXT: | nvsize=8, nvalign=4]
diff --git a/test/Layout/ms_struct-bitfields.c b/test/Layout/ms_struct-bitfields.c
new file mode 100644
index 000000000000..9cb455b5cc42
--- /dev/null
+++ b/test/Layout/ms_struct-bitfields.c
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple armv7-apple-darwin -fdump-record-layouts %s 2>/dev/null \
+// RUN: | FileCheck %s
+
+// rdar://22275433
+
+#pragma ms_struct on
+
+union A {
+ unsigned long long x : 32;
+ unsigned long long y : 32;
+} a;
+// CHECK:*** Dumping AST Record Layout
+// CHECK-NEXT: 0 | union A
+// CHECK-NEXT: 0:0-31 | unsigned long long x
+// CHECK-NEXT: 0:0-31 | unsigned long long y
+// CHECK-NEXT: | [sizeof=8, align=1]
+
+union B {
+ __attribute__((aligned(4)))
+ unsigned long long x : 32;
+ unsigned long long y : 32;
+} b;
+// CHECK:*** Dumping AST Record Layout
+// CHECK-NEXT: 0 | union B
+// CHECK-NEXT: 0:0-31 | unsigned long long x
+// CHECK-NEXT: 0:0-31 | unsigned long long y
+// CHECK-NEXT: | [sizeof=8, align=1]
+
+union C {
+ unsigned long long : 0;
+ unsigned short y : 8;
+} c;
+// CHECK:*** Dumping AST Record Layout
+// CHECK-NEXT: 0 | union C
+// CHECK-NEXT: 0:- | unsigned long long
+// CHECK-NEXT: 0:0-7 | unsigned short y
+// CHECK-NEXT: | [sizeof=2, align=1]
+
+union D {
+ unsigned long long : 0;
+ unsigned short : 0;
+} d;
+// CHECK:*** Dumping AST Record Layout
+// CHECK-NEXT: 0 | union D
+// CHECK-NEXT: 0:- | unsigned long long
+// CHECK-NEXT: 0:- | unsigned short
+// CHECK-NEXT: | [sizeof=1, align=1]
+