diff options
-rwxr-xr-x | cgcc | 6 | ||||
-rw-r--r-- | evaluate.c | 4 | ||||
-rw-r--r-- | lib.c | 59 | ||||
-rw-r--r-- | lib.h | 16 | ||||
-rw-r--r-- | parse.c | 10 | ||||
-rw-r--r-- | symbol.c | 10 | ||||
-rw-r--r-- | validation/backend/hello.c | 2 | ||||
-rw-r--r-- | validation/backend/sum.c | 3 | ||||
-rw-r--r-- | validation/bitfield-sizes.c | 30 | ||||
-rw-r--r-- | validation/c11-atomic.c | 2 | ||||
-rw-r--r-- | validation/eval/premature-examination.c | 27 | ||||
-rw-r--r-- | validation/nocast.c | 10 | ||||
-rw-r--r-- | validation/restrict.c | 2 |
13 files changed, 125 insertions, 56 deletions
@@ -230,7 +230,7 @@ sub add_specs { ' -DNULL="((void *)0)"'; } elsif ($spec eq 'linux') { return &add_specs ('unix') . - ' -D__linux__=1 -D__linux=1 -Dlinux=linux'; + ' -D__linux__=1 -D__linux=1 -Dlinux=1'; } elsif ($spec eq 'gnu/kfreebsd') { return &add_specs ('unix') . ' -D__FreeBSD_kernel__=1'; @@ -254,7 +254,8 @@ sub add_specs { } elsif ( $spec =~ /^cygwin/) { return &add_specs ('unix') . ' -fshort-wchar' . - ' -D__CYGWIN__=1 -D__CYGWIN32__=1' . + ' -D__CYGWIN__=1' . + ($m32 ? ' -D__CYGWIN32__=1' : '') . " -D'_cdecl=__attribute__((__cdecl__))'" . " -D'__cdecl=__attribute__((__cdecl__))'" . " -D'_stdcall=__attribute__((__stdcall__))'" . @@ -263,6 +264,7 @@ sub add_specs { " -D'__fastcall=__attribute__((__fastcall__))'" . " -D'__declspec(x)=__attribute__((x))'"; } elsif ($spec eq 'i386') { + $m32 = 1; return ( ' --arch=i386' . &float_types (1, 1, 21, [24,8], [53,11], [64,15])); @@ -1501,9 +1501,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)); @@ -1825,7 +1825,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: @@ -1835,6 +1834,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); @@ -318,13 +318,7 @@ int funsigned_char = -1; int preprocess_only; -static enum { STANDARD_C89, - STANDARD_C94, - STANDARD_C99, - STANDARD_C11, - STANDARD_GNU11, - STANDARD_GNU89, - STANDARD_GNU99, } standard = STANDARD_GNU89; +enum standard standard = STANDARD_GNU89; static int arch_msize_long = 0; int arch_m64 = ARCH_M64_DEFAULT; @@ -890,27 +884,16 @@ static void handle_switch_W_finalize(void) handle_onoff_switch_finalize(warnings, ARRAY_SIZE(warnings)); /* default Wdeclarationafterstatement based on the C dialect */ - if (-1 == Wdeclarationafterstatement) - { - switch (standard) - { + if (-1 == Wdeclarationafterstatement) { + switch (standard) { case STANDARD_C89: case STANDARD_C94: Wdeclarationafterstatement = 1; break; - - case STANDARD_C99: - case STANDARD_GNU89: - case STANDARD_GNU99: - case STANDARD_C11: - case STANDARD_GNU11: + default: Wdeclarationafterstatement = 0; break; - - default: - assert (0); } - } } @@ -1096,6 +1079,15 @@ static char **handle_switch_s(const char *arg, char **next) else if (!strcmp(arg, "gnu11")) standard = STANDARD_GNU11; + else if (!strcmp(arg, "c17") || + !strcmp(arg, "c18") || + !strcmp(arg, "iso9899:2017") || + !strcmp(arg, "iso9899:2018")) + standard = STANDARD_C17; + else if (!strcmp(arg, "gnu17") || + !strcmp(arg, "gnu18")) + standard = STANDARD_GNU17; + else die ("Unsupported C dialect"); } @@ -1422,36 +1414,33 @@ static void predefined_macros(void) predefine("__STDC__", 1, "1"); switch (standard) { - case STANDARD_C89: - predefine("__STRICT_ANSI__", 1, "1"); + default: break; case STANDARD_C94: predefine("__STDC_VERSION__", 1, "199409L"); - predefine("__STRICT_ANSI__", 1, "1"); break; case STANDARD_C99: - predefine("__STDC_VERSION__", 1, "199901L"); - predefine("__STRICT_ANSI__", 1, "1"); - break; - - case STANDARD_GNU89: - default: - break; - case STANDARD_GNU99: predefine("__STDC_VERSION__", 1, "199901L"); break; case STANDARD_C11: - predefine("__STRICT_ANSI__", 1, "1"); case STANDARD_GNU11: + predefine("__STDC_VERSION__", 1, "201112L"); + break; + case STANDARD_C17: + case STANDARD_GNU17: + predefine("__STDC_VERSION__", 1, "201710L"); + break; + } + if (!(standard & STANDARD_GNU) && (standard != STANDARD_NONE)) + predefine("__STRICT_ANSI__", 1, "1"); + if (standard >= STANDARD_C11) { predefine("__STDC_NO_ATOMICS__", 1, "1"); predefine("__STDC_NO_COMPLEX__", 1, "1"); predefine("__STDC_NO_THREADS__", 1, "1"); - predefine("__STDC_VERSION__", 1, "201112L"); - break; } predefine("__CHAR_BIT__", 1, "%d", bits_in_char); @@ -224,6 +224,22 @@ enum { }; extern int arch_cmodel; +enum standard { + STANDARD_NONE, + STANDARD_GNU, + STANDARD_C89, + STANDARD_GNU89 = STANDARD_C89 | STANDARD_GNU, + STANDARD_C94, + STANDARD_GNU94 = STANDARD_C94 | STANDARD_GNU, + STANDARD_C99, + STANDARD_GNU99 = STANDARD_C99 | STANDARD_GNU, + STANDARD_C11, + STANDARD_GNU11 = STANDARD_C11 | STANDARD_GNU, + STANDARD_C17, + STANDARD_GNU17 = STANDARD_C17 | STANDARD_GNU, +}; +extern enum standard standard; + extern void dump_macro_definitions(void); extern struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **files); extern struct symbol_list *__sparse(char *filename); @@ -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; } @@ -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) 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..fc2c27ae 100644 --- a/validation/c11-atomic.c +++ b/validation/c11-atomic.c @@ -66,7 +66,7 @@ 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) 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/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..80c437b0 100644 --- a/validation/restrict.c +++ b/validation/restrict.c @@ -66,7 +66,7 @@ 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) |