Search code examples
c++gccdeserialization

std::complex and GCC's g++: ignoring packed attribute because of unpacked non-POD field


I'm trying to write a C++ library, which is going to target an ARM Linux system, but leaving C-compatible "bindings" and structs for using with CFFI on other languages.

The library deals with a serial stream that I don't control, and that I want to de-serialize.

I have the following (simplified) struct on stream.h:

#pragma once 

#include "cpp_compat.h"

#include <stdbool.h>
#include <stdint.h>

#define BB_FRAME_IQ_SAMPLES_COUNT 512
#define BB_FRAME_MAGIC 0xAA5555AA

#ifdef __cplusplus
extern "C"
{
#endif

    typedef struct __attribute__((__packed__))
    {
        /** Every frame starts with BB_FRAME_MAGIC. */
        uint32_t magic;

        /** Baseband IQ samples. */
        fcomplex_t bb_iq_samples[BB_FRAME_IQ_SAMPLES_COUNT];

        uint8_t someparams[9]; // simplification

        uint32_t reserved_n[6];

        uint32_t crc;
    } bb_frame_t;

#ifdef __cplusplus
}
#endif

fcomplex_t is where the C/C++ compatibility happens, thanks to cpp_compat.h:

#pragma once

#ifdef __cplusplus
#include <complex>

using fcomplex_t = std::complex<float>;

#else
#include <complex.h>

typedef _Complex float fcomplex_t;

#endif

However, I'm having this warning when building the code in C++:

[build] stream.h:41:37: warning: ignoring packed attribute because of unpacked non-POD field ‘fcomplex_t <unnamed struct>::bb_iq_samples [512]’
[build]    41 |         fcomplex_t bb_iq_samples[BB_FRAME_IQ_SAMPLES_COUNT];
[build]       |                    ^~~~~~~~~~~~~

And this scares me because I really need the packed attribute to work to correctly de-serialize the frames from the serial stream.

The compiler is arm-linux-gnueabihf-g++ (GCC) 12.2.1 20221203 [releases/gcc-12 revision c03cb4b762aceeba95da918b042583af0d9f6030]. I got it from a buildroot using the Linaro toolchain.

So the question is, how can I make this work without errors?

P.S.: It's worth noting that the C++ standard guarantees that std::complex<float> and _Complex float are memory-compatible.

EDIT 1: In the meanwhile, I found out that x86's GCC also complains about the issue but Clang (tested with version 16) does not. Seems to be something GCC-specific.


Solution

  • Raised the problem on GCC.

    It's apparently an intended behaviour of the compiler.

    More details in https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108342