1// RUN: %check_clang_tidy %s bugprone-tagged-union-member-count %t
2
3typedef enum Tags3 {
4 tags3_1,
5 tags3_2,
6 tags3_3,
7} Tags3;
8
9typedef enum Tags4 {
10 tags4_1,
11 tags4_2,
12 tags4_3,
13 tags4_4,
14} Tags4;
15
16enum class Classtags3 {
17 classtags3_1,
18 classtags3_2,
19 classtags3_3,
20};
21
22enum class Typedtags3 : unsigned int {
23 typedtags3_1,
24 typedtags3_2,
25 typedtags3_3,
26};
27
28typedef union Union3 {
29 short *Shorts;
30 int *Ints;
31 float *Floats;
32} Union3;
33
34typedef 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.
42class 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.
49class 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.
56class 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)
71class 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)
77class 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)
91class 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)
101class 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)
119class 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)
134class 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)
140struct 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)
146class 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)
152struct 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)
158class 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)
164struct 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)
175class TaggedUnionClassWithAnonymousUnion {
176 Tags3 Tag;
177 union {
178 char A;
179 short B;
180 int C;
181 long D;
182 };
183};
184
185namespace testnamespace {
186
187enum Tags3 {
188 tags3_1,
189 tags3_2,
190 tags3_3,
191};
192
193union 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)
201struct 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)
207class 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)
215struct 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)
221class 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)
227template <typename Tag, typename Union>
228struct TemplatedStructWithNamespacedTagAndUnion {
229 Tag Kind;
230 Union Data;
231};
232
233TemplatedStructWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedStruct3;
234
235// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3)
236template <typename Tag, typename Union>
237class TemplatedClassWithNamespacedTagAndUnion {
238 Tag Kind;
239 Union Data;
240};
241
242TemplatedClassWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedClass3;
243
244// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3)
245template <typename Tag, typename Union>
246struct TemplatedStruct {
247 Tag Kind;
248 Union Data;
249};
250
251TemplatedStruct<Tags3, Union3> TemplatedStruct1; // No warning expected
252TemplatedStruct<Tags3, Union4> TemplatedStruct2;
253
254// CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3)
255template <typename Tag, typename Union>
256class TemplatedClass {
257 Tag Kind;
258 Union Data;
259};
260
261TemplatedClass<Tags3, Union3> TemplatedClass1; // No warning expected
262TemplatedClass<Tags3, Union4> TemplatedClass2;
263
264// CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3)
265template <typename T>
266struct 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)
273template <typename T>
274class TemplatedClassButTaggedUnionPartIsNotTemplated {
275 Tags3 Kind;
276 Union4 Data;
277 T SomethingElse;
278};
279
280#define DECLARE_TAGGED_UNION_STRUCT(Tag, Union, Name)\
281struct 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)
287DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro);
288
289#define DECLARE_TAGGED_UNION_CLASS(Tag, Union, Name)\
290class 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)
296DECLARE_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.
300void DoNotMatchLambdas() {
301 enum {
302 A
303 } e;
304 union {
305 long A;
306 char B;
307 } u;
308 auto L = [e, u] () {};
309}
310

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