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