266 lines · cpp
1// RUN: %clang_cc1 -std=c++2a -fsyntax-only -triple x86_64-linux-gnu -fdump-record-layouts %s | FileCheck %s2 3namespace Empty {4 struct A {};5 struct B { [[no_unique_address]] A a; char b; };6 static_assert(sizeof(B) == 1);7 8 // CHECK:*** Dumping AST Record Layout9 // CHECK: 0 | struct Empty::B10 // CHECK-NEXT: 0 | struct Empty::A a (empty)11 // CHECK-NEXT: 0 | char b12 // CHECK-NEXT: | [sizeof=1, dsize=1, align=1,13 // CHECK-NEXT: | nvsize=1, nvalign=1]14 15 struct C {};16 struct D {17 [[no_unique_address]] A a;18 [[no_unique_address]] C c;19 char d;20 };21 static_assert(sizeof(D) == 1);22 23 // CHECK:*** Dumping AST Record Layout24 // CHECK: 0 | struct Empty::D25 // CHECK-NEXT: 0 | struct Empty::A a (empty)26 // CHECK-NEXT: 0 | struct Empty::C c (empty)27 // CHECK-NEXT: 0 | char d28 // CHECK-NEXT: | [sizeof=1, dsize=1, align=1,29 // CHECK-NEXT: | nvsize=1, nvalign=1]30 31 struct E {32 [[no_unique_address]] A a1;33 [[no_unique_address]] A a2;34 char e;35 };36 static_assert(sizeof(E) == 2);37 38 // CHECK:*** Dumping AST Record Layout39 // CHECK: 0 | struct Empty::E40 // CHECK-NEXT: 0 | struct Empty::A a1 (empty)41 // CHECK-NEXT: 1 | struct Empty::A a2 (empty)42 // CHECK-NEXT: 0 | char e43 // CHECK-NEXT: | [sizeof=2, dsize=2, align=1,44 // CHECK-NEXT: | nvsize=2, nvalign=1]45 46 struct F {47 ~F();48 [[no_unique_address]] A a1;49 [[no_unique_address]] A a2;50 char f;51 };52 static_assert(sizeof(F) == 2);53 54 // CHECK:*** Dumping AST Record Layout55 // CHECK: 0 | struct Empty::F56 // CHECK-NEXT: 0 | struct Empty::A a1 (empty)57 // CHECK-NEXT: 1 | struct Empty::A a2 (empty)58 // CHECK-NEXT: 0 | char f59 // CHECK-NEXT: | [sizeof=2, dsize=1, align=1,60 // CHECK-NEXT: | nvsize=2, nvalign=1]61 62 struct G { [[no_unique_address]] A a; ~G(); };63 static_assert(sizeof(G) == 1);64 65 // CHECK:*** Dumping AST Record Layout66 // CHECK: 0 | struct Empty::G67 // CHECK-NEXT: 0 | struct Empty::A a (empty)68 // CHECK-NEXT: | [sizeof=1, dsize=0, align=1,69 // CHECK-NEXT: | nvsize=1, nvalign=1]70 71 struct H { [[no_unique_address]] A a, b; ~H(); };72 static_assert(sizeof(H) == 2);73 74 // CHECK:*** Dumping AST Record Layout75 // CHECK: 0 | struct Empty::H76 // CHECK-NEXT: 0 | struct Empty::A a (empty)77 // CHECK-NEXT: 1 | struct Empty::A b (empty)78 // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,79 // CHECK-NEXT: | nvsize=2, nvalign=1]80 81 struct OversizedEmpty : A {82 ~OversizedEmpty();83 [[no_unique_address]] A a;84 };85 static_assert(sizeof(OversizedEmpty) == 2);86 87 // CHECK:*** Dumping AST Record Layout88 // CHECK: 0 | struct Empty::OversizedEmpty89 // CHECK-NEXT: 0 | struct Empty::A (base) (empty)90 // CHECK-NEXT: 1 | struct Empty::A a (empty)91 // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,92 // CHECK-NEXT: | nvsize=2, nvalign=1]93 94 struct HasOversizedEmpty {95 [[no_unique_address]] OversizedEmpty m;96 };97 static_assert(sizeof(HasOversizedEmpty) == 2);98 99 // CHECK:*** Dumping AST Record Layout100 // CHECK: 0 | struct Empty::HasOversizedEmpty101 // CHECK-NEXT: 0 | struct Empty::OversizedEmpty m (empty)102 // CHECK-NEXT: 0 | struct Empty::A (base) (empty)103 // CHECK-NEXT: 1 | struct Empty::A a (empty)104 // CHECK-NEXT: | [sizeof=2, dsize=0, align=1,105 // CHECK-NEXT: | nvsize=2, nvalign=1]106 107 struct EmptyWithNonzeroDSize {108 [[no_unique_address]] A a;109 int x;110 [[no_unique_address]] A b;111 int y;112 [[no_unique_address]] A c;113 };114 static_assert(sizeof(EmptyWithNonzeroDSize) == 12);115 116 // CHECK:*** Dumping AST Record Layout117 // CHECK: 0 | struct Empty::EmptyWithNonzeroDSize118 // CHECK-NEXT: 0 | struct Empty::A a (empty)119 // CHECK-NEXT: 0 | int x120 // CHECK-NEXT: 4 | struct Empty::A b (empty)121 // CHECK-NEXT: 4 | int y122 // CHECK-NEXT: 8 | struct Empty::A c (empty)123 // CHECK-NEXT: | [sizeof=12, dsize=12, align=4,124 // CHECK-NEXT: | nvsize=12, nvalign=4]125 126 struct EmptyWithNonzeroDSizeNonPOD {127 ~EmptyWithNonzeroDSizeNonPOD();128 [[no_unique_address]] A a;129 int x;130 [[no_unique_address]] A b;131 int y;132 [[no_unique_address]] A c;133 };134 static_assert(sizeof(EmptyWithNonzeroDSizeNonPOD) == 12);135 136 // CHECK:*** Dumping AST Record Layout137 // CHECK: 0 | struct Empty::EmptyWithNonzeroDSizeNonPOD138 // CHECK-NEXT: 0 | struct Empty::A a (empty)139 // CHECK-NEXT: 0 | int x140 // CHECK-NEXT: 4 | struct Empty::A b (empty)141 // CHECK-NEXT: 4 | int y142 // CHECK-NEXT: 8 | struct Empty::A c (empty)143 // CHECK-NEXT: | [sizeof=12, dsize=8, align=4,144 // CHECK-NEXT: | nvsize=9, nvalign=4]145}146 147namespace POD {148 // Cannot reuse tail padding of a PDO type.149 struct A { int n; char c[3]; };150 struct B { [[no_unique_address]] A a; char d; };151 static_assert(sizeof(B) == 12);152 153 // CHECK:*** Dumping AST Record Layout154 // CHECK: 0 | struct POD::B155 // CHECK-NEXT: 0 | struct POD::A a156 // CHECK-NEXT: 0 | int n157 // CHECK-NEXT: 4 | char[3] c158 // CHECK-NEXT: 8 | char d159 // CHECK-NEXT: | [sizeof=12, dsize=12, align=4,160 // CHECK-NEXT: | nvsize=12, nvalign=4]161}162 163namespace NonPOD {164 struct A { int n; char c[3]; ~A(); };165 struct B { [[no_unique_address]] A a; char d; };166 static_assert(sizeof(B) == 8);167 168 // CHECK:*** Dumping AST Record Layout169 // CHECK: 0 | struct NonPOD::B170 // CHECK-NEXT: 0 | struct NonPOD::A a171 // CHECK-NEXT: 0 | int n172 // CHECK-NEXT: 4 | char[3] c173 // CHECK-NEXT: 7 | char d174 // CHECK-NEXT: | [sizeof=8, dsize=8, align=4,175 // CHECK-NEXT: | nvsize=8, nvalign=4]176}177 178namespace NVSizeGreaterThanDSize {179 // The nvsize of an object includes the complete size of its empty subobjects180 // (although it's unclear why). Ensure this corner case is handled properly.181 struct alignas(8) A { ~A(); }; // dsize 0, nvsize 0, size 8182 struct B : A { char c; }; // dsize 1, nvsize 8, size 8183 static_assert(sizeof(B) == 8);184 185 // CHECK:*** Dumping AST Record Layout186 // CHECK: 0 | struct NVSizeGreaterThanDSize::B187 // CHECK-NEXT: 0 | struct NVSizeGreaterThanDSize::A (base) (empty)188 // CHECK-NEXT: 0 | char c189 // CHECK-NEXT: | [sizeof=8, dsize=1, align=8,190 // CHECK-NEXT: | nvsize=8, nvalign=8]191 192 struct V { int n; };193 194 // V is at offset 16, not offset 12, because B's tail padding is strangely not195 // usable for virtual bases.196 struct C : B, virtual V {};197 static_assert(sizeof(C) == 24);198 199 // CHECK:*** Dumping AST Record Layout200 // CHECK: 0 | struct NVSizeGreaterThanDSize::C201 // CHECK-NEXT: 0 | (C vtable pointer)202 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::B (base)203 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A (base) (empty)204 // CHECK-NEXT: 8 | char c205 // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::V (virtual base)206 // CHECK-NEXT: 16 | int n207 // CHECK-NEXT: | [sizeof=24, dsize=20, align=8,208 // CHECK-NEXT: | nvsize=16, nvalign=8]209 210 struct D : virtual V {211 [[no_unique_address]] B b;212 };213 static_assert(sizeof(D) == 24);214 215 // CHECK:*** Dumping AST Record Layout216 // CHECK: 0 | struct NVSizeGreaterThanDSize::D217 // CHECK-NEXT: 0 | (D vtable pointer)218 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::B b219 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A (base) (empty)220 // CHECK-NEXT: 8 | char c221 // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::V (virtual base)222 // CHECK-NEXT: 16 | int n223 // CHECK-NEXT: | [sizeof=24, dsize=20, align=8,224 // CHECK-NEXT: | nvsize=16, nvalign=8]225 226 struct X : virtual A { [[no_unique_address]] A a; };227 struct E : virtual A {228 [[no_unique_address]] A a;229 // Here, we arrange for X to hang over the end of the nvsize of E. This230 // should force the A vbase to be laid out at offset 24, not 16.231 [[no_unique_address]] X x;232 };233 static_assert(sizeof(E) == 32);234 235 // CHECK:*** Dumping AST Record Layout236 // CHECK: 0 | struct NVSizeGreaterThanDSize::E237 // CHECK-NEXT: 0 | (E vtable pointer)238 // CHECK-NEXT: 0 | struct NVSizeGreaterThanDSize::A a (empty)239 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::X x240 // CHECK-NEXT: 8 | (X vtable pointer)241 // CHECK-NEXT: 8 | struct NVSizeGreaterThanDSize::A a (empty)242 // CHECK-NEXT: 16 | struct NVSizeGreaterThanDSize::A (virtual base) (empty)243 // CHECK-NEXT: 24 | struct NVSizeGreaterThanDSize::A (virtual base) (empty)244 // CHECK-NEXT: | [sizeof=32, dsize=16, align=8,245 // CHECK-NEXT: | nvsize=16, nvalign=8]246}247 248namespace RepeatedVBase {249 struct alignas(16) A { ~A(); };250 struct B : A {};251 struct X : virtual A, virtual B {};252 struct Y { [[no_unique_address]] X x; char c; };253 static_assert(sizeof(Y) == 32);254 255 // CHECK:*** Dumping AST Record Layout256 // CHECK: 0 | struct RepeatedVBase::Y257 // CHECK-NEXT: 0 | struct RepeatedVBase::X x258 // CHECK-NEXT: 0 | (X vtable pointer)259 // CHECK-NEXT: 0 | struct RepeatedVBase::A (virtual base) (empty)260 // CHECK-NEXT: 16 | struct RepeatedVBase::B (virtual base) (empty)261 // CHECK-NEXT: 16 | struct RepeatedVBase::A (base) (empty)262 // CHECK-NEXT: 8 | char c263 // CHECK-NEXT: | [sizeof=32, dsize=9, align=16,264 // CHECK-NEXT: | nvsize=9, nvalign=16]265}266