https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85800
Bug ID: 85800 Summary: A miscompilation bug with unsigned char Product: gcc Version: 7.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: juneyoung.lee at sf dot snu.ac.kr Target Milestone: --- Created attachment 44136 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44136&action=edit A source file that raises the bug. ``` $ cat test-main.c #include <string.h> #include <stdio.h> #include <stdint.h> // If f(A, B + 4) is given, and integer representation of A and B + 4 // are the same, c1 == c2 in the loop becomes true, // so arr3 = arr1. Hence r = A, and *A should be 10. // However, if compiled with -O3, *A is still 1. void store_10_to_p(int *p, int *q) { unsigned char arr1[8]; unsigned char arr2[8]; unsigned char arr3[8]; // Type punning with char* is allowed. memcpy((unsigned char*)arr1, (unsigned char *)&p, sizeof(p)); memcpy((unsigned char*)arr2, (unsigned char *)&q, sizeof(q)); // Now arr1 is p, arr2 is q. for (int i = 0; i < sizeof(q); i++) { int c1 = (int)arr1[i], c2 = (int)arr2[i]; // Note that c1 == c2 is a comparison between _integers_ (not pointers). if (c1 == c2) // Always true if p and q have same integer representation. arr3[i] = arr1[i]; else arr3[i] = arr2[i]; } // Now arr3 is equivalent to arr1, which is p. int *r; memcpy(&r, (unsigned char *)arr3, sizeof(r)); // Now r is p. *p = 1; *r = 10; } int main() { int B[4], A[4]; printf("%p %p\n", A, &B[4]); store_10_to_p(A, &B[4]); printf("%d\n", A[0]); return 0; } $ gcc -O3 -o test-main test-main.c $ ./test-main 0x7fffffffe5a0 0x7fffffffe5a0 1 $ gcc -O0 -o test-main test-main.c $ ./test-main 0x7fffffffe5b0 0x7fffffffe5b0 10 ``` The output should be 10 because the integral representation of A and B[4] are the same, but compiling with -O3 gives 1.