http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60972
Bug ID: 60972 Summary: Mixing #pragma pack and __attribute__((packed)) leads to spurious warnings. Product: gcc Version: 4.9.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: toojays at toojays dot net ┌(toojays@kano)─(568)─(0)─(2014 04 26 10:35:27) └─(/tmp)─> /opt/gcc-4.9/bin/gcc --version | head -n1 gcc (GCC) 4.9.0 ┌(toojays@kano)─(569)─(0)─(2014 04 26 10:35:35) └─(/tmp)─> cat packed.cpp #include <cstdint> #include <type_traits> #pragma pack(push, 1) struct A { private: uint16_t x; uint32_t y; public: A () = default; A (uint16_t x_, uint32_t y_) : x(x_), y(y_) {} }; #pragma pack(pop) struct __attribute__((packed)) B { A xx; uint32_t yy; A zz; }; A a; B b; static_assert(std::is_pod<A>::value, "Expect A to be POD."); static_assert(std::is_pod<B>::value, "Expect B to be POD."); ┌(toojays@kano)─(570)─(0)─(2014 04 26 10:35:46) └─(/tmp)─> /opt/gcc-4.9/bin/gcc -std=c++11 -o packed.o -c packed.cpp -g packed.cpp:22:5: warning: ignoring packed attribute because of unpacked non-POD field ‘A B::xx’ A xx; ^ packed.cpp:26:5: warning: ignoring packed attribute because of unpacked non-POD field ‘A B::zz’ A zz; I have three problems with these warnings: 1) The warning claims that A is non-POD, but the type trait disagrees. 2) The warning claims that A is not-packed, but in fact it is. 3) Despite saying the attribute would be ignored, GCC went ahead and packed struct B anyway. I am on amd64. If B is not packed then B::yy would be aligned to a 4-byte boundary. Instead, the structures are packed, as shown: ┌(toojays@kano)─(571)─(0)─(2014 04 26 10:36:19) └─(/tmp)─> pahole packed.o die__process_class: tag not supported (template_type_parameter)! die__process_class: tag not supported (template_value_parameter)! struct A { private: uint16_t x; /* 0 2 */ uint32_t y; /* 2 4 */ void A(class A *); void A(class A *, uint16_t, uint32_t); /* size: 6, cachelines: 1, members: 2 */ /* last cacheline: 6 bytes */ }; struct B { struct A xx; /* 0 6 */ uint32_t yy; /* 6 4 */ struct A zz; /* 10 6 */ void B(class B *); /* size: 16, cachelines: 1, members: 3 */ /* last cacheline: 16 bytes */ }; If I consistently use #pragma or __attribute__ for both structures, GCC does not complain, and my structures are packed as I would expect.