Bug 89519 - POD data member fails to be packed; G++ incorrectly claims it is non-POD
Summary: POD data member fails to be packed; G++ incorrectly claims it is non-POD
Status: RESOLVED WONTFIX
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 8.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-02-27 15:36 UTC by Matt Whitlock
Modified: 2019-02-27 20:05 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matt Whitlock 2019-02-27 15:36:55 UTC
/* === 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.
Comment 1 Andrew Pinski 2019-02-27 18:00:35 UTC
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.
Comment 2 Andrew Pinski 2019-02-27 18:03:43 UTC
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.
Comment 3 Matt Whitlock 2019-02-27 18:06:20 UTC
(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.
Comment 4 Andrew Pinski 2019-02-27 18:28:07 UTC
(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.
Comment 5 Matt Whitlock 2019-02-27 19:03:09 UTC
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.
Comment 6 Jonathan Wakely 2019-02-27 19:57:56 UTC
(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
Comment 7 Jonathan Wakely 2019-02-27 20:05:10 UTC
(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.