/* === 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.
C++98 says S is non POD. This is why the difference comes into play. To be abi compatible with the two language options it needs to be that way.
If there is a change, then using two sources one compiled with -std=c++98 and one with -std=c++11 (or later) will not be ABI compatible.
(In reply to Andrew Pinski from comment #2) > If there is a change, then using two sources one compiled with -std=c++98 > and one with -std=c++11 (or later) will not be ABI compatible. ABI compatibility isn't guaranteed across C++ language standards anyway, is it? For instance, the ABI of std::string differs between C++98 and C++11.
(In reply to Matt Whitlock from comment #3) > ABI compatibility isn't guaranteed across C++ language standards anyway, is > it? For instance, the ABI of std::string differs between C++98 and C++11. What you are thinking about is the old std::string and the new C++11 compatible std::string. std::string is not different between C++98 and C++11 in GCC; both use the new std::string.
I found this: https://gcc.gnu.org/ml/gcc/2012-01/msg00056.html It seems pretty resolute. I guess that means this report is a WONTFIX. For what it's worth, having two conflicting definitions of "POD" is confusing.
(In reply to Matt Whitlock from comment #3) > For instance, the ABI of std::string differs between C++98 and C++11. No it doesn't. https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
(In reply to Matt Whitlock from comment #0) > test.cpp:9:4: warning: ignoring packed attribute because of unpacked non-POD > field 'S P::s' I think this diagnostic would be improved if it said "ignoring packed attribute because of unpacked field 'S P::s' which is not POD for the purposes of layout" That would refer to the term from the ABI spec that is relevant to class layout, which is not the same as the property tested by std::is_pod. (In reply to Matt Whitlock from comment #5) > For what it's worth, having two conflicting definitions of "POD" is > confusing. The std::is_pod trait is deprecated in the C++2a draft, and the clauses describing the core language no longer use the term POD at all.