[PATCH] Fix recognition of empty structures/unions

Serge Pavlov sepavloff at gmail.com
Tue Mar 26 09:46:55 PDT 2013


sepavloff added you to the CC list for the revision "Fix recognition of empty structures/unions".

Hi all,

This change fixes the recognition of empty structures/unions so that a structure with a bit field of zero length is correctly recognized as empty. To make it possible, the recognition is moved from parser to semantic analyzer. The fix is required to correctly warn about issues with C/C++ compatibility.

Could someone please review this fix?
Thank you.
--Serge

http://llvm-reviews.chandlerc.com/D578

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Parse/ParseDecl.cpp
  lib/Sema/SemaDecl.cpp
  test/Sema/empty.c

Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -50,10 +50,6 @@
   "complex integer types are a GNU extension">, InGroup<GNU>;
 def ext_thread_before : Extension<"'__thread' before '%0'">;
 
-def ext_empty_struct_union : Extension<
-  "empty %select{struct|union}0 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 error_empty_enum : Error<"use of empty enum">;
 def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">;
 def err_invalid_short_spec : Error<"'short %0' is invalid">;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -5285,6 +5285,10 @@
 
 def err_typecheck_cond_incompatible_operands_null : Error<
   "non-pointer operand type %0 incompatible with %select{NULL|nullptr}1">;
+def ext_empty_struct_union : Extension<
+  "empty %select{struct|union}0 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;
 } // End of general sema category.
 
 // inline asm.
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -3065,13 +3065,6 @@
   ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
   Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
 
-  // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
-  // C++.
-  if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus) {
-    Diag(Tok, diag::ext_empty_struct_union) << (TagType == TST_union);
-    Diag(Tok, diag::warn_empty_struct_union_compat) << (TagType == TST_union);
-  }
-
   SmallVector<Decl *, 32> FieldDecls;
 
   // While we still have something to read, read the declarations in the struct.
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10775,6 +10775,21 @@
         if (IFD->getDeclName())
           ++NumNamedMembers;
     }
+
+    if (!getLangOpts().CPlusPlus) {
+      bool  is_empty = true;
+      for (RecordDecl::field_iterator i = Record->field_begin(),
+                                      e = Record->field_end(); is_empty && i != e; ++i) {
+        if (!i->isBitField() || i->getBitWidthValue(Context) > 0)
+          is_empty = false;
+      }
+      if (is_empty) {
+        // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
+        // C++.
+        Diag(RecLoc, diag::ext_empty_struct_union) << Record->isUnion();
+        Diag(RecLoc, diag::warn_empty_struct_union_compat) << Record->isUnion();
+      }
+    }
   }
 
   // Verify that all the fields are okay.
Index: test/Sema/empty.c
===================================================================
--- /dev/null
+++ test/Sema/empty.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify -Wc++-compat
+
+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 {{empty struct has size 0 in C, size 1 in C++}}
+  int : 0;
+};
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D578.1.patch
Type: text/x-patch
Size: 3641 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130326/23616bca/attachment.bin>


More information about the cfe-commits mailing list