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

186 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 -triple x86_64-unknown-linux -std=c++14 -analyze -analyzer-checker=optin.performance -analyzer-config optin.performance.Padding:AllowedPad=2 -verify %s
// expected-warning@+1{{Excessive padding in 'struct IntSandwich' (6 padding bytes, where 2 is optimal)}}
struct IntSandwich {
char c1;
int i;
char c2;
};
// expected-warning@+1{{Excessive padding in 'struct TurDuckHen' (6 padding bytes, where 2 is optimal)}}
struct TurDuckHen {
char c1;
struct IntSandwich i;
char c2;
};
#pragma pack(push)
#pragma pack(2)
// expected-warning@+1{{Excessive padding in 'struct SmallIntSandwich' (4 padding bytes, where 0 is optimal)}}
struct SmallIntSandwich {
char c1;
int i1;
char c2;
int i2;
char c3;
int i3;
char c4;
};
#pragma pack(pop)
union SomeUnion { // no-warning
char c;
short s;
int i;
};
// expected-warning@+1{{Excessive padding in 'struct HoldsAUnion' (6 padding bytes, where 2 is optimal)}}
struct HoldsAUnion {
char c1;
union SomeUnion u;
char c2;
};
struct SmallCharArray { // no-warning
char c[5];
};
struct MediumIntArray { // no-warning
int i[5];
};
// expected-warning@+1{{Excessive padding in 'struct StructSandwich' (6 padding bytes, where 2 is optimal)}}
struct StructSandwich {
struct SmallCharArray s;
struct MediumIntArray m;
struct SmallCharArray s2;
};
// expected-warning@+1{{Excessive padding in 'TypedefSandwich' (6 padding bytes, where 2 is optimal)}}
typedef struct {
char c1;
int i;
char c2;
} TypedefSandwich;
// expected-warning@+1{{Excessive padding in 'struct StructAttrAlign' (10 padding bytes, where 2 is optimal)}}
struct StructAttrAlign {
char c1;
int i;
char c2;
} __attribute__((aligned(8)));
// expected-warning@+1{{Excessive padding in 'struct OverlyAlignedChar' (8185 padding bytes, where 4089 is optimal)}}
struct OverlyAlignedChar {
char c1;
int x;
char c2;
char c __attribute__((aligned(4096)));
};
// expected-warning@+1{{Excessive padding in 'struct HoldsOverlyAlignedChar' (8190 padding bytes, where 4094 is optimal)}}
struct HoldsOverlyAlignedChar {
char c1;
struct OverlyAlignedChar o;
char c2;
};
void internalStructFunc() {
// expected-warning@+1{{Excessive padding in 'struct X' (6 padding bytes, where 2 is optimal)}}
struct X {
char c1;
int t;
char c2;
};
struct X obj;
}
void typedefStructFunc() {
// expected-warning@+1{{Excessive padding in 'S' (6 padding bytes, where 2 is optimal)}}
typedef struct {
char c1;
int t;
char c2;
} S;
S obj;
}
// expected-warning@+1{{Excessive padding in 'struct DefaultAttrAlign' (22 padding bytes, where 6 is optimal)}}
struct DefaultAttrAlign {
char c1;
long long i;
char c2;
} __attribute__((aligned));
// expected-warning@+1{{Excessive padding in 'struct SmallArrayShortSandwich' (2 padding bytes, where 0 is optimal)}}
struct SmallArrayShortSandwich {
char c1;
short s;
char c2;
} ShortArray[20];
// expected-warning@+1{{Excessive padding in 'struct SmallArrayInFunc' (2 padding bytes, where 0 is optimal)}}
struct SmallArrayInFunc {
char c1;
short s;
char c2;
};
void arrayHolder() {
struct SmallArrayInFunc Arr[15];
}
// expected-warning@+1{{Excessive padding in 'class VirtualIntSandwich' (10 padding bytes, where 2 is optimal)}}
class VirtualIntSandwich {
virtual void foo() {}
char c1;
int i;
char c2;
};
// constructed so as not to have tail padding
// expected-warning@+1{{Excessive padding in 'class InnerPaddedB' (6 padding bytes, where 2 is optimal)}}
class InnerPaddedB {
char c1;
int i1;
char c2;
int i2;
};
class Empty {}; // no-warning
// expected-warning@+1{{Excessive padding in 'class LotsOfSpace' (6 padding bytes, where 2 is optimal)}}
class LotsOfSpace {
Empty e1;
int i;
Empty e2;
};
// expected-warning@+1{{Excessive padding in 'TypedefSandwich2' (6 padding bytes, where 2 is optimal)}}
typedef struct {
char c1;
// expected-warning@+1{{Excessive padding in 'TypedefSandwich2::NestedTypedef' (6 padding bytes, where 2 is optimal)}}
typedef struct {
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' (6 padding bytes, where 2 is optimal)}}
struct Nested {
char c1;
T t;
char c2;
};
};
struct Holder { // no-warning
Foo<int>::Nested t1;
Foo<char>::Nested t2;
};