434 lines
13 KiB
C++
434 lines
13 KiB
C++
|
// RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fdump-record-layouts \
|
||
|
// RUN: -fsyntax-only -fxl-pragma-pack %s | \
|
||
|
// RUN: FileCheck %s
|
||
|
|
||
|
// RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fdump-record-layouts \
|
||
|
// RUN: -fsyntax-only -fxl-pragma-pack %s | \
|
||
|
// RUN: FileCheck %s
|
||
|
|
||
|
namespace test1 {
|
||
|
// Test the class layout when having a double which is/is not the first struct
|
||
|
// member.
|
||
|
struct D {
|
||
|
double d1;
|
||
|
int i1;
|
||
|
};
|
||
|
|
||
|
struct DoubleFirst {
|
||
|
struct D d2;
|
||
|
int i2;
|
||
|
};
|
||
|
|
||
|
struct IntFirst {
|
||
|
int i3;
|
||
|
struct D d3;
|
||
|
};
|
||
|
|
||
|
int a = sizeof(DoubleFirst);
|
||
|
int b = sizeof(IntFirst);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test1::D
|
||
|
// CHECK-NEXT: 0 | double d1
|
||
|
// CHECK-NEXT: 8 | int i1
|
||
|
// CHECK-NEXT: | [sizeof=16, dsize=16, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=16, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test1::DoubleFirst
|
||
|
// CHECK-NEXT: 0 | struct test1::D d2
|
||
|
// CHECK-NEXT: 0 | double d1
|
||
|
// CHECK-NEXT: 8 | int i1
|
||
|
// CHECK-NEXT: 16 | int i2
|
||
|
// CHECK-NEXT: | [sizeof=24, dsize=24, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=24, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test1::IntFirst
|
||
|
// CHECK-NEXT: 0 | int i3
|
||
|
// CHECK-NEXT: 4 | struct test1::D d3
|
||
|
// CHECK-NEXT: 4 | double d1
|
||
|
// CHECK-NEXT: 12 | int i1
|
||
|
// CHECK-NEXT: | [sizeof=20, dsize=20, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=20, nvalign=4, preferrednvalign=4]
|
||
|
} // namespace test1
|
||
|
|
||
|
namespace test2 {
|
||
|
// Test the class layout when having a zero-sized bitfield followed by double.
|
||
|
struct Double {
|
||
|
int : 0;
|
||
|
double d;
|
||
|
};
|
||
|
|
||
|
int a = sizeof(Double);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test2::Double
|
||
|
// CHECK-NEXT: 0:- | int
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: | [sizeof=8, dsize=8, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=8, nvalign=4, preferrednvalign=4]
|
||
|
} // namespace test2
|
||
|
|
||
|
namespace test3 {
|
||
|
// Test the class layout when having a double member in union.
|
||
|
union A {
|
||
|
int b;
|
||
|
double d;
|
||
|
};
|
||
|
|
||
|
struct UnionStruct {
|
||
|
union A a;
|
||
|
int i;
|
||
|
};
|
||
|
|
||
|
int a = sizeof(UnionStruct);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | union test3::A
|
||
|
// CHECK-NEXT: 0 | int b
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: | [sizeof=8, dsize=8, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=8, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test3::UnionStruct
|
||
|
// CHECK-NEXT: 0 | union test3::A a
|
||
|
// CHECK-NEXT: 0 | int b
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: 8 | int i
|
||
|
// CHECK-NEXT: | [sizeof=16, dsize=16, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=16, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
} // namespace test3
|
||
|
|
||
|
namespace test4 {
|
||
|
// Test the class layout when having multiple base classes.
|
||
|
struct A {
|
||
|
int a;
|
||
|
};
|
||
|
|
||
|
struct B {
|
||
|
double d;
|
||
|
};
|
||
|
|
||
|
class S : A, B {
|
||
|
};
|
||
|
|
||
|
int a = sizeof(S);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test4::A
|
||
|
// CHECK-NEXT: 0 | int a
|
||
|
// CHECK-NEXT: | [sizeof=4, dsize=4, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=4, nvalign=4, preferrednvalign=4]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test4::B
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: | [sizeof=8, dsize=8, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=8, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | class test4::S
|
||
|
// CHECK-NEXT: 0 | struct test4::A (base)
|
||
|
// CHECK-NEXT: 0 | int a
|
||
|
// CHECK-NEXT: 4 | struct test4::B (base)
|
||
|
// CHECK-NEXT: 4 | double d
|
||
|
// CHECK-NEXT: | [sizeof=12, dsize=12, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=12, nvalign=4, preferrednvalign=4]
|
||
|
} // namespace test4
|
||
|
|
||
|
namespace test5 {
|
||
|
struct Empty {
|
||
|
};
|
||
|
|
||
|
struct EmptyDer : Empty {
|
||
|
double d;
|
||
|
};
|
||
|
|
||
|
struct NonEmpty {
|
||
|
int i;
|
||
|
};
|
||
|
|
||
|
struct NonEmptyDer : NonEmpty {
|
||
|
double d;
|
||
|
};
|
||
|
|
||
|
int a = sizeof(EmptyDer);
|
||
|
int b = sizeof(NonEmptyDer);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test5::Empty (empty)
|
||
|
// CHECK-NEXT: | [sizeof=1, dsize=1, align=1, preferredalign=1,
|
||
|
// CHECK-NEXT: | nvsize=1, nvalign=1, preferrednvalign=1]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test5::EmptyDer
|
||
|
// CHECK-NEXT: 0 | struct test5::Empty (base) (empty)
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: | [sizeof=8, dsize=8, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=8, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test5::NonEmpty
|
||
|
// CHECK-NEXT: 0 | int i
|
||
|
// CHECK-NEXT: | [sizeof=4, dsize=4, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=4, nvalign=4, preferrednvalign=4]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test5::NonEmptyDer
|
||
|
// CHECK-NEXT: 0 | struct test5::NonEmpty (base)
|
||
|
// CHECK-NEXT: 0 | int i
|
||
|
// CHECK-NEXT: 4 | double d
|
||
|
// CHECK-NEXT: | [sizeof=12, dsize=12, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=12, nvalign=4, preferrednvalign=4]
|
||
|
} // namespace test5
|
||
|
|
||
|
namespace test6 {
|
||
|
struct A {
|
||
|
struct B {
|
||
|
double d[3];
|
||
|
} b;
|
||
|
};
|
||
|
|
||
|
int a = sizeof(A);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test6::A::B
|
||
|
// CHECK-NEXT: 0 | double [3] d
|
||
|
// CHECK-NEXT: | [sizeof=24, dsize=24, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=24, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test6::A
|
||
|
// CHECK-NEXT: 0 | struct test6::A::B b
|
||
|
// CHECK-NEXT: 0 | double [3] d
|
||
|
// CHECK-NEXT: | [sizeof=24, dsize=24, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=24, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
} // namespace test6
|
||
|
|
||
|
namespace test7 {
|
||
|
struct A {
|
||
|
struct B {
|
||
|
long double _Complex d[3];
|
||
|
} b;
|
||
|
};
|
||
|
|
||
|
int a = sizeof(A);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test7::A::B
|
||
|
// CHECK-NEXT: 0 | _Complex long double [3] d
|
||
|
// CHECK-NEXT: | [sizeof=48, dsize=48, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=48, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test7::A
|
||
|
// CHECK-NEXT: 0 | struct test7::A::B b
|
||
|
// CHECK-NEXT: 0 | _Complex long double [3] d
|
||
|
// CHECK-NEXT: | [sizeof=48, dsize=48, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=48, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
} // namespace test7
|
||
|
|
||
|
namespace test8 {
|
||
|
struct Emp {};
|
||
|
|
||
|
struct Y : Emp {
|
||
|
double d;
|
||
|
};
|
||
|
|
||
|
struct Z : Emp {
|
||
|
Y y;
|
||
|
};
|
||
|
|
||
|
int a = sizeof(Z);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test8::Emp (empty)
|
||
|
// CHECK-NEXT: | [sizeof=1, dsize=1, align=1, preferredalign=1,
|
||
|
// CHECK-NEXT: | nvsize=1, nvalign=1, preferrednvalign=1]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test8::Y
|
||
|
// CHECK-NEXT: 0 | struct test8::Emp (base) (empty)
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: | [sizeof=8, dsize=8, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=8, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test8::Z
|
||
|
// CHECK-NEXT: 0 | struct test8::Emp (base) (empty)
|
||
|
// CHECK-NEXT: 8 | struct test8::Y y
|
||
|
// CHECK-NEXT: 8 | struct test8::Emp (base) (empty)
|
||
|
// CHECK-NEXT: 8 | double d
|
||
|
// CHECK-NEXT: | [sizeof=16, dsize=16, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=16, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
} // namespace test8
|
||
|
|
||
|
namespace test9 {
|
||
|
// Test the class layout when having a zero-extent array in a base class, which
|
||
|
// renders the base class not empty.
|
||
|
struct A { char zea[0]; };
|
||
|
|
||
|
struct B : A { double d; };
|
||
|
|
||
|
struct C { double d; };
|
||
|
struct D : A, C { char x; };
|
||
|
|
||
|
int a = sizeof(B);
|
||
|
int b = sizeof(D);
|
||
|
|
||
|
// CHECK: 0 | struct test9::B
|
||
|
// CHECK-NEXT: 0 | struct test9::A (base)
|
||
|
// CHECK-NEXT: 0 | char [0] zea
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: | [sizeof=8, dsize=8, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=8, nvalign=4, preferrednvalign=4]
|
||
|
|
||
|
// CHECK: 0 | struct test9::D
|
||
|
// CHECK-NEXT: 0 | struct test9::A (base)
|
||
|
// CHECK-NEXT: 0 | char [0] zea
|
||
|
// CHECK-NEXT: 0 | struct test9::C (base)
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: 8 | char x
|
||
|
// CHECK-NEXT: | [sizeof=12, dsize=9, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=9, nvalign=4, preferrednvalign=4]
|
||
|
|
||
|
} // namespace test9
|
||
|
|
||
|
namespace test10 {
|
||
|
struct A { double x; };
|
||
|
struct B : A {};
|
||
|
|
||
|
int a = sizeof(B);
|
||
|
|
||
|
// CHECK: 0 | struct test10::B
|
||
|
// CHECK-NEXT: 0 | struct test10::A (base)
|
||
|
// CHECK-NEXT: 0 | double x
|
||
|
// CHECK-NEXT: | [sizeof=8, dsize=8, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=8, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
} // namespace test10
|
||
|
|
||
|
namespace test11 {
|
||
|
// Test how #pragma pack and align attribute interacts with AIX `power`
|
||
|
// alignment rules.
|
||
|
struct A {
|
||
|
char a;
|
||
|
double __attribute__((aligned(16))) d;
|
||
|
int i;
|
||
|
};
|
||
|
|
||
|
struct B {
|
||
|
double __attribute__((aligned(4))) d1;
|
||
|
char a;
|
||
|
double d2;
|
||
|
};
|
||
|
|
||
|
#pragma pack(2)
|
||
|
struct C {
|
||
|
int i;
|
||
|
short j;
|
||
|
double k;
|
||
|
};
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
#pragma pack(2)
|
||
|
struct D {
|
||
|
double d;
|
||
|
short j;
|
||
|
int i;
|
||
|
};
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
#pragma pack(8)
|
||
|
struct E {
|
||
|
double __attribute__((aligned(4))) d;
|
||
|
short s;
|
||
|
};
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
#pragma pack(4)
|
||
|
struct F : public D {
|
||
|
double d;
|
||
|
};
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
#pragma pack(2)
|
||
|
struct G : public E {
|
||
|
int i;
|
||
|
};
|
||
|
#pragma pack(pop)
|
||
|
|
||
|
int a = sizeof(A);
|
||
|
int b = sizeof(B);
|
||
|
int c = sizeof(C);
|
||
|
int d = sizeof(D);
|
||
|
int e = sizeof(E);
|
||
|
int f = sizeof(F);
|
||
|
int g = sizeof(G);
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test11::A
|
||
|
// CHECK-NEXT: 0 | char a
|
||
|
// CHECK-NEXT: 16 | double d
|
||
|
// CHECK-NEXT: 24 | int i
|
||
|
// CHECK-NEXT: | [sizeof=32, dsize=32, align=16, preferredalign=16,
|
||
|
// CHECK-NEXT: | nvsize=32, nvalign=16, preferrednvalign=16]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test11::B
|
||
|
// CHECK-NEXT: 0 | double d1
|
||
|
// CHECK-NEXT: 8 | char a
|
||
|
// CHECK-NEXT: 12 | double d2
|
||
|
// CHECK-NEXT: | [sizeof=24, dsize=24, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=24, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test11::C
|
||
|
// CHECK-NEXT: 0 | int i
|
||
|
// CHECK-NEXT: 4 | short j
|
||
|
// CHECK-NEXT: 6 | double k
|
||
|
// CHECK-NEXT: | [sizeof=14, dsize=14, align=2, preferredalign=2,
|
||
|
// CHECK-NEXT: | nvsize=14, nvalign=2, preferrednvalign=2]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test11::D
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: 8 | short j
|
||
|
// CHECK-NEXT: 10 | int i
|
||
|
// CHECK-NEXT: | [sizeof=14, dsize=14, align=2, preferredalign=2,
|
||
|
// CHECK-NEXT: | nvsize=14, nvalign=2, preferrednvalign=2]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test11::E
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: 8 | short s
|
||
|
// CHECK-NEXT: | [sizeof=16, dsize=16, align=4, preferredalign=8,
|
||
|
// CHECK-NEXT: | nvsize=16, nvalign=4, preferrednvalign=8]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test11::F
|
||
|
// CHECK-NEXT: 0 | struct test11::D (base)
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: 8 | short j
|
||
|
// CHECK-NEXT: 10 | int i
|
||
|
// CHECK-NEXT: 16 | double d
|
||
|
// CHECK-NEXT: | [sizeof=24, dsize=24, align=4, preferredalign=4,
|
||
|
// CHECK-NEXT: | nvsize=24, nvalign=4, preferrednvalign=4]
|
||
|
|
||
|
// CHECK: *** Dumping AST Record Layout
|
||
|
// CHECK-NEXT: 0 | struct test11::G
|
||
|
// CHECK-NEXT: 0 | struct test11::E (base)
|
||
|
// CHECK-NEXT: 0 | double d
|
||
|
// CHECK-NEXT: 8 | short s
|
||
|
// CHECK-NEXT: 16 | int i
|
||
|
// CHECK-NEXT: | [sizeof=20, dsize=20, align=2, preferredalign=2,
|
||
|
// CHECK-NEXT: | nvsize=20, nvalign=2, preferrednvalign=2]
|
||
|
|
||
|
} // namespace test11
|