diff --git a/.gitignore b/.gitignore index b45a33d..5798078 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ sparse-0.4.2.tar.bz2 /sparse-0.4.4.tar.bz2 /sparse-0.4.5.rc1.tar.xz /sparse-0.5.0.tar.xz +/sparse-0.5.1.tar.xz diff --git a/0001-build-assign-extra-flags-to-ALL_CFLAGS-instead-of-CF.patch b/0001-build-assign-extra-flags-to-ALL_CFLAGS-instead-of-CF.patch new file mode 100644 index 0000000..dfd8c48 --- /dev/null +++ b/0001-build-assign-extra-flags-to-ALL_CFLAGS-instead-of-CF.patch @@ -0,0 +1,47 @@ +From 9d93230dc87f372c23fc7b9b90057b6a7979fff1 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Wed, 18 Oct 2017 10:51:05 -0400 +Subject: [PATCH] build: assign extra flags to ALL_CFLAGS instead of CFLAGS + +The fedora packaging tools want to override $CFLAGS when building +sparse, but that fails on a couple of targets. + +There are a couple of build targets in the makefile that want to add +options to $CFLAGS. When we do a build though, we pass $ALL_CFLAGS to +the compiler, and that ends up without those extra options, if CFLAGS= +was specified on the command line. + +I'm not sure if this is a recursive variable expansion bug in make, but +we can work around it either way. Fix the two specific build targets to +add the options to $ALL_CFLAGS instead of $CFLAGS. + +Signed-off-by: Jeff Layton +--- + Makefile | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index d0341764158e..b24680b885fe 100644 +--- a/Makefile ++++ b/Makefile +@@ -83,7 +83,7 @@ PROGRAMS += test-inspect + INST_PROGRAMS += test-inspect + test-inspect_EXTRA_DEPS := ast-model.o ast-view.o ast-inspect.o + test-inspect_OBJS := test-inspect.o $(test-inspect_EXTRA_DEPS) +-$(test-inspect_OBJS) $(test-inspect_OBJS:.o=.sc): CFLAGS += $(GTK_CFLAGS) ++$(test-inspect_OBJS) $(test-inspect_OBJS:.o=.sc): ALL_CFLAGS += $(GTK_CFLAGS) + test-inspect_EXTRA_OBJS := $(GTK_LIBS) + else + $(warning Your system does not have gtk3/gtk2, disabling test-inspect) +@@ -208,7 +208,7 @@ ifneq ($(DEP_FILES),) + include $(DEP_FILES) + endif + +-c2xml.o c2xml.sc: CFLAGS += $(LIBXML_CFLAGS) ++c2xml.o c2xml.sc: ALL_CFLAGS += $(LIBXML_CFLAGS) + + pre-process.sc: CHECKER_FLAGS += -Wno-vla + +-- +2.13.6 + diff --git a/master-update.patch b/master-update.patch deleted file mode 100644 index 51ccd8b..0000000 --- a/master-update.patch +++ /dev/null @@ -1,3937 +0,0 @@ -commit 67a7f893b14526002afc0b478a744cfb4acbfebe -Author: Emilio G. Cota -Date: Wed Jan 8 16:32:42 2014 -0500 - - Define __CHAR_BIT__ - - gcc defines __CHAR_BIT__ as a pre-defined macro. - - Define __CHAR_BIT__ in sparse so that code that needs it (e.g. code - using CHAR_BIT from limits.h) does not generate false warnings. - - Signed-off-by: Emilio G. Cota - Signed-off-by: Christopher Li - -diff --git a/lib.c b/lib.c -index bf3e91c0be46..51b97fd3e1e2 100644 ---- a/lib.c -+++ b/lib.c -@@ -928,6 +928,7 @@ void create_builtin_stream(void) - add_pre_buffer("#weak_define __LONG_LONG_MAX__ " STRINGIFY(__LONG_LONG_MAX__) "\n"); - add_pre_buffer("#weak_define __WCHAR_MAX__ " STRINGIFY(__WCHAR_MAX__) "\n"); - add_pre_buffer("#weak_define __SIZEOF_POINTER__ " STRINGIFY(__SIZEOF_POINTER__) "\n"); -+ add_pre_buffer("#weak_define __CHAR_BIT__ " STRINGIFY(__CHAR_BIT__) "\n"); - } - - static struct symbol_list *sparse_tokenstream(struct token *token) -diff --git a/validation/builtin_char_bit.c b/validation/builtin_char_bit.c -new file mode 100644 -index 000000000000..30e6bed46fea ---- /dev/null -+++ b/validation/builtin_char_bit.c -@@ -0,0 +1,7 @@ -+#include -+ -+static unsigned int word_bits = sizeof(unsigned int) * CHAR_BIT; -+ -+/* -+ * check-name: __CHAR_BIT__ -+ */ - -commit 2667c2d4ab3342b54283d16f1d62e6d715f3b373 -Author: Joe Perches -Date: Wed Feb 26 19:19:25 2014 -0800 - - sparse: Allow override of sizeof(bool) warning - - Allow an override to emit or not the sizeof(bool) warning. - Add a "-Wsizeof-bool" description to the manpage. - - Signed-off-by: Joe Perches - Reviewed-by: Josh Triplett - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index 66556150ddac..a45f59ba8f3d 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -2057,7 +2057,8 @@ static struct symbol *evaluate_sizeof(struct expression *expr) - } - - if (size == 1 && is_bool_type(type)) { -- warning(expr->pos, "expression using sizeof bool"); -+ if (Wsizeof_bool) -+ warning(expr->pos, "expression using sizeof bool"); - size = bits_in_char; - } - -diff --git a/lib.c b/lib.c -index 51b97fd3e1e2..844797d5db2e 100644 ---- a/lib.c -+++ b/lib.c -@@ -226,6 +226,7 @@ int Wparen_string = 0; - int Wptr_subtraction_blows = 0; - int Wreturn_void = 0; - int Wshadow = 0; -+int Wsizeof_bool = 0; - int Wtransparent_union = 0; - int Wtypesign = 0; - int Wundef = 0; -@@ -438,6 +439,7 @@ static const struct warning { - { "ptr-subtraction-blows", &Wptr_subtraction_blows }, - { "return-void", &Wreturn_void }, - { "shadow", &Wshadow }, -+ { "sizeof-bool", &Wsizeof_bool }, - { "transparent-union", &Wtransparent_union }, - { "typesign", &Wtypesign }, - { "undef", &Wundef }, -diff --git a/lib.h b/lib.h -index f09b338577fc..f6cd9b4d89c2 100644 ---- a/lib.h -+++ b/lib.h -@@ -120,6 +120,7 @@ extern int Wparen_string; - extern int Wptr_subtraction_blows; - extern int Wreturn_void; - extern int Wshadow; -+extern int Wsizeof_bool; - extern int Wtransparent_union; - extern int Wtypesign; - extern int Wundef; -diff --git a/sparse.1 b/sparse.1 -index cd6be26abb88..54da09b5a7df 100644 ---- a/sparse.1 -+++ b/sparse.1 -@@ -297,6 +297,14 @@ Such declarations can lead to error-prone code. - Sparse does not issue these warnings by default. - . - .TP -+.B \-Wsizeof-bool -+Warn when checking the sizeof a _Bool. -+ -+C99 does not specify the sizeof a _Bool. gcc uses 1. -+ -+Sparse does not issue these warnings by default. -+. -+.TP - .B \-Wtransparent\-union - Warn about any declaration using the GCC extension - \fB__attribute__((transparent_union))\fR. - -commit cb14f76857ead767d3fa932b5606ed11f0c8482e -Author: John Keeping -Date: Sun Mar 2 12:31:59 2014 +0000 - - validation/sizeof-bool: fix broken test case - - Since commit 2667c2d (sparse: Allow override of sizeof(bool) warning, - 2014-02-26) the default has been not to warn on sizeof(bool). This - means that the sizeof-bool test case now needs an explicit command in - order to trigger the warning it is testing. - - Signed-off-by: John Keeping - Signed-off-by: Christopher Li - -diff --git a/validation/sizeof-bool.c b/validation/sizeof-bool.c -index 6c68748a0b3f..05e76a44e88e 100644 ---- a/validation/sizeof-bool.c -+++ b/validation/sizeof-bool.c -@@ -6,6 +6,7 @@ static int a(void) - * check-name: sizeof(_Bool) is valid - * check-description: sizeof(_Bool) was rejected because _Bool is not an even - * number of bytes -+ * check-command: sparse -Wsizeof-bool $file - * check-error-start - sizeof-bool.c:3:16: warning: expression using sizeof bool - * check-error-end - -commit 5798e4cf8fdb3090e4d4864e6d9824de69dfc786 -Author: John Keeping -Date: Sun Mar 9 11:32:50 2014 +0000 - - evaluate: split out implementation of compatible_assignment_types - - This will allow us to reuse the logic when processing a transparent - union by checking each member in turn without printing a warning unless - none of the members match. - - Signed-off-by: John Keeping - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index a45f59ba8f3d..8f6c07ee9d78 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -1307,10 +1307,9 @@ static int whitelist_pointers(struct symbol *t1, struct symbol *t2) - return !Wtypesign; - } - --static int compatible_assignment_types(struct expression *expr, struct symbol *target, -- struct expression **rp, const char *where) -+static int check_assignment_types(struct symbol *target, struct expression **rp, -+ const char **typediff) - { -- const char *typediff; - struct symbol *source = degenerate(*rp); - struct symbol *t, *s; - int tclass = classify_type(target, &t); -@@ -1327,8 +1326,8 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t - return 1; - } else if (!(sclass & TYPE_RESTRICT)) - goto Cast; -- typediff = "different base types"; -- goto Err; -+ *typediff = "different base types"; -+ return 0; - } - - if (tclass == TYPE_PTR) { -@@ -1342,8 +1341,8 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t - goto Cast; - } - if (!(sclass & TYPE_PTR)) { -- typediff = "different base types"; -- goto Err; -+ *typediff = "different base types"; -+ return 0; - } - b1 = examine_pointer_target(t); - b2 = examine_pointer_target(s); -@@ -1356,19 +1355,19 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t - * or mix address spaces [sparse]. - */ - if (t->ctype.as != s->ctype.as) { -- typediff = "different address spaces"; -- goto Err; -+ *typediff = "different address spaces"; -+ return 0; - } - if (mod2 & ~mod1) { -- typediff = "different modifiers"; -- goto Err; -+ *typediff = "different modifiers"; -+ return 0; - } - goto Cast; - } - /* It's OK if the target is more volatile or const than the source */ -- typediff = type_difference(&t->ctype, &s->ctype, 0, mod1); -- if (typediff) -- goto Err; -+ *typediff = type_difference(&t->ctype, &s->ctype, 0, mod1); -+ if (*typediff) -+ return 0; - return 1; - } - -@@ -1379,22 +1378,34 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t - /* XXX: need to turn into comparison with NULL */ - if (t == &bool_ctype && (sclass & TYPE_PTR)) - goto Cast; -- typediff = "different base types"; -- goto Err; -+ *typediff = "different base types"; -+ return 0; - } -- typediff = "invalid types"; -- --Err: -- 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)); -- *rp = cast_to(*rp, target); -+ *typediff = "invalid types"; - return 0; -+ - Cast: - *rp = cast_to(*rp, target); - return 1; - } - -+static int compatible_assignment_types(struct expression *expr, struct symbol *target, -+ struct expression **rp, const char *where) -+{ -+ const char *typediff; -+ struct symbol *source = degenerate(*rp); -+ -+ if (!check_assignment_types(target, rp, &typediff)) { -+ 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)); -+ *rp = cast_to(*rp, target); -+ return 0; -+ } -+ -+ return 1; -+} -+ - static void mark_assigned(struct expression *expr) - { - struct symbol *sym; - -commit 7698bae699639892d639b8a9c270efdb8c46725c -Author: John Keeping -Date: Sun Mar 9 11:32:51 2014 +0000 - - Support GCC's transparent unions - - This stops warnings in code using socket operations with a modern glibc, - which otherwise result in warnings of the form: - - warning: incorrect type in argument 2 (invalid types) - expected union __CONST_SOCKADDR_ARG [usertype] __addr - got struct sockaddr * - - Since transparent unions are only applicable to function arguments, we - create a new function to check that the types are compatible - specifically in this context. - - Also change the wording of the existing warning slightly since sparse - does now support them. The warning is left in case people want to avoid - using transparent unions. - - Signed-off-by: John Keeping - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index 8f6c07ee9d78..98fc52b83236 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -1406,6 +1406,32 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t - return 1; - } - -+static int compatible_transparent_union(struct symbol *target, -+ struct expression **rp) -+{ -+ struct symbol *t, *member; -+ classify_type(target, &t); -+ if (t->type != SYM_UNION || !t->transparent_union) -+ return 0; -+ -+ FOR_EACH_PTR(t->symbol_list, member) { -+ const char *typediff; -+ if (check_assignment_types(member, rp, &typediff)) -+ return 1; -+ } END_FOR_EACH_PTR(member); -+ -+ return 0; -+} -+ -+static int compatible_argument_type(struct expression *expr, struct symbol *target, -+ struct expression **rp, const char *where) -+{ -+ if (compatible_transparent_union(target, rp)) -+ return 1; -+ -+ return compatible_assignment_types(expr, target, rp, where); -+} -+ - static void mark_assigned(struct expression *expr) - { - struct symbol *sym; -@@ -2173,7 +2199,7 @@ static int evaluate_arguments(struct symbol *f, struct symbol *fn, struct expres - static char where[30]; - examine_symbol_type(target); - sprintf(where, "argument %d", i); -- compatible_assignment_types(expr, target, p, where); -+ compatible_argument_type(expr, target, p, where); - } - - i++; -diff --git a/parse.c b/parse.c -index 9cc5f6562544..785630ade3c7 100644 ---- a/parse.c -+++ b/parse.c -@@ -1208,7 +1208,12 @@ static struct token *attribute_designated_init(struct token *token, struct symbo - static struct token *attribute_transparent_union(struct token *token, struct symbol *attr, struct decl_state *ctx) - { - if (Wtransparent_union) -- warning(token->pos, "ignoring attribute __transparent_union__"); -+ warning(token->pos, "attribute __transparent_union__"); -+ -+ if (ctx->ctype.base_type && ctx->ctype.base_type->type == SYM_UNION) -+ ctx->ctype.base_type->transparent_union = 1; -+ else -+ warning(token->pos, "attribute __transparent_union__ applied to non-union type"); - return token; - } - -diff --git a/symbol.h b/symbol.h -index 43c165befe76..ccb5dcb9b406 100644 ---- a/symbol.h -+++ b/symbol.h -@@ -174,7 +174,8 @@ struct symbol { - evaluated:1, - string:1, - designated_init:1, -- forced_arg:1; -+ forced_arg:1, -+ transparent_union:1; - struct expression *array_size; - struct ctype ctype; - struct symbol_list *arguments; -diff --git a/validation/transparent-union.c b/validation/transparent-union.c -new file mode 100644 -index 000000000000..149c7d947683 ---- /dev/null -+++ b/validation/transparent-union.c -@@ -0,0 +1,25 @@ -+struct a { -+ int field; -+}; -+struct b { -+ int field; -+}; -+ -+typedef union { -+ struct a *a; -+ struct b *b; -+} transparent_arg __attribute__((__transparent_union__)); -+ -+static void foo(transparent_arg arg) -+{ -+} -+ -+static void bar(void) -+{ -+ struct b arg = { 0 }; -+ foo((struct a *) &arg); -+} -+ -+/* -+ * check-name: Transparent union attribute. -+ */ - -commit 0f25c6a78e08fdc15af5e599d836fa24349c042f -Author: Linus Torvalds -Date: Sun Mar 30 09:49:13 2014 -0700 - - Add warning about duplicate initializers - - Noticed this while looking at an independent bug reported by Hans - Verkuil. - - Signed-off-by: Linus Torvalds - Reviewed-by: Josh Triplett - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index 98fc52b83236..b86b21bf050a 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -3081,10 +3081,18 @@ static void check_duplicates(struct symbol *sym) - { - int declared = 0; - struct symbol *next = sym; -+ int initialized = sym->initializer != NULL; - - while ((next = next->same_symbol) != NULL) { - const char *typediff; - evaluate_symbol(next); -+ if (initialized && next->initializer) { -+ sparse_error(sym->pos, "symbol '%s' has multiple initializers (originally initialized at %s:%d)", -+ show_ident(sym->ident), -+ stream_name(next->pos.stream), next->pos.line); -+ /* Only warn once */ -+ initialized = 0; -+ } - declared++; - typediff = type_difference(&sym->ctype, &next->ctype, 0, 0); - if (typediff) { - -commit 6e71132697e13a56625bac0bc51392e8f819c6de -Author: Linus Torvalds -Date: Sun Mar 30 10:13:54 2014 -0700 - - Use any previous initializer to size a symbol - - When we size a symbol, we only have one initializer per symbol, but we - may have multiple symbol declarations for the same symbol. So make sure - to walk the "same_symbol" chain to find the initializer, rather than - assuming it is attached to the current declaration. - - Reported-by: Hans Verkuil - Signed-off-by: Linus Torvalds - Signed-off-by: Christopher Li - -diff --git a/symbol.c b/symbol.c -index eb6e1215ee87..4b91abd8021e 100644 ---- a/symbol.c -+++ b/symbol.c -@@ -354,6 +354,15 @@ static int count_array_initializer(struct symbol *t, struct expression *expr) - return nr; - } - -+static struct expression *get_symbol_initializer(struct symbol *sym) -+{ -+ do { -+ if (sym->initializer) -+ return sym->initializer; -+ } while ((sym = sym->same_symbol) != NULL); -+ return NULL; -+} -+ - static struct symbol * examine_node_type(struct symbol *sym) - { - struct symbol *base_type = examine_base_type(sym); -@@ -376,12 +385,15 @@ static struct symbol * examine_node_type(struct symbol *sym) - sym->ctype.alignment = alignment; - - /* Unsized array? The size might come from the initializer.. */ -- if (bit_size < 0 && base_type->type == SYM_ARRAY && sym->initializer) { -- struct symbol *node_type = base_type->ctype.base_type; -- int count = count_array_initializer(node_type, sym->initializer); -- -- if (node_type && node_type->bit_size >= 0) -- bit_size = node_type->bit_size * count; -+ if (bit_size < 0 && base_type->type == SYM_ARRAY) { -+ struct expression *initializer = get_symbol_initializer(sym); -+ if (initializer) { -+ struct symbol *node_type = base_type->ctype.base_type; -+ int count = count_array_initializer(node_type, initializer); -+ -+ if (node_type && node_type->bit_size >= 0) -+ bit_size = node_type->bit_size * count; -+ } - } - - sym->bit_size = bit_size; - -commit 488f14955196fab95bb3a834c9979a24cc4cb390 -Author: Hans Verkuil -Date: Thu Apr 3 11:17:11 2014 -0700 - - Add test case for extern array - - Has report this bug which fix by Linus in the previous commit. - Sparse will report "cannot size expression" on the array size. - It is cause by the second extern declare with imcompleted size. - - Signed-off-by: Hans Verkuil - Signed-off-by: Christopher Li - -diff --git a/validation/extern-array.c b/validation/extern-array.c -new file mode 100644 -index 000000000000..58bc7ae6861f ---- /dev/null -+++ b/validation/extern-array.c -@@ -0,0 +1,14 @@ -+extern const char *v4l2_type_names[]; -+const char *v4l2_type_names[] = { -+ "test" -+}; -+extern const char *v4l2_type_names[]; -+ -+static void test(void) -+{ -+ unsigned sz = sizeof(v4l2_type_names); -+} -+/* -+ * check-name: duplicate extern array -+ */ -+ - -commit 2c82340a20c10f9db2f560ecb18692f2e186c9db -Author: Hans Verkuil -Date: Thu Apr 3 11:26:28 2014 -0700 - - Add test case for anonymous union initializer - - Signed-off-by: Hans Verkuil - Signed-off-by: Christopher Li - -diff --git a/validation/anon-union.c b/validation/anon-union.c -new file mode 100644 -index 000000000000..487f957b8eb1 ---- /dev/null -+++ b/validation/anon-union.c -@@ -0,0 +1,11 @@ -+struct s { -+ union { -+ int val; -+ }; -+}; -+ -+static struct s foo = { .val = 5, }; -+/* -+ * check-name: test anonymous union initializer -+ */ -+ - -commit 42ebe4166c52a0c4cb8b50ab488374ac5c92ff2b -Author: Hans Verkuil -Date: Thu Apr 3 11:46:22 2014 -0700 - - Add test case for the ioc type check - - Running sparse over this gives: - - error: bad integer constant expression - - Signed-off-by: Hans Verkuil - Signed-off-by: Christopher Li - -diff --git a/validation/ioc-typecheck.c b/validation/ioc-typecheck.c -new file mode 100644 -index 000000000000..aa060f7be185 ---- /dev/null -+++ b/validation/ioc-typecheck.c -@@ -0,0 +1,17 @@ -+extern unsigned int __invalid_size_argument_for_IOC; -+#define _IOC_TYPECHECK(t) \ -+ ((sizeof(t) == sizeof(t[1]) && \ -+ sizeof(t) < (1 << 14)) ? \ -+ sizeof(t) : __invalid_size_argument_for_IOC) -+ -+#define TEST_IOCTL (50 | (_IOC_TYPECHECK(unsigned) << 8)) -+ -+static unsigned iocnrs[] = { -+ [TEST_IOCTL & 0xff] = 1, -+}; -+/* -+ * check-name: correct handling of _IOC_TYPECHECK -+ * -+ * check-error-start -+ * check-error-end -+ */ - -commit 38d1124ec5cd10e117e320e25a55305dca0899b6 -Author: Linus Torvalds -Date: Thu Apr 3 12:01:00 2014 -0700 - - Fix error at anoymous unions - - Ok, this fixes the warning, but we seem to still mess up the actual - initializer. It looks like some later phase gets the offset wrong, so - when we lay things out in memory, we'll put things at offset zero - (which is right for your test-case, but not if there was something - before that anonymous union). - - Regardless, that only matters for real code generation, not for using - sparse as a semantic checker, so this patch is correct and is an - improvement. - - Reported-by: Hans Verkuil - Signed-off-by: Linus Torvalds - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index b86b21bf050a..7ce8c555117a 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -2209,17 +2209,6 @@ static int evaluate_arguments(struct symbol *f, struct symbol *fn, struct expres - return 1; - } - --static struct symbol *find_struct_ident(struct symbol *ctype, struct ident *ident) --{ -- struct symbol *sym; -- -- FOR_EACH_PTR(ctype->symbol_list, sym) { -- if (sym->ident == ident) -- return sym; -- } END_FOR_EACH_PTR(sym); -- return NULL; --} -- - static void convert_index(struct expression *e) - { - struct expression *child = e->idx_expression; -@@ -2328,11 +2317,12 @@ static struct expression *check_designators(struct expression *e, - } - e = e->idx_expression; - } else if (e->type == EXPR_IDENTIFIER) { -+ int offset = 0; - if (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION) { - err = "field name not in struct or union"; - break; - } -- ctype = find_struct_ident(ctype, e->expr_ident); -+ ctype = find_identifier(e->expr_ident, ctype->symbol_list, &offset); - if (!ctype) { - err = "unknown field name in"; - break; - -commit 2ea26979e9134849c17a45aedcc80e20f27323b9 -Author: Cody P Schafer -Date: Tue Apr 15 10:22:49 2014 -0700 - - build: allow use of LLVM_CONFIG to override llvm-config config script - - On systems like ubuntu 12.04, llvm-config is llvm 2.9, but - llvm-config-3.0 and llvm-config-3.3 (for example) are versions 3.0 and - 3.3 respectively. Allow overriding the name/path of the llvm-config - script so people can use these versioned config scripts - - Signed-off-by: Cody P Schafer - Reviewed-by: Josh Triplett - Signed-off-by: Christopher Li - -diff --git a/Makefile b/Makefile -index c3f310409f6c..f453dedcc62c 100644 ---- a/Makefile -+++ b/Makefile -@@ -30,9 +30,10 @@ HAVE_GCC_DEP:=$(shell touch .gcc-test.c && \ - $(CC) -c -Wp,-MD,.gcc-test.d .gcc-test.c 2>/dev/null && \ - echo 'yes'; rm -f .gcc-test.d .gcc-test.o .gcc-test.c) - HAVE_GTK2:=$(shell pkg-config --exists gtk+-2.0 2>/dev/null && echo 'yes') --HAVE_LLVM:=$(shell llvm-config --version >/dev/null 2>&1 && echo 'yes') --HAVE_LLVM_VERSION:=$(shell llvm-config --version | grep "^[3-9].*" >/dev/null 2>&1 && echo yes) --LLVM_VERSION=$(shell llvm-config --version) -+LLVM_CONFIG:=llvm-config -+HAVE_LLVM:=$(shell $(LLVM_CONFIG) --version >/dev/null 2>&1 && echo 'yes') -+HAVE_LLVM_VERSION:=$(shell $(LLVM_CONFIG) --version | grep "^[3-9].*" >/dev/null 2>&1 && echo yes) -+LLVM_VERSION:=$(shell $(LLVM_CONFIG) --version) - - GCC_BASE = $(shell $(CC) --print-file-name=) - BASIC_CFLAGS = -DGCC_BASE=\"$(GCC_BASE)\" -@@ -84,9 +85,9 @@ HAVE_LLVM=no - else - LLVM_PROGS := sparse-llvm - $(LLVM_PROGS): LD := g++ --LLVM_LDFLAGS := $(shell llvm-config --ldflags) --LLVM_CFLAGS := $(shell llvm-config --cflags | sed -e "s/-DNDEBUG//g") --LLVM_LIBS := $(shell llvm-config --libs) -+LLVM_LDFLAGS := $(shell $(LLVM_CONFIG) --ldflags) -+LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cflags | sed -e "s/-DNDEBUG//g") -+LLVM_LIBS := $(shell $(LLVM_CONFIG) --libs) - PROGRAMS += $(LLVM_PROGS) - INST_PROGRAMS += sparse-llvm sparsec - sparse-llvm.o: BASIC_CFLAGS += $(LLVM_CFLAGS) - -commit fe5eda126b9f5315e0049fd174d2326fecea6249 -Author: Cody P Schafer -Date: Tue Apr 15 12:51:29 2014 -0700 - - sparse{i,c}: use LLVM_CONFIG to find llc and lli - - Some systems have multiple llvm versions installed, and have prefixed - executables ("-"). While we could require the user to - specify a variable for each executable (LLC, LLI), using llvm-config - --bindir to locate them and allowing them to override using LLVM_CONFIG - makes much less work. - - Signed-off-by: Cody P Schafer - Signed-off-by: Christopher Li - -diff --git a/sparsec b/sparsec -index 9c90b3054f09..9dc96c956e47 100755 ---- a/sparsec -+++ b/sparsec -@@ -34,7 +34,9 @@ TMPFILE=`mktemp -t tmp.XXXXXX`".o" - - $DIRNAME/sparse-llvm $SPARSEOPTS > $TMPLLVM - --llc -o - $TMPLLVM | as -o $TMPFILE -+LLC=`"${LLVM_CONFIG:-llvm-config}" --bindir`/llc -+ -+$LLC -o - $TMPLLVM | as -o $TMPFILE - - if [ $NEED_LINK -eq 1 ]; then - if [ -z $OUTFILE ]; then -diff --git a/sparsei b/sparsei -index 463215423c95..3431a9f0b59b 100755 ---- a/sparsei -+++ b/sparsei -@@ -3,7 +3,7 @@ - set +e - - DIRNAME=`dirname $0` --LLI=`llvm-config --bindir`/lli -+LLI=`"${LLVM_CONFIG:-llvm-config}" --bindir`/lli - - if [ $# -eq 0 ]; then - echo "`basename $0`: no input files" - -commit f11dd94ea7eaf505d27b313f6e2eb72eeee5d013 -Author: Cody P Schafer -Date: Tue Apr 15 16:08:57 2014 -0700 - - parse: support c99 [static ...] in abstract array declarators - - The n1570 specifies (in 6.7.6.2.3) that either type-qualifiers - (ie: "restrict") come first and are followed by "static" or the - opposite ("static" then type-qualifiers). - - Also add a test. - - Signed-off-by: Cody P Schafer - Signed-off-by: Christopher Li - -diff --git a/ident-list.h b/ident-list.h -index e93aae762948..c0fc18fcfe4d 100644 ---- a/ident-list.h -+++ b/ident-list.h -@@ -91,6 +91,7 @@ IDENT(artificial); IDENT(__artificial__); - IDENT(leaf); IDENT(__leaf__); - IDENT(vector_size); IDENT(__vector_size__); - IDENT(error); IDENT(__error__); -+IDENT(static); - - - /* Preprocessor idents. Direct use of __IDENT avoids mentioning the keyword -diff --git a/parse.c b/parse.c -index 785630ade3c7..55a57a74195b 100644 ---- a/parse.c -+++ b/parse.c -@@ -1533,12 +1533,28 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta - return token; - } - -+static struct token *abstract_array_static_declarator(struct token *token, int *has_static) -+{ -+ while (token->ident == &static_ident) { -+ if (*has_static) -+ sparse_error(token->pos, "duplicate array static declarator"); -+ -+ *has_static = 1; -+ token = token->next; -+ } -+ return token; -+ -+} -+ - static struct token *abstract_array_declarator(struct token *token, struct symbol *sym) - { - struct expression *expr = NULL; -+ int has_static = 0; -+ -+ token = abstract_array_static_declarator(token, &has_static); - - if (match_idents(token, &restrict_ident, &__restrict_ident, NULL)) -- token = token->next; -+ token = abstract_array_static_declarator(token->next, &has_static); - token = parse_expression(token, &expr); - sym->array_size = expr; - return token; -diff --git a/validation/abstract-array-declarator-static.c b/validation/abstract-array-declarator-static.c -new file mode 100644 -index 000000000000..92f06bdc6d99 ---- /dev/null -+++ b/validation/abstract-array-declarator-static.c -@@ -0,0 +1,14 @@ -+ -+extern void f1(int g[static 1]); -+extern void f2(int g[static restrict 1]); -+extern void f3(int g[restrict static 1]); -+extern void f4(int g[static restrict static 1]); /* duplicate static error */ -+extern void f5(int g[restrict static static 1]); /* duplicate static error */ -+ -+/* -+ * check-name: abstract array declarator static -+ * check-error-start -+abstract-array-declarator-static.c:5:38: error: duplicate array static declarator -+abstract-array-declarator-static.c:6:38: error: duplicate array static declarator -+ * check-error-end -+ */ - -commit d917662d54ba68d0c3b03e994cb1fa66d7b19c30 -Author: Andy Shevchenko -Date: Tue Jun 17 12:11:45 2014 +0300 - - lib.c: skip --param parameters - - Very dumb patch to just skip --param allow-store-data-races=0 introduced in - newer GCC versions. - - Without this patch sparse recognizes parameter of the --param option as a file - name which obviously couldn't be found. - - Signed-off-by: Andy Shevchenko - Signed-off-by: Christopher Li - -diff --git a/lib.c b/lib.c -index 844797d5db2e..0bc4b2b48476 100644 ---- a/lib.c -+++ b/lib.c -@@ -675,22 +675,42 @@ static char **handle_version(char *arg, char **next) - exit(0); - } - -+static char **handle_param(char *arg, char **next) -+{ -+ char *value = NULL; -+ -+ /* For now just skip any '--param=*' or '--param *' */ -+ if (*arg == '\0') { -+ value = *++next; -+ } else if (isspace(*arg) || *arg == '=') { -+ value = ++arg; -+ } -+ -+ if (!value) -+ die("missing argument for --param option"); -+ -+ return next; -+} -+ - struct switches { - const char *name; - char **(*fn)(char *, char **); -+ unsigned int prefix:1; - }; - - static char **handle_long_options(char *arg, char **next) - { - static struct switches cmd[] = { -+ { "param", handle_param, 1 }, - { "version", handle_version }, - { NULL, NULL } - }; - struct switches *s = cmd; - - while (s->name) { -- if (!strcmp(s->name, arg)) -- return s->fn(arg, next); -+ int optlen = strlen(s->name); -+ if (!strncmp(s->name, arg, optlen + !s->prefix)) -+ return s->fn(arg + optlen, next); - s++; - } - return next; - -commit 1db35d0a95caee0f0c57e5dc227822381579620d -Author: Christopher Li -Date: Sun Jun 29 00:38:08 2014 -0700 - - Minor clean up for option handling - - Remove the loop for short option. - - Signed-off-by: Christopher Li - -diff --git a/lib.c b/lib.c -index 0bc4b2b48476..4e6fc81c8c2f 100644 ---- a/lib.c -+++ b/lib.c -@@ -661,6 +661,14 @@ static char **handle_nostdinc(char *arg, char **next) - return next; - } - -+static char **handle_switch_n(char *arg, char **next) -+{ -+ if (!strcmp (arg, "nostdinc")) -+ return handle_nostdinc(arg, next); -+ -+ return next; -+} -+ - static char **handle_base_dir(char *arg, char **next) - { - gcc_base_dir = *++next; -@@ -669,6 +677,15 @@ static char **handle_base_dir(char *arg, char **next) - return next; - } - -+static char **handle_switch_g(char *arg, char **next) -+{ -+ if (!strcmp (arg, "gcc-base-dir")) -+ return handle_base_dir(arg, next); -+ -+ return next; -+} -+ -+ - static char **handle_version(char *arg, char **next) - { - printf("%s\n", SPARSE_VERSION); -@@ -714,46 +731,33 @@ static char **handle_long_options(char *arg, char **next) - s++; - } - return next; -- - } - - static char **handle_switch(char *arg, char **next) - { -- static struct switches cmd[] = { -- { "nostdinc", handle_nostdinc }, -- { "gcc-base-dir", handle_base_dir}, -- { NULL, NULL } -- }; -- struct switches *s; -- - switch (*arg) { -+ case 'a': return handle_switch_a(arg, next); - case 'D': return handle_switch_D(arg, next); - case 'E': return handle_switch_E(arg, next); -+ case 'f': return handle_switch_f(arg, next); -+ case 'g': return handle_switch_g(arg, next); -+ case 'G': return handle_switch_G(arg, next); - case 'I': return handle_switch_I(arg, next); - case 'i': return handle_switch_i(arg, next); - case 'M': return handle_switch_M(arg, next); - case 'm': return handle_switch_m(arg, next); -+ case 'n': return handle_switch_n(arg, next); - case 'o': return handle_switch_o(arg, next); -+ case 'O': return handle_switch_O(arg, next); -+ case 's': return handle_switch_s(arg, next); - case 'U': return handle_switch_U(arg, next); - case 'v': return handle_switch_v(arg, next); - case 'W': return handle_switch_W(arg, next); -- case 'O': return handle_switch_O(arg, next); -- case 'f': return handle_switch_f(arg, next); -- case 'G': return handle_switch_G(arg, next); -- case 'a': return handle_switch_a(arg, next); -- case 's': return handle_switch_s(arg, next); - case '-': return handle_long_options(arg + 1, next); - default: - break; - } - -- s = cmd; -- while (s->name) { -- if (!strcmp(s->name, arg)) -- return s->fn(arg, next); -- s++; -- } -- - /* - * Ignore unknown command line options: - * they're probably gcc switches - -commit b3e9d87c6a98bde0c95bc8badfde75c06661738b -Author: Jeff Layton -Date: Wed Jul 16 12:27:42 2014 -0400 - - sparse: make bits_to_bytes round up instead of down - - Currently, sparse handles arrays of bools incorrectly. If you declare an - array of bools like this: - - static _Bool boolarray[3] = { - [0] = 1, - [1] = 1, - }; - - ...you get warnings like this (which are bogus): - - ./test.c:2:10: warning: Initializer entry defined twice - ./test.c:3:10: also defined here - - The problem is that bits_to_bytes rounds down instead of up, and sparse - defaults to _Bool being only 1 bit in size. This causes sparse to think - that they sit within the same byte, when they do not. - - Fix bits_to_bytes to round up instead of down, and fix the call in - init_ctype to no longer correct for it. Also add a validation - test to ensure that we don't break this in the future. - - Signed-off-by: Jeff Layton - Signed-off-by: Christopher Li - -diff --git a/symbol.c b/symbol.c -index 4b91abd8021e..1a3df636c7b7 100644 ---- a/symbol.c -+++ b/symbol.c -@@ -900,7 +900,7 @@ void init_ctype(void) - struct symbol *sym = ctype->ptr; - unsigned long bit_size = ctype->bit_size ? *ctype->bit_size : -1; - unsigned long maxalign = ctype->maxalign ? *ctype->maxalign : 0; -- unsigned long alignment = bits_to_bytes(bit_size + bits_in_char - 1); -+ unsigned long alignment = bits_to_bytes(bit_size); - - if (alignment > maxalign) - alignment = maxalign; -diff --git a/target.h b/target.h -index 1030c7c38993..140df3c1a64d 100644 ---- a/target.h -+++ b/target.h -@@ -49,7 +49,7 @@ extern int enum_alignment; - - static inline int bits_to_bytes(int bits) - { -- return bits >= 0 ? bits / bits_in_char : -1; -+ return bits >= 0 ? (bits + bits_in_char - 1) / bits_in_char : -1; - } - - static inline int bytes_to_bits(int bytes) -diff --git a/validation/initializer-entry-defined-twice.c b/validation/initializer-entry-defined-twice.c -index 968e3dd1af2a..8a5bd3a95631 100644 ---- a/validation/initializer-entry-defined-twice.c -+++ b/validation/initializer-entry-defined-twice.c -@@ -41,6 +41,16 @@ static struct same_offset not_an_error = { - .field1 = { }, - .field2 = 0 - }; -+ -+/* -+ * _Bools generally take a whole byte, so ensure that we can initialize -+ * them without spewing a warning. -+ */ -+static _Bool boolarray[3] = { -+ [0] = 1, -+ [1] = 1, -+}; -+ - /* - * check-name: Initializer entry defined twice - * - -commit 09e7a493cf3d92a6ccd7611b69bd41cb5727f765 -Author: Christopher Li -Date: Tue Jul 15 23:20:09 2014 -0700 - - round up the array element size to byte align - - When layout the array element, the element size should - round up to byte align. - - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index 7ce8c555117a..03992d03ae1d 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -2302,7 +2302,7 @@ static struct expression *check_designators(struct expression *e, - } - type = ctype->ctype.base_type; - if (ctype->bit_size >= 0 && type->bit_size >= 0) { -- unsigned offset = e->idx_to * type->bit_size; -+ unsigned offset = array_element_offset(type->bit_size, e->idx_to); - if (offset >= ctype->bit_size) { - err = "index out of bounds in"; - break; -diff --git a/symbol.c b/symbol.c -index 1a3df636c7b7..a6976279dde2 100644 ---- a/symbol.c -+++ b/symbol.c -@@ -234,7 +234,8 @@ static struct symbol * examine_array_type(struct symbol *sym) - return sym; - - if (array_size) { -- bit_size = base_type->bit_size * get_expression_value_silent(array_size); -+ bit_size = array_element_offset(base_type->bit_size, -+ get_expression_value_silent(array_size)); - if (array_size->type != EXPR_VALUE) { - if (Wvla) - warning(array_size->pos, "Variable length array is used."); -diff --git a/target.h b/target.h -index 140df3c1a64d..78c85cf7e5e6 100644 ---- a/target.h -+++ b/target.h -@@ -57,4 +57,12 @@ static inline int bytes_to_bits(int bytes) - return bytes * bits_in_char; - } - -+static inline unsigned long array_element_offset(unsigned long base_bits, int idx) -+{ -+ int fragment = base_bits % bits_in_char; -+ if (fragment) -+ base_bits += bits_in_char - fragment; -+ return base_bits * idx; -+} -+ - #endif - -commit 748b856ed3e7b63faed20ed6f64dfb12371e3cf3 -Author: Linus Torvalds -Date: Tue Apr 1 10:20:34 2014 -0700 - - Fix scoping of extern symbols in block scope - - We'd only match them with other symbols marked 'extern', but really, we - should match them with any top-level non-static symbol. - - Signed-off-by: Linus Torvalds - Signed-off-by: Christopher Li - -diff --git a/symbol.c b/symbol.c -index a6976279dde2..0ceff6281a96 100644 ---- a/symbol.c -+++ b/symbol.c -@@ -577,11 +577,12 @@ void check_declaration(struct symbol *sym) - sym->same_symbol = next; - return; - } -- if (sym->ctype.modifiers & next->ctype.modifiers & MOD_EXTERN) { -- if ((sym->ctype.modifiers ^ next->ctype.modifiers) & MOD_INLINE) -- continue; -- sym->same_symbol = next; -- return; -+ /* Extern in block level matches a TOPLEVEL non-static symbol */ -+ if (sym->ctype.modifiers & MOD_EXTERN) { -+ if ((next->ctype.modifiers & (MOD_TOPLEVEL|MOD_STATIC)) == MOD_TOPLEVEL) { -+ sym->same_symbol = next; -+ return; -+ } - } - - if (!Wshadow || warned) - -commit 7abd8a76b4e07ad60b5262e4c7858e638467fab8 -Author: Christopher Li -Date: Sat Aug 2 10:56:59 2014 -0700 - - Make same_symbol list share the same scope - - Consider the following case, extern inline declare after - extern declare of the same function. - - extern int g(int); - extern __inline__ int g(int x) - { - return x; - } - - Sparse will give the first function global scope and - the second one file scope. Also the first one will get the - function body from the second one. That cause the failure - of the validation/extern-inlien.c - - This change rebind the scope of the same_symbol chain to - the new scope. It will pass the extern-inline.c test case. - - Signed-off-by: Christopher Li - -diff --git a/parse.c b/parse.c -index 55a57a74195b..eaa1883831d9 100644 ---- a/parse.c -+++ b/parse.c -@@ -2611,6 +2611,7 @@ static struct token *parse_function_body(struct token *token, struct symbol *dec - info(prev->definition->pos, " the previous one is here"); - } else { - while (prev) { -+ rebind_scope(prev, decl->scope); - prev->definition = decl; - prev = prev->same_symbol; - } -diff --git a/scope.c b/scope.c -index b415ace97012..cbf2fcf57364 100644 ---- a/scope.c -+++ b/scope.c -@@ -46,6 +46,20 @@ void bind_scope(struct symbol *sym, struct scope *scope) - add_symbol(&scope->symbols, sym); - } - -+ -+void rebind_scope(struct symbol *sym, struct scope *new) -+{ -+ struct scope *old = sym->scope; -+ -+ if (old == new) -+ return; -+ -+ if (old) -+ delete_ptr_list_entry((struct ptr_list**) &old->symbols, sym, 1); -+ -+ bind_scope(sym, new); -+} -+ - static void start_scope(struct scope **s) - { - struct scope *scope = __alloc_scope(0); -diff --git a/scope.h b/scope.h -index 045c3568e50d..9bbb6757b636 100644 ---- a/scope.h -+++ b/scope.h -@@ -55,6 +55,7 @@ extern void start_function_scope(void); - extern void end_function_scope(void); - - extern void bind_scope(struct symbol *, struct scope *); -+extern void rebind_scope(struct symbol *, struct scope *); - - extern int is_outer_scope(struct scope *); - #endif - -commit 5119a12a0efd88f0f997699b80e26beec10c4e73 -Author: Linus Torvalds -Date: Thu Sep 18 10:14:51 2014 +0800 - - Fix initializers in anonymous structs and unions - - The "trivial fix" is to just save off the offset in check_designators - (add a new field to the "EXPR_IDENTIFIER" part of "struct expression" - and then pick up that offset in "convert_ident()" - - However, that has exactly the same issue with the whole fake - EXPR_IDENTIFIER created by "next_designators()". Now we need to - initialize the offset field there too. And, for the same reason as - before, the field that "next_designator()" picks may not *have* an - identifier, because the next designator may in fact be an anonymous - union. - - Anyway, with all that said, maybe this really confusing and hacky - patch would work. It passes my tests. The magic offset calculation in - next_designators() has a big comment about what the heck it is doing, - and otherwise it's a fairly straightforward case of "save offset from - check_designators() time to be used by convert_ident()". - - My stupid test-case is this incredibly hacky thing: - - struct A { - int aa; - int bb; - }; - - struct S { - int a; - union { - int b; - int c; - } u[10]; - int dummy; - union { - int d; - int e; - }; - }; - - int fn(void) - { - struct S s = { - .a = 1, - .u[2].b = 2, - .dummy = 1, - { 3 } - }; - return s.dummy*1000 + s.d*100 + s.u[2].b*10 + s.a; // 1321 - } - - where I use "./test-linearize" to verify that the initializer layout - matches the code generation layout (so that 'fn' function *should* - linearize to just a simple "ret.32 $1321", and with this patch it - does). - - But I bet this misses some case. However, the current state wrt - initializer offsets really is very broken, so maybe it's ok. - - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index 03992d03ae1d..31a6a49329b8 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -2223,9 +2223,10 @@ static void convert_index(struct expression *e) - static void convert_ident(struct expression *e) - { - struct expression *child = e->ident_expression; -- struct symbol *sym = e->field; -+ int offset = e->offset; -+ - e->type = EXPR_POS; -- e->init_offset = sym->offset; -+ e->init_offset = offset; - e->init_nr = 1; - e->init_expr = child; - } -@@ -2277,6 +2278,7 @@ static struct expression *first_subobject(struct symbol *ctype, int class, - new = alloc_expression(e->pos, EXPR_IDENTIFIER); - new->ident_expression = e; - new->field = new->ctype = field; -+ new->offset = field->offset; - } - *v = new; - return new; -@@ -2327,6 +2329,7 @@ static struct expression *check_designators(struct expression *e, - err = "unknown field name in"; - break; - } -+ e->offset = offset; - e->field = e->ctype = ctype; - last = e; - if (!e->ident_expression) { -@@ -2386,6 +2389,7 @@ static struct expression *next_designators(struct expression *old, - } else if (old->type == EXPR_IDENTIFIER) { - struct expression *copy; - struct symbol *field; -+ int offset = 0; - - copy = next_designators(old->ident_expression, - old->ctype, e, v); -@@ -2397,6 +2401,17 @@ static struct expression *next_designators(struct expression *old, - } - copy = e; - *v = new = alloc_expression(e->pos, EXPR_IDENTIFIER); -+ /* -+ * We can't necessarily trust "field->offset", -+ * because the field might be in an anonymous -+ * union, and the field offset is then the offset -+ * within that union. -+ * -+ * The "old->offset - old->field->offset" -+ * would be the offset of such an anonymous -+ * union. -+ */ -+ offset = old->offset - old->field->offset; - } else { - field = old->field; - new = alloc_expression(e->pos, EXPR_IDENTIFIER); -@@ -2406,6 +2421,7 @@ static struct expression *next_designators(struct expression *old, - new->expr_ident = field->ident; - new->ident_expression = copy; - new->ctype = field; -+ new->offset = field->offset + offset; - convert_ident(old); - } - return new; -diff --git a/expression.h b/expression.h -index e31d14051e01..80b3be5f526f 100644 ---- a/expression.h -+++ b/expression.h -@@ -149,6 +149,7 @@ struct expression { - struct expression_list *expr_list; - // EXPR_IDENTIFIER - struct /* ident_expr */ { -+ int offset; - struct ident *expr_ident; - struct symbol *field; - struct expression *ident_expression; - -commit d92353b4eacbac54d693edd62fb565f071e3ba86 -Author: Omar Sandoval -Date: Wed Sep 24 14:01:01 2014 -0700 - - sparse-llvm: Fix LLVM 3.5 linker errors - - llvm-config 3.5 no longer lists the non-LLVM libraries needed for linkage when - passed --libs. The --system-libs flag was added for this purpose. This adds - these libraries while silently doing nothing for older versions of LLVM. - - Signed-off-by: Omar Sandoval - Signed-off-by: Christopher Li - -diff --git a/Makefile b/Makefile -index f453dedcc62c..3b36943925e9 100644 ---- a/Makefile -+++ b/Makefile -@@ -88,6 +88,7 @@ $(LLVM_PROGS): LD := g++ - LLVM_LDFLAGS := $(shell $(LLVM_CONFIG) --ldflags) - LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cflags | sed -e "s/-DNDEBUG//g") - LLVM_LIBS := $(shell $(LLVM_CONFIG) --libs) -+LLVM_LIBS += $(shell llvm-config --system-libs 2>/dev/null) - PROGRAMS += $(LLVM_PROGS) - INST_PROGRAMS += sparse-llvm sparsec - sparse-llvm.o: BASIC_CFLAGS += $(LLVM_CFLAGS) - -commit a5bdeee9e145cc4313526f9722f80674321ab491 -Author: Pavel Roskin -Date: Wed Sep 24 22:53:31 2014 -0400 - - Use LLVM_CONFIG instead of llvm-config in Makefile - - Signed-off-by: Pavel Roskin - Reviewed-by: Omar Sandoval - Signed-off-by: Christopher Li - -diff --git a/Makefile b/Makefile -index 3b36943925e9..33f91f1c1974 100644 ---- a/Makefile -+++ b/Makefile -@@ -88,7 +88,7 @@ $(LLVM_PROGS): LD := g++ - LLVM_LDFLAGS := $(shell $(LLVM_CONFIG) --ldflags) - LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cflags | sed -e "s/-DNDEBUG//g") - LLVM_LIBS := $(shell $(LLVM_CONFIG) --libs) --LLVM_LIBS += $(shell llvm-config --system-libs 2>/dev/null) -+LLVM_LIBS += $(shell $(LLVM_CONFIG) --system-libs 2>/dev/null) - PROGRAMS += $(LLVM_PROGS) - INST_PROGRAMS += sparse-llvm sparsec - sparse-llvm.o: BASIC_CFLAGS += $(LLVM_CFLAGS) - -commit 4d8811879a1cc48c1cdd0b0466dc6865c715d149 -Author: Thomas Graf -Date: Thu Sep 25 10:11:17 2014 +0200 - - sparse: Make -Werror turn warnigns into errors - - Make sparse fail and return an error code if a warning is encountered - and -Werror is specified or a hard error is found. This allows to use - sparse in automated build systems to more easily catch new sparse - warnings. - - The validation script is extended to parse the expected output message - for an error message and validate the a non zero return value if such - a error message is found. - - Also changes cgcc to die if the checker fails. - - Signed-off-by: Thomas Graf - Signed-off-by: Christopher Li - -diff --git a/cgcc b/cgcc -index c075e5f1308e..204bda35fa90 100755 ---- a/cgcc -+++ b/cgcc -@@ -70,7 +70,7 @@ if ($do_check) { - - print "$check\n" if $verbose; - if ($do_compile) { -- system ($check); -+ system ($check) == 0 or die; - } else { - exec ($check); - } -diff --git a/lib.c b/lib.c -index 4e6fc81c8c2f..83956623d037 100644 ---- a/lib.c -+++ b/lib.c -@@ -126,25 +126,6 @@ void info(struct position pos, const char * fmt, ...) - va_end(args); - } - --void warning(struct position pos, const char * fmt, ...) --{ -- va_list args; -- -- if (!max_warnings) { -- show_info = 0; -- return; -- } -- -- if (!--max_warnings) { -- show_info = 0; -- fmt = "too many warnings"; -- } -- -- va_start(args, fmt); -- do_warn("warning: ", pos, fmt, args); -- va_end(args); --} -- - static void do_error(struct position pos, const char * fmt, va_list args) - { - static int errors = 0; -@@ -165,6 +146,32 @@ static void do_error(struct position pos, const char * fmt, va_list args) - errors++; - } - -+void warning(struct position pos, const char * fmt, ...) -+{ -+ va_list args; -+ -+ if (Werror) { -+ va_start(args, fmt); -+ do_error(pos, fmt, args); -+ va_end(args); -+ return; -+ } -+ -+ if (!max_warnings) { -+ show_info = 0; -+ return; -+ } -+ -+ if (!--max_warnings) { -+ show_info = 0; -+ fmt = "too many warnings"; -+ } -+ -+ va_start(args, fmt); -+ do_warn("warning: ", pos, fmt, args); -+ va_end(args); -+} -+ - void sparse_error(struct position pos, const char * fmt, ...) - { - va_list args; -@@ -219,6 +226,7 @@ int Wdesignated_init = 1; - int Wdo_while = 0; - int Winit_cstring = 0; - int Wenum_mismatch = 1; -+int Werror = 0; - int Wnon_pointer_null = 1; - int Wold_initializer = 1; - int Wone_bit_signed_bitfield = 1; -@@ -431,6 +439,7 @@ static const struct warning { - { "designated-init", &Wdesignated_init }, - { "do-while", &Wdo_while }, - { "enum-mismatch", &Wenum_mismatch }, -+ { "error", &Werror }, - { "init-cstring", &Winit_cstring }, - { "non-pointer-null", &Wnon_pointer_null }, - { "old-initializer", &Wold_initializer }, -@@ -462,7 +471,7 @@ static char **handle_onoff_switch(char *arg, char **next, const struct warning w - - if (!strcmp(p, "sparse-all")) { - for (i = 0; i < n; i++) { -- if (*warnings[i].flag != WARNING_FORCE_OFF) -+ if (*warnings[i].flag != WARNING_FORCE_OFF && warnings[i].flag != &Werror) - *warnings[i].flag = WARNING_ON; - } - } -diff --git a/lib.h b/lib.h -index f6cd9b4d89c2..dc0168404869 100644 ---- a/lib.h -+++ b/lib.h -@@ -112,6 +112,7 @@ extern int Wdefault_bitfield_sign; - extern int Wdesignated_init; - extern int Wdo_while; - extern int Wenum_mismatch; -+extern int Werror; - extern int Winit_cstring; - extern int Wnon_pointer_null; - extern int Wold_initializer; -diff --git a/sparse.1 b/sparse.1 -index 54da09b5a7df..acdce531bec0 100644 ---- a/sparse.1 -+++ b/sparse.1 -@@ -24,6 +24,9 @@ off those warnings, pass the negation of the associated warning option, - Turn on all sparse warnings, except for those explicitly disabled via - \fB\-Wno\-something\fR. - .TP -+.B \-Werror -+Turn all sparse warnings into errors. -+.TP - .B \-Waddress\-space - Warn about code which mixes pointers to different address spaces. - -diff --git a/sparse.c b/sparse.c -index 233585b33002..7d389b1e8a2f 100644 ---- a/sparse.c -+++ b/sparse.c -@@ -287,6 +287,9 @@ static void check_symbols(struct symbol_list *list) - check_context(ep); - } - } END_FOR_EACH_PTR(sym); -+ -+ if (die_if_error) -+ exit(1); - } - - int main(int argc, char **argv) -diff --git a/validation/test-suite b/validation/test-suite -index 3c011c6a6e6f..61667a56729c 100755 ---- a/validation/test-suite -+++ b/validation/test-suite -@@ -106,20 +106,26 @@ do_test() - fi - verbose "Using command : $cmd" - -+ # grab the expected output -+ sed -n '/check-output-start/,/check-output-end/p' $file \ -+ | grep -v check-output > "$file".output.expected -+ sed -n '/check-error-start/,/check-error-end/p' $file \ -+ | grep -v check-error > "$file".error.expected -+ - # grab the expected exit value - get_value "check-exit-value" $file - if [ "$?" -eq "0" ]; then - expected_exit_value=`echo $last_result | tr -d ' '` - else -- expected_exit_value=0 -+ grep -q -E "^[^:]+:[[:digit:]]+:[[:digit:]]+: error:" "$file".error.expected -+ if [ "$?" -eq "0" ]; then -+ expected_exit_value=1 -+ else -+ expected_exit_value=0 -+ fi - fi - verbose "Expecting exit value: $expected_exit_value" - -- # grab the expected output -- sed -n '/check-output-start/,/check-output-end/p' $file \ -- | grep -v check-output > "$file".output.expected -- sed -n '/check-error-start/,/check-error-end/p' $file \ -- | grep -v check-error > "$file".error.expected - - # grab the actual output & exit value - $cmd 1> $file.output.got 2> $file.error.got - -commit fe57afa0b44a5f49046cf1ac84040bcf172b8fa8 -Author: Christopher Li -Date: Fri Oct 10 22:37:07 2014 +0800 - - rename -Werror to -Wsparse-error - - Sparse is often share compile flags. So Werror is usually - mean gcc should treat warning as error. Apply the same - option to sparse will cause the Linux kernel checking fail - the build. We don't want that. - - Rename the sparse option to -Wsparse-error. It allow caller - to control gcc and sparse behavior seperately. - - It also make sparse return error status only when -Wsparse-error - is present. - - Signed-off-by: Christopher Li - -diff --git a/lib.c b/lib.c -index 83956623d037..b1b18aa71679 100644 ---- a/lib.c -+++ b/lib.c -@@ -150,7 +150,7 @@ void warning(struct position pos, const char * fmt, ...) - { - va_list args; - -- if (Werror) { -+ if (Wsparse_error) { - va_start(args, fmt); - do_error(pos, fmt, args); - va_end(args); -@@ -226,7 +226,7 @@ int Wdesignated_init = 1; - int Wdo_while = 0; - int Winit_cstring = 0; - int Wenum_mismatch = 1; --int Werror = 0; -+int Wsparse_error = 0; - int Wnon_pointer_null = 1; - int Wold_initializer = 1; - int Wone_bit_signed_bitfield = 1; -@@ -439,7 +439,7 @@ static const struct warning { - { "designated-init", &Wdesignated_init }, - { "do-while", &Wdo_while }, - { "enum-mismatch", &Wenum_mismatch }, -- { "error", &Werror }, -+ { "sparse-error", &Wsparse_error }, - { "init-cstring", &Winit_cstring }, - { "non-pointer-null", &Wnon_pointer_null }, - { "old-initializer", &Wold_initializer }, -@@ -471,7 +471,7 @@ static char **handle_onoff_switch(char *arg, char **next, const struct warning w - - if (!strcmp(p, "sparse-all")) { - for (i = 0; i < n; i++) { -- if (*warnings[i].flag != WARNING_FORCE_OFF && warnings[i].flag != &Werror) -+ if (*warnings[i].flag != WARNING_FORCE_OFF && warnings[i].flag != &Wsparse_error) - *warnings[i].flag = WARNING_ON; - } - } -diff --git a/lib.h b/lib.h -index dc0168404869..15b69fa2576f 100644 ---- a/lib.h -+++ b/lib.h -@@ -112,7 +112,7 @@ extern int Wdefault_bitfield_sign; - extern int Wdesignated_init; - extern int Wdo_while; - extern int Wenum_mismatch; --extern int Werror; -+extern int Wsparse_error; - extern int Winit_cstring; - extern int Wnon_pointer_null; - extern int Wold_initializer; -diff --git a/sparse.1 b/sparse.1 -index acdce531bec0..63fceb91f513 100644 ---- a/sparse.1 -+++ b/sparse.1 -@@ -24,7 +24,7 @@ off those warnings, pass the negation of the associated warning option, - Turn on all sparse warnings, except for those explicitly disabled via - \fB\-Wno\-something\fR. - .TP --.B \-Werror -+.B \-Wsparse\-error - Turn all sparse warnings into errors. - .TP - .B \-Waddress\-space -diff --git a/sparse.c b/sparse.c -index 7d389b1e8a2f..6b3324cfc6cc 100644 ---- a/sparse.c -+++ b/sparse.c -@@ -288,7 +288,7 @@ static void check_symbols(struct symbol_list *list) - } - } END_FOR_EACH_PTR(sym); - -- if (die_if_error) -+ if (Wsparse_error && die_if_error) - exit(1); - } - -diff --git a/validation/test-suite b/validation/test-suite -index 61667a56729c..744383dc112e 100755 ---- a/validation/test-suite -+++ b/validation/test-suite -@@ -117,12 +117,7 @@ do_test() - if [ "$?" -eq "0" ]; then - expected_exit_value=`echo $last_result | tr -d ' '` - else -- grep -q -E "^[^:]+:[[:digit:]]+:[[:digit:]]+: error:" "$file".error.expected -- if [ "$?" -eq "0" ]; then -- expected_exit_value=1 -- else -- expected_exit_value=0 -- fi -+ expected_exit_value=0 - fi - verbose "Expecting exit value: $expected_exit_value" - - -commit c1763a249aba0a40bd326c845c2a146132a02448 -Author: Ard Biesheuvel -Date: Mon Sep 8 08:30:03 2014 +0200 - - sparse: treat function pointers as pointers to const data - - This code snippet: - - static void bar(void const *arg) - { - int (*foo)(void) = arg; - } - - produces the following warning: - - test.c:4:28: warning: incorrect type in initializer (different modifiers) - test.c:4:28: expected int ( *foo )( ... ) - test.c:4:28: got void const *arg - - which is caused by the fact that the function pointer 'foo' is not annotated - as being a pointer to const data. However, dereferencing a function pointer - does not produce an lvalue, so a function pointer points to const data by - definition, and we should treat it accordingly. - - To avoid producing a warning on the inverse case, i.e., - - static void bar(void) - { - void *foo = bar; - } - - we only address the case where the function pointer is the target of - an assignment. - - Reviewed-by: Josh Triplett - Signed-off-by: Ard Biesheuvel - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index 31a6a49329b8..7bd47e66d1f1 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -1358,6 +1358,15 @@ static int check_assignment_types(struct symbol *target, struct expression **rp, - *typediff = "different address spaces"; - return 0; - } -+ /* -+ * If this is a function pointer assignment, it is -+ * actually fine to assign a pointer to const data to -+ * it, as a function pointer points to const data -+ * implicitly, i.e., dereferencing it does not produce -+ * an lvalue. -+ */ -+ if (b1->type == SYM_FN) -+ mod1 |= MOD_CONST; - if (mod2 & ~mod1) { - *typediff = "different modifiers"; - return 0; - -commit b6c1d2fe571a8c0b023d17f0557774c8af93fe85 -Author: Ramsay Jones -Date: Sat Sep 27 13:52:35 2014 +0100 - - Add the __restrict__ keyword - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/ident-list.h b/ident-list.h -index c0fc18fcfe4d..d5a145f852da 100644 ---- a/ident-list.h -+++ b/ident-list.h -@@ -86,7 +86,7 @@ IDENT(stdcall); IDENT(__stdcall__); - IDENT(fastcall); IDENT(__fastcall__); - IDENT(dllimport); IDENT(__dllimport__); - IDENT(dllexport); IDENT(__dllexport__); --IDENT(restrict); IDENT(__restrict); -+IDENT(restrict); IDENT(__restrict); IDENT(__restrict__); - IDENT(artificial); IDENT(__artificial__); - IDENT(leaf); IDENT(__leaf__); - IDENT(vector_size); IDENT(__vector_size__); -diff --git a/parse.c b/parse.c -index eaa1883831d9..ec835efb040e 100644 ---- a/parse.c -+++ b/parse.c -@@ -435,6 +435,7 @@ static struct init_keyword { - /* Ignored for now.. */ - { "restrict", NS_TYPEDEF, .op = &restrict_op}, - { "__restrict", NS_TYPEDEF, .op = &restrict_op}, -+ { "__restrict__", NS_TYPEDEF, .op = &restrict_op}, - - /* Storage class */ - { "auto", NS_TYPEDEF, .op = &auto_op }, -@@ -1553,7 +1554,7 @@ static struct token *abstract_array_declarator(struct token *token, struct symbo - - token = abstract_array_static_declarator(token, &has_static); - -- if (match_idents(token, &restrict_ident, &__restrict_ident, NULL)) -+ if (match_idents(token, &restrict_ident, &__restrict_ident, &__restrict___ident, NULL)) - token = abstract_array_static_declarator(token->next, &has_static); - token = parse_expression(token, &expr); - sym->array_size = expr; -diff --git a/validation/alternate-keywords.c b/validation/alternate-keywords.c -new file mode 100644 -index 000000000000..2e91a354d2fb ---- /dev/null -+++ b/validation/alternate-keywords.c -@@ -0,0 +1,46 @@ -+ -+extern float strtof(const char *__restrict__ ptr, char **__restrict__ endptr); -+extern double strtod(const char *__restrict ptr, char **__restrict endptr); -+/* restrict: -std=c99 or -std=gnu99 or -std=c11 */ -+extern long double strtold(const char *restrict ptr, char **restrict endptr); -+ -+extern int (*funcs[])(void); -+ -+/* typeof: no -std or -std=gnu90 or -std=gnu99 or -std=gnu11 */ -+extern typeof (funcs[0]) f0; -+extern __typeof (funcs[1]) f1; -+extern __typeof__(funcs[2]) f2; -+ -+typedef unsigned short uint16_t; -+typedef unsigned int uint32_t; -+typedef unsigned long long uint64_t; -+ -+static __inline__ uint16_t swap16(uint16_t val) -+{ -+ return ((((uint16_t)(val) & (uint16_t)0x00ffU) << 8) | -+ (((uint16_t)(val) & (uint16_t)0xff00U) >> 8)); -+} -+ -+static __inline uint32_t swap32(uint32_t val) -+{ -+ return ((((uint32_t)(val) & (uint32_t)0x000000ffUL) << 24) | -+ (((uint32_t)(val) & (uint32_t)0x0000ff00UL) << 8) | -+ (((uint32_t)(val) & (uint32_t)0x00ff0000UL) >> 8) | -+ (((uint32_t)(val) & (uint32_t)0xff000000UL) >> 24)); -+} -+ -+/* inline: no -std or -std=gnu90 or -std=c99 or -std=c11 */ -+static inline uint64_t swap64(uint64_t val) -+{ -+ return ((((uint64_t)(val) & (uint64_t)0x00000000000000ffULL) << 56) | -+ (((uint64_t)(val) & (uint64_t)0x000000000000ff00ULL) << 40) | -+ (((uint64_t)(val) & (uint64_t)0x0000000000ff0000ULL) << 24) | -+ (((uint64_t)(val) & (uint64_t)0x00000000ff000000ULL) << 8) | -+ (((uint64_t)(val) & (uint64_t)0x000000ff00000000ULL) >> 8) | -+ (((uint64_t)(val) & (uint64_t)0x0000ff0000000000ULL) >> 24) | -+ (((uint64_t)(val) & (uint64_t)0x00ff000000000000ULL) >> 40) | -+ (((uint64_t)(val) & (uint64_t)0xff00000000000000ULL) >> 56)); -+} -+/* -+ * check-name: alternate keywords -+ */ -diff --git a/validation/reserved.c b/validation/reserved.c -index caacd21fac75..e5d7af862ed5 100644 ---- a/validation/reserved.c -+++ b/validation/reserved.c -@@ -30,6 +30,7 @@ reserved.c:8:12: error: Trying to use reserved word '__const' as identifier - reserved.c:9:12: error: Trying to use reserved word '__const__' as identifier - reserved.c:10:12: error: Trying to use reserved word 'restrict' as identifier - reserved.c:11:12: error: Trying to use reserved word '__restrict' as identifier -+reserved.c:12:12: error: Trying to use reserved word '__restrict__' as identifier - reserved.c:13:12: error: Trying to use reserved word 'typedef' as identifier - reserved.c:14:12: error: Trying to use reserved word '__typeof' as identifier - reserved.c:15:12: error: Trying to use reserved word '__typeof__' as identifier -diff --git a/validation/restrict-array.c b/validation/restrict-array.c -index 3facebf4fcd6..04bfdad9d573 100644 ---- a/validation/restrict-array.c -+++ b/validation/restrict-array.c -@@ -7,6 +7,31 @@ extern int lio_listio64 (int __mode, - struct aiocb64 *__const __list[__restrict_arr], - int __nent, struct sigevent *__restrict __sig); - -+#undef __restrict_arr -+#define __restrict_arr __restrict__ -+ -+struct gaicb; -+ -+extern int getaddrinfo_a (int __mode, struct gaicb *__list[__restrict_arr], -+ int __ent, struct sigevent *__restrict __sig); -+ -+#undef __restrict_arr -+#define __restrict_arr restrict -+ -+typedef struct re_pattern_buffer regex_t; -+typedef int regoff_t; -+typedef struct -+{ -+ regoff_t rm_so; /* Byte offset from string's start to substring's start. */ -+ regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ -+} regmatch_t; -+typedef unsigned long int size_t; -+ -+extern int regexec (const regex_t *__restrict __preg, -+ const char *__restrict __string, size_t __nmatch, -+ regmatch_t __pmatch[__restrict_arr], -+ int __eflags); -+ - /* - * check-name: restrict array attribute - */ - -commit 126a785f0e010d6f1fe07cf0989e4969836ec804 -Author: Ramsay Jones -Date: Mon Aug 4 19:33:42 2014 +0100 - - sparse: add 'gnu_inline' to the ignored attributes - - Add some more ignored attributes which are used in glibc header files, - along with a simple test case which includes all three inline attributes - (__gnu_inline__, __always_inline__ and __noinline__). - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/parse.c b/parse.c -index ec835efb040e..896420b5b973 100644 ---- a/parse.c -+++ b/parse.c -@@ -536,6 +536,8 @@ const char *ignored_attributes[] = { - "__format__", - "format_arg", - "__format_arg__", -+ "gnu_inline", -+ "__gnu_inline__", - "hot", - "__hot__", - "leaf", -diff --git a/validation/attr-inline.c b/validation/attr-inline.c -new file mode 100644 -index 000000000000..1b88ddb9d6b3 ---- /dev/null -+++ b/validation/attr-inline.c -@@ -0,0 +1,21 @@ -+ -+static inline __attribute__((__always_inline__)) int gt(int lhs, int rhs) -+{ -+ return lhs > rhs; -+} -+ -+extern inline __attribute__((__gnu_inline__)) int ge(int lhs, int rhs) -+{ -+ return lhs >= rhs; -+} -+ -+static __attribute__((__warning__("That's junk!"))) __attribute__((__unused__)) -+__attribute__((__noinline__)) -+void junk(void) -+{ -+ __asm__(""); -+} -+ -+/* -+ * check-name: inline attributes -+ */ - -commit d32b2f7c202fd27206169ca99da898ca9c20dfab -Author: Ramsay Jones -Date: Mon Aug 4 19:34:30 2014 +0100 - - don't call isdigit/tolower with a char argument - - This suppresses some "array subscript has type 'char'" warnings from - gcc (version 4.8.3). (see also, commit cf5114a1) - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/expression.c b/expression.c -index 4353dbe2babf..7293d472b053 100644 ---- a/expression.c -+++ b/expression.c -@@ -240,7 +240,7 @@ static struct token *builtin_offsetof_expr(struct token *token, - - static unsigned long long parse_num(const char *nptr, char **end) - { -- if (nptr[0] == '0' && tolower(nptr[1]) == 'b') -+ if (nptr[0] == '0' && tolower((unsigned char)nptr[1]) == 'b') - return strtoull(&nptr[2], end, 2); - return strtoull(nptr, end, 0); - } -diff --git a/lib.c b/lib.c -index b1b18aa71679..db35a3d1fee5 100644 ---- a/lib.c -+++ b/lib.c -@@ -289,7 +289,7 @@ static char **handle_switch_D(char *arg, char **next) - const char *name = arg + 1; - const char *value = "1"; - -- if (!*name || isspace(*name)) -+ if (!*name || isspace((unsigned char)*name)) - die("argument to `-D' is missing"); - - for (;;) { -@@ -708,7 +708,7 @@ static char **handle_param(char *arg, char **next) - /* For now just skip any '--param=*' or '--param *' */ - if (*arg == '\0') { - value = *++next; -- } else if (isspace(*arg) || *arg == '=') { -+ } else if (isspace((unsigned char)*arg) || *arg == '=') { - value = ++arg; - } - - -commit 7885fb7f6b076cbe35d484e4b1e50eaaa546fb99 -Author: Ramsay Jones -Date: Mon Aug 4 19:37:31 2014 +0100 - - Makefile: suppress error message from shell - - In particular, on systems which do not have 'llvm-config' installed, - every invocation of make issues the following messages: - - /bin/sh: llvm-config: command not found - make: llvm-config: Command not found - - A simple solution would be to suppress these messages by redirecting - stderr to the bit-bucket within the definitions of HAVE_LLVM_VERSION - and LLVM_VERSION. - - As an alternative, however, we move the definition of LLVM_VERSION - down the file within the HAVE_LLVM conditional, which ensures that - the 'llvm-config' command exists. In addition, the HAVE_LLVM_VERSION - variable is replaced with an equivalent conditional expression. - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/Makefile b/Makefile -index 33f91f1c1974..9a483398fb36 100644 ---- a/Makefile -+++ b/Makefile -@@ -32,8 +32,6 @@ HAVE_GCC_DEP:=$(shell touch .gcc-test.c && \ - HAVE_GTK2:=$(shell pkg-config --exists gtk+-2.0 2>/dev/null && echo 'yes') - LLVM_CONFIG:=llvm-config - HAVE_LLVM:=$(shell $(LLVM_CONFIG) --version >/dev/null 2>&1 && echo 'yes') --HAVE_LLVM_VERSION:=$(shell $(LLVM_CONFIG) --version | grep "^[3-9].*" >/dev/null 2>&1 && echo yes) --LLVM_VERSION:=$(shell $(LLVM_CONFIG) --version) - - GCC_BASE = $(shell $(CC) --print-file-name=) - BASIC_CFLAGS = -DGCC_BASE=\"$(GCC_BASE)\" -@@ -76,13 +74,9 @@ else - $(warning Your system does not have libgtk2, disabling test-inspect) - endif - --ifneq ($(HAVE_LLVM),yes) --$(warning Your system does not have llvm, disabling sparse-llvm) --else --ifneq ($(HAVE_LLVM_VERSION),yes) --$(warning LLVM 3.0 or later required. Your system has version $(LLVM_VERSION) installed.) --HAVE_LLVM=no --else -+ifeq ($(HAVE_LLVM),yes) -+LLVM_VERSION:=$(shell $(LLVM_CONFIG) --version) -+ifeq ($(shell expr "$(LLVM_VERSION)" : '[3-9]\.'),2) - LLVM_PROGS := sparse-llvm - $(LLVM_PROGS): LD := g++ - LLVM_LDFLAGS := $(shell $(LLVM_CONFIG) --ldflags) -@@ -93,7 +87,11 @@ PROGRAMS += $(LLVM_PROGS) - INST_PROGRAMS += sparse-llvm sparsec - sparse-llvm.o: BASIC_CFLAGS += $(LLVM_CFLAGS) - sparse-llvm_EXTRA_OBJS := $(LLVM_LIBS) $(LLVM_LDFLAGS) -+else -+$(warning LLVM 3.0 or later required. Your system has version $(LLVM_VERSION) installed.) - endif -+else -+$(warning Your system does not have llvm, disabling sparse-llvm) - endif - - LIB_H= token.h parse.h lib.h symbol.h scope.h expression.h target.h \ - -commit e23abfd8844e605cfdeecb29ff9b733c95f5d2d5 -Author: Ramsay Jones -Date: Mon Aug 4 19:38:24 2014 +0100 - - don't run sparse{c,i} tests when sparse-llvm is disabled - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/validation/test-suite b/validation/test-suite -index 744383dc112e..7f0f83eea02e 100755 ---- a/validation/test-suite -+++ b/validation/test-suite -@@ -7,12 +7,18 @@ default_cmd="sparse \$file" - tests_list=`find . -name '*.c' | sed -e 's#^\./\(.*\)#\1#' | sort` - prog_name=`basename $0` - -+if [ ! -x "$default_path/sparse-llvm" ]; then -+ disabled_cmds="sparsec sparsei sparse-llvm" -+fi -+ - # counts: - # - tests that have not been converted to test-suite format -+# - tests that are disabled - # - tests that passed - # - tests that failed - # - tests that failed but are known to fail - unhandled_tests=0 -+disabled_tests=0 - ok_tests=0 - ko_tests=0 - known_ko_tests=0 -@@ -80,6 +86,7 @@ echo " help prints usage" - # - 0 if the test passed, - # - 1 if it failed, - # - 2 if it is not a "test-suite" test. -+# - 3 if the test is disabled. - do_test() - { - test_failed=0 -@@ -95,8 +102,6 @@ do_test() - fi - test_name=$last_result - -- echo " TEST $test_name ($file)" -- - # does the test provide a specific command ? - cmd=`eval echo $default_path/$default_cmd` - get_value "check-command" $file -@@ -104,6 +109,20 @@ do_test() - last_result=`echo $last_result | sed -e 's/^ *//'` - cmd=`eval echo $default_path/$last_result` - fi -+ -+ # check for disabled commands -+ set -- $cmd -+ base_cmd=`basename $1` -+ for i in $disabled_cmds; do -+ if [ "$i" == "$base_cmd" ] ; then -+ disabled_tests=`expr $disabled_tests + 1` -+ echo " DISABLE $test_name ($file)" -+ return 3 -+ fi -+ done -+ -+ echo " TEST $test_name ($file)" -+ - verbose "Using command : $cmd" - - # grab the expected output -@@ -169,6 +188,9 @@ do_test_suite() - if [ "$unhandled_tests" -ne "0" ]; then - echo "$unhandled_tests tests could not be handled by $prog_name" - fi -+ if [ "$disabled_tests" -ne "0" ]; then -+ echo "$disabled_tests tests were disabled" -+ fi - } - - ## - -commit 85e2e2a25266ffd24f08f3a396e7ac57fb307fbc -Author: Ramsay Jones -Date: Mon Aug 4 19:39:12 2014 +0100 - - Add support for multiarch system header files - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/Makefile b/Makefile -index 9a483398fb36..3f3c71a9940d 100644 ---- a/Makefile -+++ b/Makefile -@@ -36,6 +36,9 @@ HAVE_LLVM:=$(shell $(LLVM_CONFIG) --version >/dev/null 2>&1 && echo 'yes') - GCC_BASE = $(shell $(CC) --print-file-name=) - BASIC_CFLAGS = -DGCC_BASE=\"$(GCC_BASE)\" - -+MULTIARCH_TRIPLET = $(shell $(CC) -print-multiarch 2>/dev/null) -+BASIC_CFLAGS += -DMULTIARCH_TRIPLET=\"$(MULTIARCH_TRIPLET)\" -+ - ifeq ($(HAVE_GCC_DEP),yes) - BASIC_CFLAGS += -Wp,-MD,$(@D)/.$(@F).d - endif -diff --git a/cgcc b/cgcc -index 204bda35fa90..e69a831fb52b 100755 ---- a/cgcc -+++ b/cgcc -@@ -11,6 +11,7 @@ my $gendeps = 0; - my $do_check = 0; - my $do_compile = 1; - my $gcc_base_dir; -+my $multiarch_dir; - my $verbose = 0; - - while (@ARGV) { -@@ -44,6 +45,12 @@ while (@ARGV) { - next; - } - -+ if (/^-multiarch-dir$/) { -+ $multiarch_dir = shift @ARGV; -+ die ("$0: missing argument for -multiarch-dir option") if !$multiarch_dir; -+ next; -+ } -+ - # If someone adds "-E", don't pre-process twice. - $do_compile = 0 if $_ eq '-E'; - -@@ -66,8 +73,11 @@ if ($do_check) { - } - - $gcc_base_dir = qx($cc -print-file-name=) if !$gcc_base_dir; -+ chomp($gcc_base_dir); # possibly remove '\n' from compiler - $check .= " -gcc-base-dir " . $gcc_base_dir if $gcc_base_dir; - -+ $check .= " -multiarch-dir " . $multiarch_dir if $multiarch_dir; -+ - print "$check\n" if $verbose; - if ($do_compile) { - system ($check) == 0 or die; -diff --git a/lib.c b/lib.c -index db35a3d1fee5..8dc5bcf9dc18 100644 ---- a/lib.c -+++ b/lib.c -@@ -59,6 +59,7 @@ int gcc_minor = __GNUC_MINOR__; - int gcc_patchlevel = __GNUC_PATCHLEVEL__; - - static const char *gcc_base_dir = GCC_BASE; -+static const char *multiarch_dir = MULTIARCH_TRIPLET; - - struct token *skip_to(struct token *token, int op) - { -@@ -371,6 +372,14 @@ static char **handle_switch_M(char *arg, char **next) - return next; - } - -+static char **handle_multiarch_dir(char *arg, char **next) -+{ -+ multiarch_dir = *++next; -+ if (!multiarch_dir) -+ die("missing argument for -multiarch-dir option"); -+ return next; -+} -+ - static char **handle_switch_m(char *arg, char **next) - { - if (!strcmp(arg, "m64")) { -@@ -379,7 +388,8 @@ static char **handle_switch_m(char *arg, char **next) - arch_m64 = 0; - } else if (!strcmp(arg, "msize-long")) { - arch_msize_long = 1; -- } -+ } else if (!strcmp(arg, "multiarch-dir")) -+ return handle_multiarch_dir(arg, next); - return next; - } - -@@ -890,6 +900,12 @@ void create_builtin_stream(void) - add_pre_buffer("#weak_define __GNUC_MINOR__ %d\n", gcc_minor); - add_pre_buffer("#weak_define __GNUC_PATCHLEVEL__ %d\n", gcc_patchlevel); - -+ /* add the multiarch include directories, if any */ -+ if (multiarch_dir && *multiarch_dir) { -+ add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir); -+ add_pre_buffer("#add_system \"/usr/local/include/%s\"\n", multiarch_dir); -+ } -+ - /* We add compiler headers path here because we have to parse - * the arguments to get it, falling back to default. */ - add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir); -diff --git a/sparse.1 b/sparse.1 -index 63fceb91f513..4adaf6c92427 100644 ---- a/sparse.1 -+++ b/sparse.1 -@@ -338,6 +338,12 @@ Sparse does not issue these warnings by default. - .B \-gcc-base-dir \fIdir\fR - Look for compiler-provided system headers in \fIdir\fR/include/ and \fIdir\fR/include-fixed/. - . -+.TP -+.B \-multiarch-dir \fIdir\fR -+Look for system headers in the multiarch subdirectory \fIdir\fR. -+The \fIdir\fR name would normally take the form of the target's -+normalized GNU triplet. (e.g. i386-linux-gnu). -+. - .SH OTHER OPTIONS - .TP - .B \-ftabstop=WIDTH - -commit d4029acb1036726aa83261bda14f31e9a55d7e59 -Author: Ramsay Jones -Date: Mon Aug 4 19:39:55 2014 +0100 - - cgcc: use only the cc command to determine $gcc_base_dir - - Capture the c-compiler command, in the $ccom variable, in order to - later invoke the compiler without extraneous command-line options. - In particular, use the $ccom variable in order to cleanly invoke the - compiler when setting the $gcc_base_dir variable. - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/cgcc b/cgcc -index e69a831fb52b..d6392e0aa75a 100755 ---- a/cgcc -+++ b/cgcc -@@ -3,6 +3,7 @@ - - my $cc = $ENV{'REAL_CC'} || 'cc'; - my $check = $ENV{'CHECK'} || 'sparse'; -+my $ccom = $cc; - - my $m32 = 0; - my $m64 = 0; -@@ -72,7 +73,7 @@ if ($do_check) { - $check .= &add_specs ('host_os_specs'); - } - -- $gcc_base_dir = qx($cc -print-file-name=) if !$gcc_base_dir; -+ $gcc_base_dir = qx($ccom -print-file-name=) if !$gcc_base_dir; - chomp($gcc_base_dir); # possibly remove '\n' from compiler - $check .= " -gcc-base-dir " . $gcc_base_dir if $gcc_base_dir; - - -commit 71e642abf7129b553521df8dddf4511383016a78 -Author: Ramsay Jones -Date: Mon Aug 4 19:40:32 2014 +0100 - - cgcc: use $ccom to set $multiarch_dir if not specified - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/cgcc b/cgcc -index d6392e0aa75a..8ee8da123522 100755 ---- a/cgcc -+++ b/cgcc -@@ -77,6 +77,8 @@ if ($do_check) { - chomp($gcc_base_dir); # possibly remove '\n' from compiler - $check .= " -gcc-base-dir " . $gcc_base_dir if $gcc_base_dir; - -+ $multiarch_dir = qx($ccom -print-multiarch) if ! defined $multiarch_dir; -+ chomp($multiarch_dir); # possibly remove '\n' from compiler - $check .= " -multiarch-dir " . $multiarch_dir if $multiarch_dir; - - print "$check\n" if $verbose; - -commit c1c3f969fbd0d05ad24ab037defde500e7b3c77a -Author: Christopher Li -Date: Sat Oct 25 17:05:52 2014 +0800 - - teach next_designators() use array_element_offset() - - I miss a spot when converting array size caculation using - array_element_offet(). "next_designators()" is still using - "n*bit_size" to caculate the element offset. It is wrong - for the case of bool array. - - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index 7bd47e66d1f1..035e4487c753 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -2380,7 +2380,7 @@ static struct expression *next_designators(struct expression *old, - old->ctype, e, v); - if (!copy) { - n = old->idx_to + 1; -- if (n * old->ctype->bit_size == ctype->bit_size) { -+ if (array_element_offset(old->ctype->bit_size, n) == ctype->bit_size) { - convert_index(old); - return NULL; - } - -commit 307a9806e9db1121d763db4214e16835cd7ea34b -Author: Ramsay Jones -Date: Sat Oct 11 20:56:16 2014 +0100 - - test-suite: remove bashism to avoid test failures - - The use of the '==' operator in a test/[ conditional is a non-POSIX - bash extension. In order to avoid test failures on systems that do - not have bash as the system shell (/bin/sh), replace the use of the - '==' operator with the POSIX compatible '=' operator. - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/validation/test-suite b/validation/test-suite -index 7f0f83eea02e..df5a7c60d053 100755 ---- a/validation/test-suite -+++ b/validation/test-suite -@@ -114,7 +114,7 @@ do_test() - set -- $cmd - base_cmd=`basename $1` - for i in $disabled_cmds; do -- if [ "$i" == "$base_cmd" ] ; then -+ if [ "$i" = "$base_cmd" ] ; then - disabled_tests=`expr $disabled_tests + 1` - echo " DISABLE $test_name ($file)" - return 3 - -commit 13a3e97e26f14e2632ebfaed04abd0f68a28b6f2 -Author: Ramsay Jones -Date: Sat Oct 11 20:57:25 2014 +0100 - - cgcc: avoid passing a sparse-only option to cc - - Passing the '-Wsparse-error' to cgcc can cause that option to be - passed to the C compiler (usually gcc), if the given source file - does not provoke any sparse warnings, which in turn results in - a failure to compile that file. - - In order to avoid passing this sparse option to the compiler, we - add the '-Wsparse-error' option to the regular expression check - in the 'check_only_option' function. - - In addition, we replace the plain call to 'die' when sparse exits - with non-zero status (maybe due to -Wsparse-error), with a simple - 'exit 1'. This suppresses an 'Died at ./cgcc line 86.' message on - exit from cgcc. - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/cgcc b/cgcc -index 8ee8da123522..8e3817472824 100755 ---- a/cgcc -+++ b/cgcc -@@ -83,7 +83,7 @@ if ($do_check) { - - print "$check\n" if $verbose; - if ($do_compile) { -- system ($check) == 0 or die; -+ system ($check) == 0 or exit 1; - } else { - exec ($check); - } -@@ -101,7 +101,7 @@ exit 0; - - sub check_only_option { - my ($arg) = @_; -- return 1 if $arg =~ /^-W(no-?)?(default-bitfield-sign|one-bit-signed-bitfield|cast-truncate|bitwise|typesign|context|undef|ptr-subtraction-blows|cast-to-as|decl|transparent-union|address-space|enum-mismatch|do-while|old-initializer|non-pointer-null|paren-string|return-void|designated-init|sparse-all)$/; -+ return 1 if $arg =~ /^-W(no-?)?(default-bitfield-sign|one-bit-signed-bitfield|cast-truncate|bitwise|typesign|context|undef|ptr-subtraction-blows|cast-to-as|decl|transparent-union|address-space|enum-mismatch|do-while|old-initializer|non-pointer-null|paren-string|return-void|designated-init|sparse-all|sparse-error)$/; - return 1 if $arg =~ /^-v(no-?)?(entry|dead)$/; - return 0; - } - -commit 7f9fbccc06bc1b2b4e8f2ebfd8cf8148e54478a4 -Author: Ramsay Jones -Date: Sat Oct 11 20:58:14 2014 +0100 - - parse.c: remove duplicate 'may_alias' ignored_attributes - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/parse.c b/parse.c -index 896420b5b973..b43d6835528b 100644 ---- a/parse.c -+++ b/parse.c -@@ -548,8 +548,6 @@ const char *ignored_attributes[] = { - "__l1_data__", - "l2", - "__l2__", -- "may_alias", -- "__may_alias__", - "malloc", - "__malloc__", - "may_alias", - -commit 78f9e8faafed4a5ec7e3141360a0dc01910656e4 -Author: Ramsay Jones -Date: Tue Oct 14 00:03:31 2014 +0100 - - compile-i386.c: don't ignore return value of write(2) - - Some versions of gcc (e.g. v4.8.2) complain about ignoring the return - value of a call to the write(2) system call, since the system header - files have marked its declaration with the warn_unused_result attribute. - - In order to suppress the compiler warning, check the return value from - 'write' and, if it indicates an error (a negative return value), exit - the process using 'die' to display an error message. Replace a second - call to 'write', which does not provoke a compiler warning, with similar - code for consistency. - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/compile-i386.c b/compile-i386.c -index 88169ecbcb5a..44b72ec39f28 100644 ---- a/compile-i386.c -+++ b/compile-i386.c -@@ -732,7 +732,8 @@ static void emit_insn_atom(struct function *f, struct atom *atom) - atom->insn, - comment[0] ? "\t\t" : "", comment); - -- write(STDOUT_FILENO, s, strlen(s)); -+ if (write(STDOUT_FILENO, s, strlen(s)) < 0) -+ die("can't write to stdout"); - } - - static void emit_atom_list(struct function *f) -@@ -742,9 +743,8 @@ static void emit_atom_list(struct function *f) - FOR_EACH_PTR(f->atom_list, atom) { - switch (atom->type) { - case ATOM_TEXT: { -- ssize_t rc = write(STDOUT_FILENO, atom->text, -- atom->text_len); -- (void) rc; /* FIXME */ -+ if (write(STDOUT_FILENO, atom->text, atom->text_len) < 0) -+ die("can't write to stdout"); - break; - } - case ATOM_INSN: - -commit 5556d1b618418c7c42d35458200c213756066b71 -Author: Aaro Koskinen -Date: Fri Nov 7 14:44:47 2014 +0200 - - build: allow use of PKG_CONFIG to override pkg-config - - Allow overriding pkg-config e.g. when cross-compiling. - - Signed-off-by: Aaro Koskinen - Signed-off-by: Christopher Li - -diff --git a/Makefile b/Makefile -index 3f3c71a9940d..c7031afda00b 100644 ---- a/Makefile -+++ b/Makefile -@@ -17,6 +17,7 @@ CFLAGS += -Wall -Wwrite-strings - LDFLAGS += -g - LD = gcc - AR = ar -+PKG_CONFIG = pkg-config - - ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) - # -@@ -25,11 +26,11 @@ ALL_CFLAGS = $(CFLAGS) $(BASIC_CFLAGS) - # CFLAGS += -O0 -DDEBUG -g3 -gdwarf-2 - # - --HAVE_LIBXML:=$(shell pkg-config --exists libxml-2.0 2>/dev/null && echo 'yes') -+HAVE_LIBXML:=$(shell $(PKG_CONFIG) --exists libxml-2.0 2>/dev/null && echo 'yes') - HAVE_GCC_DEP:=$(shell touch .gcc-test.c && \ - $(CC) -c -Wp,-MD,.gcc-test.d .gcc-test.c 2>/dev/null && \ - echo 'yes'; rm -f .gcc-test.d .gcc-test.o .gcc-test.c) --HAVE_GTK2:=$(shell pkg-config --exists gtk+-2.0 2>/dev/null && echo 'yes') -+HAVE_GTK2:=$(shell $(PKG_CONFIG) --exists gtk+-2.0 2>/dev/null && echo 'yes') - LLVM_CONFIG:=llvm-config - HAVE_LLVM:=$(shell $(LLVM_CONFIG) --version >/dev/null 2>&1 && echo 'yes') - -@@ -60,14 +61,14 @@ INST_MAN1=sparse.1 cgcc.1 - ifeq ($(HAVE_LIBXML),yes) - PROGRAMS+=c2xml - INST_PROGRAMS+=c2xml --c2xml_EXTRA_OBJS = `pkg-config --libs libxml-2.0` -+c2xml_EXTRA_OBJS = `$(PKG_CONFIG) --libs libxml-2.0` - else - $(warning Your system does not have libxml, disabling c2xml) - endif - - ifeq ($(HAVE_GTK2),yes) --GTK2_CFLAGS := $(shell pkg-config --cflags gtk+-2.0) --GTK2_LIBS := $(shell pkg-config --libs gtk+-2.0) -+GTK2_CFLAGS := $(shell $(PKG_CONFIG) --cflags gtk+-2.0) -+GTK2_LIBS := $(shell $(PKG_CONFIG) --libs gtk+-2.0) - PROGRAMS += test-inspect - INST_PROGRAMS += test-inspect - test-inspect_EXTRA_DEPS := ast-model.o ast-view.o ast-inspect.o -@@ -187,7 +188,7 @@ DEP_FILES := $(wildcard .*.o.d) - $(if $(DEP_FILES),$(eval include $(DEP_FILES))) - - c2xml.o: c2xml.c $(LIB_H) -- $(QUIET_CC)$(CC) `pkg-config --cflags libxml-2.0` -o $@ -c $(ALL_CFLAGS) $< -+ $(QUIET_CC)$(CC) `$(PKG_CONFIG) --cflags libxml-2.0` -o $@ -c $(ALL_CFLAGS) $< - - compat-linux.o: compat/strtold.c compat/mmap-blob.c $(LIB_H) - compat-solaris.o: compat/mmap-blob.c $(LIB_H) - -commit 6c2d743d2f130a8bf9014410f928bae3647e3108 -Author: Christopher Li -Date: Thu Dec 11 22:54:48 2014 +0800 - - Ptr list sorting should use memmove instead of memcpy - - The target buffer is overlapped with source buffer. - This cause the duplicate entry warning reported by Hans. - - Reported-by: Hans Verkuil - Signed-off-by: Christopher Li - -diff --git a/sort.c b/sort.c -index afd7184d8fe8..430ba447845c 100644 ---- a/sort.c -+++ b/sort.c -@@ -99,7 +99,7 @@ static void verify_seq_sorted (struct ptr_list *l, int n, - assert (nbuf >= nr); \ - memcpy ((b)->list, buffer, nr * sizeof (void *)); \ - nbuf -= nr; \ -- memcpy (buffer, buffer + nr, nbuf * sizeof (void *)); \ -+ memmove (buffer, buffer + nr, nbuf * sizeof (void *)); \ - } while (0) - - #define DUMP_TO(b) \ - -commit 1a900d9f37bb060329274970b25753181ce14223 -Author: Christian Borntraeger -Date: Thu Jan 22 10:51:50 2015 +0100 - - s390x: add the proper defines for data types - - This patch fixes several issues when compiling code under s390x - (64bit) with cgcc, e.g. - /usr/include/gnu/stubs.h:8:12: error: unable to open 'gnu/stubs-32.h' - by providing the proper defines. - - Signed-off-by: Christian Borntraeger - Signed-off-by: Christopher Li - -diff --git a/cgcc b/cgcc -index 8e3817472824..d7b1c99cd7ea 100755 ---- a/cgcc -+++ b/cgcc -@@ -279,6 +279,12 @@ sub add_specs { - &float_types (1, 1, 21, [24,8], [53,11], [113,15]) . - &define_size_t ($m64 ? "long unsigned int" : "unsigned int") . - ' -D__SIZEOF_POINTER__=' . ($m64 ? '8' : '4')); -+ } elsif ($spec eq 's390x') { -+ return (' -D__s390x__ -D__s390__ -D_BIG_ENDIAN' . -+ &integer_types (8, 16, 32, $m64 ? 64 : 32, 64) . -+ &float_types (1, 1, 36, [24,8], [53,11], [113,15]) . -+ &define_size_t ("long unsigned int") . -+ ' -D__SIZEOF_POINTER__=' . ($m64 ? '8' : '4')); - } elsif ($spec eq 'host_os_specs') { - my $os = `uname -s`; - chomp $os; -@@ -294,6 +300,8 @@ sub add_specs { - return &add_specs ('x86_64'); - } elsif ($arch =~ /^(ppc)$/i) { - return &add_specs ('ppc'); -+ } elsif ($arch =~ /^(s390x)$/i) { -+ return &add_specs ('s390x'); - } elsif ($arch =~ /^(sparc64)$/i) { - return &add_specs ('sparc64'); - } - -commit de1fa7e60d3d179a1b67c47a0429b2d0ac4e4842 -Author: Christopher Li -Date: Thu Feb 5 21:45:15 2015 -0800 - - Make macro expanded string immutable - - The string is shared between different macro expand. - It is wrong to modify the string in place if the string - is used in a macro. Avoid overwriting the string in that - case. - - Reported-by: Rasmus Villemoes - Tested-by: Luc Van Oostenryck - Signed-off-by: Christopher Li - -diff --git a/char.c b/char.c -index 08ca22305ef9..9bd3fc0dbad7 100644 ---- a/char.c -+++ b/char.c -@@ -93,6 +93,7 @@ struct token *get_string_constant(struct token *token, struct expression *expr) - static char buffer[MAX_STRING]; - int len = 0; - int bits; -+ int esc_count = 0; - - while (!done) { - switch (token_type(next)) { -@@ -111,6 +112,8 @@ struct token *get_string_constant(struct token *token, struct expression *expr) - const char *p = token->string->data; - const char *end = p + token->string->length - 1; - while (p < end) { -+ if (*p == '\\') -+ esc_count++; - p = parse_escape(p, &v, end, bits, token->pos); - if (len < MAX_STRING) - buffer[len] = v; -@@ -123,11 +126,13 @@ struct token *get_string_constant(struct token *token, struct expression *expr) - len = MAX_STRING; - } - -- if (len >= string->length) /* can't cannibalize */ -- string = __alloc_string(len+1); -- string->length = len+1; -- memcpy(string->data, buffer, len); -- string->data[len] = '\0'; -+ if (esc_count || len >= string->length) { -+ if (string->immutable || len >= string->length) /* can't cannibalize */ -+ string = __alloc_string(len+1); -+ string->length = len+1; -+ memcpy(string->data, buffer, len); -+ string->data[len] = '\0'; -+ } - expr->string = string; - expr->wide = is_wide; - return token; -diff --git a/pre-process.c b/pre-process.c -index 1aa3d2c4852e..5c386a85d15e 100644 ---- a/pre-process.c -+++ b/pre-process.c -@@ -209,7 +209,7 @@ static void expand_list(struct token **list) - - static void preprocessor_line(struct stream *stream, struct token **line); - --static struct token *collect_arg(struct token *prev, int vararg, struct position *pos) -+static struct token *collect_arg(struct token *prev, int vararg, struct position *pos, int count) - { - struct stream *stream = input_streams + prev->pos.stream; - struct token **p = &prev->next; -@@ -231,6 +231,11 @@ static struct token *collect_arg(struct token *prev, int vararg, struct position - case TOKEN_STREAMBEGIN: - *p = &eof_token_entry; - return next; -+ case TOKEN_STRING: -+ case TOKEN_WIDE_STRING: -+ if (count > 1) -+ next->string->immutable = 1; -+ break; - } - if (false_nesting) { - *p = next->next; -@@ -276,7 +281,7 @@ static int collect_arguments(struct token *start, struct token *arglist, struct - arglist = arglist->next; /* skip counter */ - - if (!wanted) { -- next = collect_arg(start, 0, &what->pos); -+ next = collect_arg(start, 0, &what->pos, 0); - if (eof_token(next)) - goto Eclosing; - if (!eof_token(start->next) || !match_op(next, ')')) { -@@ -286,7 +291,7 @@ static int collect_arguments(struct token *start, struct token *arglist, struct - } else { - for (count = 0; count < wanted; count++) { - struct argcount *p = &arglist->next->count; -- next = collect_arg(start, p->vararg, &what->pos); -+ next = collect_arg(start, p->vararg, &what->pos, p->normal); - arglist = arglist->next->next; - if (eof_token(next)) - goto Eclosing; -@@ -323,7 +328,7 @@ Efew: - goto out; - Emany: - while (match_op(next, ',')) { -- next = collect_arg(next, 0, &what->pos); -+ next = collect_arg(next, 0, &what->pos, 0); - count++; - } - if (eof_token(next)) -@@ -1259,8 +1264,15 @@ static struct token *parse_expansion(struct token *expansion, struct token *argl - } else { - try_arg(token, TOKEN_MACRO_ARGUMENT, arglist); - } -- if (token_type(token) == TOKEN_ERROR) -+ switch (token_type(token)) { -+ case TOKEN_ERROR: - goto Earg; -+ -+ case TOKEN_STRING: -+ case TOKEN_WIDE_STRING: -+ token->string->immutable = 1; -+ break; -+ } - } - token = alloc_token(&expansion->pos); - token_type(token) = TOKEN_UNTAINT; -diff --git a/token.h b/token.h -index 8dbd80fdb518..af66b2b84384 100644 ---- a/token.h -+++ b/token.h -@@ -164,7 +164,8 @@ enum special_token { - }; - - struct string { -- unsigned int length; -+ unsigned int length:31; -+ unsigned int immutable:1; - char data[]; - }; - - -commit 40791b94c56b1a6da2a0ddeb1f9d5c9d64de8f93 -Author: Luc Van Oostenryck -Date: Sat Jan 24 00:59:35 2015 +0100 - - Teach sparse about the __COUNTER__ predefined macro - - __COUNTER__ macro is expanded to a sequential number starting from 0. - This is sometimes used to declare unique variable names. - - Implement support for __COUNTER__ in sparse including a set of - small test programs for the test suite. - - Signed-off-by: Luc Van Oostenryck - Acked-by: Sam Ravnborg - Reviewed-by: Josh Triplett - Tested-by: Christian Borntraeger - Signed-off-by: Christopher Li - -diff --git a/ident-list.h b/ident-list.h -index d5a145f852da..b65b667da720 100644 ---- a/ident-list.h -+++ b/ident-list.h -@@ -108,6 +108,7 @@ __IDENT(__TIME___ident, "__TIME__", 0); - __IDENT(__func___ident, "__func__", 0); - __IDENT(__FUNCTION___ident, "__FUNCTION__", 0); - __IDENT(__PRETTY_FUNCTION___ident, "__PRETTY_FUNCTION__", 0); -+__IDENT(__COUNTER___ident, "__COUNTER__", 0); - - /* Sparse commands */ - IDENT_RESERVED(__context__); -diff --git a/pre-process.c b/pre-process.c -index 5c386a85d15e..7c57ba1cddfe 100644 ---- a/pre-process.c -+++ b/pre-process.c -@@ -45,6 +45,7 @@ - #include "scope.h" - - static int false_nesting = 0; -+static int counter_macro = 0; // __COUNTER__ expansion - - #define INCLUDEPATHS 300 - const char *includepath[INCLUDEPATHS+1] = { -@@ -181,6 +182,8 @@ static int expand_one_symbol(struct token **list) - time(&t); - strftime(buffer, 9, "%T", localtime(&t)); - replace_with_string(token, buffer); -+ } else if (token->ident == &__COUNTER___ident) { -+ replace_with_integer(token, counter_macro++); - } - return 1; - } -@@ -1894,6 +1897,7 @@ static void init_preprocessor(void) - sym->normal = 0; - } - -+ counter_macro = 0; - } - - static void handle_preprocessor_line(struct stream *stream, struct token **line, struct token *start) -diff --git a/validation/preprocessor/counter1.c b/validation/preprocessor/counter1.c -new file mode 100644 -index 000000000000..98187ee64a65 ---- /dev/null -+++ b/validation/preprocessor/counter1.c -@@ -0,0 +1,12 @@ -+__COUNTER__ -+__COUNTER__ -+/* -+ * check-name: __COUNTER__ #1 -+ * check-command: sparse -E $file -+ * -+ * check-output-start -+ -+0 -+1 -+ * check-output-end -+ */ -diff --git a/validation/preprocessor/counter2.c b/validation/preprocessor/counter2.c -new file mode 100644 -index 000000000000..9883b6822d1e ---- /dev/null -+++ b/validation/preprocessor/counter2.c -@@ -0,0 +1,14 @@ -+__FILE__ __COUNTER__ -+#include -+__FILE__ __COUNTER__ -+/* -+ * check-name: __COUNTER__ #2 -+ * check-command: sparse -Ipreprocessor -E $file -+ * -+ * check-output-start -+ -+"preprocessor/counter2.c" 0 -+"preprocessor/counter2.h" 1 -+"preprocessor/counter2.c" 2 -+ * check-output-end -+ */ -diff --git a/validation/preprocessor/counter2.h b/validation/preprocessor/counter2.h -new file mode 100644 -index 000000000000..447b70ab741d ---- /dev/null -+++ b/validation/preprocessor/counter2.h -@@ -0,0 +1 @@ -+__FILE__ __COUNTER__ -diff --git a/validation/preprocessor/counter3.c b/validation/preprocessor/counter3.c -new file mode 100644 -index 000000000000..fa3f173b1046 ---- /dev/null -+++ b/validation/preprocessor/counter3.c -@@ -0,0 +1,14 @@ -+/* -+ * check-name: __COUNTER__ #3 -+ * check-command: sparse -Ipreprocessor -E preprocessor/counter1.c $file -+ * -+ * check-output-start -+ -+0 -+1 -+"preprocessor/counter2.c" 0 -+"preprocessor/counter2.h" 1 -+"preprocessor/counter2.c" 2 -+ * check-output-end -+ */ -+#include "counter2.c" - -commit 95940a8d5c7cc6ec8f42479cdcaed189957ba09f -Author: Michael Stefaniuc -Date: Thu Mar 12 00:19:19 2015 +0100 - - Add the __builtin functions needed for INFINITY and nan(). - - Signed-off-by: Michael Stefaniuc - Signed-off-by: Christopher Li - -diff --git a/lib.c b/lib.c -index 8dc5bcf9dc18..58a7f2edb613 100644 ---- a/lib.c -+++ b/lib.c -@@ -876,6 +876,17 @@ void declare_builtin_functions(void) - add_pre_buffer("extern int __builtin_islessgreater(float, float);\n"); - add_pre_buffer("extern int __builtin_isunordered(float, float);\n"); - -+ /* And some INFINITY / NAN stuff.. */ -+ add_pre_buffer("extern double __builtin_huge_val(void);\n"); -+ add_pre_buffer("extern float __builtin_huge_valf(void);\n"); -+ add_pre_buffer("extern long double __builtin_huge_vall(void);\n"); -+ add_pre_buffer("extern double __builtin_inf(void);\n"); -+ add_pre_buffer("extern float __builtin_inff(void);\n"); -+ add_pre_buffer("extern long double __builtin_infl(void);\n"); -+ add_pre_buffer("extern double __builtin_nan(const char *);\n"); -+ add_pre_buffer("extern float __builtin_nanf(const char *);\n"); -+ add_pre_buffer("extern long double __builtin_nanl(const char *);\n"); -+ - /* And some __FORTIFY_SOURCE ones.. */ - add_pre_buffer ("extern __SIZE_TYPE__ __builtin_object_size(void *, int);\n"); - add_pre_buffer ("extern void * __builtin___memcpy_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); - -commit 76a73716e4fd76c81259968a7c7cb2fb73d993d7 -Author: Michael Stefaniuc -Date: Thu Mar 12 00:22:14 2015 +0100 - - Add a define for __builtin_ms_va_copy() - - Signed-off-by: Michael Stefaniuc - Signed-off-by: Christopher Li - -diff --git a/lib.c b/lib.c -index 58a7f2edb613..d5b56b012a21 100644 ---- a/lib.c -+++ b/lib.c -@@ -970,6 +970,7 @@ void create_builtin_stream(void) - add_pre_buffer("#define __builtin_va_alist (*(void *)0)\n"); - add_pre_buffer("#define __builtin_va_arg_incr(x) ((x) + 1)\n"); - add_pre_buffer("#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n"); -+ add_pre_buffer("#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n"); - add_pre_buffer("#define __builtin_va_end(arg)\n"); - add_pre_buffer("#define __builtin_ms_va_end(arg)\n"); - add_pre_buffer("#define __builtin_va_arg_pack()\n"); - -commit 0f71312959ed8f7692deaedeb35d7612004f8d72 -Author: Ard Biesheuvel -Date: Sun Nov 16 11:00:15 2014 +0800 - - Ignore pure attribute in assignement - - The pure attribute only take effect in function node. - There is no way to make a value itself pure. - - Reported-by: Ard Biesheuvel - Signed-off-by: Christopher Li - -diff --git a/evaluate.c b/evaluate.c -index 035e4487c753..e350c0c08e0f 100644 ---- a/evaluate.c -+++ b/evaluate.c -@@ -623,7 +623,7 @@ static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *i - - static void examine_fn_arguments(struct symbol *fn); - --#define MOD_IGN (MOD_VOLATILE | MOD_CONST) -+#define MOD_IGN (MOD_VOLATILE | MOD_CONST | MOD_PURE) - - const char *type_difference(struct ctype *c1, struct ctype *c2, - unsigned long mod1, unsigned long mod2) -diff --git a/validation/pure-function.c b/validation/pure-function.c -new file mode 100644 -index 000000000000..04bb85e4dbb1 ---- /dev/null -+++ b/validation/pure-function.c -@@ -0,0 +1,16 @@ -+ -+static __attribute__((__pure__)) int pure1(void) -+{ -+ int i = 0; -+ return i; -+} -+ -+static __attribute__((__pure__)) void *pure2(void) -+{ -+ void *i = (void *)0; -+ return i; -+} -+ -+/* -+ * check-name: Pure function attribute -+ */ - -commit efd34fafe5cba2eedfe889e49698f5eb119547bd -Author: Michael Stefaniuc -Date: Wed Apr 8 23:48:39 2015 +0200 - - Add tests for the builtin INF and nan() functions. - - Test file cross checked with - gcc -c -Wall -Werror -Wno-unused-variable validation/builtin_inf.c - - Signed-off-by: Michael Stefaniuc - Signed-off-by: Christopher Li - -diff --git a/validation/builtin_inf.c b/validation/builtin_inf.c -new file mode 100644 -index 000000000000..48546e480cf8 ---- /dev/null -+++ b/validation/builtin_inf.c -@@ -0,0 +1,13 @@ -+static double d = __builtin_huge_val(); -+static float f = __builtin_huge_valf(); -+static long double l = __builtin_huge_vall(); -+static double di = __builtin_inf(); -+static float fi = __builtin_inff(); -+static long double li = __builtin_infl(); -+static double dn = __builtin_nan(""); -+static float fn = __builtin_nanf(""); -+static long double ln = __builtin_nanl(""); -+ -+/* -+ * check-name: __builtin INFINITY / nan() -+ */ - -commit 60432109a5cb0687d255cd0d022ae7711e6340f5 -Author: Heiko Carstens -Date: Tue Apr 28 12:48:39 2015 +0200 - - sparse/parse.c: ignore hotpatch attribute - - gcc knows about a new "hotpatch" attribute which sparse can safely ignore, - since it modifies only which code will be generated just like the - "no_instrument_function" attribute. - - The gcc hotpatch feature patch: - https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=11762b8363737591bfb9c66093bc2edf289b917f - - Currently the Linux kernel makes use of this attribute: - https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=61f552141c9c0e88b3fdc7046265781ffd8fa68a - - Without this patch sparse will emit warnings like - "error: attribute 'hotpatch': unknown attribute" - - Signed-off-by: Heiko Carstens - Signed-off-by: Christopher Li - -diff --git a/parse.c b/parse.c -index b43d6835528b..8afae73d5325 100644 ---- a/parse.c -+++ b/parse.c -@@ -540,6 +540,8 @@ const char *ignored_attributes[] = { - "__gnu_inline__", - "hot", - "__hot__", -+ "hotpatch", -+ "__hotpatch__", - "leaf", - "__leaf__", - "l1_text", - -commit c04667e25447ca068c85c9a74ac3c12bfd79cd5e -Author: Azat Khuzhin -Date: Fri Jun 12 08:20:39 2015 +0300 - - sparse, llvm: compile: skip function prototypes to avoid SIGSEGV - - You can't pass function to LLVMConstNull(), according to - Constant::getNullValue, and sparse-llvm already handle functions differently - (i.e. there will be no call to LLVMConstNull(), but this is not true for - function prototypes, because of how linearize_fn() works: - ``` - static struct entrypoint *linearize_fn(...) - { - ... - if (!base_type->stmt) - return NULL; - ... - } - ``` - - ``` - Constant *Constant::getNullValue(Type *Ty) { - switch (Ty->getTypeID()) { - ... - default: - // Function, Label, or Opaque type? - llvm_unreachable("Cannot create a null constant of that type!"); - } - } - ``` - - Signed-off-by: Azat Khuzhin - Signed-off-by: Christopher Li - -diff --git a/sparse-llvm.c b/sparse-llvm.c -index ecb5b28ef7be..6b41afd85e49 100644 ---- a/sparse-llvm.c -+++ b/sparse-llvm.c -@@ -1070,6 +1070,13 @@ static LLVMValueRef output_data(LLVMModuleRef module, struct symbol *sym) - return data; - } - -+static int is_prototype(struct symbol *sym) -+{ -+ if (sym->type == SYM_NODE) -+ sym = sym->ctype.base_type; -+ return sym && sym->type == SYM_FN && !sym->stmt; -+} -+ - static int compile(LLVMModuleRef module, struct symbol_list *list) - { - struct symbol *sym; -@@ -1077,6 +1084,10 @@ static int compile(LLVMModuleRef module, struct symbol_list *list) - FOR_EACH_PTR(list, sym) { - struct entrypoint *ep; - expand_symbol(sym); -+ -+ if (is_prototype(sym)) -+ continue; -+ - ep = linearize_symbol(sym); - if (ep) - output_fn(module, ep); - -commit a53cea28f0db1c799668476ec7612cf120cddcc0 -Author: Azat Khuzhin -Date: Fri Jun 12 08:20:40 2015 +0300 - - validation/prototype: regression for skipping prototypes - - Signed-off-by: Azat Khuzhin - Signed-off-by: Christopher Li - -diff --git a/validation/prototype.c b/validation/prototype.c -new file mode 100644 -index 000000000000..481cc93e05a2 ---- /dev/null -+++ b/validation/prototype.c -@@ -0,0 +1,6 @@ -+static int prototype(void); -+ -+/* -+ * check-name: Compile skip function prototype -+ * check-command: ./sparsec -c $file -o tmp.o -+ */ - -commit 0d2809b500cd831851d1ac734419165949b0f0ab -Author: Dan Carpenter -Date: Thu Jul 23 11:24:14 2015 +0300 - - ptrlist: reading deleted items in NEXT_PTR_LIST() - - If you call DELETE_CURRENT_PTR(), then you can sometimes end up with a - __list->nr that is zero. The FOR_EACH_PTR() macro can handle this but - the NEXT_PTR_LIST() macro returns ptr = 0xf0f0f0f0 which leads to a - segfault. - - Signed-off-by: Dan Carpenter - Signed-off-by: Christopher Li - -diff --git a/ptrlist.h b/ptrlist.h -index 58d3bdaa2514..61e159fdcf98 100644 ---- a/ptrlist.h -+++ b/ptrlist.h -@@ -97,6 +97,8 @@ static inline void *last_ptr_list(struct ptr_list *list) - } else { \ - __list = __list->next; \ - ptr = NULL; \ -+ while (__list->nr == 0 && __list != __head) \ -+ __list = __list->next; \ - if (__list != __head) { \ - __nr = 0; \ - ptr = PTR_ENTRY(__list,0); \ - -commit 0dac4783ea5700dd4dff6a45b849cb3ec9d62372 -Author: Tony Camuso -Date: Mon Aug 10 08:33:54 2015 -0400 - - .gitignore: add cscope and Qt project files - - Signed-off-by: Tony Camuso - Signed-off-by: Christopher Li - -diff --git a/.gitignore b/.gitignore -index d32d0631ab6d..44218a2fed91 100644 ---- a/.gitignore -+++ b/.gitignore -@@ -40,3 +40,6 @@ series - # local makefile - local.mk - -+# cscope and Qt files -+cscope.out -+*.pro* - -commit 38c9e9f3b3faba3dea7f42c37d565a425867060e -Author: Tony Camuso -Date: Mon Aug 10 08:35:32 2015 -0400 - - Add default case to switches on enum variables - - Missing enum members in case statements in c2xml.c and parse.c were - causing compile time complaints by gcc 5.1.1. Adding a default case - satisfies the compiler and notifies the reviewer that there are - cases not explicitly mentioned being handled by the default case. - - Signed-off-by: Tony Camuso - Signed-off-by: Christopher Li - -diff --git a/c2xml.c b/c2xml.c -index 67486c779d06..c45d5818a976 100644 ---- a/c2xml.c -+++ b/c2xml.c -@@ -214,6 +214,8 @@ static void examine_symbol(struct symbol *sym, xmlNodePtr node) - case SYM_UNINITIALIZED: - newProp(child, "base-type-builtin", builtin_typename(sym)); - break; -+ default: -+ break; - } - return; - } -@@ -330,4 +332,3 @@ int main(int argc, char **argv) - - return 0; - } -- -diff --git a/parse.c b/parse.c -index 8afae73d5325..4e38f3fbe3d1 100644 ---- a/parse.c -+++ b/parse.c -@@ -2771,6 +2771,9 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis - case SYM_ENUM: - case SYM_RESTRICT: - base_type->ident = ident; -+ break; -+ default: -+ break; - } - } - } else if (base_type && base_type->type == SYM_FN) { - -commit 8efbac18a251580615e3a5c587155fd7233b1b13 -Author: Luc Van Oostenryck -Date: Thu Jan 7 02:47:09 2016 +0100 - - Fix size calculation of unsized bool array - - This stops sparse from issuing the error message - "error: cannot size expression" - for code like: - static _Bool boolarray[] = { - 0, - 1, - }; - static int n = sizeof(boolarray); - - The fix consists of using array_element_offset() for calculating - the size of unsized arrays, like it is done elsewhere for sized ones. - - Signed-off-by: Luc Van Oostenryck - Signed-off-by: Christopher Li - -diff --git a/symbol.c b/symbol.c -index 0ceff6281a96..92a7a6253a52 100644 ---- a/symbol.c -+++ b/symbol.c -@@ -393,7 +393,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 = node_type->bit_size * count; -+ bit_size = array_element_offset(node_type->bit_size, count); - } - } - -diff --git a/validation/bool-array.c b/validation/bool-array.c -new file mode 100644 -index 000000000000..6c4c87234923 ---- /dev/null -+++ b/validation/bool-array.c -@@ -0,0 +1,47 @@ -+static _Bool boolarray_d1[1]; -+static _Bool boolarray_d8[8]; -+static _Bool boolarray_i2[2] = { -+ 0, -+ 1, -+}; -+static int nd1 = sizeof(boolarray_d1); -+static int nd8 = sizeof(boolarray_d8); -+static int ni2 = sizeof(boolarray_i2); -+ -+ -+static long longarray_u2[] = { -+ 0, -+ 1, -+}; -+static int nl2 = sizeof(longarray_u2); -+ -+/* -+ * Used to get "warning: excessive elements in array initializer" -+ * for all elements but the first one. -+ * Note: only occurs if nbr of elements is a multiple of 8 -+ * (if not, theer was another problem) -+ */ -+static _Bool boolarray_u8[] = { -+ 0, -+ 1, -+ 0, -+ 1, -+ 0, -+ 1, -+ 0, -+ 1, -+}; -+ -+/* -+ * Used to get "error: cannot size expression" for the sizeof. -+ */ -+static _Bool boolarray_u2[] = { -+ 0, -+ 1, -+}; -+static int nu2 = sizeof(boolarray_u2); -+ -+/* -+ * check-name: sizeof(bool array) -+ * check-command: sparse -Wno-sizeof-bool $file -+ */ - -commit 7647c775497f8c0f5841051377fba8cbb495c275 -Author: Luc Van Oostenryck -Date: Tue Jan 5 17:25:53 2016 +0100 - - Do not drop 'nocast' modifier when taking the address. - - With the following code: - typedef unsigned long __nocast cputime_t; - - void task_cputime_adjusted(cputime_t *); - - void current_task_runtime_100ns(void) - { - cputime_t utime; - - task_cputime_adjusted(&utime); - } - - sparse emits the following message: - x.c:16:32: warning: incorrect type in argument 1 (different modifiers) - x.c:16:32: expected unsigned long [nocast] [usertype] * - x.c:16:32: got unsigned long * - x.c:16:32: warning: implicit cast to nocast type - - In other words, when taking the address of 'utime', sparse drops the 'nocast' - modifier and then complains that task_cputime_adjusted() is not given a - 'nocast' pointer as expected ... - - This feels wrong to me. - - The proposed fix is to simply not dropping the 'nocast' modifier when - taking the address, like done for a normal type qualifier. - This gives very reasonable behaviour for all the test cases I could - think of: - - taking the address or dereferencing doesn't drop the nocast - - arithmetic operations on nocast give a nocast result. - - implicit to/from cast is OK only if the base type are the same - - implicit to/from pointer cast is OK only if the base type are the same - - This still gives a "leaky" semantic: the nocast modifier can be lost via - an implicit cast to a non-qualified value. - - Explicit cast to or from nocast values doesn't give any warning, maybe - it's OK, maybe it's not but it's orthogonal to the current issue. - - Is this the wanted semantic for the nocast modifier? - - Reported-by: Roman Kagan - Signed-off-by: Luc Van Oostenryck - Signed-off-by: Christopher Li - -diff --git a/symbol.h b/symbol.h -index ccb5dcb9b406..9b3f1604e27a 100644 ---- a/symbol.h -+++ b/symbol.h -@@ -247,7 +247,7 @@ struct symbol { - #define MOD_SIZE (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL) - #define MOD_IGNORE (MOD_TOPLEVEL | MOD_STORAGE | MOD_ADDRESSABLE | \ - MOD_ASSIGNED | MOD_USERTYPE | MOD_ACCESSED | MOD_EXPLICITLY_SIGNED) --#define MOD_PTRINHERIT (MOD_VOLATILE | MOD_CONST | MOD_NODEREF | MOD_STORAGE | MOD_NORETURN) -+#define MOD_PTRINHERIT (MOD_VOLATILE | MOD_CONST | MOD_NODEREF | MOD_STORAGE | MOD_NORETURN | MOD_NOCAST) - - - /* Current parsing/evaluation function */ -diff --git a/validation/nocast.c b/validation/nocast.c -new file mode 100644 -index 000000000000..c28676a3115f ---- /dev/null -+++ b/validation/nocast.c -@@ -0,0 +1,197 @@ -+#define __nocast __attribute__((nocast)) -+typedef unsigned long __nocast ulong_nc_t; -+ -+extern void use_val(ulong_nc_t); -+extern void use_ptr(ulong_nc_t *); -+ -+/* use address */ -+static void good_use_address(void) -+{ -+ ulong_nc_t t; -+ -+ use_ptr(&t); -+} -+ -+static ulong_nc_t *good_ret_address(void) -+{ -+ static ulong_nc_t t; -+ -+ return &t; -+} -+ -+static ulong_nc_t good_deref(ulong_nc_t *t) -+{ -+ return *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; -+static ulong_nc_t *bad_ptr_to = 1UL; -+static unsigned long *bad_ptr_from = &t; -+ -+/* arithmetic operation */ -+static ulong_nc_t good_arith(ulong_nc_t t, unsigned int n) -+{ -+ return t + n; -+} -+ -+/* implicit cast to other types */ -+static unsigned long good_ret_samecast(ulong_nc_t t) -+{ -+ return t; -+} -+static unsigned long long bad_ret_biggercast(ulong_nc_t t) -+{ -+ return t; -+} -+static long bad_ret_signcast(ulong_nc_t t) -+{ -+ return t; -+} -+static short bad_ret_smallercast(ulong_nc_t t) -+{ -+ return t; -+} -+ -+static void assign_val(ulong_nc_t t) -+{ -+ ulong_nc_t good_c = t; -+ unsigned long good_ul = t; -+ unsigned long long bad_ull = t; -+ long bad_l = t; -+ short bad_i = t; -+} -+ -+static void assign_via_ptr(ulong_nc_t *t) -+{ -+ ulong_nc_t good_c = *t; -+ unsigned long good_ul = *t; -+ unsigned long long bad_ull = *t; -+ long bad_l = *t; -+ short bad_i = *t; -+} -+ -+static void assign_ptr(ulong_nc_t *t) -+{ -+ ulong_nc_t *good_same_type = t; -+ unsigned long *bad_mod = t; -+ unsigned long long __nocast *bad_size = t; -+ short __nocast *bad_i = t; -+ long __nocast *bad_l = t; -+} -+ -+/* implicit cast to nocast */ -+static void implicit_assign_to(void) -+{ -+ ulong_nc_t t; -+ unsigned long ul = 1; -+ unsigned short us = 1; -+ unsigned long long ull = 1; -+ long l = 1; -+ -+ t = ul; /* implicit to nocast from same type: OK? */ -+ t = us; -+ t = ull; -+ t = l; -+} -+ -+static void bad_implicit_arg_to(void) -+{ -+ unsigned long ul = 1; -+ unsigned short us = 1; -+ unsigned long long ull = 1; -+ long l = 1; -+ -+ use_val(ul); /* implicit to nocast from same type: OK? */ -+ use_val(us); -+ use_val(ull); -+ use_val(l); -+} -+ -+/* implicit cast from nocast */ -+static unsigned long good_implicit_ret_ul(ulong_nc_t t) -+{ -+ return t; /* implicit to nocast from same type: OK? */ -+} -+ -+static unsigned short bad_implicit_ret_us(ulong_nc_t t) -+{ -+ return t; -+} -+ -+static unsigned long long bad_implicit_ret_ull(ulong_nc_t t) -+{ -+ return t; -+} -+ -+static long bad_implicit_ret_l(ulong_nc_t t) -+{ -+ return t; -+} -+ -+/* FIXME: explicit cast: should we complain? */ -+static ulong_nc_t good_samecast(ulong_nc_t v) -+{ -+ return (ulong_nc_t) v; -+} -+ -+static ulong_nc_t bad_tocast(unsigned long v) -+{ -+ return (ulong_nc_t) v; -+} -+ -+static unsigned long bad_fromcast(ulong_nc_t v) -+{ -+ return (unsigned long) v; -+} -+ -+/* -+ * check-name: nocast.c -+ * -+ * check-error-start -+nocast.c:34:33: warning: incorrect type in initializer (different base types) -+nocast.c:34:33: expected unsigned long [nocast] [usertype] *static [toplevel] bad_ptr_to -+nocast.c:34:33: got unsigned long -+nocast.c:34:33: warning: implicit cast to nocast type -+nocast.c:35:39: warning: incorrect type in initializer (different modifiers) -+nocast.c:35:39: expected unsigned long *static [toplevel] bad_ptr_from -+nocast.c:35:39: got unsigned long static [nocast] [toplevel] * -+nocast.c:35:39: warning: implicit cast from nocast type -+nocast.c:50:16: warning: implicit cast from nocast type -+nocast.c:54:16: warning: implicit cast from nocast type -+nocast.c:58:16: warning: implicit cast from nocast type -+nocast.c:65:38: warning: implicit cast from nocast type -+nocast.c:66:22: warning: implicit cast from nocast type -+nocast.c:67:23: warning: implicit cast from nocast type -+nocast.c:74:38: warning: implicit cast from nocast type -+nocast.c:75:22: warning: implicit cast from nocast type -+nocast.c:76:23: warning: implicit cast from nocast type -+nocast.c:82:34: warning: incorrect type in initializer (different modifiers) -+nocast.c:82:34: expected unsigned long *bad_mod -+nocast.c:82:34: got unsigned long [nocast] [usertype] *t -+nocast.c:82:34: warning: implicit cast from nocast type -+nocast.c:83:49: warning: incorrect type in initializer (different type sizes) -+nocast.c:83:49: expected unsigned long long [nocast] *bad_size -+nocast.c:83:49: got unsigned long [nocast] [usertype] *t -+nocast.c:83:49: warning: implicit cast to/from nocast type -+nocast.c:84:33: warning: incorrect type in initializer (different type sizes) -+nocast.c:84:33: expected short [nocast] *bad_i -+nocast.c:84:33: got unsigned long [nocast] [usertype] *t -+nocast.c:84:33: warning: implicit cast to/from nocast type -+nocast.c:85:32: warning: implicit cast to/from nocast type -+nocast.c:98:13: warning: implicit cast to nocast type -+nocast.c:99:13: warning: implicit cast to nocast type -+nocast.c:100:13: warning: implicit cast to nocast type -+nocast.c:111:17: warning: implicit cast to nocast type -+nocast.c:112:17: warning: implicit cast to nocast type -+nocast.c:113:17: warning: implicit cast to nocast type -+nocast.c:124:16: warning: implicit cast from nocast type -+nocast.c:129:16: warning: implicit cast from nocast type -+nocast.c:134:16: warning: implicit cast from nocast type -+ * check-error-end -+ */ - -commit 153fbd0bbbfd952c6e3c1f6494e71d6ba903f7ed -Author: Christopher Li -Date: Thu Sep 29 00:38:31 2016 -0700 - - Fix warning compiling sparse-llvm - - -pedantic in the llvm-config --cflags cause a lot of warning. - - Signed-off-by: Christopher Li - -diff --git a/Makefile b/Makefile -index c7031afda00b..f59993f7c4b3 100644 ---- a/Makefile -+++ b/Makefile -@@ -84,7 +84,7 @@ ifeq ($(shell expr "$(LLVM_VERSION)" : '[3-9]\.'),2) - LLVM_PROGS := sparse-llvm - $(LLVM_PROGS): LD := g++ - LLVM_LDFLAGS := $(shell $(LLVM_CONFIG) --ldflags) --LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cflags | sed -e "s/-DNDEBUG//g") -+LLVM_CFLAGS := $(shell $(LLVM_CONFIG) --cflags | sed -e "s/-DNDEBUG//g" | sed -e "s/-pedantic//g") - LLVM_LIBS := $(shell $(LLVM_CONFIG) --libs) - LLVM_LIBS += $(shell $(LLVM_CONFIG) --system-libs 2>/dev/null) - PROGRAMS += $(LLVM_PROGS) -diff --git a/token.h b/token.h -index af66b2b84384..f7d88eb4568b 100644 ---- a/token.h -+++ b/token.h -@@ -230,7 +230,7 @@ extern struct token * tokenize_buffer(void *, unsigned long, struct token **); - extern void show_identifier_stats(void); - extern struct token *preprocess(struct token *); - --static inline int match_op(struct token *token, int op) -+static inline int match_op(struct token *token, unsigned int op) - { - return token->pos.type == TOKEN_SPECIAL && token->special == op; - } - -commit 65f90e77057687ad5a6e8196d99aaf93bd0f5443 -Author: Ramsay Jones -Date: Thu Oct 6 00:49:18 2016 +0100 - - sparse: add 'alloc_align' to the ignored attributes - - Signed-off-by: Ramsay Jones - Signed-off-by: Christopher Li - -diff --git a/parse.c b/parse.c -index 4e38f3fbe3d1..2e0edcadb98b 100644 ---- a/parse.c -+++ b/parse.c -@@ -504,6 +504,8 @@ static struct init_keyword { - const char *ignored_attributes[] = { - "alias", - "__alias__", -+ "alloc_align", -+ "__alloc_align__", - "alloc_size", - "__alloc_size__", - "always_inline", -diff --git a/validation/alloc-align.c b/validation/alloc-align.c -new file mode 100644 -index 000000000000..e414257aa54a ---- /dev/null -+++ b/validation/alloc-align.c -@@ -0,0 +1,38 @@ -+typedef unsigned long int size_t; -+ -+/* -+ * The alloc_align attribute is used to tell the compiler that the return -+ * value points to memory, where the returned pointer minimum alignment is given -+ * by one of the functions parameters. GCC uses this information to improve -+ * pointer alignment analysis. -+ * -+ * The function parameter denoting the allocated alignment is specified by one -+ * integer argument, whose number is the argument of the attribute. Argument -+ * numbering starts at one. -+ * -+ * For instance, -+ * -+ * void* my_memalign(size_t, size_t) __attribute__((alloc_align(1))) -+ * -+ * declares that my_memalign returns memory with minimum alignment given by -+ * parameter 1. -+ */ -+ -+#define __alloc_align(x) __attribute__((__alloc_align__(x))) -+ -+/* -+ * The aligned_alloc function allocates space for an object whose alignment is -+ * specified by alignment, whose size is specified by size, and whose value is -+ * indeterminate. The value of alignment shall be a valid alignment supported -+ * by the implementation and the value of size shall be an integral multiple -+ * of alignment. -+ * -+ * The aligned_alloc function returns either a null pointer or a pointer to the -+ * allocated space. -+ */ -+void *aligned_alloc(size_t alignment, size_t size) __alloc_align(1); -+ -+ -+/* -+ * check-name: attribute __alloc_align__ -+ */ - -commit ffc860be91930f52f14193f9ee4166931e2e8fab -Author: Lance Richardson -Date: Wed Sep 28 14:41:05 2016 -0400 - - sparse: ignore __assume_aligned__ attribute - - The __assume_aligned__ attribute can be safely ignored, add it - to the list of ignored attributes and add a test to verify that - this attribute is ignored. - - Signed-off-by: Lance Richardson - Signed-off-by: Christopher Li - -diff --git a/parse.c b/parse.c -index 2e0edcadb98b..66f9353f8247 100644 ---- a/parse.c -+++ b/parse.c -@@ -512,6 +512,8 @@ const char *ignored_attributes[] = { - "__always_inline__", - "artificial", - "__artificial__", -+ "assume_aligned", -+ "__assume_aligned__", - "bounded", - "__bounded__", - "cdecl", -diff --git a/validation/attr_aligned.c b/validation/attr_aligned.c -new file mode 100644 -index 000000000000..dc44e9fdd42d ---- /dev/null -+++ b/validation/attr_aligned.c -@@ -0,0 +1,6 @@ -+void *foo(void) __attribute__((__assume_aligned__(4096))); -+void *foo(void) __attribute__((assume_aligned(4096))); -+/* -+ * check-name: attribute assume_aligned -+ */ -+ - -commit 6c283a05175c512e2d564753cd0b1a7bfc68c620 -Author: Rui Teng -Date: Wed Jun 1 10:45:26 2016 +0800 - - sparse: add no_sanitize_address as an ignored attribute - - Add attribute "no_sanitize_address" or "__no_sanitize_address__" as an ignored - attribute. Fixes this sparse warning: - - include/linux/compiler.h:232:8: error: attribute 'no_sanitize_address': unknown attribute - - Also add test case for 'no_sanitize_address': validation/attr-no_sanitize_address.c. - 'make check' says for this test case: - TEST attribute no_sanitize_address (attr-no_sanitize_address.c) - - Signed-off-by: Rui Teng - Signed-off-by: Christopher Li - -diff --git a/parse.c b/parse.c -index 66f9353f8247..205e12644a6c 100644 ---- a/parse.c -+++ b/parse.c -@@ -607,6 +607,8 @@ const char *ignored_attributes[] = { - "__warning__", - "weak", - "__weak__", -+ "no_sanitize_address", -+ "__no_sanitize_address__", - }; - - -diff --git a/validation/attr-no_sanitize_address.c b/validation/attr-no_sanitize_address.c -new file mode 100644 -index 000000000000..b57ee55a5b90 ---- /dev/null -+++ b/validation/attr-no_sanitize_address.c -@@ -0,0 +1,9 @@ -+#define __no_sanitize_address __attribute__((no_sanitize_address)) -+ -+static void __no_sanitize_address bar(void) -+{ -+} -+ -+/* -+ * check-name: attribute no_sanitize_address -+ */ - -commit 1db3b627dfff5a6ab7a7af3259603eb0a10b45aa -Author: Jeff Layton -Date: Mon Nov 14 14:12:16 2016 -0500 - - Handle SForced in storage_modifiers - - We have been seeing errors like this for a while now in the sparse - Fedora package, when doing kernel builds: - - ./include/linux/err.h:53:25: warning: dereference of noderef expression - ./include/linux/err.h:35:16: warning: dereference of noderef expression - - This spews all over the build because this comes from IS_ERR(), which - is called everywhere. Even odder, it turns out that if we build the - package with -fpic turned off, then it works fine. - - With some brute-force debugging, I think I've finally found the cause. - This array is missing the SForced element. When this is added then the - problem goes away. - - As to why this goes away when -fpic is removed, I can only assume that - we get lucky with the memory layout and have a zeroed out region just - beyond the end of the array. - - Fixes: 3829c4d8b097776e6b3472290a9fae08a705ab7a - Cc: Al Viro - Signed-off-by: Jeff Layton - Signed-off-by: Christopher Li - -diff --git a/parse.c b/parse.c -index 205e12644a6c..b52c6abea40f 100644 ---- a/parse.c -+++ b/parse.c -@@ -105,7 +105,7 @@ enum { - }; - - enum { -- CInt = 0, CSInt, CUInt, CReal, CChar, CSChar, CUChar -+ CInt = 0, CSInt, CUInt, CReal, CChar, CSChar, CUChar, CMax, - }; - - enum { -@@ -1281,7 +1281,7 @@ static const char *storage_class[] = - - static unsigned long storage_modifiers(struct decl_state *ctx) - { -- static unsigned long mod[] = -+ static unsigned long mod[CMax] = - { - [SAuto] = MOD_AUTO, - [SExtern] = MOD_EXTERN, - -commit ce18a906b82d0341cb33a71f7b1d8b98d11b345d -Author: Lance Richardson -Date: Wed Sep 21 10:13:58 2016 -0400 - - sparse: update __builtin_object_size() prototype - - Sparse emits a large number of warnings for the linux kernel source - tree of the form: - ./arch/x86/include/asm/uaccess.h:735:18: \ - warning: incorrect type in argument 1 (different modifiers) - ./arch/x86/include/asm/uaccess.h:735:18: expected void * - ./arch/x86/include/asm/uaccess.h:735:18: got void const *from - - Fix by making the first parameter to __builtin_object_size() - type "const void *" instead of "void *", which is consistent with GCC - behavior (the prototype for this builtin in GCC documentation is evidently - incorrect). - - Signed-off-by: Lance Richardson - Acked-by: Luc Van Oostenryck - Signed-off-by: Christopher Li - -diff --git a/lib.c b/lib.c -index d5b56b012a21..2d66aa058b82 100644 ---- a/lib.c -+++ b/lib.c -@@ -888,7 +888,7 @@ void declare_builtin_functions(void) - add_pre_buffer("extern long double __builtin_nanl(const char *);\n"); - - /* And some __FORTIFY_SOURCE ones.. */ -- add_pre_buffer ("extern __SIZE_TYPE__ __builtin_object_size(void *, int);\n"); -+ add_pre_buffer ("extern __SIZE_TYPE__ __builtin_object_size(const void *, int);\n"); - add_pre_buffer ("extern void * __builtin___memcpy_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); - add_pre_buffer ("extern void * __builtin___memmove_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); - add_pre_buffer ("extern void * __builtin___mempcpy_chk(void *, const void *, __SIZE_TYPE__, __SIZE_TYPE__);\n"); diff --git a/sources b/sources index 0883237..05ac247 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -9900853ec3c3b86457e680c5afce72b1 sparse-0.5.0.tar.xz +SHA512 (sparse-0.5.1.tar.xz) = 85cd6ace80e0c23ba3c329e839bf0e08398fdcd89d718dfb1ae12c42a3bd97dd5140a983c6ffaf9f338f00d6ff35f7ed508293676f76d3656ce418e743acf052 diff --git a/sparse.spec b/sparse.spec index 58c32df..331295a 100644 --- a/sparse.spec +++ b/sparse.spec @@ -1,6 +1,6 @@ Name: sparse -Version: 0.5.0 -Release: 13%{?dist} +Version: 0.5.1 +Release: 1%{?dist} Summary: A semantic parser of source files Group: Development/Tools License: MIT @@ -9,7 +9,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: libxml2-devel gtk2-devel Source0: http://www.kernel.org/pub/software/devel/sparse/dist/sparse-%{version}.tar.xz -Patch1: master-update.patch +Patch1: 0001-build-assign-extra-flags-to-ALL_CFLAGS-instead-of-CF.patch %description Sparse is a semantic parser of source files: it's neither a compiler @@ -47,8 +47,7 @@ make DESTDIR="%{buildroot}" PREFIX="%{_prefix}" \\\ %{nil} %build -%make_destdir %{?_smp_mflags} CFLAGS="%{optflags} -Wwrite-strings -DGCC_BASE=\\\"`gcc --print-file-name=`\\\"" \ - HAVE_LLVM=no +%make_destdir CFLAGS="%{optflags}" HAVE_LLVM=no V=1 %install rm -rf %{buildroot} @@ -80,6 +79,9 @@ make clean %{_libdir}/pkgconfig/%{name}.pc %changelog +* Wed Oct 18 2017 Jeff Layton - 0.5.1-1 +- Update to v0.5.1 release + * Thu Aug 03 2017 Fedora Release Engineering - 0.5.0-13 - Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild