llvm-project/clang/test/Analysis/padding_c.c

237 lines
4.7 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 -analyze -analyzer-checker=optin.performance -analyzer-config optin.performance.Padding:AllowedPad=2 -verify %s
#if __has_include(<stdalign.h>)
#include <stdalign.h>
#endif
#if __has_include(<stdalign.h>) || defined(__cplusplus)
// expected-warning@+1{{Excessive padding in 'struct FieldAttrAlign' (6 padding}}
struct FieldAttrAlign {
char c1;
alignas(4) int i;
char c2;
};
// expected-warning@+1{{Excessive padding in 'struct FieldAttrOverAlign' (10 padding}}
struct FieldAttrOverAlign {
char c1;
alignas(8) int i;
char c2;
};
#endif // __has_include(<stdalign.h>) || defined(__cplusplus)
// Re-ordering members of these structs won't reduce padding, so don't warn
struct LeadingChar { // no-warning
char c;
int i;
};
struct TrailingChar { // no-warning
int i;
char c;
};
struct Helpless { // no-warning
struct TrailingChar i1;
struct LeadingChar i2;
char c;
};
#pragma pack(push)
#pragma pack(1)
struct SquishedIntSandwich { // no-warning
char c1;
int i;
char c2;
};
#pragma pack(pop)
// Re-ordering members of these structs will reduce padding, so warn
struct IntSandwich { // expected-warning{{Excessive padding in 'struct IntSandwich'}}
char c1;
int i;
char c2;
};
struct TurDuckHen { // expected-warning{{Excessive padding in 'struct TurDuckHen'}}
char c1;
struct IntSandwich i;
char c2;
};
#pragma pack(push)
#pragma pack(2)
struct SmallIntSandwich { // expected-warning{{Excessive padding in '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;
};
struct HoldsAUnion { // expected-warning{{Excessive padding in 'struct HoldsAUnion'}}
char c1;
union SomeUnion u;
char c2;
};
struct BigCharArray { // no-warning
char c[129];
};
struct SmallCharArray { // no-warning
char c[5];
};
struct MediumIntArray { // no-warning
int i[5];
};
struct LargeSizeToSmallSize { // expected-warning{{Excessive padding in 'struct LargeSizeToSmallSize'}}
struct BigCharArray b;
struct MediumIntArray m;
struct SmallCharArray s;
};
struct LargeAlignToSmallAlign { // no-warning
struct MediumIntArray m;
struct BigCharArray b;
struct SmallCharArray s;
};
// Currently ignoring VLA padding problems. Still need to make sure we don't
// choke on VLAs though
struct HoldsVLA { // no-warning
char c1;
int x;
char c2;
int vla[];
};
// Currently ignoring bitfield padding problems. Still need to make sure we
// don't choke on bitfields though
struct HoldsBitfield { // no-warning
char c1;
int x;
char c2;
unsigned char b1 : 3;
unsigned char b2 : 3;
unsigned char b3 : 2;
};
typedef struct { // expected-warning{{Excessive padding in 'TypedefSandwich'}}
char c1;
int i;
char c2;
} TypedefSandwich;
// expected-warning@+1{{Excessive padding in 'struct StructAttrAlign' (10 padding}}
struct StructAttrAlign {
char c1;
int i;
char c2;
} __attribute__((aligned(8)));
struct CorrectOverlyAlignedChar { // no-warning
char c __attribute__((aligned(4096)));
char c1;
int x1;
char c2;
int x2;
char c3;
};
struct OverlyAlignedChar { // expected-warning{{Excessive padding in 'struct OverlyAlignedChar'}}
char c1;
int x;
char c2;
char c __attribute__((aligned(4096)));
};
struct HoldsOverlyAlignedChar { // expected-warning{{Excessive padding in 'struct HoldsOverlyAlignedChar'}}
char c1;
struct OverlyAlignedChar o;
char c2;
};
void internalStructFunc() {
struct X { // expected-warning{{Excessive padding in 'struct X'}}
char c1;
int t;
char c2;
};
struct X obj;
}
void typedefStructFunc() {
typedef struct { // expected-warning{{Excessive padding in 'S'}}
char c1;
int t;
char c2;
} S;
S obj;
}
void anonStructFunc() {
struct { // expected-warning{{Excessive padding in 'struct (anonymous}}
char c1;
int t;
char c2;
} obj;
}
struct CorrectDefaultAttrAlign { // no-warning
long long i;
char c1;
char c2;
} __attribute__((aligned));
struct TooSmallShortSandwich { // no-warning
char c1;
short s;
char c2;
};
// expected-warning@+1{{Excessive padding in 'struct SmallArrayShortSandwich'}}
struct SmallArrayShortSandwich {
char c1;
short s;
char c2;
} ShortArray[20];
// expected-warning@+1{{Excessive padding in 'struct SmallArrayInFunc'}}
struct SmallArrayInFunc {
char c1;
short s;
char c2;
};
void arrayHolder() {
struct SmallArrayInFunc Arr[15];
}
// xxxexpected-warning@+1{{Excessive padding in 'struct SmallArrayInStruct'}}
struct SmallArrayInStruct {
char c1;
short s;
char c2;
};
struct HoldsSmallArray {
struct SmallArrayInStruct Field[20];
} HoldsSmallArrayElt;
void nestedPadding() {
struct HoldsSmallArray Arr[15];
}