From 89be37b467850bf7c86dfe227352f09721092385 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 8 Aug 2017 18:07:17 +0000 Subject: [PATCH] Restore previous structure ABI behavior for bit-fields with the packed attribute for PS4 targets. An ABI change was introduced in r254596 that modified structure layouts when the 'packed' attribute was used on one-byte bitfields. Since the PS4 target needs to maintain backwards compatibility for all structure layouts, this change reintroduces the old behavior for PS4 targets only. It also introduces PS4 specific cases to the relevant test. Patch by Matthew Voss. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@310388 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 3 +++ lib/Sema/SemaDeclAttr.cpp | 28 ++++++++++++++++------ test/Sema/struct-packed-align.c | 14 ++++++++++- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a07be3f82c..74ea2d5fd5 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3202,6 +3202,9 @@ def warn_int_to_void_pointer_cast : Warning< "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 warn_no_underlying_type_specified_for_enum_bitfield : Warning< "enums in the Microsoft ABI are signed integers by default; consider giving " "the enum %0 an unsigned underlying type to make this code portable">, diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 6e29717643..cef84116db 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1304,14 +1304,28 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) { TD->addAttr(::new (S.Context) PackedAttr(Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); else if (FieldDecl *FD = dyn_cast(D)) { - // Report warning about changed offset in the newer compiler versions. - if (!FD->getType()->isDependentType() && - !FD->getType()->isIncompleteType() && FD->isBitField() && - S.Context.getTypeAlign(FD->getType()) <= 8) - S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield); + bool BitfieldByteAligned = (!FD->getType()->isDependentType() && + !FD->getType()->isIncompleteType() && + FD->isBitField() && + S.Context.getTypeAlign(FD->getType()) <= 8); + + if (S.getASTContext().getTargetInfo().getTriple().isPS4()) { + if (BitfieldByteAligned) + // The PS4 target needs to maintain ABI backwards compatibility. + 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())); + } else { + // Report warning about changed offset in the newer compiler versions. + if (BitfieldByteAligned) + S.Diag(Attr.getLoc(), diag::warn_attribute_packed_for_bitfield); + + FD->addAttr(::new (S.Context) PackedAttr( + Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); + } - FD->addAttr(::new (S.Context) PackedAttr( - Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } diff --git a/test/Sema/struct-packed-align.c b/test/Sema/struct-packed-align.c index abdcd8e6b9..aeba8d6fd9 100644 --- a/test/Sema/struct-packed-align.c +++ b/test/Sema/struct-packed-align.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 %s -fsyntax-only -verify // RUN: %clang_cc1 %s -fsyntax-only -triple=x86_64-windows-coff -verify +// RUN: %clang_cc1 %s -fsyntax-only -triple=x86_64-scei-ps4 -verify // Packed structs. struct s { @@ -146,13 +147,24 @@ extern int n2[__alignof(struct nS) == 1 ? 1 : -1]; // See the documentation of -Wpacked-bitfield-compat for more information. struct packed_chars { char a:4; +#ifdef __ORBIS__ + // Test for pre-r254596 clang behavior on the PS4 target. PS4 must maintain + // ABI backwards compatibility. + char b:8 __attribute__ ((packed)); + // expected-warning@-1 {{'packed' attribute ignored for field of type 'char'}} + char c:4; +#else char b:8 __attribute__ ((packed)); // expected-warning@-1 {{'packed' attribute was ignored on bit-fields with single-byte alignment in older versions of GCC and Clang}} char c:4; +#endif }; -#if defined(_WIN32) && !defined(__declspec) // _MSC_VER is unavailable in cc1. +#if (defined(_WIN32) || defined(__ORBIS__)) && !defined(__declspec) // _MSC_VER is unavailable in cc1. // On Windows clang uses MSVC compatible layout in this case. +// +// Additionally, test for pre-r254596 clang behavior on the PS4 target. PS4 +// must maintain ABI backwards compatibility. extern int o1[sizeof(struct packed_chars) == 3 ? 1 : -1]; extern int o2[__alignof(struct packed_chars) == 1 ? 1 : -1]; #else -- 2.40.0