https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89519
Bug ID: 89519 Summary: POD data member fails to be packed; G++ incorrectly claims it is non-POD Product: gcc Version: 8.3.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: gcc at mattwhitlock dot name Target Milestone: --- /* === BEGIN TEST CASE === */ #include <type_traits> class S { int i; }; struct P { char c; S s; } __attribute__ ((packed)); static_assert(std::is_pod<S>::value, "S should be a POD type"); static_assert(sizeof(P) == sizeof(char) + sizeof(S), "P should be packed"); /* === END TEST CASE === */ $ g++ -c test.cpp test.cpp:9:4: warning: ignoring packed attribute because of unpacked non-POD field 'S P::s' S s; ^ test.cpp:13:25: error: static assertion failed: P should be packed static_assert(sizeof(P) == sizeof(char) + sizeof(S), "P should be packed"); ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~ As you can see, S is indeed a POD type, as evidenced by std::is_pod<S>::value being true, yet the compiler fails to pack it. This may be due to a discrepancy between C++'s definition of a POD type and G++'s internal concept of "POD for the purpose of layout," as explained in Bug 83732 Comment 3. Workaround: changing the access control of S::i to public (for example by changing "class S" to "struct S") makes G++ pack P::s correctly. However, this should not be necessary, as the standard only requires all non-static data members in a standard-layout type to have the *same* access control, which need not be public.