diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4f8165bbc8ee5..aa9a8a60e586d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -111,6 +111,12 @@ Resolutions to C++ Defect Reports - Implemented `DR2397 `_ which allows ``auto`` specifier for pointers and reference to arrays. +Warnings +^^^^^^^^ +- Address a false positive in ``-Wpacked`` when applied to a non-pod type using + Clang ABI >= 15 (fixes `#62353`_, + fallout from the non-POD packing ABI fix in LLVM 15) + C Language Changes ------------------ - Support for outputs from asm goto statements along indirect edges has been diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 641e9d62149e9..aca50912dceac 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2198,11 +2198,19 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) { << (InBits ? 1 : 0); // (byte|bit) } + const auto *CXXRD = dyn_cast(RD); + // Warn if we packed it unnecessarily, when the unpacked alignment is not // greater than the one after packing, the size in bits doesn't change and // the offset of each field is identical. + // Unless the type is non-POD (for Clang ABI > 15), where the packed + // attribute on such a type does allow the type to be packed into other + // structures that use the packed attribute. if (Packed && UnpackedAlignment <= Alignment && - UnpackedSizeInBits == getSizeInBits() && !HasPackedField) + UnpackedSizeInBits == getSizeInBits() && !HasPackedField && + (!CXXRD || CXXRD->isPOD() || + Context.getLangOpts().getClangABICompat() <= + LangOptions::ClangABI::Ver15)) Diag(D->getLocation(), diag::warn_unnecessary_packed) << Context.getTypeDeclType(RD); } diff --git a/clang/test/CodeGenCXX/warn-padded-packed.cpp b/clang/test/CodeGenCXX/warn-padded-packed.cpp index cf4890e40005d..c51a6c9443f6e 100644 --- a/clang/test/CodeGenCXX/warn-padded-packed.cpp +++ b/clang/test/CodeGenCXX/warn-padded-packed.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple=x86_64-none-none -Wpadded -Wpacked -verify %s -emit-llvm-only +// RUN: %clang_cc1 -triple=x86_64-none-none -Wpadded -Wpacked -verify=expected,top %s -emit-llvm-only +// RUN: %clang_cc1 -triple=x86_64-none-none -Wpadded -Wpacked -verify=expected,abi15 -fclang-abi-compat=15 %s -emit-llvm-only struct S1 { char c; @@ -154,7 +155,7 @@ struct S28 { char c1; short s1; char c2; - S28_non_pod p1; // expected-warning {{not packing field 'p1' as it is non-POD for the purposes of layout}} + S28_non_pod p1; // top-warning {{not packing field 'p1' as it is non-POD for the purposes of layout}} } __attribute__((packed)); struct S29_non_pod_align_1 { @@ -167,6 +168,16 @@ struct S29 { } __attribute__((packed)); // no warning static_assert(alignof(S29) == 1, ""); +struct S30 { +protected: + short s; +} __attribute__((packed)); // no warning +struct S30_use { // abi15-warning {{packed attribute is unnecessary for 'S30_use'}} + char c; + S30 u; +} __attribute__((packed)); +static_assert(sizeof(S30_use) == 3, ""); + // The warnings are emitted when the layout of the structs is computed, so we have to use them. void f(S1*, S2*, S3*, S4*, S5*, S6*, S7*, S8*, S9*, S10*, S11*, S12*, S13*, S14*, S15*, S16*, S17*, S18*, S19*, S20*, S21*, S22*, S23*, S24*, S25*, diff --git a/clang/test/Layout/aix-Wpacked-expecting-diagnostics.cpp b/clang/test/Layout/aix-Wpacked-expecting-diagnostics.cpp index 37982fcb74b96..1576b8561cb56 100644 --- a/clang/test/Layout/aix-Wpacked-expecting-diagnostics.cpp +++ b/clang/test/Layout/aix-Wpacked-expecting-diagnostics.cpp @@ -6,6 +6,8 @@ // RUN: -fdump-record-layouts -fsyntax-only -verify -x c++ < %s | \ // RUN: FileCheck %s +// expected-no-diagnostics + struct A { double d; }; @@ -14,7 +16,7 @@ struct B { char x[8]; }; -struct [[gnu::packed]] C : B, A { // expected-warning{{packed attribute is unnecessary for 'C'}} +struct [[gnu::packed]] C : B, A { char x alignas(4)[8]; };