┌(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.
Confirmed. Another problem with the warnings is that there's no flag controlling them. I'd expect one of -Wno-packed, -Wno-attributes, or -Wno-ignored-attributes to disable the warning, but none of them do so.
cc-ing C++ FE maintainers
(In reply to Eric Gallager from comment #1) > Confirmed. Another problem with the warnings is that there's no flag > controlling them. I'd expect one of -Wno-packed, -Wno-attributes, or > -Wno-ignored-attributes to disable the warning, but none of them do so. That part makes this fall under bug 44209
The master branch has been updated by Sandra Loosemore <sandra@gcc.gnu.org>: https://gcc.gnu.org/g:a2e03736fc932ef613ad01a9499126cbaa538bf8 commit r15-9155-ga2e03736fc932ef613ad01a9499126cbaa538bf8 Author: Sandra Loosemore <sloosemore@baylibre.com> Date: Wed Apr 2 18:20:35 2025 +0000 Doc: #pragma pack documentation cleanup [PR114957] [PR78008] [PR60972] This patch addresses a number of issues with the documentation of - None of the things in this section had @cindex entries [PR114957]. - The document formatting didn't match that of other #pragma documentation sections. - The effect of #pragma pack(0) wasn't documented [PR78008]. - There's a long-standing bug [PR60972] reporting that #pragma pack and the __attribute__(packed) don't get along well. It seems worthwhile to warn users about that since elsewhere pragmas are cross-referenced with related or equivalent attributes. gcc/ChangeLog PR c/114957 PR c/78008 PR c++/60972 * doc/extend.texi (Structure-Layout Pragmas): Add @cindex entries and reformat the pragma descriptions to match the markup used for other pragmas. Document what #pragma pack(0) does. Add cross-references to similar attributes.
I've updated the manual to document that this doesn't work, and say "don't do that". However, the actual bug is not fixed. If anyone ever does so, please address the FIXME in extend.texi.