1 | // RUN: %clang_analyze_cc1 -verify %s \ |
2 | // RUN: -analyzer-checker=optin.performance \ |
3 | // RUN: -analyzer-config optin.performance.Padding:AllowedPad=2 |
4 | |
5 | // RUN: not %clang_analyze_cc1 -verify %s \ |
6 | // RUN: -analyzer-checker=core \ |
7 | // RUN: -analyzer-checker=optin.performance.Padding \ |
8 | // RUN: -analyzer-config optin.performance.Padding:AllowedPad=-10 \ |
9 | // RUN: 2>&1 | FileCheck %s -check-prefix=CHECK-PAD-NEGATIVE-VALUE |
10 | |
11 | // CHECK-PAD-NEGATIVE-VALUE: (frontend): invalid input for checker option |
12 | // CHECK-PAD-NEGATIVE-VALUE-SAME: 'optin.performance.Padding:AllowedPad', that |
13 | // CHECK-PAD-NEGATIVE-VALUE-SAME: expects a non-negative value |
14 | |
15 | #if __has_include(<stdalign.h>) |
16 | #include <stdalign.h> |
17 | #endif |
18 | |
19 | #if __has_include(<stdalign.h>) || defined(__cplusplus) |
20 | // expected-warning@+1{{Excessive padding in 'struct FieldAttrAlign' (6 padding}} |
21 | struct FieldAttrAlign { |
22 | char c1; |
23 | alignas(4) int i; |
24 | char c2; |
25 | }; |
26 | |
27 | // expected-warning@+1{{Excessive padding in 'struct FieldAttrOverAlign' (10 padding}} |
28 | struct FieldAttrOverAlign { |
29 | char c1; |
30 | alignas(8) int i; |
31 | char c2; |
32 | }; |
33 | |
34 | #endif // __has_include(<stdalign.h>) || defined(__cplusplus) |
35 | |
36 | // Re-ordering members of these structs won't reduce padding, so don't warn |
37 | struct LeadingChar { // no-warning |
38 | char c; |
39 | int i; |
40 | }; |
41 | |
42 | struct TrailingChar { // no-warning |
43 | int i; |
44 | char c; |
45 | }; |
46 | |
47 | struct Helpless { // no-warning |
48 | struct TrailingChar i1; |
49 | struct LeadingChar i2; |
50 | char c; |
51 | }; |
52 | |
53 | #pragma pack(push) |
54 | #pragma pack(1) |
55 | struct SquishedIntSandwich { // no-warning |
56 | char c1; |
57 | int i; |
58 | char c2; |
59 | }; |
60 | #pragma pack(pop) |
61 | |
62 | // Re-ordering members of these structs will reduce padding, so warn |
63 | struct IntSandwich { // expected-warning{{Excessive padding in 'struct IntSandwich'}} |
64 | char c1; |
65 | int i; |
66 | char c2; |
67 | }; |
68 | |
69 | struct TurDuckHen { // expected-warning{{Excessive padding in 'struct TurDuckHen'}} |
70 | char c1; |
71 | struct IntSandwich i; |
72 | char c2; |
73 | }; |
74 | |
75 | #pragma pack(push) |
76 | #pragma pack(2) |
77 | struct SmallIntSandwich { // expected-warning{{Excessive padding in 'struct SmallIntSandwich'}} |
78 | char c1; |
79 | int i1; |
80 | char c2; |
81 | int i2; |
82 | char c3; |
83 | int i3; |
84 | char c4; |
85 | }; |
86 | #pragma pack(pop) |
87 | |
88 | union SomeUnion { // no-warning |
89 | char c; |
90 | short s; |
91 | int i; |
92 | }; |
93 | |
94 | struct HoldsAUnion { // expected-warning{{Excessive padding in 'struct HoldsAUnion'}} |
95 | char c1; |
96 | union SomeUnion u; |
97 | char c2; |
98 | }; |
99 | |
100 | struct BigCharArray { // no-warning |
101 | char c[129]; |
102 | }; |
103 | |
104 | struct SmallCharArray { // no-warning |
105 | char c[5]; |
106 | }; |
107 | |
108 | struct MediumIntArray { // no-warning |
109 | int i[5]; |
110 | }; |
111 | |
112 | struct LargeSizeToSmallSize { // expected-warning{{Excessive padding in 'struct LargeSizeToSmallSize'}} |
113 | struct BigCharArray b; |
114 | struct MediumIntArray m; |
115 | struct SmallCharArray s; |
116 | }; |
117 | |
118 | struct LargeAlignToSmallAlign { // no-warning |
119 | struct MediumIntArray m; |
120 | struct BigCharArray b; |
121 | struct SmallCharArray s; |
122 | }; |
123 | |
124 | // Currently ignoring VLA padding problems. Still need to make sure we don't |
125 | // choke on VLAs though |
126 | struct HoldsVLA { // no-warning |
127 | char c1; |
128 | int x; |
129 | char c2; |
130 | int vla[]; |
131 | }; |
132 | |
133 | // Currently ignoring bitfield padding problems. Still need to make sure we |
134 | // don't choke on bitfields though |
135 | struct HoldsBitfield { // no-warning |
136 | char c1; |
137 | int x; |
138 | char c2; |
139 | unsigned char b1 : 3; |
140 | unsigned char b2 : 3; |
141 | unsigned char b3 : 2; |
142 | }; |
143 | |
144 | typedef struct { // expected-warning{{Excessive padding in 'TypedefSandwich'}} |
145 | char c1; |
146 | int i; |
147 | char c2; |
148 | } TypedefSandwich; |
149 | |
150 | // expected-warning@+1{{Excessive padding in 'struct StructAttrAlign' (10 padding}} |
151 | struct StructAttrAlign { |
152 | char c1; |
153 | int i; |
154 | char c2; |
155 | } __attribute__((aligned(8))); |
156 | |
157 | struct CorrectOverlyAlignedChar { // no-warning |
158 | char c __attribute__((aligned(4096))); |
159 | char c1; |
160 | int x1; |
161 | char c2; |
162 | int x2; |
163 | char c3; |
164 | }; |
165 | |
166 | struct OverlyAlignedChar { // expected-warning{{Excessive padding in 'struct OverlyAlignedChar'}} |
167 | char c1; |
168 | int x; |
169 | char c2; |
170 | char c __attribute__((aligned(4096))); |
171 | }; |
172 | |
173 | struct HoldsOverlyAlignedChar { // expected-warning{{Excessive padding in 'struct HoldsOverlyAlignedChar'}} |
174 | char c1; |
175 | struct OverlyAlignedChar o; |
176 | char c2; |
177 | }; |
178 | |
179 | void internalStructFunc() { |
180 | struct X { // expected-warning{{Excessive padding in 'struct X'}} |
181 | char c1; |
182 | int t; |
183 | char c2; |
184 | }; |
185 | struct X obj; |
186 | } |
187 | |
188 | void typedefStructFunc() { |
189 | typedef struct { // expected-warning{{Excessive padding in 'S'}} |
190 | char c1; |
191 | int t; |
192 | char c2; |
193 | } S; |
194 | S obj; |
195 | } |
196 | |
197 | void anonStructFunc() { |
198 | struct { // expected-warning{{Excessive padding in 'struct (anonymous}} |
199 | char c1; |
200 | int t; |
201 | char c2; |
202 | } obj; |
203 | } |
204 | |
205 | struct CorrectDefaultAttrAlign { // no-warning |
206 | long long i; |
207 | char c1; |
208 | char c2; |
209 | } __attribute__((aligned)); |
210 | |
211 | struct TooSmallShortSandwich { // no-warning |
212 | char c1; |
213 | short s; |
214 | char c2; |
215 | }; |
216 | |
217 | // expected-warning@+1{{Excessive padding in 'struct SmallArrayShortSandwich'}} |
218 | struct SmallArrayShortSandwich { |
219 | char c1; |
220 | short s; |
221 | char c2; |
222 | } ShortArray[20]; |
223 | |
224 | // expected-warning@+1{{Excessive padding in 'struct SmallArrayInFunc'}} |
225 | struct SmallArrayInFunc { |
226 | char c1; |
227 | short s; |
228 | char c2; |
229 | }; |
230 | |
231 | void arrayHolder() { |
232 | struct SmallArrayInFunc Arr[15]; |
233 | } |
234 | |
235 | // xxxexpected-warning@+1{{Excessive padding in 'struct SmallArrayInStruct'}} |
236 | struct SmallArrayInStruct { |
237 | char c1; |
238 | short s; |
239 | char c2; |
240 | }; |
241 | |
242 | struct HoldsSmallArray { |
243 | struct SmallArrayInStruct Field[20]; |
244 | } HoldsSmallArrayElt; |
245 | |
246 | void nestedPadding() { |
247 | struct HoldsSmallArray Arr[15]; |
248 | } |
249 | |