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.