summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2013-06-17 17:18:51 +0000
committerSerge Pavlov <sepavloff@gmail.com>2013-06-17 17:18:51 +0000
commitf7c1a2152ab6bb6be3ba5ab8558734afeeab91a7 (patch)
treef442713a6d22849e5f4f904fce5ad20f23b496c2 /clang
parent69817016cf79ba0dd171f89e7aae76bba81820a4 (diff)
downloadbcm5719-llvm-f7c1a2152ab6bb6be3ba5ab8558734afeeab91a7.tar.gz
bcm5719-llvm-f7c1a2152ab6bb6be3ba5ab8558734afeeab91a7.zip
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
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--clang/lib/Sema/SemaDecl.cpp28
-rw-r--r--clang/test/CodeGen/override-layout.c42
-rw-r--r--clang/test/Sema/empty1.c21
4 files changed, 50 insertions, 47 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index cb207a6c6dc..7be10c8e706 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 92e0042bccd..e62834ba1da 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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();
diff --git a/clang/test/CodeGen/override-layout.c b/clang/test/CodeGen/override-layout.c
index 99c2cd656ec..8a108a9f50c 100644
--- a/clang/test/CodeGen/override-layout.c
+++ b/clang/test/CodeGen/override-layout.c
@@ -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);
diff --git a/clang/test/Sema/empty1.c b/clang/test/Sema/empty1.c
index cd4aca8e473..d716ba52bb4 100644
--- a/clang/test/Sema/empty1.c
+++ b/clang/test/Sema/empty1.c
@@ -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;
+};
OpenPOWER on IntegriCloud