1 | // RUN: %check_clang_tidy -std=c++98-or-later %s bugprone-tagged-union-member-count %t |
2 | // Test check with C++ features |
3 | |
4 | typedef enum Tags3 { |
5 | tags3_1, |
6 | tags3_2, |
7 | tags3_3, |
8 | } Tags3; |
9 | |
10 | typedef enum Tags4 { |
11 | tags4_1, |
12 | tags4_2, |
13 | tags4_3, |
14 | tags4_4, |
15 | } Tags4; |
16 | |
17 | enum class Classtags3 { |
18 | classtags3_1, |
19 | classtags3_2, |
20 | classtags3_3, |
21 | }; |
22 | |
23 | enum class Typedtags3 : unsigned int { |
24 | typedtags3_1, |
25 | typedtags3_2, |
26 | typedtags3_3, |
27 | }; |
28 | |
29 | typedef union Union3 { |
30 | short *Shorts; |
31 | int *Ints; |
32 | float *Floats; |
33 | } Union3; |
34 | |
35 | typedef 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. |
43 | class 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. |
50 | class 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. |
57 | class 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) |
72 | class 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) |
78 | class 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) |
92 | class 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) |
102 | class 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) |
120 | class 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) |
135 | class 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) |
141 | struct 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) |
147 | class 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) |
153 | struct 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) |
159 | class 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) |
165 | struct 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) |
176 | class TaggedUnionClassWithAnonymousUnion { |
177 | Tags3 Tag; |
178 | union { |
179 | char A; |
180 | short B; |
181 | int C; |
182 | long D; |
183 | }; |
184 | }; |
185 | |
186 | namespace testnamespace { |
187 | |
188 | enum Tags3 { |
189 | tags3_1, |
190 | tags3_2, |
191 | tags3_3, |
192 | }; |
193 | |
194 | union 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) |
202 | struct 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) |
208 | class 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) |
216 | struct 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) |
222 | class 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) |
228 | template <typename Tag, typename Union> |
229 | struct TemplatedStructWithNamespacedTagAndUnion { |
230 | Tag Kind; |
231 | Union Data; |
232 | }; |
233 | |
234 | TemplatedStructWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedStruct3; |
235 | |
236 | // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3) |
237 | template <typename Tag, typename Union> |
238 | class TemplatedClassWithNamespacedTagAndUnion { |
239 | Tag Kind; |
240 | Union Data; |
241 | }; |
242 | |
243 | TemplatedClassWithNamespacedTagAndUnion<testnamespace::Union4, testnamespace::Tags3> TemplatedClass3; |
244 | |
245 | // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3) |
246 | template <typename Tag, typename Union> |
247 | struct TemplatedStruct { |
248 | Tag Kind; |
249 | Union Data; |
250 | }; |
251 | |
252 | TemplatedStruct<Tags3, Union3> TemplatedStruct1; // No warning expected |
253 | TemplatedStruct<Tags3, Union4> TemplatedStruct2; |
254 | |
255 | // CHECK-MESSAGES: :[[@LINE+2]]:7: warning: tagged union has more data members (4) than tags (3) |
256 | template <typename Tag, typename Union> |
257 | class TemplatedClass { |
258 | Tag Kind; |
259 | Union Data; |
260 | }; |
261 | |
262 | TemplatedClass<Tags3, Union3> TemplatedClass1; // No warning expected |
263 | TemplatedClass<Tags3, Union4> TemplatedClass2; |
264 | |
265 | // CHECK-MESSAGES: :[[@LINE+2]]:8: warning: tagged union has more data members (4) than tags (3) |
266 | template <typename T> |
267 | struct 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) |
274 | template <typename T> |
275 | class TemplatedClassButTaggedUnionPartIsNotTemplated { |
276 | Tags3 Kind; |
277 | Union4 Data; |
278 | T SomethingElse; |
279 | }; |
280 | |
281 | #define DECLARE_TAGGED_UNION_STRUCT(Tag, Union, Name)\ |
282 | struct 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) |
288 | DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro); |
289 | |
290 | #define DECLARE_TAGGED_UNION_CLASS(Tag, Union, Name)\ |
291 | class 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) |
297 | DECLARE_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. |
301 | void DoNotMatchLambdas() { |
302 | enum { |
303 | A |
304 | } e; |
305 | union { |
306 | long A; |
307 | char B; |
308 | } u; |
309 | auto L = [e, u] () {}; |
310 | } |
311 | |