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 @@ -1887,7 +1887,8 @@ UnfilledBitsInLastUnit = 0; LastBitfieldStorageUnitSize = 0; - bool FieldPacked = Packed || D->hasAttr(); + bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD())) || + D->hasAttr(); AlignRequirementKind AlignRequirement = AlignRequirementKind::None; CharUnits FieldSize; diff --git a/clang/test/SemaCXX/address-packed.cpp b/clang/test/SemaCXX/address-packed.cpp --- a/clang/test/SemaCXX/address-packed.cpp +++ b/clang/test/SemaCXX/address-packed.cpp @@ -121,3 +121,19 @@ Incomplete *e() const; } __attribute__((packed)); Incomplete *S2::e() const { return (Incomplete *)&d; } // no-warning + + +namespace non_classic_pod { +struct t1 { protected: int a; }; +static_assert(alignof(t1) == 4, ""); +// GCC prints warning: ignoring packed attribute because of unpacked non-POD field 't1 t2::f'` +struct t2 { t1 v1; } __attribute__((packed)); +static_assert(alignof(t2) == 4, ""); +} // namespace non_classic_pod + +namespace non_classic_pod_packed { +struct t1 { protected: int a; } __attribute__((packed)); +static_assert(alignof(t1) == 1, ""); +struct t2 { t1 v1; } __attribute__((packed)); +static_assert(alignof(t2) == 1, ""); +} // namespace non_classic_pod_packed