aboutsummaryrefslogtreecommitdiffstats
path: root/test/regression/alias.c
diff options
context:
space:
mode:
authorXavier Leroy <xavier.leroy@inria.fr>2015-07-19 17:08:17 +0200
committerXavier Leroy <xavier.leroy@inria.fr>2015-07-19 17:35:54 +0200
commit26f63d2d82d22f568ba44d12d396acca8aa11613 (patch)
treed3f73d604b03958434c8527ee059ac728e5c164b /test/regression/alias.c
parent78f1b6a57c95ecc68c104d4764fc8d5851d7dd54 (diff)
downloadcompcert-kvx-26f63d2d82d22f568ba44d12d396acca8aa11613.tar.gz
compcert-kvx-26f63d2d82d22f568ba44d12d396acca8aa11613.zip
Test to check that alias analysis is prudently conservative on ill-defined pointer manipulations.
Diffstat (limited to 'test/regression/alias.c')
-rw-r--r--test/regression/alias.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/test/regression/alias.c b/test/regression/alias.c
new file mode 100644
index 00000000..c9eb8130
--- /dev/null
+++ b/test/regression/alias.c
@@ -0,0 +1,145 @@
+/* Testing the alias analysis on ill-defined codes
+ where it should remain conservative. */
+
+typedef unsigned int uintptr_t;
+
+/* For testing with GCC */
+#define NOINLINE __attribute__((noinline))
+
+/* Passing a pointer through a long long */
+
+void NOINLINE set1(long long x)
+{
+ int * p = (int *) (uintptr_t) x;
+ *p = 1;
+}
+
+int get1(void)
+{
+ int x = 0;
+ set1((uintptr_t) &x);
+ return x;
+}
+
+/* Passing a pointer through a double */
+
+void NOINLINE set2(double x)
+{
+ int * p = (int *) (uintptr_t) x;
+ *p = 1;
+}
+
+int get2(void)
+{
+ int x = 0;
+ set2((uintptr_t) &x);
+ return x;
+}
+
+/* Tagging a pointer */
+
+void NOINLINE set3(uintptr_t x)
+{
+ int * p = (int *) (x & ~1);
+ *p = 1;
+}
+
+int get3(void)
+{
+ int x = 0;
+ set3((uintptr_t) &x | 1);
+ return x;
+}
+
+/* XOR-ing a pointer */
+
+static uintptr_t key = 0xDEADBEEF;
+
+void NOINLINE set4(uintptr_t x)
+{
+ int * p = (int *) (x ^ key);
+ *p = 1;
+}
+
+int get4(void)
+{
+ int x = 0;
+ set4((uintptr_t) &x ^ key);
+ return x;
+}
+
+/* Byte-swapping a pointer */
+
+inline uintptr_t bswap(uintptr_t x)
+{
+ return (x >> 24)
+ | (((x >> 16) & 0xFF) << 8)
+ | (((x >> 8) & 0xFF) << 16)
+ | ((x & 0xFF) << 24);
+}
+
+void NOINLINE set5(uintptr_t x)
+{
+ int * p = (int *) bswap(x);
+ *p = 1;
+}
+
+int get5(void)
+{
+ int x = 0;
+ set5(bswap((uintptr_t) &x));
+ return x;
+}
+
+/* Even more fun with xor */
+
+int x;
+
+void NOINLINE set6(int * p, uintptr_t z)
+{
+ int * q = (int *) ((uintptr_t) p ^ z);
+ *q = 1;
+}
+
+int get6(void)
+{
+ int y = 0;
+ uintptr_t z = (uintptr_t) &x ^ (uintptr_t) &y;
+ set6(&x, z);
+ int res1 = y;
+ x = 0;
+ set6(&y, z);
+ int res2 = x;
+ return res1 & res2;
+}
+
+/* Aligning pointers the hard way */
+
+int offset = 3; /* but not const */
+
+int get7(void)
+{
+ union { int i; char c[4]; } u; /* force alignment to 4 */
+ u.c[0] = 0;
+ uintptr_t x = (uintptr_t) &(u.c[offset]);
+ x = x & ~3;
+ *((char *) x) = 1;
+ return u.c[0];
+}
+
+/* Test harness */
+
+#include <stdio.h>
+
+int main()
+{
+ printf("Test 1: %d\n", get1());
+ printf("Test 2: %d\n", get2());
+ printf("Test 3: %d\n", get3());
+ printf("Test 4: %d\n", get4());
+ printf("Test 5: %d\n", get5());
+ printf("Test 6: %d\n", get6());
+ printf("Test 7: %d\n", get7());
+ return 0;
+}
+