aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--cse.c4
-rw-r--r--expand.c2
-rw-r--r--memops.c2
-rw-r--r--symbol.c19
-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/constexpr-preop.c2
-rw-r--r--validation/linear/bitfield-expand-deref.c27
-rw-r--r--validation/linear/degen-function.c13
-rw-r--r--validation/optim/cse-fcmp.c19
12 files changed, 136 insertions, 2 deletions
diff --git a/cse.c b/cse.c
index d5da26fb..6987645c 100644
--- a/cse.c
+++ b/cse.c
@@ -71,7 +71,8 @@ static void clean_up_one_instruction(struct basic_block *bb, struct instruction
case OP_SET_B: case OP_SET_A:
case OP_SET_BE: case OP_SET_AE:
- /* floating-point arithmetic */
+ /* floating-point arithmetic & comparison */
+ case OP_FPCMP ... OP_FPCMP_END:
case OP_FADD:
case OP_FSUB:
case OP_FMUL:
@@ -214,6 +215,7 @@ static int insn_compare(const void *_i1, const void *_i2)
case OP_SET_BE: case OP_SET_AE:
/* floating-point arithmetic */
+ case OP_FPCMP ... OP_FPCMP_END:
case OP_FADD:
case OP_FSUB:
case OP_FMUL:
diff --git a/expand.c b/expand.c
index f1aa838d..d44aec24 100644
--- a/expand.c
+++ b/expand.c
@@ -644,6 +644,8 @@ static int expand_dereference(struct expression *expr)
if (value) {
/* FIXME! We should check that the size is right! */
if (value->type == EXPR_VALUE) {
+ if (is_bitfield_type(value->ctype))
+ return UNSAFE;
expr->type = EXPR_VALUE;
expr->value = value->value;
expr->taint = 0;
diff --git a/memops.c b/memops.c
index 137e851e..788ed2f2 100644
--- a/memops.c
+++ b/memops.c
@@ -160,6 +160,8 @@ static void kill_dominated_stores(struct basic_block *bb)
pseudo_t pseudo = insn->src;
int local;
+ if (!insn->type)
+ continue;
if (insn->type->ctype.modifiers & MOD_VOLATILE)
continue;
diff --git a/symbol.c b/symbol.c
index 2f4afd51..61d1acbe 100644
--- a/symbol.c
+++ b/symbol.c
@@ -364,6 +364,23 @@ static struct expression *get_symbol_initializer(struct symbol *sym)
return NULL;
}
+static unsigned int implicit_array_size(struct symbol *node, unsigned int count)
+{
+ struct symbol *arr_ori = node->ctype.base_type;
+ struct symbol *arr_new = alloc_symbol(node->pos, SYM_ARRAY);
+ struct symbol *elem_type = arr_ori->ctype.base_type;
+ struct expression *size = alloc_const_expression(node->pos, count);
+ unsigned int bit_size = array_element_offset(elem_type->bit_size, count);
+
+ *arr_new = *arr_ori;
+ arr_new->bit_size = bit_size;
+ arr_new->array_size = size;
+ node->array_size = size;
+ node->ctype.base_type = arr_new;
+
+ return bit_size;
+}
+
static struct symbol * examine_node_type(struct symbol *sym)
{
struct symbol *base_type = examine_base_type(sym);
@@ -393,7 +410,7 @@ static struct symbol * examine_node_type(struct symbol *sym)
int count = count_array_initializer(node_type, initializer);
if (node_type && node_type->bit_size >= 0)
- bit_size = array_element_offset(node_type->bit_size, count);
+ bit_size = implicit_array_size(sym, count);
}
}
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/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/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/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/optim/cse-fcmp.c b/validation/optim/cse-fcmp.c
new file mode 100644
index 00000000..f2a73f57
--- /dev/null
+++ b/validation/optim/cse-fcmp.c
@@ -0,0 +1,19 @@
+extern void fun(void);
+
+int foo(double a, double b)
+{
+ if (a < b)
+ fun();
+ if (a < b)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * check-name: cse-fcmp
+ * check-command: test-linearize -Wno-decl $file
+ *
+ * check-output-ignore
+ * check-output-pattern(1): fcmp
+ */