aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rwxr-xr-xcgcc6
-rw-r--r--evaluate.c4
-rw-r--r--lib.c59
-rw-r--r--lib.h16
-rw-r--r--parse.c10
-rw-r--r--symbol.c10
-rw-r--r--validation/backend/hello.c2
-rw-r--r--validation/backend/sum.c3
-rw-r--r--validation/bitfield-sizes.c30
-rw-r--r--validation/c11-atomic.c2
-rw-r--r--validation/eval/premature-examination.c27
-rw-r--r--validation/nocast.c10
-rw-r--r--validation/restrict.c2
13 files changed, 125 insertions, 56 deletions
diff --git a/cgcc b/cgcc
index 87f4fc3e..f5a8b352 100755
--- a/cgcc
+++ b/cgcc
@@ -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]));
diff --git a/evaluate.c b/evaluate.c
index 11ad6a22..4096566e 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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);
diff --git a/lib.c b/lib.c
index f0b54688..711e8fbe 100644
--- a/lib.c
+++ b/lib.c
@@ -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);
diff --git a/lib.h b/lib.h
index 684a4955..3e565c6f 100644
--- a/lib.h
+++ b/lib.h
@@ -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);
diff --git a/parse.c b/parse.c
index 6db3cba7..fb05253b 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
}
diff --git a/symbol.c b/symbol.c
index fb14b624..3655cbb7 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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)