xref: /llvm-project/clang/test/CodeGenCXX/no-unique-address-3.cpp (revision af6c0b6d8c9dc52485d56e82f79a03de09aa188f)
1 // RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm -fdump-record-layouts -std=c++17 %s -o %t | FileCheck %s
2 
3 // CHECK-LABEL:          0 | class Empty (empty)
4 // CHECK-NEXT:             | [sizeof=1, dsize=1, align=1,
5 // CHECK-NEXT:             |  nvsize=1, nvalign=1]
6 // CHECK-LABEL:          0 | class Second
7 // CHECK-NEXT:           0 |   class Empty (base) (empty)
8 // CHECK-NEXT:       0:0-0 |   short A
9 // CHECK-NEXT:             | [sizeof=2, dsize=1, align=2,
10 // CHECK-NEXT:             |  nvsize=1, nvalign=2]
11 // CHECK-LABEL:          0 | class Foo
12 // CHECK-NEXT:           0 |   class Empty (base) (empty)
13 // CHECK-NEXT:           2 |   class Second NZNoUnique
14 // CHECK-NEXT:           2 |     class Empty (base) (empty)
15 // CHECK-NEXT:       2:0-0 |     short A
16 // CHECK-NEXT:           3 |   char B
17 // CHECK-NEXT:             | [sizeof=4, dsize=4, align=2,
18 // CHECK-NEXT:             |  nvsize=4, nvalign=2]
19 
20 class Empty {};
21 
22 // CHECK-LABEL: LLVMType:%class.Second = type { i8, i8 }
23 // CHECK-NEXT:  NonVirtualBaseLLVMType:%class.Second.base = type { i8 }
24 class Second : Empty {
25   short A : 1;
26 };
27 
28 // CHECK-LABEL:   LLVMType:%class.Foo = type { [2 x i8], %class.Second.base, i8 }
29 // CHECK-NEXT:    NonVirtualBaseLLVMType:%class.Foo = type { [2 x i8], %class.Second.base, i8 }
30 class Foo : Empty {
31   [[no_unique_address]] Second NZNoUnique;
32   char B;
33 };
34 Foo I;
35 
36 // CHECK-LABEL:          0 | class SecondEmpty (empty)
37 // CHECK-NEXT:           0 |   class Empty (base) (empty)
38 // CHECK-NEXT:             | [sizeof=1, dsize=0, align=1,
39 // CHECK-NEXT:             |  nvsize=1, nvalign=1]
40 class SecondEmpty: Empty {
41 };
42 
43 // CHECK-LABEL:          0 | class Bar
44 // CHECK-NEXT:           0 |   class Empty (base) (empty)
45 // CHECK-NEXT:           1 |   class SecondEmpty ZNoUnique (empty)
46 // CHECK-NEXT:           1 |     class Empty (base) (empty)
47 // CHECK-NEXT:           0 |   char C
48 // CHECK-NEXT:             | [sizeof=2, dsize=1, align=1,
49 // CHECK-NEXT:             |  nvsize=2, nvalign=1]
50 
51 // CHECK-LABEL:  LLVMType:%class.Bar = type { i8, i8 }
52 // CHECK-NEXT:   NonVirtualBaseLLVMType:%class.Bar = type { i8, i8 }
53 class Bar : Empty {
54   [[no_unique_address]] SecondEmpty ZNoUnique;
55   char C;
56 };
57 Bar J;
58 
59 // CHECK-LABEL:          0 | class IntFieldClass
60 // CHECK-NEXT:           0 |   class Empty (base) (empty)
61 // CHECK-NEXT:           2 |   class Second Field
62 // CHECK-NEXT:           2 |     class Empty (base) (empty)
63 // CHECK-NEXT:       2:0-0 |     short A
64 // CHECK-NEXT:           4 |   int C
65 // CHECK-NEXT:             | [sizeof=8, dsize=8, align=4,
66 // CHECK-NEXT:             |  nvsize=8, nvalign=4]
67 
68 // CHECK-LABEL:   LLVMType:%class.IntFieldClass = type { [2 x i8], %class.Second.base, i32 }
69 // CHECK-NEXT:    NonVirtualBaseLLVMType:%class.IntFieldClass = type { [2 x i8], %class.Second.base, i32 }
70 class IntFieldClass : Empty {
71   [[no_unique_address]] Second Field;
72   int C;
73 };
74 IntFieldClass K;
75 
76 // CHECK-LABEL:         0 | class UnionClass
77 // CHECK-NEXT:          0 |   class Empty (base) (empty)
78 // CHECK-NEXT:          0 |   union UnionClass
79 // CHECK-NEXT:          0 |     int I
80 // CHECK-NEXT:          0 |     char C
81 // CHECK-NEXT:          4 |   int C
82 // CHECK-NEXT:            | [sizeof=8, dsize=8, align=4,
83 // CHECK-NEXT:            |  nvsize=8, nvalign=4]
84 
85 // CHECK-LABEL:  LLVMType:%class.UnionClass = type { %union.anon, i32 }
86 // CHECK-NEXT:   NonVirtualBaseLLVMType:%class.UnionClass = type { %union.anon, i32 }
87 // CHECK-NEXT:   IsZeroInitializable:1
88 // CHECK-NEXT:   BitFields:[
89 // CHECK-NEXT: ]>
90 class UnionClass : Empty {
91   [[no_unique_address]] union {
92     int I;
93     char C;
94   } U;
95   int C;
96 };
97 UnionClass L;
98 
99 // CHECK-LABEL:         0 | class EnumClass
100 // CHECK-NEXT:          0 |   class Empty (base) (empty)
101 // CHECK-NEXT:          0 |   enum E A
102 // CHECK-NEXT:          4 |   int C
103 // CHECK-NEXT:            | [sizeof=8, dsize=8, align=4,
104 // CHECK-NEXT:            |  nvsize=8, nvalign=4]
105 
106 // CHECK-LABEL:  LLVMType:%class.EnumClass = type { i32, i32 }
107 // CHECK-NEXT:   NonVirtualBaseLLVMType:%class.EnumClass = type { i32, i32 }
108 // CHECK-NEXT:   IsZeroInitializable:1
109 // CHECK-NEXT:   BitFields:[
110 // CHECK-NEXT: ]>
111 class EnumClass : Empty {
112   [[no_unique_address]] enum class E { X, Y, Z } A;
113   int C;
114 };
115 EnumClass M;
116 
117 // CHECK-LABEL:         0 | class NoBaseField
118 // CHECK-NEXT:          0 |   class Empty (base) (empty)
119 // CHECK-NEXT:          1 |   class Empty A (empty)
120 // CHECK-NEXT:          0 |   int B
121 // CHECK-NEXT:            | [sizeof=4, dsize=4, align=4,
122 // CHECK-NEXT:            |  nvsize=4, nvalign=4]
123 
124 // CHECK-LABEL:  LLVMType:%class.NoBaseField = type { i32 }
125 // CHECK-NEXT:   NonVirtualBaseLLVMType:%class.NoBaseField = type { i32 }
126 // CHECK-NEXT:   IsZeroInitializable:1
127 // CHECK-NEXT:   BitFields:[
128 // CHECK-NEXT: ]>
129 class NoBaseField : Empty {
130   [[no_unique_address]] Empty A;
131   int B;
132 };
133 NoBaseField N;
134 
135 // CHECK-LABEL:        0 | class FinalEmpty (empty)
136 // CHECK-NEXT:           | [sizeof=1, dsize=1, align=1,
137 // CHECK-NEXT:           |  nvsize=1, nvalign=1]
138 
139 // CHECK-LABEL:        0 | class FinalClass
140 // CHECK-NEXT:         0 |   class Empty (base) (empty)
141 // CHECK-NEXT:         0 |   class FinalEmpty A (empty)
142 // CHECK-NEXT:         0 |   int B
143 // CHECK-NEXT:           | [sizeof=4, dsize=4, align=4,
144 // CHECK-NEXT:           |  nvsize=4, nvalign=4]
145 class FinalEmpty final {};
146 class FinalClass final : Empty {
147   [[no_unique_address]] FinalEmpty A;
148   int B;
149 } O;
150 
151 
152 // CHECK-LABEL:        0 | union Union2Class::PaddedUnion
153 // CHECK-NEXT:         0 |   class Empty A (empty)
154 // CHECK-NEXT:         0 |   char B
155 // CHECK-NEXT:           | [sizeof=2, dsize=1, align=2,
156 // CHECK-NEXT:           |  nvsize=1, nvalign=2]
157 
158 // CHECK-LABEL:        0 | class Union2Class
159 // CHECK-NEXT:         0 |   class Empty (base) (empty)
160 // CHECK-NEXT:         2 |   union Union2Class::PaddedUnion U
161 // CHECK-NEXT:         2 |     class Empty A (empty)
162 // CHECK-NEXT:         2 |     char B
163 // CHECK-NEXT:         3 |   char C
164 // CHECK-NEXT:           | [sizeof=4, dsize=4, align=2,
165 // CHECK-NEXT:           |  nvsize=4, nvalign=2]
166 class Union2Class : Empty {
167   [[no_unique_address]] union PaddedUnion {
168   private:
169     Empty A;
170     alignas(2) char B;
171   } U;
172   char C;
173 } P;
174 
175 // CHECK-LABEL:          0 | struct NotEmptyWithBitfield
176 // CHECK-NEXT:           0 |   class Empty (base) (empty)
177 // CHECK-NEXT:           0 |   char[2] A
178 // CHECK-NEXT:       2:0-0 |   int B
179 // CHECK-NEXT:             | [sizeof=4, dsize=3, align=4,
180 // CHECK-NEXT:             |  nvsize=3, nvalign=4]
181 
182 // CHECK-LABEL:          0 | union C::
183 // CHECK-NEXT:           0 |   short C
184 // CHECK-NEXT:           0 |   struct NotEmptyWithBitfield A
185 // CHECK-NEXT:           0 |     class Empty (base) (empty)
186 // CHECK-NEXT:           0 |     char[2] A
187 // CHECK-NEXT:       2:0-0 |     int B
188 // CHECK-NEXT:             | [sizeof=4, dsize=3, align=4,
189 // CHECK-NEXT:             |  nvsize=3, nvalign=4]
190 
191 // CHECK-LABEL:          0 | struct C
192 // CHECK-NEXT:           0 |   union C::
193 // CHECK-NEXT:           0 |     short C
194 // CHECK-NEXT:           0 |     struct NotEmptyWithBitfield A
195 // CHECK-NEXT:           0 |       class Empty (base) (empty)
196 // CHECK-NEXT:           0 |       char[2] A
197 // CHECK-NEXT:       2:0-0 |       int B
198 // CHECK-NEXT:             | [sizeof=4, dsize=3, align=4,
199 // CHECK-NEXT:             |  nvsize=3, nvalign=4]
200 struct NotEmptyWithBitfield : Empty {
201   char A[2];
202   int B : 1;
203 };
204 struct C {
205   [[no_unique_address]] union {
206     short C;
207     [[no_unique_address]] NotEmptyWithBitfield A;
208   } U;
209 } Q;
210