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.

Reply via email to