In the function
size_t csps_socket_read(csps_socket_t *s, csps_packet_wrapper_t *packet, size_t sz)
I get the warning: "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]" on the following line:
packet_size = ((csps_packet_full_header_t *)s->receive_mem)->size + header_size;
If I rewrite like this:
csps_packet_full_header_t *packet_full_header = (csps_packet_full_header_t *)s->receive_mem;
packet_size = packet_full_header->size + header_size;
I get no warning. Why? Is the problem still there but gcc can't see it?
Here's the structs involved:
typedef struct csps_socket_t_
{
void* fp;
bool open;
uint8_t receive_mem[CSPS_SOCKET_MEM];
uint32_t receive_index;
} csps_socket_t;
typedef struct ATTR_PACKED csps_packet_full_header_t_
{
uint8_t version:4;
uint8_t pclass:4;
uint8_t ch:1;
uint8_t reserved:7;
uint16_t size;
uint16_t sequence;
uint16_t checksum;
uint8_t src[8];
uint8_t dst[8];
} csps_packet_full_header_t;
Basically this is a bug in GCC's -Wstrict-aliasing
machinery. It's known to both produce false warnings and miss real aliasing violations (see this comment from developers).
The problem is there in both cases, casting unrelated structs will violate aliasing rules and will likely cause GCC to produce unexpected code.