diff options
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 28 | ||||
| -rw-r--r-- | clang/test/CodeGen/override-layout.c | 42 | ||||
| -rw-r--r-- | clang/test/Sema/empty1.c | 21 | 
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; +};  | 

