llvm-project/clang/test/Analysis/padding_cpp.cpp

203 lines
4.4 KiB
C++
Raw Normal View History

[PATCH] Adding checker to detect excess padding in records 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
2015-12-15 05:38:59 +08:00
// 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