1 | // RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t |
2 | |
3 | typedef enum Tags3 { |
4 | tags3_1, |
5 | tags3_2, |
6 | tags3_3, |
7 | } Tags3; |
8 | |
9 | typedef enum Tags4 { |
10 | tags4_1, |
11 | tags4_2, |
12 | tags4_3, |
13 | tags4_4, |
14 | } Tags4; |
15 | |
16 | enum class Classtags3 { |
17 | classtags3_1, |
18 | classtags3_2, |
19 | classtags3_3, |
20 | }; |
21 | |
22 | enum class Typedtags3 : unsigned int { |
23 | typedtags3_1, |
24 | typedtags3_2, |
25 | typedtags3_3, |
26 | }; |
27 | |
28 | typedef union Union3 { |
29 | short *Shorts; |
30 | int *Ints; |
31 | float *Floats; |
32 | } Union3; |
33 | |
34 | typedef union Union4 { |
35 | short *Shorts; |
36 | double *Doubles; |
37 | int *Ints; |
38 | float *Floats; |
39 | } Union4; |
40 | |
41 | // It is not obvious which enum is the tag for the union. |
42 | class MaybeTaggedUnion1 { // No warnings expected. |
43 | enum Tags3 TagA; |
44 | enum Tags4 TagB; |
45 | union Union4 Data; |
46 | }; |
47 | |
48 | // It is not obvious which union does the tag belong to. |
49 | class MaybeTaggedUnion2 { // No warnings expected. |
50 | enum Tags3 Tag; |
51 | union Union3 DataB; |
52 | union Union3 DataA; |
53 | }; |
54 | |
55 | // It is not obvious which union does the tag belong to. |
56 | class MaybeTaggedUnion3 { // No warnings expected. |
57 | enum Tags3 Tag; |
58 | union { |
59 | int I1; |
60 | int I2; |
61 | int I3; |
62 | }; |
63 | union { |
64 | float F1; |
65 | float F2; |
66 | float F3; |
67 | }; |
68 | }; |
69 | |
70 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
71 | class TaggedUnionClassPredefinedTagAndPredefinedUnion { |
72 | enum Tags3 Tag; |
73 | union Union4 Data; |
74 | }; |
75 | |
76 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
77 | class TaggedUnionClassPredefinedTagAndInlineUnion { |
78 | enum Tags3 Tag; |
79 | union { |
80 | int *Ints; |
81 | char Characters[13]; |
82 | class { |
83 | double Re; |
84 | double Im; |
85 | } Complex; |
86 | long L; |
87 | } Data; |
88 | }; |
89 | |
90 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
91 | class TaggedUnionClassInlineTagAndPredefinedUnion { |
92 | enum { |
93 | tag1, |
94 | tag2, |
95 | tag3, |
96 | } Tag; |
97 | union Union4 Data; |
98 | }; |
99 | |
100 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
101 | class TaggedUnionClassInlineTagAndInlineUnion { |
102 | enum { |
103 | tag1, |
104 | tag2, |
105 | tag3, |
106 | } Tag; |
107 | union { |
108 | int *Ints; |
109 | char Characters[13]; |
110 | class { |
111 | double Re; |
112 | double Im; |
113 | } Complex; |
114 | long L; |
115 | } Data; |
116 | }; |
117 | |
118 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
119 | class TaggedUnionClassWithNestedTaggedUnionClass { |
120 | enum Tags3 Tag; |
121 | union { |
122 | float F; |
123 | int I; |
124 | long L; |
125 | // CHECK-MESSAGES: :[[@LINE+1]]:11: warning: tagged union has more data members (4) than tags (3) |
126 | class Innerdecl { |
127 | enum Tags3 Tag; |
128 | union Union4 Data; |
129 | } Inner; |
130 | } Data; |
131 | }; |
132 | |
133 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
134 | class TaggedUnionClassWithTypedefedTag { |
135 | Tags3 Tag; |
136 | Union4 Data; |
137 | }; |
138 | |
139 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
140 | struct TaggedUnionStructWithEnumClass { |
141 | enum Classtags3 Tag; |
142 | Union4 Data; |
143 | }; |
144 | |
145 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
146 | class TaggedUnionClasswithEnumClass { |
147 | enum Classtags3 Tag; |
148 | Union4 Data; |
149 | }; |
150 | |
151 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
152 | struct TaggedUnionStructWithTypedEnum { |
153 | Typedtags3 Tag; |
154 | Union4 Data; |
155 | }; |
156 | |
157 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
158 | class TaggedUnionClassWithTypedEnum { |
159 | Typedtags3 Tag; |
160 | Union4 Data; |
161 | }; |
162 | |
163 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
164 | struct AnonymousTaggedUnionStruct { |
165 | Tags3 Tag; |
166 | union { |
167 | char A; |
168 | short B; |
169 | int C; |
170 | long D; |
171 | }; |
172 | }; |
173 | |
174 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
175 | class TaggedUnionClassWithAnonymousUnion { |
176 | Tags3 Tag; |
177 | union { |
178 | char A; |
179 | short B; |
180 | int C; |
181 | long D; |
182 | }; |
183 | }; |
184 | |
185 | namespace testnamespace { |
186 | |
187 | enum Tags3 { |
188 | tags3_1, |
189 | tags3_2, |
190 | tags3_3, |
191 | }; |
192 | |
193 | union Union4 { |
194 | short *Shorts; |
195 | double *Doubles; |
196 | int *Ints; |
197 | float *Floats; |
198 | }; |
199 | |
200 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
201 | struct TaggedUnionStructInNamespace { |
202 | Tags3 Tags; |
203 | Union4 Data; |
204 | }; |
205 | |
206 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
207 | class TaggedUnionClassInNamespace { |
208 | Tags3 Tags; |
209 | Union4 Data; |
210 | }; |
211 | |
212 | } // namespace testnamespace |
213 | |
214 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
215 | struct TaggedUnionStructWithNamespacedTagAndUnion { |
216 | testnamespace::Tags3 Tags; |
217 | testnamespace::Union4 Data; |
218 | }; |
219 | |
220 | // CHECK-MESSAGES: :[[@LINE+1]]:7: warning: tagged union has more data members (4) than tags (3) |
221 | class TaggedUnionClassWithNamespacedTagAndUnion { |
222 | testnamespace::Tags3 Tags; |
223 | testnamespace::Union4 Data; |
224 | }; |
225 | |
226 | // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3) |
227 | template <typename Tag, typename Union> |
228 | struct TemplatedStructWithNamespacedTagAndUnion { |
229 | Tag Kind; |
230 | Union Data; |
231 | }; |
232 | |
233 | TemplatedStructWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedStruct3; |
234 | |
235 | // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3) |
236 | template <typename Tag, typename Union> |
237 | class TemplatedClassWithNamespacedTagAndUnion { |
238 | Tag Kind; |
239 | Union Data; |
240 | }; |
241 | |
242 | TemplatedClassWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedClass3; |
243 | |
244 | // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3) |
245 | template <typename Tag, typename Union> |
246 | struct TemplatedStruct { |
247 | Tag Kind; |
248 | Union Data; |
249 | }; |
250 | |
251 | TemplatedStruct<Tags3, Union3> TemplatedStruct1; // No warning expected |
252 | TemplatedStruct<Tags3, Union4> TemplatedStruct2; |
253 | |
254 | // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3) |
255 | template <typename Tag, typename Union> |
256 | class TemplatedClass { |
257 | Tag Kind; |
258 | Union Data; |
259 | }; |
260 | |
261 | TemplatedClass<Tags3, Union3> TemplatedClass1; // No warning expected |
262 | TemplatedClass<Tags3, Union4> TemplatedClass2; |
263 | |
264 | // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3) |
265 | template <typename T> |
266 | struct TemplatedStructButTaggedUnionPartIsNotTemplated { |
267 | Tags3 Kind; |
268 | Union4 Data; |
269 | T SomethingElse; |
270 | }; |
271 | |
272 | // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3) |
273 | template <typename T> |
274 | class TemplatedClassButTaggedUnionPartIsNotTemplated { |
275 | Tags3 Kind; |
276 | Union4 Data; |
277 | T SomethingElse; |
278 | }; |
279 | |
280 | #define DECLARE_TAGGED_UNION_STRUCT(Tag, Union, Name)\ |
281 | struct Name {\ |
282 | Tag Kind;\ |
283 | Union Data;\ |
284 | } |
285 | |
286 | // CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3) |
287 | DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro); |
288 | |
289 | #define DECLARE_TAGGED_UNION_CLASS(Tag, Union, Name)\ |
290 | class Name {\ |
291 | Tag Kind;\ |
292 | Union Data;\ |
293 | } |
294 | |
295 | // CHECK-MESSAGES: :[[@LINE+1]]:43: warning: tagged union has more data members (4) than tags (3) |
296 | DECLARE_TAGGED_UNION_CLASS(Tags3, Union4, TaggedUnionClassFromMacro); |
297 | |
298 | // Lambdas implicitly compile down to an unnamed CXXRecordDecl and if they have captures, |
299 | // then those become unnamed fields. |
300 | void DoNotMatchLambdas() { |
301 | enum { |
302 | A |
303 | } e; |
304 | union { |
305 | long A; |
306 | char B; |
307 | } u; |
308 | auto L = [e, u] () {}; |
309 | } |
310 | |