[PATCH] Warn on zero-sized structures inside extern "C" block (PR5065)
Richard Smith
richard at metafoo.co.uk
Tue Nov 12 12:04:14 PST 2013
================
Comment at: include/clang/Basic/DiagnosticSemaKinds.td:5721
@@ -5720,1 +5720,3 @@
InGroup<CXXCompat>, DefaultIgnore;
+def warn_zero_size_struct_union : Warning<"%select{|empty }0"
+ "%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">,
----------------
Maybe name this `warn_..._union_in_extern_c` or similar?
================
Comment at: lib/Sema/SemaDecl.cpp:12074-12075
@@ +12073,4 @@
+ // For C++ filter out types that cannot be referenced in C code.
+ if (Record->getLexicalDeclContext()->isExternCContext() &&
+ !Record->isDependentType()) {
+ if (CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(Record)) {
----------------
You could also check that `Record->getDeclContext()->getRedeclContext()->isFileContext()` here (that is, it's not a local class nor a member class).
================
Comment at: lib/Sema/SemaDecl.cpp:12076
@@ +12075,3 @@
+ !Record->isDependentType()) {
+ if (CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(Record)) {
+ CheckForZeroSize =
----------------
This is redundant. In `CPlusPlus` mode, every `RecordDecl` is a `CXXRecordDecl`.
================
Comment at: lib/Sema/SemaDecl.cpp:12105
@@ -12082,1 +12104,3 @@
+ FieldType->isDependentType() ||
+ FieldType->isUndeducedType() ||
!Context.getTypeSizeInChars(FieldType).isZero())
----------------
Non-static data members can't have deduced types, so this is impossible.
================
Comment at: lib/Sema/SemaDecl.cpp:12111-12132
@@ -12086,16 +12110,24 @@
- // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
- // C++.
- if (ZeroSize)
- Diag(RecLoc, diag::warn_zero_size_struct_union_compat) << IsEmpty
- << Record->isUnion() << (NonBitFields > 1);
+ if (!getLangOpts().CPlusPlus) {
+ // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed
+ // in C++.
+ 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 (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();
+ // Structs without named members are extension in C (C99 6.7.2.1p7), but
+ // are accepted by GCC.
+ 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();
+ }
+ } else if (ZeroSize) {
+ // Empty structs are OK in C++ but will warn if its declaration is inside
+ // extern "C" block.
+ Diag(RecLoc, diag::warn_zero_size_struct_union) << IsEmpty
+ << Record->isUnion() << (NonBitFields > 1);
}
}
----------------
It would be simpler to organize this as:
if (ZeroSize)
Diag(..., getLangOpts().CPlusPlus ? diag::..._extern_c : diag::..._compat) ...
if (NonBitFields == 0 && !getLangOpts().CPlusPlus) {
...
}
http://llvm-reviews.chandlerc.com/D2151
More information about the cfe-commits
mailing list