diff options
author | Warren Hunt <whunt@google.com> | 2013-12-06 00:01:17 +0000 |
---|---|---|
committer | Warren Hunt <whunt@google.com> | 2013-12-06 00:01:17 +0000 |
commit | 5ec042b219241ea73f33a143a0e5735c2f57886b (patch) | |
tree | 41a962cb129ea99b26781df6c7a43207178e21d1 /test/Layout | |
parent | b5d65e84c9b9f5e9e059ae5c30dd1a3b37c4246f (diff) | |
download | clang-5ec042b219241ea73f33a143a0e5735c2f57886b.tar.gz |
Support MS-ABI's concept of "Required Alignment" imposed by
__declspec(align())
This patch implements required alignment in a way that makes
__declspec(align()) and #pragma pack play correctly together. In the
MS-ABI, __declspec(align()) is a hard rule and cannot be overridden by
#pragma pack. This cases each record to have two interesting alignments
"preferred alignment" (which matches Itanium's concept of alignment) and
"required alignment" which is an alignment that must never be violated,
even in the case of #pragma pack. This patch introduces the concept of
Required Alignment to the record builder and tracks/uses it
appropriately. Test cases are included.
Differential Revision: http://llvm-reviews.chandlerc.com/D2283
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196549 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Layout')
-rw-r--r-- | test/Layout/ms-x86-pack-and-align.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/test/Layout/ms-x86-pack-and-align.cpp b/test/Layout/ms-x86-pack-and-align.cpp new file mode 100644 index 0000000000..f9f2b30f5f --- /dev/null +++ b/test/Layout/ms-x86-pack-and-align.cpp @@ -0,0 +1,120 @@ +// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple i686-pc-win32 -fdump-record-layouts -fsyntax-only -cxx-abi microsoft %s 2>&1 \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple x86_64-pc-win32 -fdump-record-layouts -fsyntax-only -cxx-abi microsoft %s 2>/dev/null \ +// RUN: | FileCheck %s -check-prefix CHECK-X64 + +extern "C" int printf(const char *fmt, ...); +char buffer[419430400]; + +struct A { + char a; + A() { + printf("A = %d\n", (int)((char*)this - buffer)); + printf("A.a = %d\n", (int)((char*)&a - buffer)); + } +}; + +struct B { + __declspec(align(4)) long long a; + B() { + printf("B = %d\n", (int)((char*)this - buffer)); + printf("B.a = %d\n", (int)((char*)&a - buffer)); + } +}; + +#pragma pack(push, 2) +struct X { + B a; + char b; + int c; + X() { + printf("X = %d\n", (int)((char*)this - buffer)); + printf("X.a = %d\n", (int)((char*)&a - buffer)); + printf("X.b = %d\n", (int)((char*)&b - buffer)); + printf("X.c = %d\n", (int)((char*)&c - buffer)); + } +}; + +// CHECK: *** Dumping AST Record Layout +// CHECK: 0 | struct X +// CHECK: 0 | struct B a +// CHECK: 0 | long long a +// CHECK: 8 | char b +// CHECK: 10 | int c +// CHECK: | [sizeof=16, align=4 +// CHECK: | nvsize=16, nvalign=4] +// CHECK-X64: *** Dumping AST Record Layout +// CHECK-X64: 0 | struct X +// CHECK-X64: 0 | struct B a +// CHECK-X64: 0 | long long a +// CHECK-X64: 8 | char b +// CHECK-X64: 10 | int c +// CHECK-X64: | [sizeof=16, align=4 +// CHECK-X64: | nvsize=16, nvalign=4] + +struct Y : A, B { + char a; + int b; + Y() { + printf("Y = %d\n", (int)((char*)this - buffer)); + printf("Y.a = %d\n", (int)((char*)&a - buffer)); + printf("Y.b = %d\n", (int)((char*)&b - buffer)); + } +}; + +// CHECK: *** Dumping AST Record Layout +// CHECK: 0 | struct Y +// CHECK: 0 | struct A (base) +// CHECK: 0 | char a +// CHECK: 4 | struct B (base) +// CHECK: 4 | long long a +// CHECK: 12 | char a +// CHECK: 14 | int b +// CHECK: | [sizeof=20, align=4 +// CHECK: | nvsize=20, nvalign=4] +// CHECK-X64: *** Dumping AST Record Layout +// CHECK-X64: 0 | struct Y +// CHECK-X64: 0 | struct A (base) +// CHECK-X64: 0 | char a +// CHECK-X64: 4 | struct B (base) +// CHECK-X64: 4 | long long a +// CHECK-X64: 12 | char a +// CHECK-X64: 14 | int b +// CHECK-X64: | [sizeof=20, align=4 +// CHECK-X64: | nvsize=20, nvalign=4] + +struct Z : virtual B { + char a; + int b; + Z() { + printf("Z = %d\n", (int)((char*)this - buffer)); + printf("Z.a = %d\n", (int)((char*)&a - buffer)); + printf("Z.b = %d\n", (int)((char*)&b - buffer)); + } +}; + +// CHECK: *** Dumping AST Record Layout +// CHECK: 0 | struct Z +// CHECK: 0 | (Z vbtable pointer) +// CHECK: 4 | char a +// CHECK: 6 | int b +// CHECK: 12 | struct B (virtual base) +// CHECK: 12 | long long a +// CHECK: | [sizeof=20, align=4 +// CHECK: | nvsize=10, nvalign=2] +// CHECK-X64: *** Dumping AST Record Layout +// CHECK-X64: 0 | struct Z +// CHECK-X64: 0 | (Z vbtable pointer) +// CHECK-X64: 8 | char a +// CHECK-X64: 10 | int b +// CHECK-X64: 16 | struct B (virtual base) +// CHECK-X64: 16 | long long a +// CHECK-X64: | [sizeof=24, align=4 +// CHECK-X64: | nvsize=14, nvalign=2] + +#pragma pack(pop) + +int a[ +sizeof(X)+ +sizeof(Y)+ +sizeof(Z)]; |