
The intent of this checker is to generate a report for any class / structure that could reduce its padding by reordering the fields. This results in a very noisy checker. To reduce the noise, this checker will currently only warn when the number of bytes over "optimal" is more than 24. This value is configurable with -analyzer-config performance.Padding:AllowedPad=N. Small values of AllowedPad have the potential to generate hundreds of reports, and gigabytes of HTML reports. The checker searches for padding violations in two main ways. First, it goes record by record. A report is generated if the fields could be reordered in a way that reduces the padding by more than AllowedPad bytes. Second, the checker will generate a report if an array will cause more than AllowedPad padding bytes to be generated. The record checker currently skips many ABI specific cases. Classes with base classes are skipped because base class tail padding is ABI specific. Bitfields are just plain hard, and duplicating that code seems like a bad idea. VLAs are both uncommon and non-trivial to fix. The array checker isn't very thorough right now. It only checks to see if the element type's fields could be reordered, and it doesn't recursively check to see if any of the fields' fields could be reordered. At some point in the future, it would be nice if "arrays" could also look at array new usages and malloc patterns that appear to be creating arrays. llvm-svn: 255545
203 lines
4.4 KiB
C++
203 lines
4.4 KiB
C++
// RUN: %clang_cc1 -std=c++14 -analyze -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
|