diff options
31 files changed, 534 insertions, 89 deletions
@@ -110,6 +110,8 @@ static struct symbol *evaluate_string(struct expression *expr) sym->ctype.modifiers = MOD_STATIC; sym->ctype.base_type = array; sym->initializer = initstr; + sym->examined = 1; + sym->evaluated = 1; initstr->ctype = sym; initstr->string = expr->string; @@ -119,6 +121,8 @@ static struct symbol *evaluate_string(struct expression *expr) array->ctype.alignment = 1; array->ctype.modifiers = MOD_STATIC; array->ctype.base_type = &char_ctype; + array->examined = 1; + array->evaluated = 1; addr->symbol = sym; addr->ctype = &lazy_ptr_ctype; @@ -379,10 +383,8 @@ static inline int classify_type(struct symbol *type, struct symbol **base) if (type->type == SYM_NODE) type = type->ctype.base_type; if (type->type == SYM_TYPEOF) { - type = evaluate_expression(type->initializer); - if (!type) - type = &bad_ctype; - else if (type->type == SYM_NODE) + type = examine_symbol_type(type); + if (type->type == SYM_NODE) type = type->ctype.base_type; } if (type->type == SYM_ENUM) @@ -1501,9 +1503,9 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t struct expression **rp, const char *where) { const char *typediff; - struct symbol *source = degenerate(*rp); if (!check_assignment_types(target, rp, &typediff)) { + struct symbol *source = *rp ? (*rp)->ctype : NULL; warning(expr->pos, "incorrect type in %s (%s)", where, typediff); info(expr->pos, " expected %s", show_typename(target)); info(expr->pos, " got %s", show_typename(source)); @@ -1540,6 +1542,16 @@ static int compatible_argument_type(struct expression *expr, struct symbol *targ return compatible_assignment_types(expr, target, rp, where); } +static void mark_addressable(struct expression *expr) +{ + while (expr->type == EXPR_BINOP && expr->op == '+') + expr = expr->left; + if (expr->type == EXPR_SYMBOL) { + struct symbol *sym = expr->symbol; + sym->ctype.modifiers |= MOD_ADDRESSABLE; + } +} + static void mark_assigned(struct expression *expr) { struct symbol *sym; @@ -1762,6 +1774,7 @@ static struct symbol *degenerate(struct expression *expr) *expr = *expr->unop; ctype = create_pointer(expr, ctype, 1); expr->ctype = ctype; + mark_addressable(expr); default: /* nothing */; } @@ -1780,10 +1793,7 @@ static struct symbol *evaluate_addressof(struct expression *expr) ctype = op->ctype; *expr = *op->unop; - if (expr->type == EXPR_SYMBOL) { - struct symbol *sym = expr->symbol; - sym->ctype.modifiers |= MOD_ADDRESSABLE; - } + mark_addressable(expr); /* * symbol expression evaluation is lazy about the type @@ -1817,7 +1827,6 @@ static struct symbol *evaluate_dereference(struct expression *expr) ctype = ctype->ctype.base_type; target = ctype->ctype.base_type; - examine_symbol_type(target); switch (ctype->type) { default: @@ -1827,6 +1836,7 @@ static struct symbol *evaluate_dereference(struct expression *expr) *expr = *op; return expr->ctype; case SYM_PTR: + examine_symbol_type(target); node = alloc_symbol(expr->pos, SYM_NODE); node->ctype.modifiers = target->ctype.modifiers & MOD_SPECIFIER; merge_type(node, ctype); @@ -3380,9 +3390,11 @@ void check_duplicates(struct symbol *sym) declared++; typediff = type_difference(&sym->ctype, &next->ctype, 0, 0); if (typediff) { - sparse_error(sym->pos, "symbol '%s' redeclared with different type (originally declared at %s:%d) - %s", - show_ident(sym->ident), - stream_name(next->pos.stream), next->pos.line, typediff); + sparse_error(sym->pos, "symbol '%s' redeclared with different type (%s):", + show_ident(sym->ident), typediff); + info(sym->pos, " %s", show_typename(sym)); + info(next->pos, "note: previously declared as:"); + info(next->pos, " %s", show_typename(next)); return; } } @@ -621,12 +621,70 @@ static int expand_addressof(struct expression *expr) return expand_expression(expr->unop); } +/// +// lookup the type of a struct's memeber at the requested offset +static struct symbol *find_member(struct symbol *sym, int offset) +{ + struct ptr_list *head, *list; + + head = (struct ptr_list *) sym->symbol_list; + list = head; + if (!head) + return NULL; + do { + int nr = list->nr; + int i; + for (i = 0; i < nr; i++) { + struct symbol *ent = (struct symbol *) list->list[i]; + int curr = ent->offset; + if (curr == offset) + return ent; + if (curr > offset) + return NULL; + } + } while ((list = list->next) != head); + return NULL; +} + +/// +// lookup a suitable default initializer value at the requested offset +static struct expression *default_initializer(struct symbol *sym, int offset) +{ + static struct expression value; + struct symbol *type; + +redo: + switch (sym->type) { + case SYM_NODE: + sym = sym->ctype.base_type; + goto redo; + case SYM_STRUCT: + type = find_member(sym, offset); + if (!type) + return NULL; + break; + case SYM_ARRAY: + type = sym->ctype.base_type; + break; + default: + return NULL; + } + + if (is_integral_type(type)) + value.type = EXPR_VALUE; + else if (is_float_type(type)) + value.type = EXPR_FVALUE; + else + return NULL; + + value.ctype = type; + return &value; +} + /* * Look up a trustable initializer value at the requested offset. * * Return NULL if no such value can be found or statically trusted. - * - * FIXME!! We should check that the size is right! */ static struct expression *constant_symbol_value(struct symbol *sym, int offset) { @@ -648,10 +706,11 @@ static struct expression *constant_symbol_value(struct symbol *sym, int offset) if (entry->init_offset < offset) continue; if (entry->init_offset > offset) - return NULL; + break; return entry->init_expr; } END_FOR_EACH_PTR(entry); - return NULL; + + value = default_initializer(sym, offset); } return value; } @@ -678,22 +737,26 @@ static int expand_dereference(struct expression *expr) * Is it "symbol" or "symbol + offset"? */ offset = 0; - if (unop->type == EXPR_BINOP && unop->op == '+') { + while (unop->type == EXPR_BINOP && unop->op == '+') { struct expression *right = unop->right; - if (right->type == EXPR_VALUE) { - offset = right->value; - unop = unop->left; - } + if (right->type != EXPR_VALUE) + break; + offset += right->value; + unop = unop->left; } if (unop->type == EXPR_SYMBOL) { struct symbol *sym = unop->symbol; + struct symbol *ctype = expr->ctype; struct expression *value = constant_symbol_value(sym, offset); /* Const symbol with a constant initializer? */ - if (value) { - /* FIXME! We should check that the size is right! */ + if (value && value->ctype) { + if (ctype->bit_size != value->ctype->bit_size) + return UNSAFE; if (value->type == EXPR_VALUE) { + if (!is_integral_type(ctype)) + return UNSAFE; if (is_bitfield_type(value->ctype)) return UNSAFE; expr->type = EXPR_VALUE; @@ -701,6 +764,8 @@ static int expand_dereference(struct expression *expr) expr->taint = 0; return 0; } else if (value->type == EXPR_FVALUE) { + if (!is_float_type(ctype)) + return UNSAFE; expr->type = EXPR_FVALUE; expr->fvalue = value->fvalue; return 0; @@ -82,6 +82,15 @@ static int local_pseudo(pseudo_t pseudo) && !address_taken(pseudo); } +static bool compatible_loads(struct instruction *a, struct instruction *b) +{ + if (is_integral_type(a->type) && is_float_type(b->type)) + return false; + if (is_float_type(a->type) && is_integral_type(b->type)) + return false; + return true; +} + static void simplify_loads(struct basic_block *bb) { struct instruction *insn; @@ -114,6 +123,8 @@ static void simplify_loads(struct basic_block *bb) continue; goto next_load; } + if (!compatible_loads(insn, dom)) + goto next_load; /* Yeehaa! Found one! */ convert_load_instruction(insn, dom->target); goto next_load; @@ -1946,12 +1946,9 @@ static struct token *handle_bitfield(struct token *token, struct decl_state *ctx width = const_expression_value(expr); bitfield->bit_size = width; - if (width < 0 || width > INT_MAX) { - sparse_error(token->pos, "invalid bitfield width, %lld.", width); - width = -1; - } else if (*ctx->ident && width == 0) { - sparse_error(token->pos, "invalid named zero-width bitfield `%s'", - show_ident(*ctx->ident)); + if (width < 0 || width > INT_MAX || (*ctx->ident && width == 0)) { + sparse_error(token->pos, "bitfield '%s' has invalid width (%lld)", + show_ident(*ctx->ident), width); width = -1; } else if (*ctx->ident) { struct symbol *base_type = bitfield->ctype.base_type; @@ -1972,6 +1969,7 @@ static struct token *handle_bitfield(struct token *token, struct decl_state *ctx } bitfield->bit_size = width; bitfield->endpos = token->pos; + bitfield->ident = *ctx->ident; return token; } @@ -215,7 +215,7 @@ restart: /// // split a ptrlist block -// @head: the ptrlist block to be splitted +// @head: the ptrlist block to be split // // A new block is inserted just after @head and the entries // at the half end of @head are moved to this new block. @@ -363,7 +363,7 @@ out: /// // remove the last entry of a ptrlist // @head: a pointer to the list -// @return: the last elemant of the list or NULL if the list is empty. +// @return: the last element of the list or NULL if the list is empty. // // :note: this doesn't repack the list void * undo_ptr_list_last(struct ptr_list **head) @@ -389,7 +389,7 @@ void * undo_ptr_list_last(struct ptr_list **head) /// // remove the last entry and repack the list // @head: a pointer to the list -// @return: the last elemant of the list or NULL if the list is empty. +// @return: the last element of the list or NULL if the list is empty. void * delete_ptr_list_last(struct ptr_list **head) { void *ptr = NULL; diff --git a/show-parse.c b/show-parse.c index f0ea9cae..044465e9 100644 --- a/show-parse.c +++ b/show-parse.c @@ -300,12 +300,12 @@ deeper: if (as) prepend(name, "%s ", show_as(as)); - if (sym->type == SYM_BASETYPE || sym->type == SYM_ENUM) + if (sym && (sym->type == SYM_BASETYPE || sym->type == SYM_ENUM)) mod &= ~MOD_SPECIFIER; s = modifier_string(mod); len = strlen(s); - name->start -= len; - memcpy(name->start, s, len); + name->start -= len; + memcpy(name->start, s, len); mod = 0; as = NULL; } @@ -254,13 +254,15 @@ static struct symbol * examine_array_type(struct symbol *sym) static struct symbol *examine_bitfield_type(struct symbol *sym) { struct symbol *base_type = examine_base_type(sym); - unsigned long bit_size, alignment, modifiers; + unsigned long alignment, modifiers; if (!base_type) return sym; - bit_size = base_type->bit_size; - if (sym->bit_size > bit_size) - warning(sym->pos, "impossible field-width, %d, for this type", sym->bit_size); + if (sym->bit_size > base_type->bit_size) { + sparse_error(sym->pos, "bitfield '%s' is wider (%d) than its type (%s)", + show_ident(sym->ident), sym->bit_size, show_typename(base_type)); + sym->bit_size = -1; + } alignment = base_type->ctype.alignment; if (!sym->ctype.alignment) @@ -451,6 +453,25 @@ static struct symbol *examine_pointer_type(struct symbol *sym) return sym; } +static struct symbol *examine_typeof(struct symbol *sym) +{ + struct symbol *base = evaluate_expression(sym->initializer); + unsigned long mod = 0; + + if (!base) + base = &bad_ctype; + if (base->type == SYM_NODE) { + mod |= base->ctype.modifiers & MOD_TYPEOF; + base = base->ctype.base_type; + } + if (base->type == SYM_BITFIELD) + warning(base->pos, "typeof applied to bitfield type"); + sym->type = SYM_NODE; + sym->ctype.modifiers = mod; + sym->ctype.base_type = base; + return examine_node_type(sym); +} + /* * Fill in type size and alignment information for * regular SYM_TYPE things. @@ -484,26 +505,8 @@ struct symbol *examine_symbol_type(struct symbol * sym) case SYM_BASETYPE: /* Size and alignment had better already be set up */ return sym; - case SYM_TYPEOF: { - struct symbol *base = evaluate_expression(sym->initializer); - if (base) { - unsigned long mod = 0; - - if (is_bitfield_type(base)) - warning(base->pos, "typeof applied to bitfield type"); - if (base->type == SYM_NODE) { - mod |= base->ctype.modifiers & MOD_TYPEOF; - base = base->ctype.base_type; - } - sym->type = SYM_NODE; - sym->ctype.modifiers = mod; - sym->ctype.base_type = base; - return examine_node_type(sym); - } - sym->type = SYM_NODE; - sym->ctype.base_type = &bad_ctype; - return sym; - } + case SYM_TYPEOF: + return examine_typeof(sym); case SYM_PREPROCESSOR: sparse_error(sym->pos, "ctype on preprocessor command? (%s)", show_ident(sym->ident)); return NULL; diff --git a/validation/backend/hello.c b/validation/backend/hello.c index b0e514be..eb89846f 100644 --- a/validation/backend/hello.c +++ b/validation/backend/hello.c @@ -1,4 +1,4 @@ -#include <stdio.h> +int puts(const char *s); int main(int argc, char *argv[]) { diff --git a/validation/backend/sum.c b/validation/backend/sum.c index fa51120e..38ebf41e 100644 --- a/validation/backend/sum.c +++ b/validation/backend/sum.c @@ -1,5 +1,4 @@ -#include <stdio.h> -#include <stdlib.h> +int printf(const char * fmt, ...); static int sum(int n) { diff --git a/validation/bitfield-sizes.c b/validation/bitfield-sizes.c new file mode 100644 index 00000000..9f76d074 --- /dev/null +++ b/validation/bitfield-sizes.c @@ -0,0 +1,30 @@ +struct a { + int a:31; + int b:32; + long c:63; + long d:64; + int x:33; // KO + long y:65; // KO +}; +static struct a a; + +struct b { + int m1:-1; // KO + int x1:2147483648; // KO + int :0; + int a0:0; // KO +}; +static struct b b; + +/* + * check-name: bitfield-sizes + * check-command: sparse -m64 $file + * + * check-error-start +bitfield-sizes.c:12:18: error: bitfield 'm1' has invalid width (-1) +bitfield-sizes.c:13:26: error: bitfield 'x1' has invalid width (2147483648) +bitfield-sizes.c:15:17: error: bitfield 'a0' has invalid width (0) +bitfield-sizes.c:6:15: error: bitfield 'x' is wider (33) than its type (int) +bitfield-sizes.c:7:15: error: bitfield 'y' is wider (65) than its type (long) + * check-error-end + */ diff --git a/validation/c11-atomic.c b/validation/c11-atomic.c index e87d06cd..17720861 100644 --- a/validation/c11-atomic.c +++ b/validation/c11-atomic.c @@ -66,11 +66,17 @@ void baz(void) /* * check-name: C11 _Atomic type qualifier - * check-command: sparse -Wno-decl $file; + * check-command: sparse -Wno-decl $file * * check-error-start -c11-atomic.c:11:6: error: symbol 'f02' redeclared with different type (originally declared at c11-atomic.c:3) - incompatible argument 1 (different modifiers) -c11-atomic.c:12:6: error: symbol 'f03' redeclared with different type (originally declared at c11-atomic.c:4) - incompatible argument 1 (different modifiers) +c11-atomic.c:11:6: error: symbol 'f02' redeclared with different type (incompatible argument 1 (different modifiers)): +c11-atomic.c:11:6: void extern [addressable] [toplevel] f02( ... ) +c11-atomic.c:3:6: note: previously declared as: +c11-atomic.c:3:6: void extern [addressable] [toplevel] f02( ... ) +c11-atomic.c:12:6: error: symbol 'f03' redeclared with different type (incompatible argument 1 (different modifiers)): +c11-atomic.c:12:6: void extern [addressable] [toplevel] f03( ... ) +c11-atomic.c:4:6: note: previously declared as: +c11-atomic.c:4:6: void extern [addressable] [toplevel] f03( ... ) c11-atomic.c:33:13: warning: incorrect type in assignment (different modifiers) c11-atomic.c:33:13: expected int *extern [assigned] puo c11-atomic.c:33:13: got int const * diff --git a/validation/eval/addressable-complex.c b/validation/eval/addressable-complex.c new file mode 100644 index 00000000..e3d4aca4 --- /dev/null +++ b/validation/eval/addressable-complex.c @@ -0,0 +1,23 @@ +extern void def(void *); + +struct s1 { + int a; +}; + +int use1(void) +{ + struct s1 s = { 3 }; + + def(&s.a); + + return s.a; +} + +/* + * check-name: eval/addressable-complex + * check-command: test-linearize -Wno-decl -fdump-ir $file + * + * check-output-ignore + * check-output-contains: load\\. + * check-output-excludes: return\\..*\\$3 + */ diff --git a/validation/eval/addressable-degen.c b/validation/eval/addressable-degen.c new file mode 100644 index 00000000..d420927e --- /dev/null +++ b/validation/eval/addressable-degen.c @@ -0,0 +1,17 @@ +extern void def(void *, unsigned int); + +static int bar(void) +{ + int x[2] = { 1, 2 }; + + def(x, sizeof(x)); + return x[1]; +} + +/* + * check-name: eval/addressable-degen + * check-command: test-linearize -fdump-ir $file + * + * check-output-ignore + * check-output-contains: load\\. + */ diff --git a/validation/eval/premature-examination.c b/validation/eval/premature-examination.c new file mode 100644 index 00000000..bd2ffa90 --- /dev/null +++ b/validation/eval/premature-examination.c @@ -0,0 +1,27 @@ +extern int i; + +int foo(void) +{ + return *i; +} + +int bar(void) +{ + return i[0]; +} + +int *qux(void) +{ + return &i[0]; +} + +/* + * check-name: premature-examination + * check-command: sparse -Wno-decl $file + * + * check-error-start +eval/premature-examination.c:5:16: error: cannot dereference this type +eval/premature-examination.c:10:17: error: cannot dereference this type +eval/premature-examination.c:15:18: error: cannot dereference this type + * check-error-end + */ diff --git a/validation/expand/constant-init-array.c b/validation/expand/constant-init-array.c new file mode 100644 index 00000000..94949be5 --- /dev/null +++ b/validation/expand/constant-init-array.c @@ -0,0 +1,15 @@ +int test_array(int i) +{ + static const int a[3] = { 1, 2, 3, }; + + return a[1]; +} + +/* + * check-name: constant-init-array + * check-command: test-linearize -Wno-decl -fdump-ir $file + * + * check-output-ignore + * check-output-excludes: phisrc\\..*return.*\\$2 + * check-output-contains: load\\. + */ diff --git a/validation/expand/constant-init-nested-array.c b/validation/expand/constant-init-nested-array.c new file mode 100644 index 00000000..0d50d955 --- /dev/null +++ b/validation/expand/constant-init-nested-array.c @@ -0,0 +1,15 @@ +int foo(void) +{ + int a[2][3] = {{0, 1, 2},{3, 4, 5}}; + return a[1][2]; +} + +/* + * check-name: constant-init-nested-array + * check-command: test-linearize -Wno-decl -fdump-ir $file + * check-known-to-fail + * + * check-output-ignore + * check-output-contains: phisrc\\..*\\$5 + * check-output-excludes: load\\. + */ diff --git a/validation/expand/constant-init-nested-struct.c b/validation/expand/constant-init-nested-struct.c new file mode 100644 index 00000000..f27de556 --- /dev/null +++ b/validation/expand/constant-init-nested-struct.c @@ -0,0 +1,23 @@ +struct s { + int a; + struct { + int b; + int c; + } s; +}; + +int foo(void) +{ + struct s s = {1, {2, 3}}; + return s.s.c; +} + +/* + * check-name: constant-init-nested-struct + * check-command: test-linearize -Wno-decl -fdump-ir $file + * check-known-to-fail + * + * check-output-ignore + * check-output-contains: phisrc\\..*\\$3 + * check-output-excludes: load\\. + */ diff --git a/validation/expand/constant-init-string.c b/validation/expand/constant-init-string.c new file mode 100644 index 00000000..42ae9bd3 --- /dev/null +++ b/validation/expand/constant-init-string.c @@ -0,0 +1,15 @@ +char foo(void) +{ + static const char s[] = "abc?"; + return s[3]; +} + +/* + * check-name: constant-init-nested-array + * check-command: test-linearize -Wno-decl -fdump-ir $file + * check-known-to-fail + * + * check-output-ignore + * check-output-contains: phisrc\\..*\\$63 + * check-output-pattern(0,1): load\\. + */ diff --git a/validation/expand/constant-union-flt2int.c b/validation/expand/constant-union-flt2int.c new file mode 100644 index 00000000..5e25b592 --- /dev/null +++ b/validation/expand/constant-union-flt2int.c @@ -0,0 +1,20 @@ +union u { + int i; + float f; +}; + +static int foo(void) +{ + union u u = { .f = 0.123 }; + return u.i; +} + +/* + * check-name: constant-union-float-to-int + * check description: must not infer the int value from the float + * check-command: test-linearize -fdump-ir $file + * + * check-output-ignore + * check-output-pattern(1): setfval\\. + * check-output-pattern(1): load\\. + */ diff --git a/validation/expand/constant-union-int2flt.c b/validation/expand/constant-union-int2flt.c new file mode 100644 index 00000000..16ce1c6f --- /dev/null +++ b/validation/expand/constant-union-int2flt.c @@ -0,0 +1,19 @@ +union u { + int i; + float f; +}; + +static float foo(void) +{ + union u u = { .i = 3 }; + return u.f; +} + +/* + * check-name: constant-union-int-to-float + * check description: must not infer the float value from the int + * check-command: test-linearize -fdump-ir $file + * + * check-output-ignore + * check-output-pattern(1): load\\. + */ diff --git a/validation/bug-expand-union0.c b/validation/expand/constant-union-size.c index dd6d60c3..8a16bf3e 100644 --- a/validation/bug-expand-union0.c +++ b/validation/expand/constant-union-size.c @@ -10,10 +10,9 @@ static int foo(void) } /* - * check-name: bug-expand-union - * check description: must not infer the value from the float - * check-command: test-linearize $file - * check-known-to-fail + * check-name: constant-union-size + * check description: the size of the initializer doesn't match + * check-command: test-linearize -fdump-ir $file * * check-output-ignore * check-output-contains: load\\. diff --git a/validation/expand/cost-deref-nested.c b/validation/expand/cost-deref-nested.c new file mode 100644 index 00000000..d6b62396 --- /dev/null +++ b/validation/expand/cost-deref-nested.c @@ -0,0 +1,20 @@ +struct s { + struct { + int u, v; + } a, b; +}; + +static const struct s s; + +static int foo(int c) +{ + return c && s.b.v; +} + +/* + * check-name: cost-deref-nested + * check-command: test-linearize -fdump-ir $file + * + * check-output-ignore + * check-output-excludes: cbr + */ diff --git a/validation/expand/default-init-array.c b/validation/expand/default-init-array.c new file mode 100644 index 00000000..b372ea09 --- /dev/null +++ b/validation/expand/default-init-array.c @@ -0,0 +1,16 @@ +int test_array(int i) +{ + static const int a[3] = { [0] = 1, [2] = 3, }; + + return a[1]; +} + +/* + * check-name: default-init-array + * check-command: test-linearize -Wno-decl -fdump-ir $file + * check-known-to-fail + * + * check-output-ignore + * check-output-contains: phisrc\\..*return.*\\$0 + * check-output-excludes: load\\. + */ diff --git a/validation/expand/default-init-struct.c b/validation/expand/default-init-struct.c new file mode 100644 index 00000000..085dd2d6 --- /dev/null +++ b/validation/expand/default-init-struct.c @@ -0,0 +1,22 @@ +struct s { + int a; + int b; + int c; +}; + + +int test_struct(void) +{ + struct s s = { .a = 1, .c = 3, }; + + return s.b; +} + +/* + * check-name: default-init-struct + * check-command: test-linearize -Wno-decl -fdump-ir $file + * + * check-output-ignore + * check-output-contains: phisrc\\..*return.*\\$0 + * check-output-excludes: load\\. + */ diff --git a/validation/expand/union-cast.c b/validation/expand/union-cast.c new file mode 100644 index 00000000..a28d01f2 --- /dev/null +++ b/validation/expand/union-cast.c @@ -0,0 +1,27 @@ +union u { + int i; + struct s { + int a; + } s; +}; + +int foo(void) +{ + struct s s = { 3 }; + union u u = (union u)s; + return u.s.a; +} + +/* + * check-name: union-cast + * check-command: test-linearize -Wno-decl -fdump-ir $file + * check-known-to-fail + * + * check-output-ignore + * check-output-excludes: load\\. + * + * check-error-start +union-cast.c:11:22: warning: cast to non-scalar +union-cast.c:11:22: warning: cast from non-scalar + * check-error-end + */ diff --git a/validation/function-redecl.c b/validation/function-redecl.c index 475f18e7..03151359 100644 --- a/validation/function-redecl.c +++ b/validation/function-redecl.c @@ -48,15 +48,45 @@ void arg_vararg(int a, ...) { } /* check-should-fail */ * check-name: function-redecl * * check-error-start -function-redecl.c:5:6: error: symbol 'ret_type' redeclared with different type (originally declared at function-redecl.c:4) - different base types -function-redecl.c:9:11: error: symbol 'ret_const' redeclared with different type (originally declared at function-redecl.c:8) - different modifiers -function-redecl.c:13:13: error: symbol 'ret_as' redeclared with different type (originally declared at function-redecl.c:12) - different address spaces -function-redecl.c:17:12: error: symbol 'ret_mod' redeclared with different type (originally declared at function-redecl.c:16) - different modifiers -function-redecl.c:21:6: error: symbol 'arg_type' redeclared with different type (originally declared at function-redecl.c:20) - incompatible argument 1 (different base types) -function-redecl.c:29:6: error: symbol 'arg_as' redeclared with different type (originally declared at function-redecl.c:28) - incompatible argument 1 (different address spaces) -function-redecl.c:33:6: error: symbol 'arg_mod' redeclared with different type (originally declared at function-redecl.c:32) - incompatible argument 1 (different modifiers) -function-redecl.c:37:6: error: symbol 'arg_more_arg' redeclared with different type (originally declared at function-redecl.c:36) - different argument counts -function-redecl.c:41:6: error: symbol 'arg_less_arg' redeclared with different type (originally declared at function-redecl.c:40) - different argument counts -function-redecl.c:45:6: error: symbol 'arg_vararg' redeclared with different type (originally declared at function-redecl.c:44) - incompatible variadic arguments +function-redecl.c:5:6: error: symbol 'ret_type' redeclared with different type (different base types): +function-redecl.c:5:6: void extern [addressable] [toplevel] ret_type( ... ) +function-redecl.c:4:5: note: previously declared as: +function-redecl.c:4:5: int extern [signed] [addressable] [toplevel] ret_type( ... ) +function-redecl.c:9:11: error: symbol 'ret_const' redeclared with different type (different modifiers): +function-redecl.c:9:11: int extern const [signed] [addressable] [toplevel] ret_const( ... ) +function-redecl.c:8:5: note: previously declared as: +function-redecl.c:8:5: int extern [signed] [addressable] [toplevel] ret_const( ... ) +function-redecl.c:13:13: error: symbol 'ret_as' redeclared with different type (different address spaces): +function-redecl.c:13:13: void <asn:1> *extern [addressable] [toplevel] ret_as( ... ) +function-redecl.c:12:6: note: previously declared as: +function-redecl.c:12:6: void *extern [addressable] [toplevel] ret_as( ... ) +function-redecl.c:17:12: error: symbol 'ret_mod' redeclared with different type (different modifiers): +function-redecl.c:17:12: void const *extern [addressable] [toplevel] ret_mod( ... ) +function-redecl.c:16:6: note: previously declared as: +function-redecl.c:16:6: void *extern [addressable] [toplevel] ret_mod( ... ) +function-redecl.c:21:6: error: symbol 'arg_type' redeclared with different type (incompatible argument 1 (different base types)): +function-redecl.c:21:6: void extern [addressable] [toplevel] arg_type( ... ) +function-redecl.c:20:6: note: previously declared as: +function-redecl.c:20:6: void extern [addressable] [toplevel] arg_type( ... ) +function-redecl.c:29:6: error: symbol 'arg_as' redeclared with different type (incompatible argument 1 (different address spaces)): +function-redecl.c:29:6: void extern [addressable] [toplevel] arg_as( ... ) +function-redecl.c:28:6: note: previously declared as: +function-redecl.c:28:6: void extern [addressable] [toplevel] arg_as( ... ) +function-redecl.c:33:6: error: symbol 'arg_mod' redeclared with different type (incompatible argument 1 (different modifiers)): +function-redecl.c:33:6: void extern [addressable] [toplevel] arg_mod( ... ) +function-redecl.c:32:6: note: previously declared as: +function-redecl.c:32:6: void extern [addressable] [toplevel] arg_mod( ... ) +function-redecl.c:37:6: error: symbol 'arg_more_arg' redeclared with different type (different argument counts): +function-redecl.c:37:6: void extern [addressable] [toplevel] arg_more_arg( ... ) +function-redecl.c:36:6: note: previously declared as: +function-redecl.c:36:6: void extern [addressable] [toplevel] arg_more_arg( ... ) +function-redecl.c:41:6: error: symbol 'arg_less_arg' redeclared with different type (different argument counts): +function-redecl.c:41:6: void extern [addressable] [toplevel] arg_less_arg( ... ) +function-redecl.c:40:6: note: previously declared as: +function-redecl.c:40:6: void extern [addressable] [toplevel] arg_less_arg( ... ) +function-redecl.c:45:6: error: symbol 'arg_vararg' redeclared with different type (incompatible variadic arguments): +function-redecl.c:45:6: void extern [addressable] [toplevel] arg_vararg( ... ) +function-redecl.c:44:6: note: previously declared as: +function-redecl.c:44:6: void extern [addressable] [toplevel] arg_vararg( ... ) * check-error-end */ diff --git a/validation/bug-expand-union1.c b/validation/memops/type-punning-flt2int.c index 582a1f4f..fadaf687 100644 --- a/validation/bug-expand-union1.c +++ b/validation/memops/type-punning-flt2int.c @@ -10,10 +10,9 @@ static int foo(void) } /* - * check-name: bug-expand-union - * check description: must not infer the value from the float + * check-name: type-punning-float-to-int + * check description: must not infer the int value from the float * check-command: test-linearize $file - * check-known-to-fail * * check-output-ignore * check-output-contains: load\\. diff --git a/validation/memops/type-punning-int2flt.c b/validation/memops/type-punning-int2flt.c new file mode 100644 index 00000000..061b7423 --- /dev/null +++ b/validation/memops/type-punning-int2flt.c @@ -0,0 +1,19 @@ +union u { + int i; + float f; +}; + +static float foo(void) +{ + union u u = { .i = 3 }; + return u.f; +} + +/* + * check-name: type-punning-int-to-float + * check description: must not infer the float value from the int + * check-command: test-linearize $file + * + * check-output-ignore + * check-output-contains: load\\. + */ diff --git a/validation/nocast.c b/validation/nocast.c index 6c5da968..2113227c 100644 --- a/validation/nocast.c +++ b/validation/nocast.c @@ -26,8 +26,8 @@ static ulong_nc_t good_deref(ulong_nc_t *t) /* assign value */ static ulong_nc_t t; -static ulong_nc_t good_assign_self = t; -static unsigned long good_assign_sametype = t; + + /* assign pointer */ static ulong_nc_t *good_ptr = &t; @@ -150,6 +150,12 @@ static unsigned long bad_fromcast(ulong_nc_t v) return (unsigned long) v; } +static void assign_value(void) +{ + ulong_nc_t good_assign_self = t; + unsigned long good_assign_sametype = t; +} + /* * check-name: nocast.c * diff --git a/validation/restrict.c b/validation/restrict.c index 92bfdae8..d7cd8ad9 100644 --- a/validation/restrict.c +++ b/validation/restrict.c @@ -66,11 +66,17 @@ void baz(void) /* * check-name: restrict qualifier - * check-command: sparse -Wno-decl $file; + * check-command: sparse -Wno-decl $file * * check-error-start -restrict.c:11:6: error: symbol 'f02' redeclared with different type (originally declared at restrict.c:3) - incompatible argument 1 (different modifiers) -restrict.c:12:6: error: symbol 'f03' redeclared with different type (originally declared at restrict.c:4) - incompatible argument 1 (different modifiers) +restrict.c:11:6: error: symbol 'f02' redeclared with different type (incompatible argument 1 (different modifiers)): +restrict.c:11:6: void extern [addressable] [toplevel] f02( ... ) +restrict.c:3:6: note: previously declared as: +restrict.c:3:6: void extern [addressable] [toplevel] f02( ... ) +restrict.c:12:6: error: symbol 'f03' redeclared with different type (incompatible argument 1 (different modifiers)): +restrict.c:12:6: void extern [addressable] [toplevel] f03( ... ) +restrict.c:4:6: note: previously declared as: +restrict.c:4:6: void extern [addressable] [toplevel] f03( ... ) restrict.c:33:13: warning: incorrect type in assignment (different modifiers) restrict.c:33:13: expected void **extern [assigned] pup restrict.c:33:13: got void *const * diff --git a/validation/typedef-redef.c b/validation/typedef-redef.c index 3a60a773..f90f266a 100644 --- a/validation/typedef-redef.c +++ b/validation/typedef-redef.c @@ -8,6 +8,9 @@ typedef long ko_t; * check-name: typedef-redef * * check-error-start -typedef-redef.c:5:14: error: symbol 'ko_t' redeclared with different type (originally declared at typedef-redef.c:4) - different type sizes +typedef-redef.c:5:14: error: symbol 'ko_t' redeclared with different type (different type sizes): +typedef-redef.c:5:14: long [usertype] ko_t +typedef-redef.c:4:14: note: previously declared as: +typedef-redef.c:4:14: int [usertype] ko_t * check-error-end */ |