1
- int foo (int * p , long * q ) {
1
+ int foo (int * p , void * * q ) {
2
2
* p = 1 ;
3
3
* q = 0 ;
4
4
return * p ;
5
5
}
6
6
int main () {
7
- long x ;
7
+ int x ;
8
8
return foo (& x , & x );
9
9
}
10
10
11
11
/*
12
- The usage in this example is essential systems programming but has undefined
13
- behavior according to ISO C due to the strict aliasing restriction.
12
+ The usage in this canonical example is essential to systems programming but has
13
+ undefined behavior according to ISO C due to the strict aliasing restriction.
14
14
15
- It returns 0 in the following invocations of clang 14.0.6 and gcc 12.2.0:
15
+ From the perspective that pointers are addresses and memory maps addresses to
16
+ bytes, we have two writes and one read of the same 4-byte memory region, and
17
+ main returns 0. Yet ISO C17 § 6.5.7 limits the lvalue types through which the
18
+ value of a declared object can be accessed to a fixed list of variations on the
19
+ declared type plus char. Here the declared type is int, so the modification
20
+ through *p is consistent with these rules, but the modification through *q (of
21
+ type void *) is not, even though int and void * have size and alignment. The
22
+ ubiquitous compiler flag -fno-strict-aliasing lifts these restrictions.
23
+
24
+ To show that this complication is relevant in practice, the example was tested
25
+ using clang 14.0.6, gcc 12.2.0, and CompCert a1f01c84 (3.11++).
26
+
27
+ It returns 0 in the following invocations:
16
28
17
- clang -O0 -w alias.c -o alias && ./alias; echo $?
18
- gcc -O0 -w alias.c -o alias && ./alias; echo $?
19
- gcc -O1 -w alias.c -o alias && ./alias; echo $?
20
- clang -fno-strict-aliasing -O1 -w alias.c -o alias && ./alias; echo $?
21
- clang -fno-strict-aliasing -O2 -w alias.c -o alias && ./alias; echo $?
22
- clang -fno-strict-aliasing -O3 -w alias.c -o alias && ./alias; echo $?
23
- gcc -fno-strict-aliasing -O2 -w alias.c -o alias && ./alias; echo $?
24
- gcc -fno-strict-aliasing -O3 -w alias.c -o alias && ./alias; echo $?
25
29
clang -m32 -O0 -w alias.c -o alias && ./alias; echo $?
26
30
gcc -m32 -O0 -w alias.c -o alias && ./alias; echo $?
27
31
gcc -m32 -O1 -w alias.c -o alias && ./alias; echo $?
@@ -31,17 +35,12 @@ clang -m32 -fno-strict-aliasing -O3 -w alias.c -o alias && ./alias; echo $?
31
35
gcc -m32 -fno-strict-aliasing -O2 -w alias.c -o alias && ./alias; echo $?
32
36
gcc -m32 -fno-strict-aliasing -O3 -w alias.c -o alias && ./alias; echo $?
33
37
34
- It also returns 0 with CompCert a1f01c844aaa0ff41aa9095e9d5d01606a0e90c9 (3.11++) :
38
+ It also returns 0 with CompCert:
35
39
36
40
../../CompCert/ccomp alias.c -c alias.o && gcc -m32 alias.o -o alias && ./alias; echo $?
37
41
38
- It returns 1 in the following invocations of clang 14.0.6 and gcc 12.2.0 :
42
+ It returns 1 in the following invocations:
39
43
40
- clang -O1 -w alias.c -o alias && ./alias; echo $?
41
- clang -O2 -w alias.c -o alias && ./alias; echo $?
42
- clang -O3 -w alias.c -o alias && ./alias; echo $?
43
- gcc -O2 -w alias.c -o alias && ./alias; echo $?
44
- gcc -O3 -w alias.c -o alias && ./alias; echo $?
45
44
clang -m32 -O1 -w alias.c -o alias && ./alias; echo $?
46
45
clang -m32 -O2 -w alias.c -o alias && ./alias; echo $?
47
46
clang -m32 -O3 -w alias.c -o alias && ./alias; echo $?
@@ -50,18 +49,10 @@ gcc -m32 -O3 -w alias.c -o alias && ./alias; echo $?
50
49
51
50
alias.v was generated using the following invocation:
52
51
53
- ../../CompCert/clightgen -dall -normalize -nostdinc -P -std=c11 alias.c
52
+ ../../CompCert/clightgen -dclight -normalize -nostdinc -P -std=c11 alias.c
54
53
55
- The corresponding clight file returns 0 in all tested invocations:
54
+ The corresponding clight file returns 0 in all invocations where the input file returned 0 :
56
55
57
- clang -O0 -w alias.light.c -o alias && ./alias; echo $?
58
- gcc -O0 -w alias.light.c -o alias && ./alias; echo $?
59
- gcc -O1 -w alias.light.c -o alias && ./alias; echo $?
60
- clang -fno-strict-aliasing -O1 -w alias.light.c -o alias && ./alias; echo $?
61
- clang -fno-strict-aliasing -O2 -w alias.light.c -o alias && ./alias; echo $?
62
- clang -fno-strict-aliasing -O3 -w alias.light.c -o alias && ./alias; echo $?
63
- gcc -fno-strict-aliasing -O2 -w alias.light.c -o alias && ./alias; echo $?
64
- gcc -fno-strict-aliasing -O3 -w alias.light.c -o alias && ./alias; echo $?
65
56
clang -m32 -O0 -w alias.light.c -o alias && ./alias; echo $?
66
57
gcc -m32 -O0 -w alias.light.c -o alias && ./alias; echo $?
67
58
gcc -m32 -O1 -w alias.light.c -o alias && ./alias; echo $?
@@ -70,11 +61,9 @@ clang -m32 -fno-strict-aliasing -O2 -w alias.light.c -o alias && ./alias; echo $
70
61
clang -m32 -fno-strict-aliasing -O3 -w alias.light.c -o alias && ./alias; echo $?
71
62
gcc -m32 -fno-strict-aliasing -O2 -w alias.light.c -o alias && ./alias; echo $?
72
63
gcc -m32 -fno-strict-aliasing -O3 -w alias.light.c -o alias && ./alias; echo $?
73
- clang -O1 -w alias.light.c -o alias && ./alias; echo $?
74
- clang -O2 -w alias.light.c -o alias && ./alias; echo $?
75
- clang -O3 -w alias.light.c -o alias && ./alias; echo $?
76
- gcc -O2 -w alias.light.c -o alias && ./alias; echo $?
77
- gcc -O3 -w alias.light.c -o alias && ./alias; echo $?
64
+
65
+ ... and returns 1 in all invocations where the input file returned 1:
66
+
78
67
clang -m32 -O1 -w alias.light.c -o alias && ./alias; echo $?
79
68
clang -m32 -O2 -w alias.light.c -o alias && ./alias; echo $?
80
69
clang -m32 -O3 -w alias.light.c -o alias && ./alias; echo $?
0 commit comments