compiling the following fragment: typedef struct pseudoheader /* pseudo header for TCP checksum calculations */ { unsigned int sip, dip; unsigned char zero; unsigned char protocol; unsigned short tcplen; } ph_struct; static inline unsigned short in_chksum_tcp( unsigned short *h) { unsigned int cksum; /* PseudoHeader must have 12 bytes */ cksum = h[0]; cksum += h[1]; /* [1] */ cksum += h[2]; cksum += h[3]; cksum += h[4]; cksum += h[5]; return cksum; } int main() { unsigned short a, b; ph_struct ph; union pseudoheader_union{ ph_struct ph; unsigned short a[6]; } p; ph.sip = 0xa0a44d4; /* [2] */ ph.dip = 0xf50ac610; ph.zero = 0; ph.protocol = 0x06; ph.tcplen = 1216; a = in_chksum_tcp(&ph); p.ph.sip = 0xa0a44d4; p.ph.dip = 0xf50ac610; p.ph.zero = 0; p.ph.protocol = 0x06; p.ph.tcplen = 1216; b = in_chksum_tcp(p.a); printf("CHKSUM: %hx %hx %d\n", a, b, sizeof(ph)); return 0; }
with: gcc -O2 the value calulated in the first invocation of in_chksum_tcp function is wrong this is NOT related to what is described in http://gcc.gnu.org/bugs.html#nonbugs_c for breaking aliasing rules. It seems that the compiler, while generating the assembly code, inverts an assignment operation (marked with [2] in the c code fragment) with the sum operation (marked with [1] in the c code fragment). -- Summary: generate wrong code with hi optimization Product: gcc Version: 3.4.1 Status: UNCONFIRMED Severity: normal Priority: P1 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: paolo dot abeni at tilab dot com CC: gcc-bugs at gcc dot gnu dot org GCC build triplet: i586-madrake-linux-gnu GCC host triplet: i586-madrake-linux-gnu GCC target triplet: i586-madrake-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18806