Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -2777,9 +2777,10 @@ "cast to %1 from smaller integer type %0">, InGroup; -def warn_attribute_ignored_for_field_of_type : Warning< - "%0 attribute ignored for field of type %1">, - InGroup; +def note_attribute_packed_for_bitfield_semantics_changed : Warning< + "offset of packed bit-field %0 has changed with GCC version 4.4 - " + "the newer semantic is provided here">, + InGroup>; def warn_transparent_union_attribute_field_size_align : Warning< "%select{alignment|size}0 of field %1 (%2 bits) does not match the " "%select{alignment|size}0 of the first field in transparent union; " Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -1040,13 +1040,15 @@ // has no effect. if (!FD->getType()->isDependentType() && !FD->getType()->isIncompleteType() && + FD->isBitField() && S.Context.getTypeAlign(FD->getType()) <= 8) - S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) - << Attr.getName() << FD->getType(); - else - FD->addAttr(::new (S.Context) - PackedAttr(Attr.getRange(), S.Context, - Attr.getAttributeSpellingListIndex())); + S.Diag(Attr.getLoc(), + diag::note_attribute_packed_for_bitfield_semantics_changed) + << FD->getDeclName(); + + FD->addAttr(::new (S.Context) + PackedAttr(Attr.getRange(), S.Context, + Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } Index: test/Sema/struct-packed-align.c =================================================================== --- test/Sema/struct-packed-align.c +++ test/Sema/struct-packed-align.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify -// expected-no-diagnostics +// RUN: %clang_cc1 %s -fsyntax-only -triple=x86_64-windows-coff -verify // Packed structs. struct s { @@ -138,3 +138,24 @@ extern int n1[sizeof(struct nS) == 9 ? 1 : -1]; extern int n2[__alignof(struct nS) == 1 ? 1 : -1]; #endif + +// Packed attribute shouldn't be ignored for bit-field of char types. +// Note from GCC reference manual: The 4.1, 4.2 and 4.3 series of GCC ignore +// the packed attribute on bit-fields of type char. This has been fixed in +// GCC 4.4 but the change can lead to differences in the structure layout. +// See the documentation of -Wpacked-bitfield-compat for more information. +struct packed_chars { + char a:4; + char b:8 __attribute__ ((packed)); + // expected-warning@-1 {{offset of packed bit-field 'b' has changed with GCC version 4.4 - the newer semantic is provided here}} + char c:4; +}; + +#if defined(_WIN32) +// On Windows clang ignores uses MSVC compatible layout in this case. +extern int o1[sizeof(struct packed_chars) == 3 ? 1 : -1]; +extern int o2[__alignof(struct packed_chars) == 1 ? 1 : -1]; +#else +extern int o1[sizeof(struct packed_chars) == 2 ? 1 : -1]; +extern int o2[__alignof(struct packed_chars) == 1 ? 1 : -1]; +#endif