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

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/tagged-union-member-count.cpp