aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/validation
diff options
Diffstat (limited to 'validation')
-rw-r--r--validation/Waddress-weak.c2
-rw-r--r--validation/Waddress.c4
-rw-r--r--validation/array-implicit-size.c26
-rw-r--r--validation/bug-bad-type.c18
-rw-r--r--validation/builtin-arith.c52
-rw-r--r--validation/constexpr-preop.c2
-rw-r--r--validation/empty-expr.c26
-rw-r--r--validation/function-pointer-type.c12
-rw-r--r--validation/linear/bitfield-expand-deref.c27
-rw-r--r--validation/linear/call-basic.c57
-rw-r--r--validation/linear/call-builtin.c17
-rw-r--r--validation/linear/call-casted-pointer.c31
-rw-r--r--validation/linear/call-complex-pointer.c32
-rw-r--r--validation/linear/call-direct.c17
-rw-r--r--validation/linear/call-indirect.c15
-rw-r--r--validation/linear/call-inline.c18
-rw-r--r--validation/linear/degen-function.c13
-rw-r--r--validation/linear/deref-ptr-ptr.c26
-rw-r--r--validation/linear/unexamined-base-type.c36
-rw-r--r--validation/optim/call-complex-pointer.c13
-rw-r--r--validation/sizeof-builtin.c15
-rw-r--r--validation/sizeof-function.c49
22 files changed, 508 insertions, 0 deletions
diff --git a/validation/Waddress-weak.c b/validation/Waddress-weak.c
index 1fe8d33c..ad2cb13a 100644
--- a/validation/Waddress-weak.c
+++ b/validation/Waddress-weak.c
@@ -9,11 +9,13 @@ int test_addr_weak_fun(void)
if ( &arr) return 1;
if ( fun) return 1;
if ( &fun) return 1;
+ if ( *fun) return 1;
if (!&var) return 0;
if (! arr) return 0;
if (!&arr) return 0;
if (! fun) return 0;
if (!&fun) return 0;
+ if (!*fun) return 0;
return -1;
}
diff --git a/validation/Waddress.c b/validation/Waddress.c
index 10556c3a..441cdb1c 100644
--- a/validation/Waddress.c
+++ b/validation/Waddress.c
@@ -15,6 +15,7 @@ lab:
if (&arr) return 1;
if (fun) return 1;
if (&fun) return 1;
+ if (*fun) return 1;
if (&var) return 1;
if (&arg) return 1;
if (&&lab) return 1;
@@ -35,6 +36,7 @@ lab:
if (!&arr) return 0;
if (!fun) return 0;
if (!&fun) return 0;
+ if (!*fun) return 0;
if (!&var) return 0;
if (!&arg) return 0;
if (!&&lab) return 0;
@@ -62,6 +64,8 @@ lab:
if (0 == fun) return 0;
if (&fun == 0) return 0;
if (0 == &fun) return 0;
+ if (*fun == 0) return 0;
+ if (0 == *fun) return 0;
if (&var == 0) return 0;
if (0 == &var) return 0;
if (&arg == 0) return 0;
diff --git a/validation/array-implicit-size.c b/validation/array-implicit-size.c
new file mode 100644
index 00000000..7011008b
--- /dev/null
+++ b/validation/array-implicit-size.c
@@ -0,0 +1,26 @@
+static int array[] = { 0, 1, 2, 3, };
+_Static_assert(sizeof(array) == 4 * sizeof(int), "size of array");
+
+
+typedef int table_t[];
+static table_t tbl2 = {
+ 0,
+ 1,
+};
+_Static_assert(sizeof(tbl2) == 2 * sizeof(int), "size of tbl2");
+
+static table_t tbl1 = {
+ 0,
+};
+_Static_assert(sizeof(tbl1) == 1 * sizeof(int), "size of tbl1");
+
+static table_t tbl3 = {
+ 0,
+ 1,
+ 2,
+};
+_Static_assert(sizeof(tbl3) == 3 * sizeof(int), "size of tbl3");
+
+/*
+ * check-name: array-implicit-size
+ */
diff --git a/validation/bug-bad-type.c b/validation/bug-bad-type.c
new file mode 100644
index 00000000..0e00efef
--- /dev/null
+++ b/validation/bug-bad-type.c
@@ -0,0 +1,18 @@
+struct s {
+ int i;
+};
+
+long a;
+void foo(void)
+{
+ (struct s) { .i = (foo - a), };
+}
+
+/*
+ * check-name: bug-bad-type
+ *
+ * check-error-start
+bug-bad-type.c:5:6: warning: symbol 'a' was not declared. Should it be static?
+bug-bad-type.c:8:32: error: arithmetics on pointers to functions
+ * check-error-end
+ */
diff --git a/validation/builtin-arith.c b/validation/builtin-arith.c
new file mode 100644
index 00000000..d08c93da
--- /dev/null
+++ b/validation/builtin-arith.c
@@ -0,0 +1,52 @@
+
+
+void test(void (*fun)(void));
+void test(void (*fun)(void))
+{
+ typedef typeof(__builtin_trap) t; // OK
+ void (*f)(void);
+ int i;
+
+ f = __builtin_trap;
+ f = &__builtin_trap;
+ f = *__builtin_trap; // OK for GCC
+ f = __builtin_trap + 0;
+ f = __builtin_trap + 1;
+ f = __builtin_trap - 1;
+
+ // (void) __builtin_trap;
+ f = (void*) __builtin_trap;
+ f = (unsigned long) __builtin_trap;
+
+ i = !__builtin_trap;
+ i = (__builtin_trap > fun);
+ i = (__builtin_trap == fun);
+ i = (fun < __builtin_trap);
+ i = (fun == __builtin_trap);
+
+ __builtin_trap - fun;
+ fun - __builtin_trap;
+}
+
+/*
+ * check-name: builtin arithmetic
+ * check-command: sparse -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-error-start
+builtin-arith.c:10:xx: error: ...
+builtin-arith.c:11:xx: error: ...
+builtin-arith.c:13:xx: error: arithmetics on pointers to functions
+builtin-arith.c:14:xx: error: arithmetics on pointers to functions
+builtin-arith.c:15:xx: error: arithmetics on pointers to functions
+builtin-arith.c:18:xx: error: ...
+builtin-arith.c:19:xx: error: ...
+builtin-arith.c:21:xx: error: ...
+builtin-arith.c:22:xx: error: ...
+builtin-arith.c:23:xx: error: ...
+builtin-arith.c:24:xx: error: ...
+builtin-arith.c:25:xx: error: ...
+builtin-arith.c:27:24: error: subtraction of functions? Share your drugs
+builtin-arith.c:28:13: error: subtraction of functions? Share your drugs
+ * check-error-end
+ */
diff --git a/validation/constexpr-preop.c b/validation/constexpr-preop.c
index 4b54defd..3fd57745 100644
--- a/validation/constexpr-preop.c
+++ b/validation/constexpr-preop.c
@@ -25,5 +25,7 @@ constexpr-preop.c:8:4: error: bad constant expression
constexpr-preop.c:9:4: error: bad constant expression
constexpr-preop.c:14:4: error: bad integer constant expression
constexpr-preop.c:15:4: error: bad integer constant expression
+constexpr-preop.c:10:4: error: index out of bounds in initializer
+constexpr-preop.c:11:4: error: index out of bounds in initializer
* check-error-end
*/
diff --git a/validation/empty-expr.c b/validation/empty-expr.c
new file mode 100644
index 00000000..61decf73
--- /dev/null
+++ b/validation/empty-expr.c
@@ -0,0 +1,26 @@
+static int foo(void)
+{
+ switch () {
+ case 0:
+ return 0;
+ default:
+ return 1;
+ }
+}
+
+static int bar(void)
+{
+ if ()
+ return 0;
+ else
+ return 1;
+}
+
+/*
+ * check-name: empty expression
+ *
+ * check-error-start
+empty-expr.c:3:17: error: an expression is expected before ')'
+empty-expr.c:13:13: error: an expression is expected before ')'
+ * check-error-end
+ */
diff --git a/validation/function-pointer-type.c b/validation/function-pointer-type.c
new file mode 100644
index 00000000..ebc4007b
--- /dev/null
+++ b/validation/function-pointer-type.c
@@ -0,0 +1,12 @@
+extern int fun(void);
+
+void fa(void) { int (*f)(void); f = &fun; }
+void f0(void) { int (*f)(void); f = fun; } // C99,C11 6.3.2.1p4
+void f1(void) { int (*f)(void); f = *fun; } // C99,C11 6.5.3.2p4
+void f2(void) { int (*f)(void); f = **fun; } // C99,C11 6.5.3.2p4
+void f3(void) { int (*f)(void); f = ***fun; } // C99,C11 6.5.3.2p4
+
+/*
+ * check-name: type of function pointers
+ * check-command: sparse -Wno-decl $file
+ */
diff --git a/validation/linear/bitfield-expand-deref.c b/validation/linear/bitfield-expand-deref.c
new file mode 100644
index 00000000..7748725f
--- /dev/null
+++ b/validation/linear/bitfield-expand-deref.c
@@ -0,0 +1,27 @@
+struct s {
+ int a:8;
+ int b:8;
+};
+
+int foo(void)
+{
+ struct s x = { .a = 12, .b = 34, };
+
+ return x.b;
+}
+
+int bar(int a)
+{
+ struct s x = { .a = 12, .b = a, };
+
+ return x.b;
+}
+
+/*
+ * check-name: bitfield expand deref
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: ret\..*\$12
+ * check-output-contains: ret\..*\$34
+ */
diff --git a/validation/linear/call-basic.c b/validation/linear/call-basic.c
new file mode 100644
index 00000000..60517e2e
--- /dev/null
+++ b/validation/linear/call-basic.c
@@ -0,0 +1,57 @@
+extern int fun(int a);
+
+int symbol(int a)
+{
+ fun(a);
+}
+
+int pointer0(int a, int (*fun)(int))
+{
+ fun(a);
+}
+
+int pointer1(int a, int (*fun)(int))
+{
+ (*fun)(a);
+}
+
+int builtin(int a)
+{
+ __builtin_popcount(a);
+}
+
+/*
+ * check-name: basic function calls
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-start
+symbol:
+.L0:
+ <entry-point>
+ call.32 %r2 <- fun, %arg1
+ ret.32 %r2
+
+
+pointer0:
+.L2:
+ <entry-point>
+ call.32 %r5 <- %arg2, %arg1
+ ret.32 %r5
+
+
+pointer1:
+.L4:
+ <entry-point>
+ call.32 %r8 <- %arg2, %arg1
+ ret.32 %r8
+
+
+builtin:
+.L6:
+ <entry-point>
+ call.32 %r11 <- __builtin_popcount, %arg1
+ ret.32 %r11
+
+
+ * check-output-end
+ */
diff --git a/validation/linear/call-builtin.c b/validation/linear/call-builtin.c
new file mode 100644
index 00000000..b1511359
--- /dev/null
+++ b/validation/linear/call-builtin.c
@@ -0,0 +1,17 @@
+typedef unsigned int u32;
+
+u32 ff(u32 a) { return __builtin_popcount(a); }
+
+u32 f0(u32 a) { return (__builtin_popcount)(a); }
+u32 f1(u32 a) { return (*__builtin_popcount)(a); } // C99,C11 6.5.3.2p4
+u32 f2(u32 a) { return (**__builtin_popcount)(a); } // C99,C11 6.5.3.2p4
+u32 f3(u32 a) { return (***__builtin_popcount)(a); } // C99,C11 6.5.3.2p4
+
+/*
+ * check-name: builtin calls
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: load
+ * check-output-pattern(5): call\..*__builtin_.*, %arg1
+ */
diff --git a/validation/linear/call-casted-pointer.c b/validation/linear/call-casted-pointer.c
new file mode 100644
index 00000000..610d6748
--- /dev/null
+++ b/validation/linear/call-casted-pointer.c
@@ -0,0 +1,31 @@
+typedef int (*fun_t)(void*);
+
+int foo(void *a, void *fun)
+{
+ return ((fun_t)fun)(a);
+}
+
+int bar(void *a, void *fun)
+{
+ return ((int (*)(void *))fun)(a);
+}
+
+int qux(void *a, void *fun)
+{
+ return (*(fun_t)fun)(a);
+}
+
+int quz(void *a, void *fun)
+{
+ return (*(int (*)(void *))fun)(a);
+}
+
+/*
+ * check-name: call via casted function pointer
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: load
+ * check-output-pattern(4): ptrcast\..* %arg2
+ * check-output-pattern(4): call\..* %arg1
+ */
diff --git a/validation/linear/call-complex-pointer.c b/validation/linear/call-complex-pointer.c
new file mode 100644
index 00000000..ea8232f1
--- /dev/null
+++ b/validation/linear/call-complex-pointer.c
@@ -0,0 +1,32 @@
+int foo(int p, int (*f0)(int), int (*f1)(int), int arg)
+{
+ return (p ? f0 : f1)(arg);
+}
+
+/*
+ * check-name: call-complex-pointer
+ * check-command: test-linearize -m64 -Wno-decl $file
+ *
+ * check-output-start
+foo:
+.L0:
+ <entry-point>
+ cbr %arg1, .L2, .L3
+
+.L2:
+ phisrc.64 %phi1 <- %arg2
+ br .L4
+
+.L3:
+ ptrcast.64 %r5 <- (64) %arg3
+ phisrc.64 %phi2 <- %r5
+ br .L4
+
+.L4:
+ phi.64 %r6 <- %phi1, %phi2
+ call.32 %r7 <- %r6, %arg4
+ ret.32 %r7
+
+
+ * check-output-end
+ */
diff --git a/validation/linear/call-direct.c b/validation/linear/call-direct.c
new file mode 100644
index 00000000..52f86306
--- /dev/null
+++ b/validation/linear/call-direct.c
@@ -0,0 +1,17 @@
+extern int fun(void);
+
+int ff(void) { return fun(); }
+
+int f0(void) { return (fun)(); }
+int f1(void) { return (*fun)(); } // C99,C11 6.5.3.2p4
+int f2(void) { return (**fun)(); } // C99,C11 6.5.3.2p4
+int f3(void) { return (***fun)(); } // C99,C11 6.5.3.2p4
+
+/*
+ * check-name: direct calls
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: load
+ * check-output-pattern(5): call\..* fun
+ */
diff --git a/validation/linear/call-indirect.c b/validation/linear/call-indirect.c
new file mode 100644
index 00000000..1275910c
--- /dev/null
+++ b/validation/linear/call-indirect.c
@@ -0,0 +1,15 @@
+int gg(int (*fun)(void)) { return fun(); }
+
+int g0(int (*fun)(void)) { return (fun)(); }
+int g1(int (*fun)(void)) { return (*fun)(); } // C99,C11 6.5.3.2p4
+int g2(int (*fun)(void)) { return (**fun)(); } // C99,C11 6.5.3.2p4
+int g3(int (*fun)(void)) { return (***fun)(); } // C99,C11 6.5.3.2p4
+
+/*
+ * check-name: indirect calls
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: load
+ * check-output-pattern(5): call\..* %arg1
+ */
diff --git a/validation/linear/call-inline.c b/validation/linear/call-inline.c
new file mode 100644
index 00000000..a33f0a1c
--- /dev/null
+++ b/validation/linear/call-inline.c
@@ -0,0 +1,18 @@
+static inline int fun(void) { return 42; }
+
+int fi(void) { return fun(); }
+
+int i0(void) { return (fun)(); }
+int i1(void) { return (*fun)(); } // C99,C11 6.5.3.2p4
+int i2(void) { return (**fun)(); } // C99,C11 6.5.3.2p4
+int i3(void) { return (***fun)(); } // C99,C11 6.5.3.2p4
+
+/*
+ * check-name: inline calls
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-excludes: load
+ * check-output-excludes: call
+ * check-output-pattern(5): ret\..* \\$42
+ */
diff --git a/validation/linear/degen-function.c b/validation/linear/degen-function.c
index 6dd3123b..4fb2d564 100644
--- a/validation/linear/degen-function.c
+++ b/validation/linear/degen-function.c
@@ -4,6 +4,7 @@ typedef int (*fun_t)(int);
fun_t fa(void) { return &fun; }
fun_t f0(void) { return fun; }
+fun_t f1(void) { return *fun; }
/*
* check-name: degen-function
@@ -34,5 +35,17 @@ f0:
ret.64 %r3
+f1:
+.L4:
+ <entry-point>
+ symaddr.64 %r5 <- fun
+ phisrc.64 %phi3(return) <- %r5
+ br .L5
+
+.L5:
+ phi.64 %r6 <- %phi3(return)
+ ret.64 %r5
+
+
* check-output-end
*/
diff --git a/validation/linear/deref-ptr-ptr.c b/validation/linear/deref-ptr-ptr.c
new file mode 100644
index 00000000..963acd36
--- /dev/null
+++ b/validation/linear/deref-ptr-ptr.c
@@ -0,0 +1,26 @@
+char *foo(char **pfmt)
+{
+ return ++*pfmt;
+}
+
+/*
+ * check-name: deref-ptr-ptr
+ * check-command: test-linearize -m64 -Wno-decl $file
+ *
+ * check-output-excludes: load[^.]
+ * check-output-contains: load\.
+ * check-output-excludes: store[^.]
+ * check-output-contains: store\.
+ *
+ * check-output-start
+foo:
+.L0:
+ <entry-point>
+ load.64 %r2 <- 0[%arg1]
+ add.64 %r3 <- %r2, $1
+ store.64 %r3 -> 0[%arg1]
+ ret.64 %r3
+
+
+ * check-output-end
+ */
diff --git a/validation/linear/unexamined-base-type.c b/validation/linear/unexamined-base-type.c
new file mode 100644
index 00000000..96aee3f0
--- /dev/null
+++ b/validation/linear/unexamined-base-type.c
@@ -0,0 +1,36 @@
+# define __force __attribute__((force))
+
+struct s {
+ int a;
+};
+
+static int foo(struct s *s)
+{
+ return (*((typeof(s->a) __force *) &s->a)) & 1;
+}
+
+static void bar(struct s *d, struct s *s1, struct s *s2)
+{
+ *d = *s1, *d = *s2;
+}
+
+/*
+ * check-name: unexamined base type
+ * check-command: test-linearize -Wno-decl $file
+ * check-description:
+ * Test case for missing examine in evaluate_dereference()'s
+ * target base type. In this case, the loaded value has a
+ * a null size, giving the wrongly generated code for foo():
+ * ptrcast.64 %r3 <- (64) %arg1
+ * load %r4 <- 0[%r3]
+ * ^^^ !! WRONG !!
+ * cast.32 %r5 <- (0) %r4
+ * ^^^ !! WRONG !!
+ * and.32 %r6 <- %r5, $1
+ * ret.32 %r6
+ *
+ * check-output-ignore
+ * check-output-excludes: load[^.]
+ * check-output-excludes: cast\..*(0)
+ * check-output-excludes: store[^.]
+ */
diff --git a/validation/optim/call-complex-pointer.c b/validation/optim/call-complex-pointer.c
new file mode 100644
index 00000000..6cfeb6ab
--- /dev/null
+++ b/validation/optim/call-complex-pointer.c
@@ -0,0 +1,13 @@
+int foo(int p, int (*f0)(int), int (*f1)(int), int arg)
+{
+ return (p ? f0 : f1)(arg);
+}
+/*
+ * check-name: call-complex-pointer
+ * check-command: test-linearize -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-output-ignore
+ * check-output-excludes: ptrcast\.
+ * check-output-contains: select\.
+ */
diff --git a/validation/sizeof-builtin.c b/validation/sizeof-builtin.c
new file mode 100644
index 00000000..7123e4de
--- /dev/null
+++ b/validation/sizeof-builtin.c
@@ -0,0 +1,15 @@
+int test(void);
+int test(void)
+{
+ return sizeof &__builtin_trap;
+}
+
+/*
+ * check-name: sizeof-builtin
+ * check-command: sparse -Wno-decl $file
+ * check-known-to-fail
+ *
+ * check-error-start
+sizeof-function.c:4:16: error: expression using addressof on a builtin function
+ * check-error-end
+ */
diff --git a/validation/sizeof-function.c b/validation/sizeof-function.c
new file mode 100644
index 00000000..27d535d4
--- /dev/null
+++ b/validation/sizeof-function.c
@@ -0,0 +1,49 @@
+extern int fun(void);
+extern int (*ptr)(void);
+
+static inline int inl(int *a)
+{
+ return *a + 1;
+}
+
+
+int test(void);
+int test(void)
+{
+ unsigned int s = 0;
+
+ // OK
+ s += sizeof &fun;
+ s += sizeof ptr;
+ s += sizeof &ptr;
+ s += sizeof &inl;
+
+ // KO
+ s += sizeof fun;
+ s += sizeof *fun;
+
+ s += sizeof *ptr;
+
+ s += sizeof inl;
+ s += sizeof *inl;
+
+ s += sizeof __builtin_trap;
+ s += sizeof *__builtin_trap;
+
+ return s;
+}
+
+/*
+ * check-name: sizeof-function
+ * check-command: sparse -Wno-decl $file
+ *
+ * check-error-start
+sizeof-function.c:22:14: warning: expression using sizeof on a function
+sizeof-function.c:23:14: warning: expression using sizeof on a function
+sizeof-function.c:25:14: warning: expression using sizeof on a function
+sizeof-function.c:27:14: warning: expression using sizeof on a function
+sizeof-function.c:28:14: warning: expression using sizeof on a function
+sizeof-function.c:30:14: warning: expression using sizeof on a function
+sizeof-function.c:31:14: warning: expression using sizeof on a function
+ * check-error-end
+ */