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 | typedef union Union3 { |
17 | short *Shorts; |
18 | int *Ints; |
19 | float *Floats; |
20 | } Union3; |
21 | |
22 | typedef union Union4 { |
23 | short *Shorts; |
24 | double *Doubles; |
25 | int *Ints; |
26 | float *Floats; |
27 | } Union4; |
28 | |
29 | // It is not obvious which enum is the tag for the union. |
30 | struct maybeTaggedUnion1 { // No warnings expected. |
31 | enum Tags3 TagA; |
32 | enum Tags4 TagB; |
33 | union Union4 Data; |
34 | }; |
35 | |
36 | // It is not obvious which union does the tag belong to. |
37 | struct maybeTaggedUnion2 { // No warnings expected. |
38 | enum Tags3 Tag; |
39 | union Union3 DataB; |
40 | union Union3 DataA; |
41 | }; |
42 | |
43 | // It is not obvious which union does the tag belong to. |
44 | struct maybeTaggedUnion3 { // No warnings expected. |
45 | enum Tags3 Tag; |
46 | union { |
47 | int I1; |
48 | int I2; |
49 | int I3; |
50 | }; |
51 | union { |
52 | float F1; |
53 | float F2; |
54 | float F3; |
55 | }; |
56 | }; |
57 | |
58 | // No warnings expected, because LastATag is just an alias |
59 | struct TaggedUnionWithAliasedEnumConstant { |
60 | enum { |
61 | ATag1, |
62 | ATag2, |
63 | ATag3, |
64 | LastATag = ATag3, |
65 | } Tag; |
66 | union { |
67 | float F; |
68 | int *Ints; |
69 | char Key[8]; |
70 | } Data; |
71 | }; |
72 | |
73 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
74 | struct TaggedUnionStructWithPredefinedTagAndPredefinedUnion { |
75 | enum Tags3 Tag; |
76 | union Union4 Data; |
77 | }; |
78 | |
79 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
80 | struct TaggedUnionStructWithPredefinedTagAndInlineUnion { |
81 | enum Tags3 Tag; |
82 | union { |
83 | int *Ints; |
84 | char Characters[13]; |
85 | struct { |
86 | double Re; |
87 | double Im; |
88 | } Complex; |
89 | long L; |
90 | } Data; |
91 | }; |
92 | |
93 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
94 | struct TaggedUnionStructWithInlineTagAndPredefinedUnion { |
95 | enum { |
96 | TaggedUnion7tag1, |
97 | TaggedUnion7tag2, |
98 | TaggedUnion7tag3, |
99 | } Tag; |
100 | union Union4 Data; |
101 | }; |
102 | |
103 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
104 | struct TaggedUnionStructWithInlineTagAndInlineUnion { |
105 | enum { |
106 | TaggedUnion8tag1, |
107 | TaggedUnion8tag2, |
108 | TaggedUnion8tag3, |
109 | } Tag; |
110 | union { |
111 | int *Ints; |
112 | char Characters[13]; |
113 | struct { |
114 | double Re; |
115 | double Im; |
116 | } Complex; |
117 | long L; |
118 | } Data; |
119 | }; |
120 | |
121 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
122 | struct TaggedUnionStructNesting { |
123 | enum Tags3 Tag; |
124 | union { |
125 | float F; |
126 | int I; |
127 | long L; |
128 | // CHECK-MESSAGES: :[[@LINE+1]]:12: warning: tagged union has more data members (4) than tags (3) |
129 | struct innerdecl { |
130 | enum Tags3 Tag; |
131 | union Union4 Data; |
132 | } Inner; |
133 | } Data; |
134 | }; |
135 | |
136 | // CHECK-MESSAGES: :[[@LINE+1]]:8: warning: tagged union has more data members (4) than tags (3) |
137 | struct TaggedUnionStructWithTypedefedTagAndTypedefedUnion { |
138 | Tags3 Tag; |
139 | Union4 Data; |
140 | }; |
141 | |
142 | #define DECLARE_TAGGED_UNION_STRUCT(Tag, Union, Name)\ |
143 | struct Name {\ |
144 | Tag Kind;\ |
145 | Union Data;\ |
146 | } |
147 | |
148 | // CHECK-MESSAGES: :[[@LINE+1]]:44: warning: tagged union has more data members (4) than tags (3) |
149 | DECLARE_TAGGED_UNION_STRUCT(Tags3, Union4, TaggedUnionStructFromMacro); |
150 | |