forked from OSchip/llvm-project
Clean up empty struct/union recognition.
Make use of getTypeSizeInChars to detect structs/unions of zero size. It allows more accurate detection of types of zero size. It however has a side effect - sequence of used types may change, that is why the test 'override-layout' was modified. llvm-svn: 184088
This commit is contained in:
parent
69817016cf
commit
f7c1a2152a
|
@ -5493,10 +5493,8 @@ def ext_empty_struct_union : Extension<
|
|||
"empty %select{struct|union}0 is a GNU extension">, InGroup<GNU>;
|
||||
def ext_no_named_members_in_struct_union : Extension<
|
||||
"%select{struct|union}0 without named members is a GNU extension">, InGroup<GNU>;
|
||||
def warn_empty_struct_union_compat : Warning<"empty %select{struct|union}0 "
|
||||
"has size 0 in C, size 1 in C++">, InGroup<CXXCompat>, DefaultIgnore;
|
||||
def warn_zero_size_struct_union_compat : Warning<"%select{struct|union}0 "
|
||||
"with only bit-fields of width 0 has size 0 in C, size 1 in C++">,
|
||||
def warn_zero_size_struct_union_compat : Warning<"%select{|empty }0"
|
||||
"%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">,
|
||||
InGroup<CXXCompat>, DefaultIgnore;
|
||||
} // End of general sema category.
|
||||
|
||||
|
|
|
@ -11236,32 +11236,34 @@ void Sema::ActOnFields(Scope* S,
|
|||
// Check if the structure/union declaration is a language extension.
|
||||
if (!getLangOpts().CPlusPlus) {
|
||||
bool ZeroSize = true;
|
||||
bool UnnamedOnly = true;
|
||||
unsigned UnnamedCnt = 0;
|
||||
bool IsEmpty = true;
|
||||
unsigned NonBitFields = 0;
|
||||
for (RecordDecl::field_iterator I = Record->field_begin(),
|
||||
E = Record->field_end(); UnnamedOnly && I != E; ++I) {
|
||||
E = Record->field_end();
|
||||
(NonBitFields == 0 || ZeroSize) && I != E; ++I) {
|
||||
IsEmpty = false;
|
||||
if (I->isUnnamedBitfield()) {
|
||||
UnnamedCnt++;
|
||||
if (I->getBitWidthValue(Context) > 0)
|
||||
ZeroSize = false;
|
||||
} else {
|
||||
UnnamedOnly = ZeroSize = false;
|
||||
++NonBitFields;
|
||||
QualType FieldType = I->getType();
|
||||
if (FieldType->isIncompleteType() ||
|
||||
!Context.getTypeSizeInChars(FieldType).isZero())
|
||||
ZeroSize = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
|
||||
// C++.
|
||||
if (ZeroSize) {
|
||||
if (UnnamedCnt == 0)
|
||||
Diag(RecLoc, diag::warn_empty_struct_union_compat) << Record->isUnion();
|
||||
else
|
||||
Diag(RecLoc, diag::warn_zero_size_struct_union_compat) << Record->isUnion();
|
||||
}
|
||||
if (ZeroSize)
|
||||
Diag(RecLoc, diag::warn_zero_size_struct_union_compat) << IsEmpty
|
||||
<< Record->isUnion() << (NonBitFields > 1);
|
||||
|
||||
// Structs without named members are extension in C (C99 6.7.2.1p7), but
|
||||
// are accepted by GCC.
|
||||
if (UnnamedOnly) {
|
||||
if (UnnamedCnt == 0)
|
||||
if (NonBitFields == 0) {
|
||||
if (IsEmpty)
|
||||
Diag(RecLoc, diag::ext_empty_struct_union) << Record->isUnion();
|
||||
else
|
||||
Diag(RecLoc, diag::ext_no_named_members_in_struct_union) << Record->isUnion();
|
||||
|
|
|
@ -19,24 +19,32 @@ struct X0 {
|
|||
int x[6] PACKED;
|
||||
};
|
||||
|
||||
void use_X0() { struct X0 x0; x0.x[5] = sizeof(struct X0); };
|
||||
|
||||
// CHECK: Type: struct X1
|
||||
struct X1 {
|
||||
char x[13];
|
||||
struct X0 y;
|
||||
} PACKED;
|
||||
|
||||
void use_X1() { struct X1 x1; x1.x[5] = sizeof(struct X1); };
|
||||
|
||||
// CHECK: Type: struct X2
|
||||
struct PACKED X2 {
|
||||
short x;
|
||||
int y;
|
||||
};
|
||||
|
||||
void use_X2() { struct X2 x2; x2.y = sizeof(struct X2); };
|
||||
|
||||
// CHECK: Type: struct X3
|
||||
struct X3 {
|
||||
short x PACKED;
|
||||
int y;
|
||||
};
|
||||
|
||||
void use_X3() { struct X3 x3; x3.y = sizeof(struct X3); };
|
||||
|
||||
#pragma pack(push,2)
|
||||
// CHECK: Type: struct X4
|
||||
struct X4 {
|
||||
|
@ -45,18 +53,26 @@ struct X4 {
|
|||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
void use_X4() { struct X4 x4; x4.y = sizeof(struct X4); };
|
||||
|
||||
// CHECK: Type: struct X5
|
||||
struct PACKED X5 { double a[19]; signed char b; };
|
||||
|
||||
void use_X5() { struct X5 x5; x5.b = sizeof(struct X5); };
|
||||
|
||||
// CHECK: Type: struct X6
|
||||
struct PACKED X6 { long double a; char b; };
|
||||
|
||||
void use_X6() { struct X6 x6; x6.b = sizeof(struct X6); };
|
||||
|
||||
// CHECK: Type: struct X7
|
||||
struct X7 {
|
||||
unsigned x;
|
||||
unsigned char y;
|
||||
} PACKED;
|
||||
|
||||
void use_X7() { struct X7 x7; x7.y = x7.x = sizeof(struct X7); }
|
||||
|
||||
// CHECK: Type: union X8
|
||||
union X8 {
|
||||
struct X7 x;
|
||||
|
@ -114,32 +130,6 @@ struct ALIGNED16 X16 {
|
|||
};
|
||||
|
||||
void use_structs() {
|
||||
struct X0 x0;
|
||||
x0.x[5] = sizeof(struct X0);
|
||||
|
||||
struct X1 x1;
|
||||
x1.x[5] = sizeof(struct X1);
|
||||
|
||||
struct X2 x2;
|
||||
x2.y = sizeof(struct X2);
|
||||
|
||||
struct X3 x3;
|
||||
x3.y = sizeof(struct X3);
|
||||
|
||||
struct X4 x4;
|
||||
x4.y = sizeof(struct X4);
|
||||
|
||||
struct X5 x5;
|
||||
x5.b = sizeof(struct X5);
|
||||
|
||||
struct X6 x6;
|
||||
x6.b = sizeof(struct X6);
|
||||
|
||||
struct X7 x7;
|
||||
typedef int X7array[sizeof(struct X7)];
|
||||
x7.x = sizeof(struct X7);
|
||||
x7.y = x7.x;
|
||||
|
||||
union X8 x8;
|
||||
typedef int X8array[sizeof(union X8)];
|
||||
x8.y = sizeof(union X8);
|
||||
|
|
|
@ -6,20 +6,33 @@ struct emp_1 { // expected-warning {{empty struct has size 0 in C, size 1 in C++
|
|||
union emp_2 { // expected-warning {{empty union has size 0 in C, size 1 in C++}}
|
||||
};
|
||||
|
||||
struct emp_3 { // expected-warning {{struct with only bit-fields of width 0 has size 0 in C, size 1 in C++}}
|
||||
struct emp_3 { // expected-warning {{struct has size 0 in C, size 1 in C++}}
|
||||
int : 0;
|
||||
};
|
||||
|
||||
union emp_4 { // expected-warning {{union with only bit-fields of width 0 has size 0 in C, size 1 in C++}}
|
||||
union emp_4 { // expected-warning {{union has size 0 in C, size 1 in C++}}
|
||||
int : 0;
|
||||
};
|
||||
|
||||
struct emp_5 { // expected-warning {{struct with only bit-fields of width 0 has size 0 in C, size 1 in C++}}
|
||||
struct emp_5 { // expected-warning {{struct has size 0 in C, size 1 in C++}}
|
||||
int : 0;
|
||||
int : 0;
|
||||
};
|
||||
|
||||
union emp_6 { // expected-warning {{union with only bit-fields of width 0 has size 0 in C, size 1 in C++}}
|
||||
union emp_6 { // expected-warning {{union has size 0 in C, size 1 in C++}}
|
||||
int : 0;
|
||||
int : 0;
|
||||
};
|
||||
|
||||
struct emp_7 { // expected-warning {{struct has size 0 in C, size 1 in C++}}
|
||||
struct emp_1 f1;
|
||||
};
|
||||
|
||||
union emp_8 { // expected-warning {{union has size 0 in C, size 1 in C++}}
|
||||
struct emp_1 f1;
|
||||
};
|
||||
|
||||
struct emp_9 { // expected-warning {{struct has size 0 in C, non-zero size in C++}}
|
||||
struct emp_1 f1;
|
||||
union emp_2 f2;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue