aboutsummaryrefslogtreecommitdiff
path: root/test/Analysis/padding_cpp.cpp
blob: ee49aea0c2bed3ae5987f6fc9b3a1cf9959555df (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=optin.performance -analyzer-config optin.performance.Padding:AllowedPad=2 -verify %s

// Make sure that the C cases still work fine, even when compiled as C++.
#include "padding_c.c"

struct BigCharArray2 { // no-warning
  char c[129];
};

// xxxexpected-warning@+1{{Excessive padding in 'struct LowAlignmentBase'}}
struct LowAlignmentBase : public BigCharArray2 {
  int i;
  char c;
};

struct CorrectLowAlignmentBase : public BigCharArray2 { // no-warning
  char c;
  int i;
};

// xxxexpected-warning@+1{{Excessive padding in 'struct LowAlignmentBase2'}}
struct LowAlignmentBase2 : public BigCharArray2 {
  char c1;
  int i;
  char c2;
};

class PaddedA { // expected-warning{{Excessive padding in 'class PaddedA'}}
  char c1;
  int i;
  char c2;
};

class VirtualPaddedA : public PaddedA { // no-warning
  virtual void foo() {}
};

class VirtualIntSandwich { // expected-warning{{Excessive padding in 'class VirtualIntSandwich'}}
  virtual void foo() {}
  char c1;
  int i;
  char c2;
};

// constructed so as not to have tail padding
class InnerPaddedB { // expected-warning{{Excessive padding in 'class InnerPaddedB'}}
  char c1;
  int i1;
  char c2;
  int i2;
};

class TailPaddedB { // expected-warning{{Excessive padding in 'class TailPaddedB'}}
  char c1;
  int i1;
  char c2;
};

class SI : public PaddedA { // no-warning
  char c;
};

class SI2 : public PaddedA { // xxxexpected-warning{{Excessive padding in 'class SI2'}}
  char c10;
  int i10;
  char c11;
};

class VirtualSI : virtual public PaddedA { // no-warning
  char c;
};

// currently not checked for
class VirtualSI2 : virtual public PaddedA { // no-warning
  char c10;
  int i10;
  char c11;
};

class VtblSI : public PaddedA { // no-warning
  virtual void foo() {}
  char c;
};

class VtblSI2 : public PaddedA { // xxxexpected-warning{{Excessive padding in 'class VtblSI2'}}
  virtual void foo() {}
  char c10;
  int i10;
  char c11;
};

class VtblSI3 : public VirtualPaddedA { // xxxexpected-warning{{Excessive padding in 'class VtblSI3'}}
  char c10;
  int i10;
  char c11;
};

class MI : public PaddedA, public InnerPaddedB { // no-warning
  char c;
};

class MI2 : public PaddedA, public InnerPaddedB { // xxxexpected-warning{{Excessive padding in 'class MI2'}}
  char c10;
  int i10;
  char c11;
};

class VtblMI : public PaddedA, public InnerPaddedB { // xxxexpected-warning{{Excessive padding in 'class VtblMI'}}
  virtual void foo() {}
  char c10;
  int i10;
  char c11;
};

class VtblMI2 : public VirtualPaddedA, public InnerPaddedB { // xxxexpected-warning{{Excessive padding in 'class VtblMI2'}}
  char c10;
  int i10;
  char c11;
};

class Empty {}; // no-warning

class LotsOfSpace { // expected-warning{{Excessive padding in 'class LotsOfSpace'}}
  Empty e1;
  int i;
  Empty e2;
};

class EBO1 : public Empty { // xxxexpected-warning{{Excessive padding in 'class EBO1'}}
  char c1;
  int i;
  char c2;
};

class EBO2 : public Empty { // xxxexpected-warning{{Excessive padding in 'class EBO2'}}
  Empty c1;
  int i;
  Empty c2;
};

template <typename T>
class TemplateSandwich { // expected-warning{{Excessive padding in 'class TemplateSandwich<int>' instantiated here}}
  char c1;
  T t;
  char c2;
};

template <typename T>
class TemplateSandwich<T *> { // expected-warning{{Excessive padding in 'class TemplateSandwich<void *>' instantiated here}}
  char c1;
  T *t;
  char c2;
};

template <>
class TemplateSandwich<long long> { // expected-warning{{Excessive padding in 'class TemplateSandwich<long long>' (}}
  char c1;
  long long t;
  char c2;
};

class Holder1 { // no-warning
  TemplateSandwich<int> t1;
  TemplateSandwich<char> t2;
  TemplateSandwich<void *> t3;
};

typedef struct { // expected-warning{{Excessive padding in 'TypedefSandwich2'}}
  char c1;
  typedef struct { // expected-warning{{Excessive padding in 'TypedefSandwich2::NestedTypedef'}}
    char c1;
    int i;
    char c2;
  } NestedTypedef;
  NestedTypedef t;
  char c2;
} TypedefSandwich2;

template <typename T>
struct Foo {
  // expected-warning@+1{{Excessive padding in 'struct Foo<int>::Nested'}}
  struct Nested {
    char c1;
    T t;
    char c2;
  };
};

struct Holder { // no-warning
  Foo<int>::Nested t1;
  Foo<char>::Nested t2;
};

struct GlobalsForLambda { // no-warning
  int i;
  char c1;
  char c2;
} G;

// expected-warning@+1{{Excessive padding in 'class (lambda}}
auto lambda1 = [ c1 = G.c1, i = G.i, c2 = G.c2 ]{};
auto lambda2 = [ i = G.i, c1 = G.c1, c2 = G.c2 ]{}; // no-warning