diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -590,6 +590,8 @@ InGroup, DefaultIgnore; def warn_unnecessary_packed : Warning< "packed attribute is unnecessary for %0">, InGroup, DefaultIgnore; +def warn_unpacked_field : Warning< + "not packing field %0 as it is non-POD">, InGroup, DefaultIgnore; // -Wunaligned-access def warn_unaligned_access : Warning< diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1888,11 +1888,17 @@ LastBitfieldStorageUnitSize = 0; llvm::Triple Target = Context.getTargetInfo().getTriple(); - bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() || - Context.getLangOpts().getClangABICompat() <= - LangOptions::ClangABI::Ver13 || - Target.isPS4() || Target.isOSDarwin())) || - D->hasAttr(); + bool FieldPacked = Packed; + if (FieldPacked && FieldClass && !FieldClass->isPOD() && + Context.getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver13 && + !Target.isPS4() && !Target.isOSDarwin()) { + Diag(D->getLocation(), diag::warn_unpacked_field) << D; + FieldPacked = false; + } + + if (!FieldPacked && D->hasAttr()) + FieldPacked = true; AlignRequirementKind AlignRequirement = AlignRequirementKind::None; CharUnits FieldSize; diff --git a/clang/test/CodeGenCXX/warn-padded-packed.cpp b/clang/test/CodeGenCXX/warn-padded-packed.cpp --- a/clang/test/CodeGenCXX/warn-padded-packed.cpp +++ b/clang/test/CodeGenCXX/warn-padded-packed.cpp @@ -146,8 +146,18 @@ unsigned char b : 8; } __attribute__((packed)); +struct S28_non_pod { + protected: + int i; +}; +struct S28 { + char c1; + short s1; + char c2; + S28_non_pod p1; // expected-warning {{not packing field 'p1' as it is non-POD}} +} __attribute__((packed)); // 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*, - S26*, S27*){} + S26*, S27*, S28*){}