123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- // RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s
- namespace Empty {
- struct A {};
- struct B { [[no_unique_address]] A a; char b; };
- static_assert(sizeof(B) == 1);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::B
- // CHECK-NEXT: 0 | struct Empty::A a (empty)
- // CHECK-NEXT: 0 | char b
- // CHECK-NEXT: | [sizeof=1, dsize=1, align=1,
- // CHECK-NEXT: | nvsize=1, nvalign=1]
- struct C {};
- struct D {
- [[no_unique_address]] A a;
- [[no_unique_address]] C c;
- char d;
- };
- static_assert(sizeof(D) == 1);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::D
- // CHECK-NEXT: 0 | struct Empty::A a (empty)
- // CHECK-NEXT: 0 | struct Empty::C c (empty)
- // CHECK-NEXT: 0 | char d
- // CHECK-NEXT: | [sizeof=1, dsize=1, align=1,
- // CHECK-NEXT: | nvsize=1, nvalign=1]
- struct E {
- [[no_unique_address]] A a1;
- [[no_unique_address]] A a2;
- char e;
- };
- static_assert(sizeof(E) == 2);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::E
- // CHECK-NEXT: 0 | struct Empty::A a1 (empty)
- // CHECK-NEXT: 1 | struct Empty::A a2 (empty)
- // CHECK-NEXT: 0 | char e
- // CHECK-NEXT: | [sizeof=2, dsize=2, align=1,
- // CHECK-NEXT: | nvsize=2, nvalign=1]
- struct F {
- ~F();
- [[no_unique_address]] A a1;
- [[no_unique_address]] A a2;
- char f;
- };
- static_assert(sizeof(F) == 2);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::F
- // CHECK-NEXT: 0 | struct Empty::A a1 (empty)
- // CHECK-NEXT: 1 | struct Empty::A a2 (empty)
- // CHECK-NEXT: 0 | char f
- // CHECK-NEXT: | [sizeof=2, dsize=1, align=1,
- // CHECK-NEXT: | nvsize=2, nvalign=1]
- struct G { [[no_unique_address]] A a; ~G(); };
- static_assert(sizeof(G) == 1);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::G
- // CHECK-NEXT: 0 | struct Empty::A a (empty)
- // CHECK-NEXT: | [sizeof=1, dsize=0, align=1,
- // CHECK-NEXT: | nvsize=1, nvalign=1]
- struct H { [[no_unique_address]] A a, b; ~H(); };
- static_assert(sizeof(H) == 2);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::H
- // CHECK-NEXT: 0 | struct Empty::A a (empty)
- // CHECK-NEXT: 1 | struct Empty::A b (empty)
- // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
- // CHECK-NEXT: | nvsize=2, nvalign=1]
- struct OversizedEmpty : A {
- ~OversizedEmpty();
- [[no_unique_address]] A a;
- };
- static_assert(sizeof(OversizedEmpty) == 2);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::OversizedEmpty
- // CHECK-NEXT: 0 | struct Empty::A (base) (empty)
- // CHECK-NEXT: 1 | struct Empty::A a (empty)
- // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
- // CHECK-NEXT: | nvsize=2, nvalign=1]
- struct HasOversizedEmpty {
- [[no_unique_address]] OversizedEmpty m;
- };
- static_assert(sizeof(HasOversizedEmpty) == 2);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::HasOversizedEmpty
- // CHECK-NEXT: 0 | struct Empty::OversizedEmpty m (empty)
- // CHECK-NEXT: 0 | struct Empty::A (base) (empty)
- // CHECK-NEXT: 1 | struct Empty::A a (empty)
- // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,
- // CHECK-NEXT: | nvsize=2, nvalign=1]
- struct EmptyWithNonzeroDSize {
- [[no_unique_address]] A a;
- int x;
- [[no_unique_address]] A b;
- int y;
- [[no_unique_address]] A c;
- };
- static_assert(sizeof(EmptyWithNonzeroDSize) == 12);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::EmptyWithNonzeroDSize
- // CHECK-NEXT: 0 | struct Empty::A a (empty)
- // CHECK-NEXT: 0 | int x
- // CHECK-NEXT: 4 | struct Empty::A b (empty)
- // CHECK-NEXT: 4 | int y
- // CHECK-NEXT: 8 | struct Empty::A c (empty)
- // CHECK-NEXT: | [sizeof=12, dsize=12, align=4,
- // CHECK-NEXT: | nvsize=12, nvalign=4]
- struct EmptyWithNonzeroDSizeNonPOD {
- ~EmptyWithNonzeroDSizeNonPOD();
- [[no_unique_address]] A a;
- int x;
- [[no_unique_address]] A b;
- int y;
- [[no_unique_address]] A c;
- };
- static_assert(sizeof(EmptyWithNonzeroDSizeNonPOD) == 12);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct Empty::EmptyWithNonzeroDSizeNonPOD
- // CHECK-NEXT: 0 | struct Empty::A a (empty)
- // CHECK-NEXT: 0 | int x
- // CHECK-NEXT: 4 | struct Empty::A b (empty)
- // CHECK-NEXT: 4 | int y
- // CHECK-NEXT: 8 | struct Empty::A c (empty)
- // CHECK-NEXT: | [sizeof=12, dsize=8, align=4,
- // CHECK-NEXT: | nvsize=9, nvalign=4]
- }
- namespace POD {
- // Cannot reuse tail padding of a PDO type.
- struct A { int n; char c[3]; };
- struct B { [[no_unique_address]] A a; char d; };
- static_assert(sizeof(B) == 12);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct POD::B
- // CHECK-NEXT: 0 | struct POD::A a
- // CHECK-NEXT: 0 | int n
- // CHECK-NEXT: 4 | char [3] c
- // CHECK-NEXT: 8 | char d
- // CHECK-NEXT: | [sizeof=12, dsize=12, align=4,
- // CHECK-NEXT: | nvsize=12, nvalign=4]
- }
- namespace NonPOD {
- struct A { int n; char c[3]; ~A(); };
- struct B { [[no_unique_address]] A a; char d; };
- static_assert(sizeof(B) == 8);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct NonPOD::B
- // CHECK-NEXT: 0 | struct NonPOD::A a
- // CHECK-NEXT: 0 | int n
- // CHECK-NEXT: 4 | char [3] c
- // CHECK-NEXT: 7 | char d
- // CHECK-NEXT: | [sizeof=8, dsize=8, align=4,
- // CHECK-NEXT: | nvsize=8, nvalign=4]
- }
- namespace NVSizeGreaterThanDSize {
- // The nvsize of an object includes the complete size of its empty subobjects
- // (although it's unclear why). Ensure this corner case is handled properly.
- struct alignas(8) A { ~A(); }; // dsize 0, nvsize 0, size 8
- struct B : A { char c; }; // dsize 1, nvsize 8, size 8
- static_assert(sizeof(B) == 8);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct NVSizeGreaterThanDSize::B
- // CHECK-NEXT: 0 | struct NVSizeGreaterThanDSize::A (base) (empty)
- // CHECK-NEXT: 0 | char c
- // CHECK-NEXT: | [sizeof=8, dsize=1, align=8,
- // CHECK-NEXT: | nvsize=8, nvalign=8]
- struct V { int n; };
- // V is at offset 16, not offset 12, because B's tail padding is strangely not
- // usable for virtual bases.
- struct C : B, virtual V {};
- static_assert(sizeof(C) == 24);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct NVSizeGreaterThanDSize::C
- // CHECK-NEXT: 0 | (C vtable pointer)
- // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::B (base)
- // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A (base) (empty)
- // CHECK-NEXT: 8 | char c
- // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::V (virtual base)
- // CHECK-NEXT: 16 | int n
- // CHECK-NEXT: | [sizeof=24, dsize=20, align=8,
- // CHECK-NEXT: | nvsize=16, nvalign=8]
- struct D : virtual V {
- [[no_unique_address]] B b;
- };
- static_assert(sizeof(D) == 24);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct NVSizeGreaterThanDSize::D
- // CHECK-NEXT: 0 | (D vtable pointer)
- // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::B b
- // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A (base) (empty)
- // CHECK-NEXT: 8 | char c
- // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::V (virtual base)
- // CHECK-NEXT: 16 | int n
- // CHECK-NEXT: | [sizeof=24, dsize=20, align=8,
- // CHECK-NEXT: | nvsize=16, nvalign=8]
- struct X : virtual A { [[no_unique_address]] A a; };
- struct E : virtual A {
- [[no_unique_address]] A a;
- // Here, we arrange for X to hang over the end of the nvsize of E. This
- // should force the A vbase to be laid out at offset 24, not 16.
- [[no_unique_address]] X x;
- };
- static_assert(sizeof(E) == 32);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct NVSizeGreaterThanDSize::E
- // CHECK-NEXT: 0 | (E vtable pointer)
- // CHECK-NEXT: 0 | struct NVSizeGreaterThanDSize::A a (empty)
- // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::X x
- // CHECK-NEXT: 8 | (X vtable pointer)
- // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A a (empty)
- // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::A (virtual base) (empty)
- // CHECK-NEXT: 24 | struct NVSizeGreaterThanDSize::A (virtual base) (empty)
- // CHECK-NEXT: | [sizeof=32, dsize=16, align=8,
- // CHECK-NEXT: | nvsize=16, nvalign=8]
- }
- namespace RepeatedVBase {
- struct alignas(16) A { ~A(); };
- struct B : A {};
- struct X : virtual A, virtual B {};
- struct Y { [[no_unique_address]] X x; char c; };
- static_assert(sizeof(Y) == 32);
- // CHECK:*** Dumping AST Record Layout
- // CHECK: 0 | struct RepeatedVBase::Y
- // CHECK-NEXT: 0 | struct RepeatedVBase::X x
- // CHECK-NEXT: 0 | (X vtable pointer)
- // CHECK-NEXT: 0 | struct RepeatedVBase::A (virtual base) (empty)
- // CHECK-NEXT: 16 | struct RepeatedVBase::B (virtual base) (empty)
- // CHECK-NEXT: 16 | struct RepeatedVBase::A (base) (empty)
- // CHECK-NEXT: 8 | char c
- // CHECK-NEXT: | [sizeof=32, dsize=9, align=16,
- // CHECK-NEXT: | nvsize=9, nvalign=16]
- }
|