All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo"
@ 2018-11-27 10:53 John Levon
  2018-11-27 10:53 ` [PATCH 02/12] sparse: add -Wno-non-ansi-function-declaration John Levon
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon, Luc Van Oostenryck

The former fix is from sparse upstream, the -U change is by me.

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Signed-off-by: John Levon <levon@movementarian.org>
---
 lib.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/lib.c b/lib.c
index b03229c..0f7ad2a 100644
--- a/lib.c
+++ b/lib.c
@@ -325,15 +325,19 @@ static char **handle_switch_D(char *arg, char **next)
 	const char *name = arg + 1;
 	const char *value = "1";
 
-	if (!*name || isspace((unsigned char)*name))
-		die("argument to `-D' is missing");
+	if (!*name) {
+		arg = *++next;
+		if (!arg)
+			die("argument to `-D' is missing");
+		name = arg;
+	}
 
-	for (;;) {
+	for (;;arg++) {
 		char c;
-		c = *++arg;
+		c = *arg;
 		if (!c)
 			break;
-		if (isspace((unsigned char)c) || c == '=') {
+		if (c == '=') {
 			*arg = '\0';
 			value = arg + 1;
 			break;
@@ -680,6 +684,8 @@ static void handle_switch_v_finalize(void)
 static char **handle_switch_U(char *arg, char **next)
 {
 	const char *name = arg + 1;
+	if (*name == '\0')
+		name = *++next;
 	add_pre_buffer ("#undef %s\n", name);
 	return next;
 }
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 02/12] sparse: add -Wno-non-ansi-function-declaration
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 03/12] sparse: add -Wbig-constants John Levon
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Signed-off-by: John Levon <levon@movementarian.org>
---
 cgcc                                       |  2 +-
 lib.c                                      |  2 ++
 lib.h                                      |  1 +
 parse.c                                    | 11 +++++++----
 sparse.1                                   |  7 +++++++
 validation/non-ansi-function-declaration.c | 10 ++++++++++
 6 files changed, 28 insertions(+), 5 deletions(-)
 create mode 100644 validation/non-ansi-function-declaration.c

diff --git a/cgcc b/cgcc
index 9f61595..b85d508 100755
--- a/cgcc
+++ b/cgcc
@@ -101,7 +101,7 @@ exit 0;
 
 sub check_only_option {
     my ($arg) = @_;
-    return 1 if $arg =~ /^-W(no-?)?(address-space|bitwise|cast-to-as|cast-truncate|context|decl|default-bitfield-sign|designated-init|do-while|enum-mismatch|init-cstring|memcpy-max-count|non-pointer-null|old-initializer|one-bit-signed-bitfield|override-init-all|paren-string|ptr-subtraction-blows|return-void|sizeof-bool|sparse-all|sparse-error|transparent-union|typesign|undef|unknown-attribute)$/;
+    return 1 if $arg =~ /^-W(no-?)?(address-space|bitwise|cast-to-as|cast-truncate|context|decl|default-bitfield-sign|designated-init|do-while|enum-mismatch|init-cstring|memcpy-max-count|non-ansi-function-declaration|non-pointer-null|old-initializer|one-bit-signed-bitfield|override-init-all|paren-string|ptr-subtraction-blows|return-void|sizeof-bool|sparse-all|sparse-error|transparent-union|typesign|undef|unknown-attribute)$/;
     return 1 if $arg =~ /^-v(no-?)?(entry|dead)$/;
     return 1 if $arg =~ /^-f(dump-linearize|memcpy-max-count)(=\S*)?$/;
     return 0;
diff --git a/lib.c b/lib.c
index 0f7ad2a..8728759 100644
--- a/lib.c
+++ b/lib.c
@@ -237,6 +237,7 @@ int Winit_cstring = 0;
 int Wenum_mismatch = 1;
 int Wsparse_error = 0;
 int Wmemcpy_max_count = 1;
+int Wnon_ansi_function_declaration = 1;
 int Wnon_pointer_null = 1;
 int Wold_initializer = 1;
 int Wone_bit_signed_bitfield = 1;
@@ -534,6 +535,7 @@ static const struct warning {
 	{ "enum-mismatch", &Wenum_mismatch },
 	{ "init-cstring", &Winit_cstring },
 	{ "memcpy-max-count", &Wmemcpy_max_count },
+	{ "non-ansi-function-declaration", &Wnon_ansi_function_declaration },
 	{ "non-pointer-null", &Wnon_pointer_null },
 	{ "old-initializer", &Wold_initializer },
 	{ "one-bit-signed-bitfield", &Wone_bit_signed_bitfield },
diff --git a/lib.h b/lib.h
index 6a86d1b..05579cc 100644
--- a/lib.h
+++ b/lib.h
@@ -128,6 +128,7 @@ extern int Wenum_mismatch;
 extern int Wsparse_error;
 extern int Winit_cstring;
 extern int Wmemcpy_max_count;
+extern int Wnon_ansi_function_declaration;
 extern int Wnon_pointer_null;
 extern int Wold_initializer;
 extern int Wone_bit_signed_bitfield;
diff --git a/parse.c b/parse.c
index 66a2769..ab8f4f7 100644
--- a/parse.c
+++ b/parse.c
@@ -1698,9 +1698,10 @@ static enum kind which_func(struct token *token,
 		/* don't complain about those */
 		if (!n || match_op(next->next, ';'))
 			return Empty;
-		warning(next->pos,
-			"non-ANSI function declaration of function '%s'",
-			show_ident(*n));
+		if (Wnon_ansi_function_declaration)
+			warning(next->pos,
+				"non-ANSI function declaration of function '%s'",
+				show_ident(*n));
 		return Empty;
 	}
 
@@ -2783,7 +2784,9 @@ static struct token *parse_k_r_arguments(struct token *token, struct symbol *dec
 {
 	struct symbol_list *args = NULL;
 
-	warning(token->pos, "non-ANSI definition of function '%s'", show_ident(decl->ident));
+	if (Wnon_ansi_function_declaration)
+		warning(token->pos, "non-ANSI definition of function '%s'", show_ident(decl->ident));
+
 	do {
 		token = declaration_list(token, &args);
 		if (!match_op(token, ';')) {
diff --git a/sparse.1 b/sparse.1
index 3bd5f1c..63bd923 100644
--- a/sparse.1
+++ b/sparse.1
@@ -230,6 +230,13 @@ The limit can be changed with \fB\-fmemcpy\-max\-count=COUNT\fR,
 the default being \fB100000\fR.
 .
 .TP
+.B \-Wnon\-ansi\-function\-declaration
+Warn about non-ANSI function declarations.
+
+Sparse issues these warnings by default.  To turn them off, use
+\fB\-Wno\-non\-ansi\-function\-declaration\fR.
+.
+.TP
 .B \-Wnon\-pointer\-null
 Warn about the use of 0 as a NULL pointer.
 
diff --git a/validation/non-ansi-function-declaration.c b/validation/non-ansi-function-declaration.c
new file mode 100644
index 0000000..48a7294
--- /dev/null
+++ b/validation/non-ansi-function-declaration.c
@@ -0,0 +1,10 @@
+
+
+extern void myfunction(), myfunc2();
+
+/*
+ * check-name: -Wno-non-ansi-function-declaration works
+ * check-command: sparse -Wno-non-ansi-function-declaration $file
+ * check-error-start
+ * check-error-end
+ */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 03/12] sparse: add -Wbig-constants
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
  2018-11-27 10:53 ` [PATCH 02/12] sparse: add -Wno-non-ansi-function-declaration John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 04/12] sparse: add -Wempty-character-constant John Levon
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Signed-off-by: John Levon <levon@movementarian.org>
---
 cgcc         | 2 +-
 expression.c | 3 +++
 lib.c        | 2 ++
 lib.h        | 1 +
 sparse.1     | 7 +++++++
 5 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/cgcc b/cgcc
index b85d508..04869c1 100755
--- a/cgcc
+++ b/cgcc
@@ -101,7 +101,7 @@ exit 0;
 
 sub check_only_option {
     my ($arg) = @_;
-    return 1 if $arg =~ /^-W(no-?)?(address-space|bitwise|cast-to-as|cast-truncate|context|decl|default-bitfield-sign|designated-init|do-while|enum-mismatch|init-cstring|memcpy-max-count|non-ansi-function-declaration|non-pointer-null|old-initializer|one-bit-signed-bitfield|override-init-all|paren-string|ptr-subtraction-blows|return-void|sizeof-bool|sparse-all|sparse-error|transparent-union|typesign|undef|unknown-attribute)$/;
+    return 1 if $arg =~ /^-W(no-?)?(address-space|big-constants|bitwise|cast-to-as|cast-truncate|context|decl|default-bitfield-sign|designated-init|do-while|enum-mismatch|init-cstring|memcpy-max-count|non-ansi-function-declaration|non-pointer-null|old-initializer|one-bit-signed-bitfield|override-init-all|paren-string|ptr-subtraction-blows|return-void|sizeof-bool|sparse-all|sparse-error|transparent-union|typesign|undef|unknown-attribute)$/;
     return 1 if $arg =~ /^-v(no-?)?(entry|dead)$/;
     return 1 if $arg =~ /^-f(dump-linearize|memcpy-max-count)(=\S*)?$/;
     return 0;
diff --git a/expression.c b/expression.c
index 9907e32..097c0a7 100644
--- a/expression.c
+++ b/expression.c
@@ -318,6 +318,9 @@ static void get_number_value(struct expression *expr, struct token *token)
 			show_token(token));
 	want_unsigned = 1;
 got_it:
+	if (!Wbig_constants)
+		do_warn = 0;
+
 	if (do_warn)
 		warning(expr->pos, "constant %s is so big it is%s%s%s",
 			show_token(token),
diff --git a/lib.c b/lib.c
index 8728759..ed7d9ed 100644
--- a/lib.c
+++ b/lib.c
@@ -223,6 +223,7 @@ static struct token *pre_buffer_end = NULL;
 
 int Waddress = 0;
 int Waddress_space = 1;
+int Wbig_constants = 1;
 int Wbitwise = 1;
 int Wcast_to_as = 0;
 int Wcast_truncate = 1;
@@ -522,6 +523,7 @@ static const struct warning {
 } warnings[] = {
 	{ "address", &Waddress },
 	{ "address-space", &Waddress_space },
+	{ "big-constants", &Wbig_constants },
 	{ "bitwise", &Wbitwise },
 	{ "cast-to-as", &Wcast_to_as },
 	{ "cast-truncate", &Wcast_truncate },
diff --git a/lib.h b/lib.h
index 05579cc..bfb3546 100644
--- a/lib.h
+++ b/lib.h
@@ -114,6 +114,7 @@ extern int preprocess_only;
 
 extern int Waddress;
 extern int Waddress_space;
+extern int Wbig_constants;
 extern int Wbitwise;
 extern int Wcast_to_as;
 extern int Wcast_truncate;
diff --git a/sparse.1 b/sparse.1
index 63bd923..cc72ad6 100644
--- a/sparse.1
+++ b/sparse.1
@@ -42,6 +42,13 @@ Sparse issues these warnings by default.  To turn them off, use
 \fB\-Wno\-address\-space\fR.
 .
 .TP
+.B \-Wbig-constants
+Warn about large integer constants that are not qualified by a size suffix.
+
+Sparse issues these warnings by default.  To turn them off, use
+\fB\-Wno\-big\-constants\fR.
+.
+.TP
 .B \-Wbitwise
 Warn about unsupported operations or type mismatches with restricted integer
 types.
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 04/12] sparse: add -Wempty-character-constant
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
  2018-11-27 10:53 ` [PATCH 02/12] sparse: add -Wno-non-ansi-function-declaration John Levon
  2018-11-27 10:53 ` [PATCH 03/12] sparse: add -Wbig-constants John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 05/12] Look across the entire compile line for smatch arguments John Levon
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Signed-off-by: John Levon <levon@movementarian.org>
---
 cgcc       | 2 +-
 lib.c      | 2 ++
 lib.h      | 1 +
 sparse.1   | 7 +++++++
 tokenize.c | 5 +++--
 5 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/cgcc b/cgcc
index 04869c1..cdb05ab 100755
--- a/cgcc
+++ b/cgcc
@@ -101,7 +101,7 @@ exit 0;
 
 sub check_only_option {
     my ($arg) = @_;
-    return 1 if $arg =~ /^-W(no-?)?(address-space|big-constants|bitwise|cast-to-as|cast-truncate|context|decl|default-bitfield-sign|designated-init|do-while|enum-mismatch|init-cstring|memcpy-max-count|non-ansi-function-declaration|non-pointer-null|old-initializer|one-bit-signed-bitfield|override-init-all|paren-string|ptr-subtraction-blows|return-void|sizeof-bool|sparse-all|sparse-error|transparent-union|typesign|undef|unknown-attribute)$/;
+    return 1 if $arg =~ /^-W(no-?)?(address-space|big-constants|bitwise|cast-to-as|cast-truncate|context|decl|default-bitfield-sign|designated-init|do-while|empty-character-constant|enum-mismatch|init-cstring|memcpy-max-count|non-ansi-function-declaration|non-pointer-null|old-initializer|one-bit-signed-bitfield|override-init-all|paren-string|ptr-subtraction-blows|return-void|sizeof-bool|sparse-all|sparse-error|transparent-union|typesign|undef|unknown-attribute)$/;
     return 1 if $arg =~ /^-v(no-?)?(entry|dead)$/;
     return 1 if $arg =~ /^-f(dump-linearize|memcpy-max-count)(=\S*)?$/;
     return 0;
diff --git a/lib.c b/lib.c
index ed7d9ed..0f3a05a 100644
--- a/lib.c
+++ b/lib.c
@@ -236,6 +236,7 @@ int Wdesignated_init = 1;
 int Wdo_while = 0;
 int Winit_cstring = 0;
 int Wenum_mismatch = 1;
+int Wempty_character_constant = 1;
 int Wsparse_error = 0;
 int Wmemcpy_max_count = 1;
 int Wnon_ansi_function_declaration = 1;
@@ -534,6 +535,7 @@ static const struct warning {
 	{ "default-bitfield-sign", &Wdefault_bitfield_sign },
 	{ "designated-init", &Wdesignated_init },
 	{ "do-while", &Wdo_while },
+	{ "empty-character-constant", &Wempty_character_constant },
 	{ "enum-mismatch", &Wenum_mismatch },
 	{ "init-cstring", &Winit_cstring },
 	{ "memcpy-max-count", &Wmemcpy_max_count },
diff --git a/lib.h b/lib.h
index bfb3546..d5693ed 100644
--- a/lib.h
+++ b/lib.h
@@ -126,6 +126,7 @@ extern int Wdefault_bitfield_sign;
 extern int Wdesignated_init;
 extern int Wdo_while;
 extern int Wenum_mismatch;
+extern int Wempty_character_constant;
 extern int Wsparse_error;
 extern int Winit_cstring;
 extern int Wmemcpy_max_count;
diff --git a/sparse.1 b/sparse.1
index cc72ad6..718bae6 100644
--- a/sparse.1
+++ b/sparse.1
@@ -208,6 +208,13 @@ Sparse issues these warnings by default.  To turn them off, use
 \fB\-Wno\-enum\-mismatch\fR.
 .
 .TP
+.B \-Wempty\-character\-constant
+Warn about a constant such as ''.
+
+Sparse issues these warnings by default.  To turn them off, use
+\fB\-Wno\-empty\-character\-constant\fR.
+.
+.TP
 .B \-Winit\-cstring
 Warn about initialization of a char array with a too long constant C string.
 
diff --git a/tokenize.c b/tokenize.c
index ff5b136..12c1f43 100644
--- a/tokenize.c
+++ b/tokenize.c
@@ -630,8 +630,9 @@ static int eat_string(int next, stream_t *stream, enum token_type type)
 	}
 	if (delim == '\'' && len <= 4) {
 		if (len == 0) {
-			sparse_error(stream_pos(stream),
-				"empty character constant");
+			if (Wempty_character_constant)
+				sparse_error(stream_pos(stream),
+					"empty character constant");
 			return nextchar(stream);
 		}
 		token_type(token) = type + len;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 05/12] Look across the entire compile line for smatch arguments
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
                   ` (2 preceding siblings ...)
  2018-11-27 10:53 ` [PATCH 04/12] sparse: add -Wempty-character-constant John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 06/12] Regularise error reporting John Levon
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

This makes smatch arguments much easier to provide in Makefiles: an addition is
enough to modify the behaviour of smatch.

Signed-off-by: John Levon <levon@movementarian.org>
---
 smatch.c | 80 ++++++++++++++++++++++++----------------------------------------
 1 file changed, 30 insertions(+), 50 deletions(-)

diff --git a/smatch.c b/smatch.c
index 8640def..bc2be4d 100644
--- a/smatch.c
+++ b/smatch.c
@@ -164,65 +164,49 @@ static int match_option(const char *arg, const char *option)
 }
 
 #define OPTION(_x) do {					\
-	if (!found && match_option((*argvp)[1], #_x)) { \
-		found = 1;				\
-		option_##_x = 1;					\
-		(*argvp)[1] = (*argvp)[0];		\
+	if (match_option((*argvp)[1], #_x)) { 		\
+		option_##_x = 1;			\
 	}                                               \
 } while (0)
 
 void parse_args(int *argcp, char ***argvp)
 {
-	while (*argcp >= 2) {
-		int found = 0;
-		if (!strcmp((*argvp)[1], "--help"))
+	int i;
+
+	for (i = 1 ; i < *argcp; i++) {
+		if (!strcmp((*argvp)[i], "--help"))
 			help();
 
-		if (!strcmp((*argvp)[1], "--show-checks"))
+		if (!strcmp((*argvp)[i], "--show-checks"))
 			show_checks();
 
-		if (!found && !strncmp((*argvp)[1], "--project=", 10)) {
-			option_project_str = (*argvp)[1] + 10;
-			(*argvp)[1] = (*argvp)[0];
-			found = 1;
-		}
-		if (!found && !strncmp((*argvp)[1], "-p=", 3)) {
-			option_project_str = (*argvp)[1] + 3;
-			(*argvp)[1] = (*argvp)[0];
-			found = 1;
-		}
-		if (!found && !strncmp((*argvp)[1], "--db-file=", 10)) {
-			option_db_file = (*argvp)[1] + 10;
-			(*argvp)[1] = (*argvp)[0];
-			found = 1;
-		}
-		if (!found && !strncmp((*argvp)[1], "--data=", 7)) {
-			option_datadir_str = (*argvp)[1] + 7;
-			(*argvp)[1] = (*argvp)[0];
-			found = 1;
-		}
-		if (!found && !strncmp((*argvp)[1], "--debug=", 8)) {
-			option_debug_check = (*argvp)[1] + 8;
-			(*argvp)[1] = (*argvp)[0];
-			found = 1;
-		}
-		if (!found && strncmp((*argvp)[1], "--trace=", 8) == 0) {
-			trace_variable = (*argvp)[1] + 8;
-			(*argvp)[1] = (*argvp)[0];
-			found = 1;
-		}
-		if (!found && strncmp((*argvp)[1], "--enable=", 9) == 0) {
-			enable_disable_checks((*argvp)[1] + 9, 1);
+		if (!strncmp((*argvp)[i], "--project=", 10))
+			option_project_str = (*argvp)[i] + 10;
+
+		if (!strncmp((*argvp)[i], "-p=", 3))
+			option_project_str = (*argvp)[i] + 3;
+
+		if (!strncmp((*argvp)[i], "--db-file=", 10))
+			option_db_file = (*argvp)[i] + 10;
+
+		if (!strncmp((*argvp)[i], "--data=", 7))
+			option_datadir_str = (*argvp)[i] + 7;
+
+		if (!strncmp((*argvp)[i], "--debug=", 8))
+			option_debug_check = (*argvp)[i] + 8;
+
+		if (strncmp((*argvp)[i], "--trace=", 8) == 0)
+			trace_variable = (*argvp)[i] + 8;
+
+		if (strncmp((*argvp)[i], "--enable=", 9) == 0) {
+			enable_disable_checks((*argvp)[i] + 9, 1);
 			option_enable = 1;
-			(*argvp)[1] = (*argvp)[0];
-			found = 1;
 		}
-		if (!found && strncmp((*argvp)[1], "--disable=", 10) == 0) {
-			enable_disable_checks((*argvp)[1] + 10, 0);
+
+		if (strncmp((*argvp)[i], "--disable=", 10) == 0) {
+			enable_disable_checks((*argvp)[i] + 10, 0);
 			option_enable = 1;
 			option_disable = 1;
-			(*argvp)[1] = (*argvp)[0];
-			found = 1;
 		}
 
 		OPTION(spammy);
@@ -240,10 +224,6 @@ void parse_args(int *argcp, char ***argvp)
 		OPTION(time);
 		OPTION(mem);
 		OPTION(no_db);
-		if (!found)
-			break;
-		(*argcp)--;
-		(*argvp)++;
 	}
 
 	if (strcmp(option_project_str, "smatch_generic") != 0)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 06/12] Regularise error reporting
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
                   ` (3 preceding siblings ...)
  2018-11-27 10:53 ` [PATCH 05/12] Look across the entire compile line for smatch arguments John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 07/12] Convert all sm_msg("warn:.." into sm_warning() John Levon
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

The idea is that parse errors and other internal errors are reported back in the
exit code, while still reporting the context where needed.

A user can specify --fatal-checks to make check-level failures do the same.

Signed-off-by: John Levon <levon@movementarian.org>
---
 check_kernel_printf.c        |  2 +-
 check_memcpy_overflow.c      |  2 +-
 check_rosenberg.c            |  2 +-
 check_uninitialized.c        | 10 +++----
 check_wrong_size_arg.c       |  2 +-
 smatch.c                     | 31 +++++++++++++++------
 smatch.h                     | 65 ++++++++++++++++++++++++++++++++++++++++++--
 smatch_auto_copy.c           |  2 +-
 smatch_comparison.c          |  6 ++--
 smatch_db.c                  | 28 +++++++++----------
 smatch_flow.c                | 24 +++++-----------
 smatch_implied.c             |  8 +++---
 smatch_links.c               |  6 ++--
 smatch_modification_hooks.c  | 12 +++-----
 smatch_param_compare_limit.c |  2 +-
 smatch_parse_call_math.c     |  2 +-
 smatch_ranges.c              |  8 +++---
 smatch_slist.c               |  4 +--
 smatch_states.c              | 18 ++++++------
 smatch_struct_assignment.c   |  2 +-
 smatch_sval.c                |  8 +++---
 21 files changed, 151 insertions(+), 93 deletions(-)

diff --git a/check_kernel_printf.c b/check_kernel_printf.c
index daf6264..ecc645e 100644
--- a/check_kernel_printf.c
+++ b/check_kernel_printf.c
@@ -345,7 +345,7 @@ static void typedef_lookup(struct typedef_lookup *tl)
 		return;
 	tl->sym = _typedef_lookup(tl->name);
 	if (!tl->sym) {
-		sm_msg("internal error: could not find typedef '%s'", tl->name);
+		sm_perror(" could not find typedef '%s'", tl->name);
 		tl->failed = 1;
 	}
 }
diff --git a/check_memcpy_overflow.c b/check_memcpy_overflow.c
index a6cc093..578c70f 100644
--- a/check_memcpy_overflow.c
+++ b/check_memcpy_overflow.c
@@ -325,7 +325,7 @@ static void register_funcs_from_file(void)
 		token = token->next;
 	}
 	if (token_type(token) != TOKEN_STREAMEND)
-		printf("internal: error parsing '%s'\n", name);
+		sm_perror("parsing '%s'", name);
 	clear_token_alloc();
 }
 
diff --git a/check_rosenberg.c b/check_rosenberg.c
index 01544cd..67cf7fe 100644
--- a/check_rosenberg.c
+++ b/check_rosenberg.c
@@ -75,7 +75,7 @@ static int check_struct(struct expression *expr, struct symbol *type)
 		}
 
 		if (!tmp->ctype.alignment) {
-			sm_msg("warn: cannot determine the alignment here\n");
+			sm_perror("cannot determine the alignment here");
 		} else if (align % tmp->ctype.alignment) {
 			print_holey_warning(expr, prev);
 			return 1;
diff --git a/check_uninitialized.c b/check_uninitialized.c
index 97d0791..7d55320 100644
--- a/check_uninitialized.c
+++ b/check_uninitialized.c
@@ -125,7 +125,7 @@ static void match_dereferences(struct expression *expr)
 		return;
 
 	name = expr_to_str(expr->unop);
-	sm_msg("error: potentially dereferencing uninitialized '%s'.", name);
+	sm_error("potentially dereferencing uninitialized '%s'.", name);
 	free_string(name);
 
 	set_state_expr(my_id, expr->unop, &initialized);
@@ -145,7 +145,7 @@ static void match_condition(struct expression *expr)
 		return;
 
 	name = expr_to_str(expr);
-	sm_msg("error: potentially using uninitialized '%s'.", name);
+	sm_error("potentially using uninitialized '%s'.", name);
 	free_string(name);
 
 	set_state_expr(my_id, expr, &initialized);
@@ -167,7 +167,7 @@ static void match_call(struct expression *expr)
 			continue;
 
 		name = expr_to_str(arg);
-		sm_msg("warn: passing uninitialized '%s'", name);
+		sm_warning("warn: passing uninitialized '%s'", name);
 		free_string(name);
 
 		set_state_expr(my_id, arg, &initialized);
@@ -228,7 +228,7 @@ static void match_call_struct_members(struct expression *expr)
 			snprintf(buf, sizeof(buf), "$->%s", sm->name + strlen(arg_name) + 1);
 			if (!member_is_used(expr, param, buf))
 				goto free;
-			sm_msg("warn: struct member %s is uninitialized", sm->name);
+			sm_warning("struct member %s is uninitialized", sm->name);
 		} END_FOR_EACH_SM(sm);
 
 free:
@@ -278,7 +278,7 @@ static void match_symbol(struct expression *expr)
 		return;
 
 	name = expr_to_str(expr);
-	sm_msg("error: uninitialized symbol '%s'.", name);
+	sm_error("uninitialized symbol '%s'.", name);
 	free_string(name);
 
 	set_state_expr(my_id, expr, &initialized);
diff --git a/check_wrong_size_arg.c b/check_wrong_size_arg.c
index 7b0baab..2a8b8d5 100644
--- a/check_wrong_size_arg.c
+++ b/check_wrong_size_arg.c
@@ -83,7 +83,7 @@ static void register_funcs_from_file(void)
 
 	}
 	if (token_type(token) != TOKEN_STREAMEND)
-		sm_msg("internal: problem parsing '%s'\n", name);
+		sm_perror("problem parsing '%s'", name);
 	clear_token_alloc();
 }
 
diff --git a/smatch.c b/smatch.c
index bc2be4d..8ec103d 100644
--- a/smatch.c
+++ b/smatch.c
@@ -41,10 +41,15 @@ int option_file_output;
 int option_time;
 int option_mem;
 char *option_datadir_str;
+int option_fatal_checks;
+
 FILE *sm_outfd;
 FILE *sql_outfd;
 FILE *caller_info_fd;
 
+int sm_nr_errors;
+int sm_nr_checks;
+
 bool __silence_warnings_for_stmt;
 
 typedef void (*reg_func) (int id);
@@ -87,7 +92,7 @@ static void show_checks(void)
 		if (!strncmp(reg_funcs[i].name, "check_", 6))
 			printf("%3d. %s\n", i, reg_funcs[i].name);
 	}
-	exit(1);
+	exit(0);
 }
 
 static void enable_disable_checks(char *s, bool enable)
@@ -117,10 +122,9 @@ static void enable_disable_checks(char *s, bool enable)
 			}
 		}
 
-		if (i == ARRAY_SIZE(reg_funcs)) {
-			printf("error: '%s' not found", s);
-			exit(1);
-		}
+		if (i == ARRAY_SIZE(reg_funcs))
+			sm_fatal("'%s' not found", s);
+
 	} while ((s = next));
 }
 
@@ -139,6 +143,7 @@ static void help(void)
 	printf("--assume-loops:  assume loops always go through at least once.\n");
 	printf("--two-passes:  use a two pass system for each function.\n");
 	printf("--file-output:  instead of printing stdout, print to \"file.c.smatch_out\".\n");
+	printf("--fatal-checks: check output is treated as an error.\n");
 	printf("--help:  print this helpful message.\n");
 	exit(1);
 }
@@ -209,6 +214,7 @@ void parse_args(int *argcp, char ***argvp)
 			option_disable = 1;
 		}
 
+		OPTION(fatal_checks);
 		OPTION(spammy);
 		OPTION(info);
 		OPTION(debug);
@@ -266,7 +272,7 @@ static char *get_data_dir(char *arg0)
 
 	if (option_datadir_str) {
 		if (access(option_datadir_str, R_OK))
-			printf("Warning: %s is not accessible -- ignore.\n",
+			sm_warning("%s is not accessible -- ignored.",
 					option_datadir_str);
 		else
 			return alloc_string(option_datadir_str);
@@ -290,8 +296,8 @@ static char *get_data_dir(char *arg0)
 	if (!access(dir, R_OK))
 		return dir;
 
-	printf("Warning: %s is not accessible.\n", dir);
-	printf("Use --no-data or --data to suppress this message.\n");
+	sm_warning("%s is not accessible.", dir);
+	sm_warning("Use --no-data or --data to suppress this message.");
 	return NULL;
 }
 
@@ -303,8 +309,12 @@ int main(int argc, char **argv)
 	sm_outfd = stdout;
 	sql_outfd = stdout;
 	caller_info_fd = stdout;
+
 	parse_args(&argc, &argv);
 
+	if (argc < 2)
+		help();
+
 	/* this gets set back to zero when we parse the first function */
 	final_pass = 1;
 
@@ -326,5 +336,10 @@ int main(int argc, char **argv)
 
 	smatch(argc, argv);
 	free_string(data_dir);
+
+	if (sm_nr_errors > 0)
+		return 1;
+	if (sm_nr_checks > 0 && option_fatal_checks)
+		return 1;
 	return 0;
 }
diff --git a/smatch.h b/smatch.h
index 6dae693..737ca48 100644
--- a/smatch.h
+++ b/smatch.h
@@ -211,6 +211,22 @@ void set_path_impossible(void);
 extern FILE *sm_outfd;
 extern FILE *sql_outfd;
 extern FILE *caller_info_fd;
+extern int sm_nr_checks;
+extern int sm_nr_errors;
+
+/*
+ * How to use these routines:
+ *
+ * sm_fatal(): an internal error of some kind that should immediately exit
+ * sm_ierror(): an internal error
+ * sm_perror(): an internal error from parsing input source
+ * sm_error(): an error from input source
+ * sm_warning(): a warning from input source
+ * sm_info(): info message (from option_info)
+ * sm_debug(): debug message
+ * sm_msg(): other message (please avoid using this)
+ */
+
 #define sm_printf(msg...) do { if (final_pass || option_debug || local_debug) fprintf(sm_outfd, msg); } while (0)
 
 static inline void sm_prefix(void)
@@ -222,7 +238,7 @@ static inline void print_implied_debug_msg();
 
 extern bool __silence_warnings_for_stmt;
 
-#define sm_msg(msg...) \
+#define sm_print_msg(type, msg...) \
 do {                                                           \
 	print_implied_debug_msg();                             \
 	if (!final_pass && !option_debug && !local_debug)      \
@@ -232,10 +248,22 @@ do {                                                           \
 	if (!option_info && is_silenced_function())	       \
 		break;					       \
 	sm_prefix();					       \
+	if (type == 1) {				       \
+		sm_printf("warn: ");			       \
+		sm_nr_checks++;			    	       \
+	} else if (type == 2) {				       \
+		sm_printf("error: ");			       \
+		sm_nr_checks++;				       \
+	} else if (type == 3) {				       \
+		sm_printf("parse error: ");		       \
+		sm_nr_errors++;				       \
+	}						       \
         sm_printf(msg);                                        \
         sm_printf("\n");                                       \
 } while (0)
 
+#define sm_msg(msg...) do { sm_print_msg(0, msg); } while (0)
+
 #define local_debug(msg...)					\
 do {								\
 	if (local_debug)					\
@@ -266,6 +294,37 @@ static inline void print_implied_debug_msg(void)
 	}							\
 } while(0)
 
+#define sm_warning(msg...) do { sm_print_msg(1, msg); } while (0)
+#define sm_error(msg...) do { sm_print_msg(2, msg); } while (0)
+#define sm_perror(msg...) do { sm_print_msg(3, msg); } while (0)
+
+static inline void sm_fatal(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vfprintf(sm_outfd, fmt, args);
+	va_end(args);
+
+	fprintf(sm_outfd, "\n");
+
+	exit(1);
+}
+
+static inline void sm_ierror(const char *fmt, ...)
+{
+	va_list args;
+
+	sm_nr_errors++;
+
+	fprintf(sm_outfd, "internal error: ");
+
+	va_start(args, fmt);
+	vfprintf(sm_outfd, fmt, args);
+	va_end(args);
+
+	fprintf(sm_outfd, "\n");
+}
 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
 
 struct smatch_state *__get_state(int owner, const char *name, struct symbol *sym);
@@ -842,8 +901,8 @@ do {										\
 		sm_debug("mem-db: %s\n", buf);					\
 		rc = sqlite3_exec(_db, buf, NULL, NULL, &err);			\
 		if (rc != SQLITE_OK) {						\
-			fprintf(stderr, "SQL error #2: %s\n", err);		\
-			fprintf(stderr, "SQL: '%s'\n", buf);			\
+			sm_ierror("SQL error #2: %s", err);			\
+			sm_ierror("SQL: '%s'", buf);				\
 			parse_error = 1;					\
 		}								\
 		break;								\
diff --git a/smatch_auto_copy.c b/smatch_auto_copy.c
index 127589f..098404e 100644
--- a/smatch_auto_copy.c
+++ b/smatch_auto_copy.c
@@ -25,7 +25,7 @@ static int *auto_copy;
 void set_auto_copy(int owner)
 {
 	if (owner <= 1 || owner > num_checks) {
-		printf("bogus set_auto_copy()\n");
+		sm_ierror("bogus set_auto_copy()");
 		return;
 	}
 	auto_copy[owner] = 1;
diff --git a/smatch_comparison.c b/smatch_comparison.c
index b0aa0ba..51b4a45 100644
--- a/smatch_comparison.c
+++ b/smatch_comparison.c
@@ -117,7 +117,7 @@ int flip_comparison(int op)
 	case SPECIAL_UNSIGNED_GT:
 		return SPECIAL_UNSIGNED_LT;
 	default:
-		sm_msg("internal smatch bug.  unhandled comparison %d", op);
+		sm_perror("unhandled comparison %d", op);
 		return op;
 	}
 }
@@ -148,7 +148,7 @@ int negate_comparison(int op)
 	case SPECIAL_UNSIGNED_GT:
 		return SPECIAL_UNSIGNED_LTE;
 	default:
-		sm_msg("internal smatch bug.  unhandled comparison %d", op);
+		sm_perror("unhandled comparison %d", op);
 		return op;
 	}
 }
@@ -2311,7 +2311,7 @@ static int parse_comparison(char **value, int *op)
 	}
 
 	if (**value != ' ') {
-		sm_msg("internal error parsing comparison.  %s", *value);
+		sm_perror("parsing comparison.  %s", *value);
 		return 0;
 	}
 
diff --git a/smatch_db.c b/smatch_db.c
index bb1a705..b431f01 100644
--- a/smatch_db.c
+++ b/smatch_db.c
@@ -107,8 +107,8 @@ void sql_exec(struct sqlite3 *db, int (*callback)(void*, int, char**, char**), v
 
 	rc = sqlite3_exec(db, sql, callback, data, &err);
 	if (rc != SQLITE_OK && !parse_error) {
-		fprintf(stderr, "SQL error #2: %s\n", err);
-		fprintf(stderr, "SQL: '%s'\n", sql);
+		sm_ierror("SQL error #2: %s", err);
+		sm_ierror("SQL: '%s'", sql);
 		parse_error = 1;
 	}
 }
@@ -2116,7 +2116,7 @@ static void init_memdb(void)
 
 	rc = sqlite3_open(":memory:", &mem_db);
 	if (rc != SQLITE_OK) {
-		printf("Error starting In-Memory database.");
+		sm_ierror("starting In-Memory database.");
 		return;
 	}
 
@@ -2126,20 +2126,20 @@ static void init_memdb(void)
 			continue;
 		ret = read(fd, buf, sizeof(buf));
 		if (ret < 0) {
-			printf("failed to read: %s\n", schema_files[i]);
+			sm_ierror("failed to read: %s", schema_files[i]);
 			continue;
 		}
 		close(fd);
 		if (ret == sizeof(buf)) {
-			printf("Schema file too large:  %s (limit %zd bytes)",
+			sm_ierror("Schema file too large:  %s (limit %zd bytes)",
 			       schema_files[i], sizeof(buf));
 			continue;
 		}
 		buf[ret] = '\0';
 		rc = sqlite3_exec(mem_db, buf, NULL, NULL, &err);
 		if (rc != SQLITE_OK) {
-			fprintf(stderr, "SQL error #2: %s\n", err);
-			fprintf(stderr, "%s\n", buf);
+			sm_ierror("SQL error #2: %s", err);
+			sm_ierror("%s", buf);
 		}
 	}
 }
@@ -2162,7 +2162,7 @@ static void init_cachedb(void)
 
 	rc = sqlite3_open(":memory:", &cache_db);
 	if (rc != SQLITE_OK) {
-		printf("Error starting In-Memory database.");
+		sm_ierror("starting In-Memory database.");
 		return;
 	}
 
@@ -2172,20 +2172,20 @@ static void init_cachedb(void)
 			continue;
 		ret = read(fd, buf, sizeof(buf));
 		if (ret < 0) {
-			printf("failed to read: %s\n", schema_files[i]);
+			sm_ierror("failed to read: %s", schema_files[i]);
 			continue;
 		}
 		close(fd);
 		if (ret == sizeof(buf)) {
-			printf("Schema file too large:  %s (limit %zd bytes)",
+			sm_ierror("Schema file too large:  %s (limit %zd bytes)",
 			       schema_files[i], sizeof(buf));
 			continue;
 		}
 		buf[ret] = '\0';
 		rc = sqlite3_exec(cache_db, buf, NULL, NULL, &err);
 		if (rc != SQLITE_OK) {
-			fprintf(stderr, "SQL error #2: %s\n", err);
-			fprintf(stderr, "%s\n", buf);
+			sm_ierror("SQL error #2: %s", err);
+			sm_ierror("%s", buf);
 		}
 	}
 }
@@ -2294,7 +2294,7 @@ static char *get_next_string(char **str)
 	if (len > 256) {
 		memcpy(string, start, 255);
 		string[255] = '\0';
-		printf("return_fix: '%s' too long", string);
+		sm_ierror("return_fix: '%s' too long", string);
 		**str = '\0';
 		return NULL;
 	}
@@ -2323,7 +2323,7 @@ static void register_return_replacements(void)
 	if (ret < 0)
 		return;
 	if (ret == sizeof(buf)) {
-		printf("file too large:  %s (limit %zd bytes)",
+		sm_ierror("file too large:  %s (limit %zd bytes)",
 		       filename, sizeof(buf));
 		return;
 	}
diff --git a/smatch_flow.c b/smatch_flow.c
index 986160d..31503d5 100644
--- a/smatch_flow.c
+++ b/smatch_flow.c
@@ -1072,7 +1072,7 @@ void __split_stmt(struct statement *stmt)
 
 		__bail_on_rest_of_function = 1;
 		final_pass = 1;
-		sm_msg("Function too hairy.  Giving up. %lu seconds",
+		sm_perror("Function too hairy.  Giving up. %lu seconds",
 		       stop.tv_sec - fn_start_time.tv_sec);
 		fake_a_return();
 		final_pass = 0;  /* turn off sm_msg() from here */
@@ -1891,27 +1891,21 @@ static void open_output_files(char *base_file)
 
 	snprintf(buf, sizeof(buf), "%s.smatch", base_file);
 	sm_outfd = fopen(buf, "w");
-	if (!sm_outfd) {
-		printf("Error:  Cannot open %s\n", buf);
-		exit(1);
-	}
+	if (!sm_outfd)
+		sm_fatal("Cannot open %s", buf);
 
 	if (!option_info)
 		return;
 
 	snprintf(buf, sizeof(buf), "%s.smatch.sql", base_file);
 	sql_outfd = fopen(buf, "w");
-	if (!sql_outfd) {
-		printf("Error:  Cannot open %s\n", buf);
-		exit(1);
-	}
+	if (!sql_outfd)
+		sm_fatal("Error:  Cannot open %s", buf);
 
 	snprintf(buf, sizeof(buf), "%s.smatch.caller_info", base_file);
 	caller_info_fd = fopen(buf, "w");
-	if (!caller_info_fd) {
-		printf("Error:  Cannot open %s\n", buf);
-		exit(1);
-	}
+	if (!caller_info_fd)
+		sm_fatal("Error:  Cannot open %s", buf);
 }
 
 void smatch(int argc, char **argv)
@@ -1924,10 +1918,6 @@ void smatch(int argc, char **argv)
 
 	gettimeofday(&start, NULL);
 
-	if (argc < 2) {
-		printf("Usage:  smatch [--debug] <filename.c>\n");
-		exit(1);
-	}
 	sparse_initialize(argc, argv, &filelist);
 	set_valid_ptr_max();
 	alloc_valid_ptr_rl();
diff --git a/smatch_implied.c b/smatch_implied.c
index fc86de2..0a137de 100644
--- a/smatch_implied.c
+++ b/smatch_implied.c
@@ -134,7 +134,7 @@ static int create_fake_history(struct sm_state *sm, int comparison, struct range
 		return 0;
 
 	if (rl_intersection(true_rl, false_rl)) {
-		sm_msg("internal error parsing (%s (%s) %s %s)",
+		sm_perror("parsing (%s (%s) %s %s)",
 			sm->name, sm->state->name, show_special(comparison), show_rl(rl));
 		sm_msg("true_rl = %s false_rl = %s intersection = %s",
 		       show_rl(true_rl), show_rl(false_rl), show_rl(rl_intersection(true_rl, false_rl)));
@@ -142,7 +142,7 @@ static int create_fake_history(struct sm_state *sm, int comparison, struct range
 	}
 
 	if (option_debug)
-		sm_msg("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
+		sm_info("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
 		       sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl),
 		       show_rl(true_rl), show_rl(false_rl));
 
@@ -403,7 +403,7 @@ static int taking_too_long(void)
 		return 0;
 
 	if (!__inline_fn && printed != cur_func_sym) {
-		sm_msg("internal: turning off implications after 60 seconds");
+		sm_perror("turning off implications after 60 seconds");
 		printed = cur_func_sym;
 	}
 	return 1;
@@ -596,7 +596,7 @@ static void separate_and_filter(struct sm_state *sm, int comparison, struct rang
 	sec = time_after.tv_sec - time_before.tv_sec;
 	if (sec > 20) {
 		sm->nr_children = 4000;
-		sm_msg("Function too hairy.  Ignoring implications after %d seconds.", sec);
+		sm_perror("Function too hairy.  Ignoring implications after %d seconds.", sec);
 	}
 }
 
diff --git a/smatch_links.c b/smatch_links.c
index 91907b5..c24f0c2 100644
--- a/smatch_links.c
+++ b/smatch_links.c
@@ -99,10 +99,8 @@ static void match_link_modify(struct sm_state *sm, struct expression *mod_expr)
 
 void set_up_link_functions(int id, int link_id)
 {
-	if (id + 1 != link_id) {
-		printf("FATAL ERROR: links need to be registered directly after the check");
-		exit(1);
-	}
+	if (id + 1 != link_id)
+		sm_fatal("FATAL ERROR: links need to be registered directly after the check");
 
 	add_merge_hook(link_id, &merge_link_states);
 	add_modification_hook(link_id, &match_link_modify);
diff --git a/smatch_modification_hooks.c b/smatch_modification_hooks.c
index 7eef7a7..b4f9e62 100644
--- a/smatch_modification_hooks.c
+++ b/smatch_modification_hooks.c
@@ -68,19 +68,15 @@ static struct smatch_state *alloc_my_state(struct expression *expr, struct smatc
 
 void add_modification_hook(int owner, modification_hook *call_back)
 {
-	if (hooks[owner]) {
-		printf("multiple modification hooks for %s\n", check_name(owner));
-		exit(1);
-	}
+	if (hooks[owner])
+		sm_fatal("multiple modification hooks for %s", check_name(owner));
 	hooks[owner] = call_back;
 }
 
 void add_modification_hook_late(int owner, modification_hook *call_back)
 {
-	if (hooks_late[owner]) {
-		printf("multiple late modification hooks for %s\n", check_name(owner));
-		exit(1);
-	}
+	if (hooks_late[owner])
+		sm_fatal("multiple late modification hooks for %s", check_name(owner));
 	hooks_late[owner] = call_back;
 }
 
diff --git a/smatch_param_compare_limit.c b/smatch_param_compare_limit.c
index acdfed9..1539e06 100644
--- a/smatch_param_compare_limit.c
+++ b/smatch_param_compare_limit.c
@@ -268,7 +268,7 @@ static int parse_comparison(char **value, int *op)
 	}
 
 	if (**value != ' ') {
-		sm_msg("internal error parsing comparison.  %s", *value);
+		sm_perror("parsing comparison.  %s", *value);
 		return 0;
 	}
 
diff --git a/smatch_parse_call_math.c b/smatch_parse_call_math.c
index 19b9e95..a84622d 100644
--- a/smatch_parse_call_math.c
+++ b/smatch_parse_call_math.c
@@ -51,7 +51,7 @@ static char pop_op(void)
 	char c;
 
 	if (!op_list) {
-		sm_msg("internal smatch error %s", __func__);
+		sm_perror("%s: no op_list", __func__);
 		return '\0';
 	}
 
diff --git a/smatch_ranges.c b/smatch_ranges.c
index afae441..fbc93fe 100644
--- a/smatch_ranges.c
+++ b/smatch_ranges.c
@@ -311,7 +311,7 @@ void filter_by_comparison(struct range_list **rl, int comparison, struct range_l
 			ret_rl = remove_range(left_orig, rl_min(right_orig), rl_min(right_orig));
 		break;
 	default:
-		sm_msg("internal error: unhandled comparison %s", show_special(comparison));
+		sm_perror("unhandled comparison %s", show_special(comparison));
 		return;
 	}
 
@@ -949,7 +949,7 @@ int true_comparison_range(struct data_range *left, int comparison, struct data_r
 			return 1;
 		return 0;
 	default:
-		sm_msg("unhandled comparison %d\n", comparison);
+		sm_perror("unhandled comparison %d", comparison);
 		return 0;
 	}
 	return 0;
@@ -1001,7 +1001,7 @@ static int false_comparison_range_sval(struct data_range *left, int comparison,
 			return 0;
 		return 1;
 	default:
-		sm_msg("unhandled comparison %d\n", comparison);
+		sm_perror("unhandled comparison %d", comparison);
 		return 0;
 	}
 	return 0;
@@ -1829,7 +1829,7 @@ void split_comparison_rl(struct range_list *left_orig, int op, struct range_list
 			right_true = remove_range(right_orig, rl_min(left_orig), rl_min(left_orig));
 		break;
 	default:
-		sm_msg("internal error: unhandled comparison %d", op);
+		sm_perror(" unhandled comparison %d", op);
 		return;
 	}
 
diff --git a/smatch_slist.c b/smatch_slist.c
index 4c74caf..0a993e9 100644
--- a/smatch_slist.c
+++ b/smatch_slist.c
@@ -757,7 +757,7 @@ static void __merge_stree(struct stree **to, struct stree *stree, int add_pool)
 		if (!one_iter.sm || !two_iter.sm)
 			break;
 		if (cmp_tracker(one_iter.sm, two_iter.sm) < 0) {
-			sm_msg("error:  Internal smatch error.");
+			sm_perror(" in %s", __func__);
 			avl_iter_next(&one_iter);
 		} else if (cmp_tracker(one_iter.sm, two_iter.sm) == 0) {
 			if (add_pool && one_iter.sm != two_iter.sm) {
@@ -775,7 +775,7 @@ static void __merge_stree(struct stree **to, struct stree *stree, int add_pool)
 			avl_iter_next(&one_iter);
 			avl_iter_next(&two_iter);
 		} else {
-			sm_msg("error:  Internal smatch error.");
+			sm_perror(" in %s", __func__);
 			avl_iter_next(&two_iter);
 		}
 	}
diff --git a/smatch_states.c b/smatch_states.c
index 53ed75c..c7a9c85 100644
--- a/smatch_states.c
+++ b/smatch_states.c
@@ -88,7 +88,7 @@ struct sm_state *set_state(int owner, const char *name, struct symbol *sym, stru
 		return NULL;
 
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
 		struct smatch_state *s;
@@ -145,7 +145,7 @@ void __push_fake_cur_stree(void)
 struct stree *__pop_fake_cur_stree(void)
 {
 	if (!fake_cur_stree_stack)
-		sm_msg("INTERNAL error: popping too many fake cur strees.");
+		sm_perror("popping too many fake cur strees.");
 	__use_pre_cond_states();
 	return pop_stree(&fake_cur_stree_stack);
 }
@@ -190,7 +190,7 @@ void __merge_stree_into_cur(struct stree *stree)
 void __set_sm(struct sm_state *sm)
 {
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug ||
 	    strcmp(check_name(sm->owner), option_debug_check) == 0) {
@@ -216,7 +216,7 @@ void __set_sm(struct sm_state *sm)
 void __set_sm_cur_stree(struct sm_state *sm)
 {
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug ||
 	    strcmp(check_name(sm->owner), option_debug_check) == 0) {
@@ -239,7 +239,7 @@ void __set_sm_cur_stree(struct sm_state *sm)
 void __set_sm_fake_stree(struct sm_state *sm)
 {
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug ||
 	    strcmp(check_name(sm->owner), option_debug_check) == 0) {
@@ -472,7 +472,7 @@ void set_true_false_states(int owner, const char *name, struct symbol *sym,
 			   struct smatch_state *false_state)
 {
 	if (read_only)
-		sm_msg("Smatch Internal Error: cur_stree is read only.");
+		sm_perror("cur_stree is read only.");
 
 	if (option_debug || strcmp(check_name(owner), option_debug_check) == 0) {
 		struct smatch_state *tmp;
@@ -487,7 +487,7 @@ void set_true_false_states(int owner, const char *name, struct symbol *sym,
 		return;
 
 	if (!cond_false_stack || !cond_true_stack) {
-		printf("Error:  missing true/false stacks\n");
+		sm_perror("missing true/false stacks");
 		return;
 	}
 
@@ -539,7 +539,7 @@ void __set_true_false_sm(struct sm_state *true_sm, struct sm_state *false_sm)
 	}
 
 	if (!cond_false_stack || !cond_true_stack) {
-		printf("Error:  missing true/false stacks\n");
+		sm_perror("missing true/false stacks");
 		return;
 	}
 
@@ -586,7 +586,7 @@ int __path_is_null(void)
 static void check_stree_stack_free(struct stree_stack **stack)
 {
 	if (*stack) {
-		sm_msg("smatch internal error:  stack not empty");
+		sm_perror("stack not empty");
 		free_stack_and_strees(stack);
 	}
 }
diff --git a/smatch_struct_assignment.c b/smatch_struct_assignment.c
index 90b666f..1929c95 100644
--- a/smatch_struct_assignment.c
+++ b/smatch_struct_assignment.c
@@ -285,7 +285,7 @@ static void __struct_members_copy(int mode, struct expression *faked,
 			break;
 		}
 		if (!right_member) {
-			sm_msg("internal.  No right member");
+			sm_perror("No right member");
 			continue;
 		}
 		assign = assign_expression(left_member, '=', right_member);
diff --git a/smatch_sval.c b/smatch_sval.c
index 9d892a0..725509a 100644
--- a/smatch_sval.c
+++ b/smatch_sval.c
@@ -339,7 +339,7 @@ static sval_t sval_binop_unsigned(struct symbol *type, sval_t left, int op, sval
 		break;
 	case '%':
 		if (right.uvalue == 0) {
-			sm_msg("internal error: %s: MOD by zero", __func__);
+			sm_perror(" %s: MOD by zero", __func__);
 			ret.uvalue = 123456789;
 		} else {
 			ret.uvalue = left.uvalue % right.uvalue;
@@ -361,7 +361,7 @@ static sval_t sval_binop_unsigned(struct symbol *type, sval_t left, int op, sval
 		ret.uvalue = left.uvalue ^ right.uvalue;
 		break;
 	default:
-		sm_msg("internal error: %s: unhandled binop %s", __func__,
+		sm_perror(" %s: unhandled binop %s", __func__,
 		       show_special(op));
 		ret.uvalue = 1234567;
 	}
@@ -397,7 +397,7 @@ static sval_t sval_binop_signed(struct symbol *type, sval_t left, int op, sval_t
 		break;
 	case '%':
 		if (right.value == 0) {
-			sm_msg("internal error: %s: MOD by zero", __func__);
+			sm_perror(" %s: MOD by zero", __func__);
 			ret.value = 123456789;
 		} else {
 			ret.value = left.value % right.value;
@@ -419,7 +419,7 @@ static sval_t sval_binop_signed(struct symbol *type, sval_t left, int op, sval_t
 		ret.value = left.value ^ right.value;
 		break;
 	default:
-		sm_msg("internal error: %s: unhandled binop %s", __func__,
+		sm_perror(" %s: unhandled binop %s", __func__,
 		       show_special(op));
 		ret.value = 1234567;
 	}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 07/12] Convert all sm_msg("warn:.." into sm_warning()
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
                   ` (4 preceding siblings ...)
  2018-11-27 10:53 ` [PATCH 06/12] Regularise error reporting John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 08/12] Convert sm_msg() with an error: prefix into sm_error() John Levon
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Signed-off-by: John Levon <levon@movementarian.org>
---
 check_64bit_shift.c                   |  2 +-
 check_access_ok_math.c                |  2 +-
 check_array_condition.c               |  2 +-
 check_assign_vs_compare.c             |  4 +-
 check_atomic_inc_dec.c                |  2 +-
 check_bit_shift.c                     |  4 +-
 check_bogus_loop.c                    |  2 +-
 check_buffer_too_small_for_struct.c   |  2 +-
 check_cast_assign.c                   |  2 +-
 check_container_of.c                  |  2 +-
 check_continue_vs_break.c             |  2 +-
 check_deref_check.c                   |  2 +-
 check_dma_mapping_error.c             |  2 +-
 check_double_checking.c               |  2 +-
 check_free.c                          |  6 +--
 check_free_strict.c                   |  8 ++--
 check_freeing_devm.c                  |  2 +-
 check_freeing_null.c                  |  2 +-
 check_get_user_overflow.c             |  6 +--
 check_held_dev.c                      |  2 +-
 check_impossible_mask.c               |  2 +-
 check_indenting.c                     |  4 +-
 check_info_leak.c                     |  2 +-
 check_kernel_printf.c                 | 76 +++++++++++++++++------------------
 check_kmalloc_to_bugon.c              |  2 +-
 check_kmalloc_wrong_size.c            |  2 +-
 check_kunmap.c                        |  4 +-
 check_leaks.c                         |  4 +-
 check_locking.c                       |  4 +-
 check_logical_instead_of_bitwise.c    |  4 +-
 check_macro_side_effects.c            |  2 +-
 check_macros.c                        |  4 +-
 check_memory.c                        |  2 +-
 check_min_t.c                         |  2 +-
 check_missing_break.c                 |  2 +-
 check_mod_timer.c                     |  2 +-
 check_no_effect.c                     |  2 +-
 check_no_if_block.c                   |  4 +-
 check_off_by_one_relative.c           |  4 +-
 check_or_vs_and.c                     | 10 ++---
 check_platform_device_put.c           |  2 +-
 check_pointer_math.c                  |  4 +-
 check_precedence.c                    | 10 ++---
 check_proc_create.c                   |  2 +-
 check_readl_infinite_loops.c          |  2 +-
 check_release_resource.c              |  2 +-
 check_resource_size.c                 |  2 +-
 check_return.c                        |  2 +-
 check_return_cast.c                   |  2 +-
 check_return_efault.c                 |  4 +-
 check_return_enomem.c                 |  2 +-
 check_return_negative_var.c           |  4 +-
 check_rosenberg.c                     |  6 +--
 check_select.c                        |  2 +-
 check_shift_to_zero.c                 |  6 +--
 check_signed.c                        | 12 +++---
 check_signed_integer_overflow_check.c |  4 +-
 check_sizeof.c                        | 12 +++---
 check_snprintf.c                      |  2 +-
 check_spectre.c                       |  2 +-
 check_stack.c                         |  2 +-
 check_strcpy_overflow.c               |  2 +-
 check_struct_type.c                   |  2 +-
 check_template.c                      |  2 +-
 check_test_bit.c                      |  2 +-
 check_uninitialized.c                 |  2 +-
 check_unwind.c                        |  2 +-
 check_wine_WtoA.c                     |  2 +-
 check_wrong_size_arg.c                |  2 +-
 check_zero_to_err_ptr.c               |  4 +-
 smatch_buf_comparison.c               |  4 +-
 smatch_flow.c                         |  2 +-
 72 files changed, 154 insertions(+), 154 deletions(-)

diff --git a/check_64bit_shift.c b/check_64bit_shift.c
index 8cc3078..89b1c23 100644
--- a/check_64bit_shift.c
+++ b/check_64bit_shift.c
@@ -54,7 +54,7 @@ static void match_shift_assignment(struct expression *expr)
 	}
 
 	name = expr_to_str_sym(right, NULL);
-	sm_msg("warn: should '%s' be a 64 bit type?", name);
+	sm_warning("should '%s' be a 64 bit type?", name);
 	free_string(name);
 }
 
diff --git a/check_access_ok_math.c b/check_access_ok_math.c
index 7db79ea..7cfcdc4 100644
--- a/check_access_ok_math.c
+++ b/check_access_ok_math.c
@@ -60,7 +60,7 @@ static void match_size(struct expression *size_expr)
 		return;
 
 	name = expr_to_str(size_expr);
-	sm_msg("warn: math in access_ok() is dangerous '%s'", name);
+	sm_warning("math in access_ok() is dangerous '%s'", name);
 
 	free_string(name);
 }
diff --git a/check_array_condition.c b/check_array_condition.c
index 3d69f6d..7b90071 100644
--- a/check_array_condition.c
+++ b/check_array_condition.c
@@ -41,7 +41,7 @@ static void match_condition(struct expression *expr)
 		return;
 
 	str = expr_to_str(expr);
-	sm_msg("warn: this array is probably non-NULL. '%s'", str);
+	sm_warning("this array is probably non-NULL. '%s'", str);
 	free_string(str);
 }
 
diff --git a/check_assign_vs_compare.c b/check_assign_vs_compare.c
index 5900633..c6b0753 100644
--- a/check_assign_vs_compare.c
+++ b/check_assign_vs_compare.c
@@ -25,7 +25,7 @@ static void check_constant(struct expression *expr)
 
 	if (!get_value(expr->right, &val))
 		return;
-	sm_msg("warn: was '== %s' instead of '='", sval_to_str(val));
+	sm_warning("was '== %s' instead of '='", sval_to_str(val));
 }
 
 static void check_address(struct expression *expr)
@@ -44,7 +44,7 @@ static void check_address(struct expression *expr)
 		return;
 
 	str = expr_to_str(right);
-	sm_msg("warn: was '== %s' instead of '='", str);
+	sm_warning("was '== %s' instead of '='", str);
 	free_string(str);
 }
 
diff --git a/check_atomic_inc_dec.c b/check_atomic_inc_dec.c
index f028112..a7c5ae7 100644
--- a/check_atomic_inc_dec.c
+++ b/check_atomic_inc_dec.c
@@ -186,7 +186,7 @@ static void check_counter(const char *name, struct symbol *sym)
 
 	if (inc_buckets[NEGATIVE] &&
 	    inc_buckets[ZERO]) {
-		// sm_msg("warn: XXX '%s' not decremented on lines: %s.", name, show_rl(inc_lines));
+		// sm_warning("XXX '%s' not decremented on lines: %s.", name, show_rl(inc_lines));
 	}
 
 }
diff --git a/check_bit_shift.c b/check_bit_shift.c
index 87f29c3..fe4ecee 100644
--- a/check_bit_shift.c
+++ b/check_bit_shift.c
@@ -63,7 +63,7 @@ static void match_assign(struct expression *expr)
 	if (!name)
 		return;
 
-	sm_msg("warn: '%s' is a shifter (not for '%s').",
+	sm_warning("'%s' is a shifter (not for '%s').",
 			name, show_special(expr->op));
 }
 
@@ -79,7 +79,7 @@ static void match_binop(struct expression *expr)
 	if (!name)
 		return;
 
-	sm_msg("warn: bit shifter '%s' used for logical '%s'",
+	sm_warning("bit shifter '%s' used for logical '%s'",
 			name, show_special(expr->op));
 }
 
diff --git a/check_bogus_loop.c b/check_bogus_loop.c
index 52ba832..44d5ace 100644
--- a/check_bogus_loop.c
+++ b/check_bogus_loop.c
@@ -81,7 +81,7 @@ static void match_loop(struct statement *stmt)
 		goto free;
 
 	if (implied_condition_false(stmt->iterator_pre_condition))
-		sm_msg("warn: we never enter this loop");
+		sm_warning("we never enter this loop");
 
 free:
 	free_string(iter_set);
diff --git a/check_buffer_too_small_for_struct.c b/check_buffer_too_small_for_struct.c
index e741fbd..06b69d8 100644
--- a/check_buffer_too_small_for_struct.c
+++ b/check_buffer_too_small_for_struct.c
@@ -88,7 +88,7 @@ static void match_dereferences(struct expression *expr)
 		return;
 
 	name = expr_to_str(right);
-	sm_msg("warn: is '%s' large enough for 'struct %s'? %s", name, left_type->ident ? left_type->ident->name : "<anon>", sval_to_str(min_size));
+	sm_warning("is '%s' large enough for 'struct %s'? %s", name, left_type->ident ? left_type->ident->name : "<anon>", sval_to_str(min_size));
 	free_string(name);
 	set_state_expr(my_id, expr, &undefined);
 }
diff --git a/check_cast_assign.c b/check_cast_assign.c
index d1fe55e..589b6d4 100644
--- a/check_cast_assign.c
+++ b/check_cast_assign.c
@@ -49,7 +49,7 @@ static void match_overflow(struct expression *expr)
 		return;
 	if (data_size >= cast_size)
 		return;
-	sm_msg("warn: potential memory corrupting cast %d vs %d bytes",
+	sm_warning("potential memory corrupting cast %d vs %d bytes",
 	       cast_size, data_size);
 }
 
diff --git a/check_container_of.c b/check_container_of.c
index a466739..411c987 100644
--- a/check_container_of.c
+++ b/check_container_of.c
@@ -49,7 +49,7 @@ static void match_condition(struct expression *expr)
 		char *name;
 
 		name = expr_to_var(expr);
-		sm_msg("warn: can '%s' even be NULL?", name);
+		sm_warning("can '%s' even be NULL?", name);
 		set_state_expr(my_id, expr, &undefined);
 		free_string(name);
 	}
diff --git a/check_continue_vs_break.c b/check_continue_vs_break.c
index e27d40a..c22ce0e 100644
--- a/check_continue_vs_break.c
+++ b/check_continue_vs_break.c
@@ -113,7 +113,7 @@ static void match_continue(struct statement *stmt)
 		return;
 	if (loop_is_macro())
 		return;
-	sm_msg("warn: continue to end of do { ... } while(0); loop");
+	sm_warning("continue to end of do { ... } while(0); loop");
 }
 
 void check_continue_vs_break(int id)
diff --git a/check_deref_check.c b/check_deref_check.c
index 5d5f514..a06cc8b 100644
--- a/check_deref_check.c
+++ b/check_deref_check.c
@@ -80,7 +80,7 @@ static void match_condition(struct expression *expr)
 	if (!sm || sm->state != &derefed)
 		return;
 
-	sm_msg("warn: variable dereferenced before check '%s' (see line %d)", sm->name, sm->line);
+	sm_warning("variable dereferenced before check '%s' (see line %d)", sm->name, sm->line);
 	set_state_expr(my_id, expr, &undefined);
 }
 
diff --git a/check_dma_mapping_error.c b/check_dma_mapping_error.c
index 5316c38..a786813 100644
--- a/check_dma_mapping_error.c
+++ b/check_dma_mapping_error.c
@@ -61,7 +61,7 @@ static void match_return(struct expression *ret_value)
 		return;
 	if (min.value == 0)
 		return;
-	sm_msg("warn: warn: dma_mapping_error() doesn't return an error code");
+	sm_warning("dma_mapping_error() doesn't return an error code");
 }
 
 void check_dma_mapping_error(int id)
diff --git a/check_double_checking.c b/check_double_checking.c
index 24d0809..83d10fd 100644
--- a/check_double_checking.c
+++ b/check_double_checking.c
@@ -215,7 +215,7 @@ static void match_condition(struct expression *expr)
 		return;
 
 	name = expr_to_str(expr);
-	sm_msg("warn: we tested '%s' before and it was '%s'", name, state->name);
+	sm_warning("we tested '%s' before and it was '%s'", name, state->name);
 	free_string(name);
 }
 
diff --git a/check_free.c b/check_free.c
index b79eed1..9e9d835 100644
--- a/check_free.c
+++ b/check_free.c
@@ -71,7 +71,7 @@ static void match_symbol(struct expression *expr)
 	if (!is_freed(expr))
 		return;
 	name = expr_to_var(expr);
-	sm_msg("warn: '%s' was already freed.", name);
+	sm_warning("'%s' was already freed.", name);
 	free_string(name);
 }
 
@@ -178,7 +178,7 @@ static void match_call(struct expression *expr)
 		if (is_free_func(expr->fn))
 			sm_msg("error: double free of '%s'", name);
 		else
-			sm_msg("warn: passing freed memory '%s'", name);
+			sm_warning("passing freed memory '%s'", name);
 		set_state_expr(my_id, arg, &ok);
 		free_string(name);
 	} END_FOR_EACH_PTR(arg);
@@ -199,7 +199,7 @@ static void match_return(struct expression *expr)
 		return;
 
 	name = expr_to_var(expr);
-	sm_msg("warn: returning freed memory '%s'", name);
+	sm_warning("returning freed memory '%s'", name);
 	set_state_expr(my_id, expr, &ok);
 	free_string(name);
 }
diff --git a/check_free_strict.c b/check_free_strict.c
index 31e3369..bf75021 100644
--- a/check_free_strict.c
+++ b/check_free_strict.c
@@ -71,7 +71,7 @@ static void match_symbol(struct expression *expr)
 	if (!is_freed(expr))
 		return;
 	name = expr_to_var(expr);
-	sm_msg("warn: '%s' was already freed.", name);
+	sm_warning("'%s' was already freed.", name);
 	free_string(name);
 }
 
@@ -175,7 +175,7 @@ static void match_call(struct expression *expr)
 		if (is_free_func(expr->fn))
 			sm_msg("error: double free of '%s'", name);
 		else
-			sm_msg("warn: passing freed memory '%s'", name);
+			sm_warning("passing freed memory '%s'", name);
 		set_state_expr(my_id, arg, &ok);
 		free_string(name);
 	} END_FOR_EACH_PTR(arg);
@@ -194,7 +194,7 @@ static void match_return(struct expression *expr)
 		return;
 
 	name = expr_to_var(expr);
-	sm_msg("warn: returning freed memory '%s'", name);
+	sm_warning("returning freed memory '%s'", name);
 	set_state_expr(my_id, expr, &ok);
 	free_string(name);
 }
@@ -240,7 +240,7 @@ static void set_param_freed(struct expression *expr, int param, char *key, char
 	if (!is_impossible_path()) {
 		sm = get_sm_state(my_id, name, sym);
 		if (sm && slist_has_state(sm->possible, &freed)) {
-			sm_msg("warn: '%s' double freed", name);
+			sm_warning("'%s' double freed", name);
 			set_state(my_id, name, sym, &ok);  /* fixme: doesn't silence anything.  I know */
 		}
 	}
diff --git a/check_freeing_devm.c b/check_freeing_devm.c
index f5b9937..02587bc 100644
--- a/check_freeing_devm.c
+++ b/check_freeing_devm.c
@@ -36,7 +36,7 @@ static void match_free_func(const char *fn, struct expression *expr, void *_arg)
 	if (!get_state_expr(my_id, arg_expr))
 		return;
 	name = expr_to_str(arg_expr);
-	sm_msg("warn: passing devm_ allocated variable to kfree. '%s'", name);
+	sm_warning("passing devm_ allocated variable to kfree. '%s'", name);
 	free_string(name);
 }
 
diff --git a/check_freeing_null.c b/check_freeing_null.c
index bd4760d..082f625 100644
--- a/check_freeing_null.c
+++ b/check_freeing_null.c
@@ -31,7 +31,7 @@ static void match_free(const char *fn, struct expression *expr, void *data)
 	if (sval.value != 0)
 		return;
 	name = expr_to_var(arg_expr);
-	sm_msg("warn: calling %s() when '%s' is always NULL.", fn, name);
+	sm_warning("calling %s() when '%s' is always NULL.", fn, name);
 	free_string(name);
 }
 
diff --git a/check_get_user_overflow.c b/check_get_user_overflow.c
index 31c627a..20ec952 100644
--- a/check_get_user_overflow.c
+++ b/check_get_user_overflow.c
@@ -143,11 +143,11 @@ static void check_expr(struct expression *expr)
 
 	name = expr_to_var_sym(expr, NULL);
 	if (overflow && underflow)
-		sm_msg("warn: check for integer over/underflow '%s'", name);
+		sm_warning("check for integer over/underflow '%s'", name);
 	else if (underflow)
-		sm_msg("warn: check for integer underflow '%s'", name);
+		sm_warning("check for integer underflow '%s'", name);
 	else
-		sm_msg("warn: check for integer overflow '%s'", name);
+		sm_warning("check for integer overflow '%s'", name);
 	free_string(name);
 
 	set_state_expr(my_max_id, expr, &capped);
diff --git a/check_held_dev.c b/check_held_dev.c
index bda095d..43f61d7 100644
--- a/check_held_dev.c
+++ b/check_held_dev.c
@@ -71,7 +71,7 @@ static void check_for_held(void)
 	stree = __get_cur_stree();
 	FOR_EACH_MY_SM(my_id, stree, tmp) {
 		if (slist_has_state(tmp->possible, &held)) {
-			sm_msg("warn: '%s' held on error path.",
+			sm_warning("'%s' held on error path.",
 				tmp->name);
 		}
 	} END_FOR_EACH_SM(tmp);
diff --git a/check_impossible_mask.c b/check_impossible_mask.c
index ba99870..b33e846 100644
--- a/check_impossible_mask.c
+++ b/check_impossible_mask.c
@@ -109,7 +109,7 @@ static void match_condition(struct expression *expr)
 		return;
 
 	str = expr_to_str(expr);
-	sm_msg("warn: masked condition '%s' is always %s.", str,
+	sm_warning("masked condition '%s' is always %s.", str,
 	       expr->op == SPECIAL_EQUAL ? "false" : "true");
 	free_string(str);
 }
diff --git a/check_indenting.c b/check_indenting.c
index 7fc2287..76a52f8 100644
--- a/check_indenting.c
+++ b/check_indenting.c
@@ -61,7 +61,7 @@ static int missing_curly_braces(struct statement *stmt)
 	if (stmt->pos.pos != inside_pos)
 		return 0;
 
-	sm_msg("warn: curly braces intended?");
+	sm_warning("curly braces intended?");
 	return 1;
 }
 
@@ -193,7 +193,7 @@ static void match_stmt(struct statement *stmt)
 		orig_pos = 0;
 		return;
 	}
-	sm_msg("warn: inconsistent indenting");
+	sm_warning("inconsistent indenting");
 	orig_pos = __prev_stmt->pos.pos;
 }
 
diff --git a/check_info_leak.c b/check_info_leak.c
index b5431b0..4059270 100644
--- a/check_info_leak.c
+++ b/check_info_leak.c
@@ -76,7 +76,7 @@ static void match_copy_to_user(const char *fn, struct expression *expr, void *un
 	if (!sm || !slist_has_state(sm->possible, &string))
 		return;
 	name = expr_to_var(src);
-	sm_msg("warn: possible info leak '%s'", name);
+	sm_warning("possible info leak '%s'", name);
 	free_string(name);
 }
 
diff --git a/check_kernel_printf.c b/check_kernel_printf.c
index ecc645e..997f89a 100644
--- a/check_kernel_printf.c
+++ b/check_kernel_printf.c
@@ -191,7 +191,7 @@ qualifier:
 				qualifier = 'H';
 				++fmt;
 			} else {
-				sm_msg("warn: invalid repeated qualifier '%c'", *fmt);
+				sm_warning("invalid repeated qualifier '%c'", *fmt);
 			}
 		}
 	}
@@ -201,14 +201,14 @@ qualifier:
 	switch (*fmt) {
 	case 'c':
 		if (qualifier)
-			sm_msg("warn: qualifier '%c' ignored for %%c specifier", qualifier);
+			sm_warning("qualifier '%c' ignored for %%c specifier", qualifier);
 
 		spec->type = FORMAT_TYPE_CHAR;
 		return ++fmt - start;
 
 	case 's':
 		if (qualifier)
-			sm_msg("warn: qualifier '%c' ignored for %%s specifier", qualifier);
+			sm_warning("qualifier '%c' ignored for %%s specifier", qualifier);
 
 		spec->type = FORMAT_TYPE_STR;
 		return ++fmt - start;
@@ -371,10 +371,10 @@ static void ip4(const char *fmt, struct symbol *type, struct symbol *basetype, i
 			endian = ENDIAN_BIG;
 			break;
 		default:
-			sm_msg("warn: '%%p%c4' can only be followed by one of [hnbl], not '%c'", fmt[0], fmt[2]);
+			sm_warning("'%%p%c4' can only be followed by one of [hnbl], not '%c'", fmt[0], fmt[2]);
 		}
 		if (isalnum(fmt[3]))
-			sm_msg("warn: '%%p%c4' can only be followed by precisely one of [hnbl]", fmt[0]);
+			sm_warning("'%%p%c4' can only be followed by precisely one of [hnbl]", fmt[0]);
 	}
 
 
@@ -395,7 +395,7 @@ static void ip4(const char *fmt, struct symbol *type, struct symbol *basetype, i
 		return;
 
 	if (is_struct_tag(basetype, "in_addr") && endian != ENDIAN_BIG)
-		sm_msg("warn: passing struct in_addr* to '%%p%c4%c', is the endianness ok?", fmt[0], fmt[2]);
+		sm_warning("passing struct in_addr* to '%%p%c4%c', is the endianness ok?", fmt[0], fmt[2]);
 
 	/* ... */
 }
@@ -407,11 +407,11 @@ static void ip6(const char *fmt, struct symbol *type, struct symbol *basetype, i
 
 	if (isalnum(fmt[2])) {
 		if (fmt[2] != 'c')
-			sm_msg("warn: '%%p%c6' can only be followed by c", fmt[0]);
+			sm_warning("'%%p%c6' can only be followed by c", fmt[0]);
 		else if (fmt[0] == 'i')
-			sm_msg("warn: '%%pi6' does not allow flag c");
+			sm_warning("'%%pi6' does not allow flag c");
 		if (isalnum(fmt[3]))
-			sm_msg("warn: '%%p%c6%c' cannot be followed by other alphanumerics", fmt[0], fmt[2]);
+			sm_warning("'%%p%c6%c' cannot be followed by other alphanumerics", fmt[0], fmt[2]);
 	}
 
 	if (type->ctype.modifiers & MOD_NODEREF)
@@ -428,7 +428,7 @@ static void ipS(const char *fmt, struct symbol *type, struct symbol *basetype, i
 	for (f = fmt+2; isalnum(*f); ++f) {
 		/* It's probably too anal checking for duplicate flags. */
 		if (!strchr("pfschnbl", *f))
-			sm_msg("warn: '%%p%cS' cannot be followed by '%c'", fmt[0], *f);
+			sm_warning("'%%p%cS' cannot be followed by '%c'", fmt[0], *f);
 	}
 
 	/*
@@ -452,9 +452,9 @@ static void hex_string(const char *fmt, struct symbol *type, struct symbol *base
 	assert(fmt[0] == 'h');
 	if (isalnum(fmt[1])) {
 		if (!strchr("CDN", fmt[1]))
-			sm_msg("warn: '%%ph' cannot be followed by '%c'", fmt[1]);
+			sm_warning("'%%ph' cannot be followed by '%c'", fmt[1]);
 		if (isalnum(fmt[2]))
-			sm_msg("warn: '%%ph' can be followed by at most one of [CDN], and no other alphanumerics");
+			sm_warning("'%%ph' can be followed by at most one of [CDN], and no other alphanumerics");
 	}
 	if (type->ctype.modifiers & MOD_NODEREF)
 		sm_msg("error: passing __user pointer to %%ph");
@@ -465,7 +465,7 @@ static void escaped_string(const char *fmt, struct symbol *type, struct symbol *
 	assert(fmt[0] == 'E');
 	while (isalnum(*++fmt)) {
 		if (!strchr("achnops", *fmt))
-			sm_msg("warn: %%pE can only be followed by a combination of [achnops]");
+			sm_warning("%%pE can only be followed by a combination of [achnops]");
 	}
 	if (type->ctype.modifiers & MOD_NODEREF)
 		sm_msg("error: passing __user pointer to %%pE");
@@ -479,7 +479,7 @@ static void resource_string(const char *fmt, struct symbol *type, struct symbol
 			"but argument %d has type '%s'", fmt[0], vaidx, type_to_str(type));
 	}
 	if (isalnum(fmt[1]))
-		sm_msg("warn: '%%p%c' cannot be followed by '%c'", fmt[0], fmt[1]);
+		sm_warning("'%%p%c' cannot be followed by '%c'", fmt[0], fmt[1]);
 }
 
 static void mac_address_string(const char *fmt, struct symbol *type, struct symbol *basetype, int vaidx)
@@ -487,15 +487,15 @@ static void mac_address_string(const char *fmt, struct symbol *type, struct symb
 	assert(tolower(fmt[0]) == 'm');
 	if (isalnum(fmt[1])) {
 		if (!(fmt[1] == 'F' || fmt[1] == 'R'))
-			sm_msg("warn: '%%p%c' cannot be followed by '%c'", fmt[0], fmt[1]);
+			sm_warning("'%%p%c' cannot be followed by '%c'", fmt[0], fmt[1]);
 		if (fmt[0] == 'm' && fmt[1] == 'F')
-			sm_msg("warn: it is pointless to pass flag F to %%pm");
+			sm_warning("it is pointless to pass flag F to %%pm");
 		if (isalnum(fmt[2]))
-			sm_msg("warn: '%%p%c%c' cannot be followed by other alphanumeric", fmt[0], fmt[1]);
+			sm_warning("'%%p%c%c' cannot be followed by other alphanumeric", fmt[0], fmt[1]);
 	}
 	/* Technically, bdaddr_t is a typedef for an anonymous struct, but this still seems to work. */
 	if (!is_char_type(basetype) && !is_struct_tag(basetype, "bdaddr_t") && basetype != &void_ctype) {
-		sm_msg("warn: '%%p%c' expects argument of type u8 * or bdaddr_t *, argument %d has type '%s'",
+		sm_warning("'%%p%c' expects argument of type u8 * or bdaddr_t *, argument %d has type '%s'",
 			fmt[0], vaidx, type_to_str(type));
 	}
 	if (type->ctype.modifiers & MOD_NODEREF)
@@ -511,9 +511,9 @@ static void dentry_file(const char *fmt, struct symbol *type, struct symbol *bas
 
 	if (isalnum(fmt[1])) {
 		if (!strchr("234", fmt[1]))
-			sm_msg("warn: '%%p%c' can only be followed by one of [234]", fmt[0]);
+			sm_warning("'%%p%c' can only be followed by one of [234]", fmt[0]);
 		if (isalnum(fmt[2]))
-			sm_msg("warn: '%%p%c%c' cannot be followed by '%c'", fmt[0], fmt[1], fmt[2]);
+			sm_warning("'%%p%c%c' cannot be followed by '%c'", fmt[0], fmt[1], fmt[2]);
 	}
 
 	if (!is_struct_tag(basetype, tag))
@@ -526,9 +526,9 @@ static void check_clock(const char *fmt, struct symbol *type, struct symbol *bas
 	assert(fmt[0] == 'C');
 	if (isalnum(fmt[1])) {
 		if (!strchr("nr", fmt[1]))
-			sm_msg("warn: '%%pC' can only be followed by one of [nr]");
+			sm_warning("'%%pC' can only be followed by one of [nr]");
 		if (isalnum(fmt[2]))
-			sm_msg("warn: '%%pC%c' cannot be followed by '%c'", fmt[1], fmt[2]);
+			sm_warning("'%%pC%c' cannot be followed by '%c'", fmt[1], fmt[2]);
 	}
 	if (!is_struct_tag(basetype, "clk"))
 		sm_msg("error: '%%pC' expects argument of type 'struct clk*', argument %d has type '%s'",
@@ -539,7 +539,7 @@ static void va_format(const char *fmt, struct symbol *type, struct symbol *baset
 {
 	assert(fmt[0] == 'V');
 	if (isalnum(fmt[1]))
-		sm_msg("warn: %%pV cannot be followed by any alphanumerics");
+		sm_warning("%%pV cannot be followed by any alphanumerics");
 	if (!is_struct_tag(basetype, "va_format"))
 		sm_msg("error: %%pV expects argument of type struct va_format*, argument %d has type '%s'", vaidx, type_to_str(type));
 }
@@ -554,7 +554,7 @@ static void netdev_feature(const char *fmt, struct symbol *type, struct symbol *
 		return;
 	}
 	if (isalnum(fmt[2]))
-		sm_msg("warn: %%pNF cannot be followed by '%c'", fmt[2]);
+		sm_warning("%%pNF cannot be followed by '%c'", fmt[2]);
 
 	typedef_lookup(&netdev);
 	if (!netdev.sym)
@@ -603,7 +603,7 @@ static void block_device(const char *fmt, struct symbol *type, struct symbol *ba
 
 	assert(fmt[0] == 'g');
 	if (isalnum(fmt[1])) {
-		sm_msg("warn: %%pg cannot be followed by '%c'", fmt[1]);
+		sm_warning("%%pg cannot be followed by '%c'", fmt[1]);
 	}
 	if (!is_struct_tag(basetype, tag))
 		sm_msg("error: '%%p%c' expects argument of type struct '%s*', argument %d has type '%s'",
@@ -655,7 +655,7 @@ pointer(const char *fmt, struct expression *arg, int vaidx)
 
 	type = get_type(arg);
 	if (!type) {
-		sm_msg("warn: could not determine type of argument %d", vaidx);
+		sm_warning("could not determine type of argument %d", vaidx);
 		return;
 	}
 	if (!is_ptr_type(type)) {
@@ -724,7 +724,7 @@ pointer(const char *fmt, struct expression *arg, int vaidx)
 			ipS(fmt, type, basetype, vaidx);
 			break;
 		default:
-			sm_msg("warn: '%%p%c' must be followed by one of [46S]", fmt[0]);
+			sm_warning("'%%p%c' must be followed by one of [46S]", fmt[0]);
 			break;
 		}
 		break;
@@ -800,11 +800,11 @@ hexbyte(const char *fmt, int fmt_len, struct expression *arg, int vaidx, struct
 
 	type = get_type(arg);
 	if (!type) {
-		sm_msg("warn: could not determine type of argument %d", vaidx);
+		sm_warning("could not determine type of argument %d", vaidx);
 		return;
 	}
 	if (type == &char_ctype || type == &schar_ctype)
-		sm_msg("warn: argument %d to %.*s specifier has type '%s'",
+		sm_warning("argument %d to %.*s specifier has type '%s'",
 		       vaidx, fmt_len, fmt, type_to_str(type));
 }
 
@@ -822,7 +822,7 @@ check_format_string(const char *fmt, const char *caller)
 			 * to pr_*, e.g. pr_warn(KERN_WARNING "something").
 			 */
 			if (f != fmt)
-				sm_msg("warn: KERN_* level not at start of string");
+				sm_warning("KERN_* level not at start of string");
 			/*
 			 * In a very few cases, the level is actually
 			 * computed and passed via %c, as in KERN_SOH
@@ -833,7 +833,7 @@ check_format_string(const char *fmt, const char *caller)
 			      f[1] == 'd' || /* KERN_DEFAULT */
 			      f[1] == 'c' || /* KERN_CONT */
 			      (f[1] == '%' && f[2] == 'c')))
-				sm_msg("warn: invalid KERN_* level: KERN_SOH_ASCII followed by '\\x%02x'", (unsigned char)f[1]);
+				sm_warning("invalid KERN_* level: KERN_SOH_ASCII followed by '\\x%02x'", (unsigned char)f[1]);
 			break;
 		case '\t':
 		case '\n':
@@ -841,14 +841,14 @@ check_format_string(const char *fmt, const char *caller)
 		case 0x20 ... 0x7e:
 			break;
 		case 0x80 ... 0xff:
-			sm_msg("warn: format string contains non-ascii character '\\x%02x'", c);
+			sm_warning("format string contains non-ascii character '\\x%02x'", c);
 			break;
 		case 0x08:
 			if (f == fmt)
 				break;
 			/* fall through */
 		default:
-			sm_msg("warn: format string contains unusual character '\\x%02x'", c);
+			sm_warning("format string contains unusual character '\\x%02x'", c);
 			break;
 		}
 	}
@@ -973,7 +973,7 @@ check_cast_from_pointer(const char *fmt, int len, struct expression *arg, int va
 	while (is_cast_expr(arg))
 		arg = arg->cast_expression;
 	if (is_ptr_type(get_final_type(arg)))
-		sm_msg("warn: argument %d to %.*s specifier is cast from pointer",
+		sm_warning("argument %d to %.*s specifier is cast from pointer",
 			va_idx, len, fmt);
 }
 
@@ -1047,10 +1047,10 @@ do_check_printf_call(const char *caller, const char *name, struct expression *ca
 		arg = get_argument_from_call_expr(callexpr->args, vaidx++);
 
 		if (spec.flags & SPECIAL && has_hex_prefix(orig_fmt, old_fmt))
-			sm_msg("warn: '%.2s' prefix is redundant when # flag is used", old_fmt-2);
+			sm_warning("'%.2s' prefix is redundant when # flag is used", old_fmt-2);
 		if (is_integer_specifier(spec.type)) {
 			if (spec.base != 16 && has_hex_prefix(orig_fmt, old_fmt))
-				sm_msg("warn: '%.2s' prefix is confusing together with '%.*s' specifier",
+				sm_warning("'%.2s' prefix is confusing together with '%.*s' specifier",
 				       old_fmt-2, (int)(fmt-old_fmt), old_fmt);
 
 			check_cast_from_pointer(old_fmt, read, arg, vaidx);
@@ -1098,7 +1098,7 @@ do_check_printf_call(const char *caller, const char *name, struct expression *ca
 					spam("warn: passing __func__ while the format string already contains the name of the function '%s'",
 					     caller);
 				else if (arg_contains_caller(arg, caller))
-					sm_msg("warn: passing string constant '%s' containing '%s' which is already part of the format string",
+					sm_warning("passing string constant '%s' containing '%s' which is already part of the format string",
 					       arg->string->data, caller);
 			}
 			break;
@@ -1134,7 +1134,7 @@ do_check_printf_call(const char *caller, const char *name, struct expression *ca
 	}
 
 	if (get_argument_from_call_expr(callexpr->args, vaidx))
-		sm_msg("warn: excess argument passed to '%s'", name);
+		sm_warning("excess argument passed to '%s'", name);
 
 
 }
diff --git a/check_kmalloc_to_bugon.c b/check_kmalloc_to_bugon.c
index 0e450c7..514a4ad 100644
--- a/check_kmalloc_to_bugon.c
+++ b/check_kmalloc_to_bugon.c
@@ -52,7 +52,7 @@ static void match_condition(struct expression *expr)
 		return;
 
 	name = expr_to_var(expr);
-	sm_msg("warn: bug on allocation failure '%s'", name);
+	sm_warning("bug on allocation failure '%s'", name);
 	free_string(name);
 }
 
diff --git a/check_kmalloc_wrong_size.c b/check_kmalloc_wrong_size.c
index f3979f9..41e1e0e 100644
--- a/check_kmalloc_wrong_size.c
+++ b/check_kmalloc_wrong_size.c
@@ -42,7 +42,7 @@ static void check_size_matches(int data_size, struct expression *size_expr)
 	if (!get_implied_value(size_expr, &sval))
 		return;
 	if (sval_cmp_val(sval, data_size) != 0)
-		sm_msg("warn: double check that we're allocating correct size: %d vs %s", data_size, sval_to_str(sval));
+		sm_warning("double check that we're allocating correct size: %d vs %s", data_size, sval_to_str(sval));
 }
 
 static void match_alloc(const char *fn, struct expression *expr, void *unused)
diff --git a/check_kunmap.c b/check_kunmap.c
index 68ceae4..c8ce632 100644
--- a/check_kunmap.c
+++ b/check_kunmap.c
@@ -36,7 +36,7 @@ static void check_assignment(void *data)
 	if (!fn)
 		return;
 	if (!strcmp(fn, "kmap"))
-		sm_msg("warn: passing the wrong variable to kunmap()");
+		sm_warning("passing the wrong variable to kunmap()");
 	free_string(fn);
 }
 
@@ -58,7 +58,7 @@ static void match_kunmap_atomic(const char *fn, struct expression *expr, void *d
 	if (!sm)
 		return;
 	if (slist_has_state(sm->possible, &no_unmap))
-		sm_msg("warn: passing the wrong variable to kmap_atomic()");
+		sm_warning("passing the wrong variable to kmap_atomic()");
 }
 
 static void match_kunmap(const char *fn, struct expression *expr, void *data)
diff --git a/check_leaks.c b/check_leaks.c
index d4f2f67..1c627a3 100644
--- a/check_leaks.c
+++ b/check_leaks.c
@@ -203,7 +203,7 @@ static void warn_if_allocated(struct expression *expr)
 		return;
 
 	name = expr_to_var(expr);
-	sm_msg("warn: overwrite may leak '%s'", name);
+	sm_warning("overwrite may leak '%s'", name);
 	free_string(name);
 
 	/* silence further warnings */
@@ -232,7 +232,7 @@ static void check_for_allocated(void)
 	FOR_EACH_MY_SM(my_id, stree, tmp) {
 		if (!slist_has_state(tmp->possible, &allocated))
 			continue;
-		sm_msg("warn: possible memory leak of '%s'", tmp->name);
+		sm_warning("possible memory leak of '%s'", tmp->name);
 	} END_FOR_EACH_SM(tmp);
 }
 
diff --git a/check_locking.c b/check_locking.c
index c307094..711bbc6 100644
--- a/check_locking.c
+++ b/check_locking.c
@@ -617,7 +617,7 @@ static int check_possible(struct sm_state *sm)
 			undef = 1;  // i don't think this is possible any more.
 	} END_FOR_EACH_PTR(tmp);
 	if ((islocked && isunlocked) || undef) {
-		sm_msg("warn: '%s' is sometimes locked here and sometimes unlocked.", sm->name);
+		sm_warning("'%s' is sometimes locked here and sometimes unlocked.", sm->name);
 		return 1;
 	}
 	return 0;
@@ -693,7 +693,7 @@ static void print_inconsistent_returns(struct tracker *lock,
 	struct range_list *printed = NULL;
 	int i;
 
-	sm_msg("warn: inconsistent returns '%s'.", lock->name);
+	sm_warning("inconsistent returns '%s'.", lock->name);
 	sm_printf("  Locked on:   ");
 
 	i = 0;
diff --git a/check_logical_instead_of_bitwise.c b/check_logical_instead_of_bitwise.c
index 6bb531d..3952208 100644
--- a/check_logical_instead_of_bitwise.c
+++ b/check_logical_instead_of_bitwise.c
@@ -49,7 +49,7 @@ static void match_logic(struct expression *expr)
 	if (sval.value == 0 || sval.value == 1)
 		return;
 
-	sm_msg("warn: should this be a bitwise op?");
+	sm_warning("should this be a bitwise op?");
 }
 
 static void match_assign(struct expression *expr)
@@ -60,7 +60,7 @@ static void match_assign(struct expression *expr)
 	if (right->type != EXPR_LOGICAL)
 		return;
 	if (is_bitshift(right->left) || is_bitshift(right->right))
-		sm_msg("warn: should this be a bitwise op?");
+		sm_warning("should this be a bitwise op?");
 }
 
 void check_logical_instead_of_bitwise(int id)
diff --git a/check_macro_side_effects.c b/check_macro_side_effects.c
index 3ee7114..29c92b0 100644
--- a/check_macro_side_effects.c
+++ b/check_macro_side_effects.c
@@ -118,7 +118,7 @@ static void match_unop(struct expression *raw_expr)
 		return;
 
 	name = expr_to_str(raw_expr);
-	sm_msg("warn: side effect in macro '%s' doing '%s'",
+	sm_warning("side effect in macro '%s' doing '%s'",
 		macro, name);
 	free_string(name);
 }
diff --git a/check_macros.c b/check_macros.c
index 288356b..8b7198e 100644
--- a/check_macros.c
+++ b/check_macros.c
@@ -33,7 +33,7 @@ static void match_inside(struct expression *expr, struct position pos)
 	name = get_macro_name(pos);
 	if (!name)
 		return;
-	sm_msg("warn: the '%s' macro might need parens", name);
+	sm_warning("the '%s' macro might need parens", name);
 }
 
 static void match_one_side(struct expression *expr, struct position pos, int op)
@@ -54,7 +54,7 @@ static void match_one_side(struct expression *expr, struct position pos, int op)
 		return;
 	if (option_project == PROJ_WINE && !strcmp("BEGIN", name))
 		return;
-	sm_msg("warn: the '%s' macro might need parens", name);
+	sm_warning("the '%s' macro might need parens", name);
 }
 
 static void match_join(struct expression *expr)
diff --git a/check_memory.c b/check_memory.c
index 614e377..776d97d 100644
--- a/check_memory.c
+++ b/check_memory.c
@@ -346,7 +346,7 @@ static void set_new_true_false_paths(const char *name, struct symbol *sym)
 	}
 
 	if (tmp == &isfree) {
-		sm_msg("warn: why do you care about freed memory? '%s'", name);
+		sm_warning("why do you care about freed memory? '%s'", name);
 	}
 
 	if (tmp == &assigned) {
diff --git a/check_min_t.c b/check_min_t.c
index 3e4ad13..9ec37f9 100644
--- a/check_min_t.c
+++ b/check_min_t.c
@@ -43,7 +43,7 @@ static void match_assign(struct expression *expr)
 		return;
 
 	name = expr_to_str(expr->right);
-	sm_msg("warn: min_t truncates here '%s' (%s vs %s)", name, sval_to_str(max_left), sval_to_str(max_right));
+	sm_warning("min_t truncates here '%s' (%s vs %s)", name, sval_to_str(max_left), sval_to_str(max_right));
 	free_string(name);
 }
 
diff --git a/check_missing_break.c b/check_missing_break.c
index 434b728..5e6f43a 100644
--- a/check_missing_break.c
+++ b/check_missing_break.c
@@ -73,7 +73,7 @@ static void print_missing_break(struct expression *expr)
 	last_print_expr = get_switch_expr();
 
 	name = expr_to_var(expr);
-	sm_msg("warn: missing break? reassigning '%s'", name);
+	sm_warning("missing break? reassigning '%s'", name);
 	free_string(name);
 }
 
diff --git a/check_mod_timer.c b/check_mod_timer.c
index 4d35f8b..6148520 100644
--- a/check_mod_timer.c
+++ b/check_mod_timer.c
@@ -28,7 +28,7 @@ static void match_mod_timer(const char *fn, struct expression *expr, void *param
 	arg = get_argument_from_call_expr(expr->args, 1);
 	if (!get_value(arg, &sval) || sval.value == 0)
 		return;
-	sm_msg("warn: mod_timer() takes an absolute time not an offset.");
+	sm_warning("mod_timer() takes an absolute time not an offset.");
 }
 
 void check_mod_timer(int id)
diff --git a/check_no_effect.c b/check_no_effect.c
index a159813..f7a7ddd 100644
--- a/check_no_effect.c
+++ b/check_no_effect.c
@@ -47,7 +47,7 @@ static void match_stmt(struct statement *stmt)
 	}
 	if (in_expression_statement())
 		return;
-	sm_msg("warn: statement has no effect %d", expr->type);
+	sm_warning("statement has no effect %d", expr->type);
 }
 
 void check_no_effect(int id)
diff --git a/check_no_if_block.c b/check_no_if_block.c
index b418b5d..d3095e9 100644
--- a/check_no_if_block.c
+++ b/check_no_if_block.c
@@ -31,7 +31,7 @@ static void match_if_stmt(struct statement *stmt)
 		return;
 	if (stmt->pos.pos != stmt->if_true->pos.pos)
 		return;
-	sm_msg("warn: if statement not indented");
+	sm_warning("if statement not indented");
 }
 
 static void match_for_stmt(struct statement *stmt)
@@ -46,7 +46,7 @@ static void match_for_stmt(struct statement *stmt)
 		return;
 	if (stmt->pos.pos != stmt->iterator_statement->pos.pos)
 		return;
-	sm_msg("warn: for statement not indented");
+	sm_warning("for statement not indented");
 }
 
 void check_no_if_block(int id)
diff --git a/check_off_by_one_relative.c b/check_off_by_one_relative.c
index e3de5c6..f6f6e6f 100644
--- a/check_off_by_one_relative.c
+++ b/check_off_by_one_relative.c
@@ -48,7 +48,7 @@ static void array_check(struct expression *expr)
 
 	array_str = expr_to_str(array);
 	offset_str = expr_to_str(offset);
-	sm_msg("warn: potentially one past the end of array '%s[%s]'", array_str, offset_str);
+	sm_warning("potentially one past the end of array '%s[%s]'", array_str, offset_str);
 	free_string(array_str);
 	free_string(offset_str);
 }
@@ -138,7 +138,7 @@ static void array_check_data_info(struct expression *expr)
 	if (equal_name) {
 		char *array_name = expr_to_str(array);
 
-		sm_msg("warn: potential off by one '%s[]' limit '%s'", array_name, equal_name);
+		sm_warning("potential off by one '%s[]' limit '%s'", array_name, equal_name);
 		free_string(array_name);
 	}
 
diff --git a/check_or_vs_and.c b/check_or_vs_and.c
index 03df76c..8d63c3d 100644
--- a/check_or_vs_and.c
+++ b/check_or_vs_and.c
@@ -75,7 +75,7 @@ static void check_or(struct expression *expr)
 	if (!inconsistent_check(left, right))
 		return;
 
-	sm_msg("warn: was && intended here instead of ||?");
+	sm_warning("was && intended here instead of ||?");
 }
 
 static int is_kernel_min_macro(struct expression *expr)
@@ -112,7 +112,7 @@ static void check_and(struct expression *expr)
 	if (!inconsistent_check(left, right))
 		return;
 
-	sm_msg("warn: was || intended here instead of &&?");
+	sm_warning("was || intended here instead of &&?");
 }
 
 static void match_logic(struct expression *expr)
@@ -146,7 +146,7 @@ static void match_condition(struct expression *expr)
 		return;
 	if (expr->op == '|') {
 		if (get_value(expr->left, &sval) || get_value(expr->right, &sval))
-			sm_msg("warn: suspicious bitop condition");
+			sm_warning("suspicious bitop condition");
 		return;
 	}
 
@@ -160,7 +160,7 @@ static void match_condition(struct expression *expr)
 
 	if ((get_value(expr->left, &sval) && sval.value == 0) ||
 	    (get_value(expr->right, &sval) && sval.value == 0))
-		sm_msg("warn: bitwise AND condition is false here");
+		sm_warning("bitwise AND condition is false here");
 }
 
 static void match_binop(struct expression *expr)
@@ -175,7 +175,7 @@ static void match_binop(struct expression *expr)
 		return;
 	if (!get_value(expr->left, &left) || !get_value(expr->right, &right))
 		return;
-	sm_msg("warn: odd binop '0x%llx & 0x%llx'", left.uvalue, right.uvalue);
+	sm_warning("odd binop '0x%llx & 0x%llx'", left.uvalue, right.uvalue);
 }
 
 void check_or_vs_and(int id)
diff --git a/check_platform_device_put.c b/check_platform_device_put.c
index 01a69b0..bf744eb 100644
--- a/check_platform_device_put.c
+++ b/check_platform_device_put.c
@@ -55,7 +55,7 @@ static void match_platform_device_del(const char *fn, struct expression *expr, v
 		return;
 	if (!slist_has_state(sm->possible, &not_added))
 		return;
-	sm_msg("warn: perhaps platform_device_put() was intended here?");
+	sm_warning("perhaps platform_device_put() was intended here?");
 }
 
 void check_platform_device_put(int id)
diff --git a/check_pointer_math.c b/check_pointer_math.c
index e9afb22..d0b9a0b 100644
--- a/check_pointer_math.c
+++ b/check_pointer_math.c
@@ -91,7 +91,7 @@ static void match_binop(struct expression *expr)
 	}
 
 	name = expr_to_str(expr->left);
-	sm_msg("warn: potential pointer math issue ('%s' is a %d bit pointer)",
+	sm_warning("potential pointer math issue ('%s' is a %d bit pointer)",
 	       name, type_bits(type));
 	free_string(name);
 }
@@ -122,7 +122,7 @@ static void check_assign(struct expression *expr)
 	if (!is_size_in_bytes(expr->right))
 		return;
 	name = expr_to_var(expr->left);
-	sm_msg("warn: potential pointer math issue ('%s' is a %d bit pointer)",
+	sm_warning("potential pointer math issue ('%s' is a %d bit pointer)",
 	       name, type_bits(type));
 	free_string(name);
 }
diff --git a/check_precedence.c b/check_precedence.c
index bacbfff..3ee0622 100644
--- a/check_precedence.c
+++ b/check_precedence.c
@@ -84,7 +84,7 @@ static void match_condition(struct expression *expr)
 	}
 
 	if (print) {
-		sm_msg("warn: add some parenthesis here?");
+		sm_warning("add some parenthesis here?");
 		return;
 	}
 
@@ -96,7 +96,7 @@ static void match_condition(struct expression *expr)
 		if (is_bool_op(expr->right))
 			i++;
 		if (i == 1)
-			sm_msg("warn: maybe use && instead of &");
+			sm_warning("maybe use && instead of &");
 	}
 }
 
@@ -105,7 +105,7 @@ static void match_binop(struct expression *expr)
 	if (expr->op != '&')
 		return;
 	if (expr->left->op == '!')
-		sm_msg("warn: add some parenthesis here?");
+		sm_warning("add some parenthesis here?");
 }
 
 static void match_mask(struct expression *expr)
@@ -117,7 +117,7 @@ static void match_mask(struct expression *expr)
 	if (expr->right->op != SPECIAL_RIGHTSHIFT)
 		return;
 
-	sm_msg("warn: shift has higher precedence than mask");
+	sm_warning("shift has higher precedence than mask");
 }
 
 static void match_subtract_shift(struct expression *expr)
@@ -128,7 +128,7 @@ static void match_subtract_shift(struct expression *expr)
 		return;
 	if (expr->right->op != '-')
 		return;
-	sm_msg("warn: subtract is higher precedence than shift");
+	sm_warning("subtract is higher precedence than shift");
 }
 
 void check_precedence(int id)
diff --git a/check_proc_create.c b/check_proc_create.c
index 92e64cf..025d217 100644
--- a/check_proc_create.c
+++ b/check_proc_create.c
@@ -43,7 +43,7 @@ static void match_create(const char *fn, struct expression *expr, void *_param_t
 		return;
 	arg_expr = get_argument_from_call_expr(expr->args, param_index[idx].name_param);
 	name = expr_to_var(arg_expr);
-	sm_msg("warn: proc file '%s' is world writable", name);
+	sm_warning("proc file '%s' is world writable", name);
 	free_string(name);
 }
 
diff --git a/check_readl_infinite_loops.c b/check_readl_infinite_loops.c
index 23e3440..8f3ca92 100644
--- a/check_readl_infinite_loops.c
+++ b/check_readl_infinite_loops.c
@@ -145,7 +145,7 @@ static void after_loop(struct statement *stmt)
 		return;
 	if (get_state(my_id, "depends on", NULL) != &readl_00)
 		return;
-	sm_msg("warn: this loop depends on readl() succeeding");
+	sm_warning("this loop depends on readl() succeeding");
 }
 
 void check_readl_infinite_loops(int id)
diff --git a/check_release_resource.c b/check_release_resource.c
index 1c7e2ab..b6f9d62 100644
--- a/check_release_resource.c
+++ b/check_release_resource.c
@@ -63,7 +63,7 @@ static void match_release(const char *fn, struct expression *expr, void *_arg_no
 		goto free;
 	if (in_tracker_list(resource_list, my_id, name, sym))
 		goto free;
-	sm_msg("warn: '%s' was not one of the resources you requested", name);
+	sm_warning("'%s' was not one of the resources you requested", name);
 free:
 	free_string(name);
 }
diff --git a/check_resource_size.c b/check_resource_size.c
index 3a32581..8bacb18 100644
--- a/check_resource_size.c
+++ b/check_resource_size.c
@@ -42,7 +42,7 @@ static void verify_size_expr(struct expression *expr)
 		return;
 	if (is_probably_ok(expr->right))
 		return;
-	sm_msg("warn: consider using resource_size() here");
+	sm_warning("consider using resource_size() here");
 }
 
 static void handle_assigned_expr(struct expression *expr)
diff --git a/check_return.c b/check_return.c
index a343d2f..3915fbe 100644
--- a/check_return.c
+++ b/check_return.c
@@ -26,7 +26,7 @@ static void must_check(const char *fn, struct expression *expr, void *data)
 
 	stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
 	if (stmt->type == STMT_EXPRESSION && stmt->expression == expr)
-		sm_msg("warn: unchecked '%s'", fn);
+		sm_warning("unchecked '%s'", fn);
 }
 
 static void register_must_check_funcs(void)
diff --git a/check_return_cast.c b/check_return_cast.c
index d6eca9e..5a87a6e 100644
--- a/check_return_cast.c
+++ b/check_return_cast.c
@@ -39,7 +39,7 @@ static void match_return(struct expression *ret_value)
 	if (sval_is_positive(sval) || sval_cmp_val(sval, -1) == 0)
 		return;
 
-	sm_msg("warn: signedness bug returning '%s'", sval_to_str(sval));
+	sm_warning("signedness bug returning '%s'", sval_to_str(sval));
 }
 
 void check_return_cast(int id)
diff --git a/check_return_efault.c b/check_return_efault.c
index 7f62467..20cb14e 100644
--- a/check_return_efault.c
+++ b/check_return_efault.c
@@ -76,7 +76,7 @@ static void match_return_var(struct expression *ret_value)
 		return;
 	if (min.value == 0)
 		return;
-	sm_msg("warn: maybe return -EFAULT instead of the bytes remaining?");
+	sm_warning("maybe return -EFAULT instead of the bytes remaining?");
 }
 
 static void match_return_call(struct expression *ret_value)
@@ -111,7 +111,7 @@ static void match_return_call(struct expression *ret_value)
 
 	if (!sval_is_negative(rl_min(rl)))
 		return;
-	sm_msg("warn: maybe return -EFAULT instead of the bytes remaining?");
+	sm_warning("maybe return -EFAULT instead of the bytes remaining?");
 }
 
 void check_return_efault(int id)
diff --git a/check_return_enomem.c b/check_return_enomem.c
index 9f8bb34..afd0f55 100644
--- a/check_return_enomem.c
+++ b/check_return_enomem.c
@@ -64,7 +64,7 @@ static void match_return(struct expression *ret_value)
 		    strcmp(expr->fn->symbol_name->name, "kzalloc") != 0)
 			continue;
 
-		sm_msg("warn: returning -1 instead of -ENOMEM is sloppy");
+		sm_warning("returning -1 instead of -ENOMEM is sloppy");
 		return;
 
 	} END_FOR_EACH_SM(sm);
diff --git a/check_return_negative_var.c b/check_return_negative_var.c
index 03db82e..9a18a43 100644
--- a/check_return_negative_var.c
+++ b/check_return_negative_var.c
@@ -33,7 +33,7 @@ static void match_return(struct expression *ret_value)
 
 	macro = get_macro_name(expr->unop->pos);
 	if (macro && !strcmp(macro, "PTR_ERR")) {
-		sm_msg("warn: returning -%s()", macro);
+		sm_warning("returning -%s()", macro);
 		return;
 	}
 
@@ -46,7 +46,7 @@ static void match_return(struct expression *ret_value)
 	if (expr->type != EXPR_CALL)
 		return;
 
-	sm_msg("warn: should this return really be negated?");
+	sm_warning("should this return really be negated?");
 }
 
 void check_return_negative_var(int id)
diff --git a/check_rosenberg.c b/check_rosenberg.c
index 67cf7fe..bde603a 100644
--- a/check_rosenberg.c
+++ b/check_rosenberg.c
@@ -48,10 +48,10 @@ static void print_holey_warning(struct expression *data, const char *member)
 
 	name = expr_to_str(data);
 	if (member) {
-		sm_msg("warn: check that '%s' doesn't leak information (struct has a hole after '%s')",
+		sm_warning("check that '%s' doesn't leak information (struct has a hole after '%s')",
 		       name, member);
 	} else {
-		sm_msg("warn: check that '%s' doesn't leak information (struct has holes)",
+		sm_warning("check that '%s' doesn't leak information (struct has holes)",
 		       name);
 	}
 	free_string(name);
@@ -198,7 +198,7 @@ static int member_uninitialized(char *name, struct symbol *outer, struct symbol
 	if (sm && !slist_has_state(sm->possible, &undefined))
 		return FALSE;
 
-	sm_msg("warn: check that '%s' doesn't leak information", buf);
+	sm_warning("check that '%s' doesn't leak information", buf);
 	return TRUE;
 }
 
diff --git a/check_select.c b/check_select.c
index a32a4e4..b9e3d1b 100644
--- a/check_select.c
+++ b/check_select.c
@@ -27,7 +27,7 @@ static void match_select(struct expression *expr)
 	expr = strip_expr(expr->conditional);
 	if (expr->type != EXPR_COMPARE)
 		return;
-	sm_msg("warn: boolean comparison inside select");
+	sm_warning("boolean comparison inside select");
 }
 
 void check_select(int id)
diff --git a/check_shift_to_zero.c b/check_shift_to_zero.c
index e8e7d90..57cc3cb 100644
--- a/check_shift_to_zero.c
+++ b/check_shift_to_zero.c
@@ -35,7 +35,7 @@ static void match_binop(struct expression *expr)
 		return;
 	if (type_bits(type) == -1 || type_bits(type) > bits.value)
 		return;
-	sm_msg("warn: right shifting more than type allows %d vs %lld", type_bits(type), bits.value);
+	sm_warning("right shifting more than type allows %d vs %lld", type_bits(type), bits.value);
 }
 
 static void match_binop2(struct expression *expr)
@@ -62,7 +62,7 @@ static void match_binop2(struct expression *expr)
 	if (mask.uvalue >> shift.uvalue)
 		return;
 
-	sm_msg("warn: mask and shift to zero");
+	sm_warning("mask and shift to zero");
 }
 
 static void match_assign(struct expression *expr)
@@ -80,7 +80,7 @@ static void match_assign(struct expression *expr)
 		return;
 	if (type_bits(type) > bits.value)
 		return;
-	sm_msg("warn: right shift assign to zero");
+	sm_warning("right shift assign to zero");
 }
 
 void check_shift_to_zero(int id)
diff --git a/check_signed.c b/check_signed.c
index 8525770..d8435e9 100644
--- a/check_signed.c
+++ b/check_signed.c
@@ -59,7 +59,7 @@ static void match_assign(struct expression *expr)
 	    !(sval.value < 256 && max.value == 127)) {
 		left_name = expr_to_str(expr->left);
 		right_name = expr_to_str(expr->right);
-		sm_msg("warn: '%s' %s can't fit into %s '%s'",
+		sm_warning("'%s' %s can't fit into %s '%s'",
 		       right_name, sval_to_numstr(sval), sval_to_numstr(max), left_name);
 		free_string(left_name);
 	}
@@ -75,10 +75,10 @@ static void match_assign(struct expression *expr)
 			return;
 		left_name = expr_to_str(expr->left);
 		if (min.value == 0) {
-			sm_msg("warn: assigning %s to unsigned variable '%s'",
+			sm_warning("assigning %s to unsigned variable '%s'",
 			       sval_to_str(sval), left_name);
 		} else {
-			sm_msg("warn: value %s can't fit into %s '%s'",
+			sm_warning("value %s can't fit into %s '%s'",
 			       sval_to_str(sval), sval_to_str(min), left_name);
 		}
 		free_string(left_name);
@@ -222,7 +222,7 @@ static int print_unsigned_never_less_than_zero(struct expression *expr)
 		return 0;
 
 	name = expr_to_str(expr->left);
-	sm_msg("warn: unsigned '%s' is never less than zero.", name);
+	sm_warning("unsigned '%s' is never less than zero.", name);
 	free_string(name);
 	return 1;
 }
@@ -286,7 +286,7 @@ static void match_condition(struct expression *expr)
 	if (!possibly_true_rl(rl_left, expr->op, rl_right)) {
 		char *name = expr_to_str(expr);
 
-		sm_msg("warn: impossible condition '(%s) => (%s %s %s)'", name,
+		sm_warning("impossible condition '(%s) => (%s %s %s)'", name,
 		       show_rl(rl_left), show_special(expr->op),
 		       show_rl(rl_right));
 		free_string(name);
@@ -295,7 +295,7 @@ static void match_condition(struct expression *expr)
 	if (!possibly_false_rl(rl_left, expr->op, rl_right)) {
 		char *name = expr_to_str(expr);
 
-		sm_msg("warn: always true condition '(%s) => (%s %s %s)'", name,
+		sm_warning("always true condition '(%s) => (%s %s %s)'", name,
 		       show_rl(rl_left_orig), show_special(expr->op),
 		       show_rl(rl_right_orig));
 		free_string(name);
diff --git a/check_signed_integer_overflow_check.c b/check_signed_integer_overflow_check.c
index e433487..aabd7ab 100644
--- a/check_signed_integer_overflow_check.c
+++ b/check_signed_integer_overflow_check.c
@@ -58,7 +58,7 @@ static void match_condition(struct expression *expr)
 	if (has_variable(left, right) == 1) {
 		left_name = expr_to_str(left);
 		right_name = expr_to_str(right);
-		sm_msg("warn: signed overflow undefined. '%s %s %s'", left_name, show_special(expr->op), right_name);
+		sm_warning("signed overflow undefined. '%s %s %s'", left_name, show_special(expr->op), right_name);
 		free_string(left_name);
 		free_string(right_name);
 	}
@@ -92,7 +92,7 @@ static void match_binop(struct expression *expr)
 		return;
 
 	str = expr_to_str(expr);
-	sm_msg("warn: potential negative subtraction from max '%s'", str);
+	sm_warning("potential negative subtraction from max '%s'", str);
 	free_string(str);
 }
 
diff --git a/check_sizeof.c b/check_sizeof.c
index 47885b1..6f4f3a6 100644
--- a/check_sizeof.c
+++ b/check_sizeof.c
@@ -35,7 +35,7 @@ static void check_pointer(struct expression *expr, char *ptr_name)
 		return;
 
 	if (strcmp(ptr_name, name) == 0)
-		sm_msg("warn: was 'sizeof(*%s)' intended?", ptr_name);
+		sm_warning("was 'sizeof(*%s)' intended?", ptr_name);
 	free_string(name);
 }
 
@@ -69,7 +69,7 @@ static void check_passes_pointer(char *name, struct expression *call)
 		if (!ptr_name)
 			continue;
 		if (strcmp(name, ptr_name) == 0)
-			sm_msg("warn: was 'sizeof(*%s)' intended?", name);
+			sm_warning("was 'sizeof(*%s)' intended?", name);
 		free_string(ptr_name);
 	} END_FOR_EACH_PTR(arg);
 }
@@ -107,19 +107,19 @@ static void check_sizeof_number(struct expression *expr)
 			return;
 	} END_FOR_EACH_PTR(tmp);
 
-	sm_msg("warn: sizeof(NUMBER)?");
+	sm_warning("sizeof(NUMBER)?");
 }
 
 static void match_sizeof(struct expression *expr)
 {
 	check_sizeof_number(expr);
 	if (expr->type == EXPR_PREOP && expr->op == '&')
-		sm_msg("warn: sizeof(&pointer)?");
+		sm_warning("sizeof(&pointer)?");
 	if (expr->type == EXPR_SIZEOF)
-		sm_msg("warn: sizeof(sizeof())?");
+		sm_warning("sizeof(sizeof())?");
 	/* the ilog2() macro is a valid place to check the size of a binop */
 	if (expr->type == EXPR_BINOP && !get_macro_name(expr->pos))
-		sm_msg("warn: taking sizeof binop");
+		sm_warning("taking sizeof binop");
 }
 
 static void register_macro_takes_sizeof_argument(void)
diff --git a/check_snprintf.c b/check_snprintf.c
index aea9f63..162e07c 100644
--- a/check_snprintf.c
+++ b/check_snprintf.c
@@ -66,7 +66,7 @@ static void match_call(struct expression *expr)
 		if (!old_buflen)
 			return;
 		if (get_absolute_max(arg, &max) && sval_cmp_val(max, old_buflen) > 0)
-			sm_msg("warn: '%s' returned from snprintf() might be larger than %d",
+			sm_warning("'%s' returned from snprintf() might be larger than %d",
 				sm->name, old_buflen);
 	} END_FOR_EACH_PTR(arg);
 }
diff --git a/check_spectre.c b/check_spectre.c
index 112a806..bb43c88 100644
--- a/check_spectre.c
+++ b/check_spectre.c
@@ -188,7 +188,7 @@ static void array_check(struct expression *expr)
 	conditions = get_conditions(offset);
 
 	name = expr_to_str(array_expr);
-	sm_msg("warn: potential spectre issue '%s' [%s]%s",
+	sm_warning("potential spectre issue '%s' [%s]%s",
 	       name,
 	       is_read(expr) ? "r" : "w",
 	       conditions ? " (local cap)" : "");
diff --git a/check_stack.c b/check_stack.c
index aede8b8..b91586f 100644
--- a/check_stack.c
+++ b/check_stack.c
@@ -54,7 +54,7 @@ static void match_declarations(struct symbol *sym)
 	}
 	if (type_bytes(base) >= MAX_ALLOWED) {
 		complained = 1;
-		sm_msg("warn: '%s' puts %d bytes on stack", name, type_bytes(base));
+		sm_warning("'%s' puts %d bytes on stack", name, type_bytes(base));
 	}
 	add_scope_hook(&scope_end, INT_PTR(type_bytes(base))); 
 }
diff --git a/check_strcpy_overflow.c b/check_strcpy_overflow.c
index 218f08b..cc7784b 100644
--- a/check_strcpy_overflow.c
+++ b/check_strcpy_overflow.c
@@ -49,7 +49,7 @@ static void match_strcpy(const char *fn, struct expression *expr, void *unused)
 		sm_msg("error: %s() '%s' too large for '%s' (%d vs %d)",
 			fn, data_name, dest_name, data_size, dest_size);
 	else if (option_spammy)
-		sm_msg("warn: %s() '%s' of unknown size might be too large for '%s'",
+		sm_warning("%s() '%s' of unknown size might be too large for '%s'",
 			fn, data_name, dest_name);
 
 	free_string(dest_name);
diff --git a/check_struct_type.c b/check_struct_type.c
index 0a46010..bbe74da 100644
--- a/check_struct_type.c
+++ b/check_struct_type.c
@@ -48,7 +48,7 @@ static void match_assign(const char *fn, struct expression *expr, void *_size_ar
 		return;
 	if (strcmp(left_type->ident->name, size_type->ident->name) == 0)
 		return;
-	sm_msg("warn: struct type mismatch '%s vs %s'", left_type->ident->name,
+	sm_warning("struct type mismatch '%s vs %s'", left_type->ident->name,
 	       size_type->ident->name);
 
 }
diff --git a/check_template.c b/check_template.c
index 626d414..6e8b6aa 100644
--- a/check_template.c
+++ b/check_template.c
@@ -94,7 +94,7 @@ static void match_return(struct expression *ret_value)
 	stree = __get_cur_stree();
 	FOR_EACH_MY_SM(my_id, stree, tmp) {
 		if (tmp->state != &unlock)
-			sm_msg("warn: returned negative with %s semaphore held",
+			sm_warning("returned negative with %s semaphore held",
 				   tmp->name);
 	} END_FOR_EACH_SM(tmp);
 }
diff --git a/check_test_bit.c b/check_test_bit.c
index 2ee1143..579228c 100644
--- a/check_test_bit.c
+++ b/check_test_bit.c
@@ -35,7 +35,7 @@ static void match_test_bit(const char *fn, struct expression *expr, void *data)
 	macro = get_macro_name(arg->pos);
 	if (macro && strstr(macro, "cpu_has"))
 		return;
-	sm_msg("warn: test_bit() takes a bit number");
+	sm_warning("test_bit() takes a bit number");
 }
 
 void check_test_bit(int id)
diff --git a/check_uninitialized.c b/check_uninitialized.c
index 7d55320..9cf28f3 100644
--- a/check_uninitialized.c
+++ b/check_uninitialized.c
@@ -167,7 +167,7 @@ static void match_call(struct expression *expr)
 			continue;
 
 		name = expr_to_str(arg);
-		sm_warning("warn: passing uninitialized '%s'", name);
+		sm_warning("passing uninitialized '%s'", name);
 		free_string(name);
 
 		set_state_expr(my_id, arg, &initialized);
diff --git a/check_unwind.c b/check_unwind.c
index 31c8235..9fa6d0c 100644
--- a/check_unwind.c
+++ b/check_unwind.c
@@ -149,7 +149,7 @@ static void match_return(struct expression *ret_value)
 	stree = __get_cur_stree();
 	FOR_EACH_MY_SM(my_id, stree, tmp) {
 		if (slist_has_state(tmp->possible, &allocated))
-			sm_msg("warn: '%s' was not released on error", tmp->name);
+			sm_warning("'%s' was not released on error", tmp->name);
 	} END_FOR_EACH_SM(tmp);
 }
 
diff --git a/check_wine_WtoA.c b/check_wine_WtoA.c
index 9648cd3..f074471 100644
--- a/check_wine_WtoA.c
+++ b/check_wine_WtoA.c
@@ -73,7 +73,7 @@ static void match_call(struct expression *expr)
 		goto free;
 	len = strlen(fn_name);
 	if (fn_name[len - 1] == 'A' && !allowed_func(fn_name)) {
-		sm_msg("warn: WtoA call '%s()'", fn_name);
+		sm_warning("WtoA call '%s()'", fn_name);
 	}
 free:
 	free_string(fn_name);
diff --git a/check_wrong_size_arg.c b/check_wrong_size_arg.c
index 2a8b8d5..06753d2 100644
--- a/check_wrong_size_arg.c
+++ b/check_wrong_size_arg.c
@@ -33,7 +33,7 @@ static void match_parameter(const char *fn, struct expression *expr, void *_para
 		return;
 
 	name = expr_to_str_sym(arg, NULL);
-	sm_msg("warn: expected a buffer size but got a comparison '%s'", name);
+	sm_warning("expected a buffer size but got a comparison '%s'", name);
 	free_string(name);
 }
 
diff --git a/check_zero_to_err_ptr.c b/check_zero_to_err_ptr.c
index 29196b7..8d5984a 100644
--- a/check_zero_to_err_ptr.c
+++ b/check_zero_to_err_ptr.c
@@ -111,14 +111,14 @@ static void match_err_ptr(const char *fn, struct expression *expr, void *data)
 			continue;
 		if (is_valid_ptr(estate_min(tmp->state)) &&
 		    is_valid_ptr(estate_max(tmp->state))) {
-			sm_msg("warn: passing a valid pointer to '%s'", fn);
+			sm_warning("passing a valid pointer to '%s'", fn);
 			return;
 		}
 		if (!rl_to_sval(estate_rl(tmp->state), &sval))
 			continue;
 		if (sval.value != 0)
 			continue;
-		sm_msg("warn: passing zero to '%s'", fn);
+		sm_warning("passing zero to '%s'", fn);
 		return;
 	} END_FOR_EACH_PTR(tmp);
 }
diff --git a/smatch_buf_comparison.c b/smatch_buf_comparison.c
index 7ef6bd8..d142817 100644
--- a/smatch_buf_comparison.c
+++ b/smatch_buf_comparison.c
@@ -239,7 +239,7 @@ static void array_check(struct expression *expr)
 
 	array_str = expr_to_str(array);
 	offset_str = expr_to_str(offset);
-	sm_msg("warn: potentially one past the end of array '%s[%s]'", array_str, offset_str);
+	sm_warning("potentially one past the end of array '%s[%s]'", array_str, offset_str);
 	free_string(array_str);
 	free_string(offset_str);
 }
@@ -402,7 +402,7 @@ static void array_check_data_info(struct expression *expr)
 	if (equal_name) {
 		char *array_name = expr_to_str(array);
 
-		sm_msg("warn: potential off by one '%s[]' limit '%s'", array_name, equal_name);
+		sm_warning("potential off by one '%s[]' limit '%s'", array_name, equal_name);
 		free_string(array_name);
 	}
 
diff --git a/smatch_flow.c b/smatch_flow.c
index 31503d5..ca36eaa 100644
--- a/smatch_flow.c
+++ b/smatch_flow.c
@@ -1123,7 +1123,7 @@ void __split_stmt(struct statement *stmt)
 		if (empty_statement(stmt->if_true) &&
 			last_stmt_on_same_line() &&
 			!get_macro_name(stmt->if_true->pos))
-			sm_msg("warn: if();");
+			sm_warning("if();");
 		__push_true_states();
 		__use_false_states();
 		__split_stmt(stmt->if_false);
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 08/12] Convert sm_msg() with an error: prefix into sm_error()
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
                   ` (5 preceding siblings ...)
  2018-11-27 10:53 ` [PATCH 07/12] Convert all sm_msg("warn:.." into sm_warning() John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 09/12] Convert some sm_msg() into more specific reporting routines John Levon
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Signed-off-by: John Levon <levon@movementarian.org>
---
 check_allocating_enough_data.c  |  2 +-
 check_atomic_inc_dec.c          |  4 +--
 check_bogus_irqrestore.c        |  2 +-
 check_check_deref.c             |  4 +--
 check_debug.c                   | 12 ++++-----
 check_deref.c                   | 12 ++++-----
 check_dev_queue_xmit.c          |  2 +-
 check_dma_on_stack.c            |  4 +--
 check_err_ptr_deref.c           | 10 ++++----
 check_free.c                    |  6 ++---
 check_free_strict.c             |  6 ++---
 check_gfp_dma.c                 |  2 +-
 check_index_overflow.c          |  6 ++---
 check_input_free_device.c       |  2 +-
 check_kernel_printf.c           | 56 ++++++++++++++++++++---------------------
 check_locking.c                 |  6 ++---
 check_memcpy_overflow.c         |  2 +-
 check_memory.c                  |  4 +--
 check_memset.c                  |  2 +-
 check_snprintf_overflow.c       |  4 +--
 check_sprintf_overflow.c        |  2 +-
 check_strcpy_overflow.c         |  2 +-
 check_string_len.c              |  2 +-
 check_testing_index_after_use.c |  2 +-
 check_type.c                    |  4 +--
 check_wait_for_common.c         |  2 +-
 check_wine_filehandles.c        |  2 +-
 27 files changed, 82 insertions(+), 82 deletions(-)

diff --git a/check_allocating_enough_data.c b/check_allocating_enough_data.c
index 5b55ed5..12cb72b 100644
--- a/check_allocating_enough_data.c
+++ b/check_allocating_enough_data.c
@@ -42,7 +42,7 @@ static void db_returns_buf_size(struct expression *expr, int param, char *unused
 		return;
 	if (sval.uvalue >= bytes)
 		return;
-	sm_msg("error: not allocating enough data %d vs %s", bytes, sval_to_str(sval));
+	sm_error("not allocating enough data %d vs %s", bytes, sval_to_str(sval));
 }
 
 void check_allocating_enough_data(int id)
diff --git a/check_atomic_inc_dec.c b/check_atomic_inc_dec.c
index a7c5ae7..6474323 100644
--- a/check_atomic_inc_dec.c
+++ b/check_atomic_inc_dec.c
@@ -49,11 +49,11 @@ static void db_inc_dec(struct expression *expr, int param, const char *key, cons
 
 	if (inc_dec == ATOMIC_INC) {
 //		if (start_state == &inc)
-//			sm_msg("error: XXX double increment '%s'", name);
+//			sm_error("XXX double increment '%s'", name);
 		set_state(my_id, name, sym, &inc);
 	} else {
 //		if (start_state == &dec)
-//			sm_msg("error: XXX double decrement '%s'", name);
+//			sm_error("XXX double decrement '%s'", name);
 		if (start_state == &inc)
 			set_state(my_id, name, sym, &orig);
 		else
diff --git a/check_bogus_irqrestore.c b/check_bogus_irqrestore.c
index 7b19037..c47077a 100644
--- a/check_bogus_irqrestore.c
+++ b/check_bogus_irqrestore.c
@@ -27,7 +27,7 @@ static void match_irqrestore(const char *fn, struct expression *expr, void *data
 	arg_expr = get_argument_from_call_expr(expr->args, 1);
 	if (!get_implied_value(arg_expr, &tmp))
 		return;
-	sm_msg("error: calling '%s()' with bogus flags", fn);
+	sm_error("calling '%s()' with bogus flags", fn);
 }
 
 void check_bogus_irqrestore(int id)
diff --git a/check_check_deref.c b/check_check_deref.c
index 725eca9..da2a5c9 100644
--- a/check_check_deref.c
+++ b/check_check_deref.c
@@ -69,7 +69,7 @@ static void check_dereference(struct expression *expr)
 		if (tmp->state == &ok)
 			continue;
 		if (tmp->state == &null) {
-			sm_msg("error: we previously assumed '%s' could be null (see line %d)",
+			sm_error("we previously assumed '%s' could be null (see line %d)",
 			       tmp->name, tmp->line);
 			add_ignore(my_id, sm->name, sm->sym);
 			return;
@@ -96,7 +96,7 @@ static void check_dereference_name_sym(char *name, struct symbol *sym)
 		if (tmp->state == &ok)
 			continue;
 		if (tmp->state == &null) {
-			sm_msg("error: we previously assumed '%s' could be null (see line %d)",
+			sm_error("we previously assumed '%s' could be null (see line %d)",
 			       tmp->name, tmp->line);
 			add_ignore(my_id, sm->name, sm->sym);
 			return;
diff --git a/check_debug.c b/check_debug.c
index 079faf6..d55865e 100644
--- a/check_debug.c
+++ b/check_debug.c
@@ -45,12 +45,12 @@ static void match_state(const char *fn, struct expression *expr, void *info)
 
 	check_arg = get_argument_from_call_expr(expr->args, 0);
 	if (check_arg->type != EXPR_STRING) {
-		sm_msg("error:  the check_name argument to %s is supposed to be a string literal", fn);
+		sm_error("the check_name argument to %s is supposed to be a string literal", fn);
 		return;
 	}
 	state_arg = get_argument_from_call_expr(expr->args, 1);
 	if (!state_arg || state_arg->type != EXPR_STRING) {
-		sm_msg("error:  the state_name argument to %s is supposed to be a string literal", fn);
+		sm_error("the state_name argument to %s is supposed to be a string literal", fn);
 		return;
 	}
 
@@ -75,7 +75,7 @@ static void match_states(const char *fn, struct expression *expr, void *info)
 
 	check_arg = get_argument_from_call_expr(expr->args, 0);
 	if (check_arg->type != EXPR_STRING) {
-		sm_msg("error:  the check_name argument to %s is supposed to be a string literal", fn);
+		sm_error("the check_name argument to %s is supposed to be a string literal", fn);
 		return;
 	}
 
@@ -103,7 +103,7 @@ static void match_print_value(const char *fn, struct expression *expr, void *inf
 
 	arg_expr = get_argument_from_call_expr(expr->args, 0);
 	if (arg_expr->type != EXPR_STRING) {
-		sm_msg("error:  the argument to %s is supposed to be a string literal", fn);
+		sm_error("the argument to %s is supposed to be a string literal", fn);
 		return;
 	}
 
@@ -352,7 +352,7 @@ static void match_possible(const char *fn, struct expression *expr, void *info)
 
 	arg_expr = get_argument_from_call_expr(expr->args, 0);
 	if (arg_expr->type != EXPR_STRING) {
-		sm_msg("error:  the argument to %s is supposed to be a string literal", fn);
+		sm_error("the argument to %s is supposed to be a string literal", fn);
 		return;
 	}
 
@@ -415,7 +415,7 @@ static void match_note(const char *fn, struct expression *expr, void *info)
 
 	arg_expr = get_argument_from_call_expr(expr->args, 0);
 	if (arg_expr->type != EXPR_STRING) {
-		sm_msg("error:  the argument to %s is supposed to be a string literal", fn);
+		sm_error("the argument to %s is supposed to be a string literal", fn);
 		return;
 	}
 	sm_msg("%s", arg_expr->string->data);
diff --git a/check_deref.c b/check_deref.c
index 59561d9..d8777db 100644
--- a/check_deref.c
+++ b/check_deref.c
@@ -87,15 +87,15 @@ static void check_dereference(struct expression *expr)
 		add_ignore(my_id, sm->name, sm->sym);
 		if (tmp->state == &null) {
 			if (option_spammy)
-				sm_msg("error: potential NULL dereference '%s'.", tmp->name);
+				sm_error("potential NULL dereference '%s'.", tmp->name);
 			return;
 		}
 		if (tmp->state == &uninitialized) {
 			if (option_spammy)
-				sm_msg("error: potentially dereferencing uninitialized '%s'.", tmp->name);
+				sm_error("potentially dereferencing uninitialized '%s'.", tmp->name);
 			return;
 		}
-		sm_msg("error: potential null dereference '%s'.  (%s returns null)",
+		sm_error("potential null dereference '%s'.  (%s returns null)",
 			tmp->name, tmp->state->name);
 		return;
 	} END_FOR_EACH_PTR(tmp);
@@ -124,15 +124,15 @@ static void check_dereference_name_sym(char *name, struct symbol *sym)
 		add_ignore(my_id, sm->name, sm->sym);
 		if (tmp->state == &null) {
 			if (option_spammy)
-				sm_msg("error: potential NULL dereference '%s'.", tmp->name);
+				sm_error("potential NULL dereference '%s'.", tmp->name);
 			return;
 		}
 		if (tmp->state == &uninitialized) {
 			if (option_spammy)
-				sm_msg("error: potentially dereferencing uninitialized '%s'.", tmp->name);
+				sm_error("potentially dereferencing uninitialized '%s'.", tmp->name);
 			return;
 		}
-		sm_msg("error: potential null dereference '%s'.  (%s returns null)",
+		sm_error("potential null dereference '%s'.  (%s returns null)",
 			tmp->name, tmp->state->name);
 		return;
 	} END_FOR_EACH_PTR(tmp);
diff --git a/check_dev_queue_xmit.c b/check_dev_queue_xmit.c
index 5a9c13d..c794e65 100644
--- a/check_dev_queue_xmit.c
+++ b/check_dev_queue_xmit.c
@@ -68,7 +68,7 @@ static void match_symbol(struct expression *expr)
 	if (valid_use())
 		return;
 	name = expr_to_var(expr);
-	sm_msg("error: '%s' was already used up by dev_queue_xmit()", name);
+	sm_error("'%s' was already used up by dev_queue_xmit()", name);
 	free_string(name);
 }
 
diff --git a/check_dma_on_stack.c b/check_dma_on_stack.c
index b6ac482..ffa9ae9 100644
--- a/check_dma_on_stack.c
+++ b/check_dma_on_stack.c
@@ -33,7 +33,7 @@ static void match_dma_func(const char *fn, struct expression *expr, void *param)
 		if (arg->unop->type != EXPR_SYMBOL)
 			return;
 		name = expr_to_str(arg);
-		sm_msg("error: doing dma on the stack (%s)", name);
+		sm_error("doing dma on the stack (%s)", name);
 		free_string(name);
 		return;
 	}
@@ -45,7 +45,7 @@ static void match_dma_func(const char *fn, struct expression *expr, void *param)
 	if (get_param_num(arg) >= 0)
 		return;
 	name = expr_to_var(arg);
-	sm_msg("error: doing dma on the stack (%s)", name);
+	sm_error("doing dma on the stack (%s)", name);
 	free_string(name);
 }
 
diff --git a/check_err_ptr_deref.c b/check_err_ptr_deref.c
index e01fb75..50a79cd 100644
--- a/check_err_ptr_deref.c
+++ b/check_err_ptr_deref.c
@@ -58,7 +58,7 @@ static void check_is_err_ptr(struct expression *expr)
 	if (!possibly_true_rl(rl, SPECIAL_EQUAL, err_ptr_rl))
 		return;
 
-	sm_msg("error: '%s' dereferencing possible ERR_PTR()", sm->name);
+	sm_error("'%s' dereferencing possible ERR_PTR()", sm->name);
 	set_state(my_id, sm->name, sm->sym, &checked);
 }
 
@@ -90,7 +90,7 @@ static void set_param_dereferenced(struct expression *call, struct expression *a
 	if (!estate || !possibly_true_rl(estate_rl(estate), SPECIAL_EQUAL, err_ptr_rl))
 		goto free;
 
-	sm_msg("error: '%s' dereferencing possible ERR_PTR()", sm->name);
+	sm_error("'%s' dereferencing possible ERR_PTR()", sm->name);
 	set_state(my_id, sm->name, sm->sym, &checked);
 
 free:
@@ -180,7 +180,7 @@ static void match_err_ptr_positive_const(const char *fn, struct expression *expr
 	if (!get_value(arg, &sval))
 		return;
 	if (sval_is_positive(sval) && sval_cmp_val(sval, 0) != 0)
-		sm_msg("error: passing non negative %s to ERR_PTR", sval_to_str(sval));
+		sm_error("passing non negative %s to ERR_PTR", sval_to_str(sval));
 }
 
 static void match_err_ptr(const char *fn, struct expression *expr, void *unused)
@@ -206,9 +206,9 @@ static void match_err_ptr(const char *fn, struct expression *expr, void *unused)
 			max = tmp_max;
 	} END_FOR_EACH_PTR(tmp);
 	if (sval_is_negative(min) && sval_cmp_val(min, -4095) < 0)
-		sm_msg("error: %s too low for ERR_PTR", sval_to_str(min));
+		sm_error("%s too low for ERR_PTR", sval_to_str(min));
 	if (sval_is_positive(max) && sval_cmp_val(max, 0) != 0)
-		sm_msg("error: passing non negative %s to ERR_PTR", sval_to_str(max));
+		sm_error("passing non negative %s to ERR_PTR", sval_to_str(max));
 }
 
 void check_err_ptr_deref(int id)
diff --git a/check_free.c b/check_free.c
index 9e9d835..44df17e 100644
--- a/check_free.c
+++ b/check_free.c
@@ -92,7 +92,7 @@ static void match_dereferences(struct expression *expr)
 	if (!is_freed(expr))
 		return;
 	name = expr_to_var(expr);
-	sm_msg("error: dereferencing freed memory '%s'", name);
+	sm_error("dereferencing freed memory '%s'", name);
 	set_state_expr(my_id, expr, &ok);
 	free_string(name);
 }
@@ -176,7 +176,7 @@ static void match_call(struct expression *expr)
 
 		name = expr_to_var(arg);
 		if (is_free_func(expr->fn))
-			sm_msg("error: double free of '%s'", name);
+			sm_error("double free of '%s'", name);
 		else
 			sm_warning("passing freed memory '%s'", name);
 		set_state_expr(my_id, arg, &ok);
@@ -217,7 +217,7 @@ static void match_free(const char *fn, struct expression *expr, void *param)
 	if (is_freed(arg)) {
 		char *name = expr_to_var(arg);
 
-		sm_msg("error: double free of '%s'", name);
+		sm_error("double free of '%s'", name);
 		free_string(name);
 	}
 	set_state_expr(my_id, arg, &freed);
diff --git a/check_free_strict.c b/check_free_strict.c
index bf75021..ae23938 100644
--- a/check_free_strict.c
+++ b/check_free_strict.c
@@ -89,7 +89,7 @@ static void match_dereferences(struct expression *expr)
 	if (!is_freed(expr))
 		return;
 	name = expr_to_var(expr);
-	sm_msg("error: dereferencing freed memory '%s'", name);
+	sm_error("dereferencing freed memory '%s'", name);
 	set_state_expr(my_id, expr, &ok);
 	free_string(name);
 }
@@ -173,7 +173,7 @@ static void match_call(struct expression *expr)
 
 		name = expr_to_var(arg);
 		if (is_free_func(expr->fn))
-			sm_msg("error: double free of '%s'", name);
+			sm_error("double free of '%s'", name);
 		else
 			sm_warning("passing freed memory '%s'", name);
 		set_state_expr(my_id, arg, &ok);
@@ -212,7 +212,7 @@ static void match_free(const char *fn, struct expression *expr, void *param)
 	if (is_freed(arg)) {
 		char *name = expr_to_var(arg);
 
-		sm_msg("error: double free of '%s'", name);
+		sm_error("double free of '%s'", name);
 		free_string(name);
 	}
 	set_state_expr(my_id, arg, &freed);
diff --git a/check_gfp_dma.c b/check_gfp_dma.c
index 755ed85..aeeb7b3 100644
--- a/check_gfp_dma.c
+++ b/check_gfp_dma.c
@@ -38,7 +38,7 @@ static void match_alloc(const char *fn, struct expression *expr, void *_arg)
 	if (sval.uvalue == 0) /* GFP_NOWAIT */
 		return;
 	if (!(sval.uvalue & ~GFP_ZONEMASK))
-		sm_msg("error: no modifiers for allocation.");
+		sm_error("no modifiers for allocation.");
 }
 
 void check_gfp_dma(int id)
diff --git a/check_index_overflow.c b/check_index_overflow.c
index 4e2be88..39815e6 100644
--- a/check_index_overflow.c
+++ b/check_index_overflow.c
@@ -315,14 +315,14 @@ static void array_check(struct expression *expr)
 		return;
 
 	if (no_break) {
-		sm_msg("error: buffer overflow '%s' %d <= %s (assuming for loop doesn't break)",
+		sm_error("buffer overflow '%s' %d <= %s (assuming for loop doesn't break)",
 			name, array_size, sval_to_str(max));
 	} else if (user_rl) {
-		sm_msg("error: buffer overflow '%s' %d <= %s user_rl='%s'%s",
+		sm_error("buffer overflow '%s' %d <= %s user_rl='%s'%s",
 			name, array_size, sval_to_str(max), show_rl(user_rl),
 			is_subtract(offset) ? " subtract" : "");
 	} else {
-		sm_msg("error: buffer overflow '%s' %d <= %s%s",
+		sm_error("buffer overflow '%s' %d <= %s%s",
 			name, array_size, sval_to_str(max),
 			is_subtract(offset) ? " subtract" : "");
 	}
diff --git a/check_input_free_device.c b/check_input_free_device.c
index e863958..b450670 100644
--- a/check_input_free_device.c
+++ b/check_input_free_device.c
@@ -55,7 +55,7 @@ static void match_input_free(const char *fn, struct expression *expr, void *data
 		return;
 	if (!slist_has_state(sm->possible, &no_free))
 		return;
-	sm_msg("error: don't call input_free_device() after input_unregister_device()");
+	sm_error("don't call input_free_device() after input_unregister_device()");
 }
 
 void check_input_free_device(int id)
diff --git a/check_kernel_printf.c b/check_kernel_printf.c
index 997f89a..38ae02b 100644
--- a/check_kernel_printf.c
+++ b/check_kernel_printf.c
@@ -379,7 +379,7 @@ static void ip4(const char *fmt, struct symbol *type, struct symbol *basetype, i
 
 
 	if (type->ctype.modifiers & MOD_NODEREF)
-		sm_msg("error: passing __user pointer to '%%p%c4'", fmt[0]);
+		sm_error("passing __user pointer to '%%p%c4'", fmt[0]);
 
 	/*
 	 * If we have a pointer to char/u8/s8, we expect the caller to
@@ -415,7 +415,7 @@ static void ip6(const char *fmt, struct symbol *type, struct symbol *basetype, i
 	}
 
 	if (type->ctype.modifiers & MOD_NODEREF)
-		sm_msg("error: passing __user pointer to '%%p%c6'", fmt[0]);
+		sm_error("passing __user pointer to '%%p%c6'", fmt[0]);
 }
 
 static void ipS(const char *fmt, struct symbol *type, struct symbol *basetype, int vaidx)
@@ -443,7 +443,7 @@ static void ipS(const char *fmt, struct symbol *type, struct symbol *basetype, i
 	    !has_struct_tag(basetype, "sockaddr_in") &&
 	    !has_struct_tag(basetype, "sockaddr_in6") &&
 	    !has_struct_tag(basetype, "__kernel_sockaddr_storage"))
-		sm_msg("error: '%%p%cS' expects argument of type struct sockaddr *, "
+		sm_error("'%%p%cS' expects argument of type struct sockaddr *, "
 			"argument %d has type '%s'", fmt[0], vaidx, type_to_str(type));
 }
 
@@ -457,7 +457,7 @@ static void hex_string(const char *fmt, struct symbol *type, struct symbol *base
 			sm_warning("'%%ph' can be followed by at most one of [CDN], and no other alphanumerics");
 	}
 	if (type->ctype.modifiers & MOD_NODEREF)
-		sm_msg("error: passing __user pointer to %%ph");
+		sm_error("passing __user pointer to %%ph");
 }
 
 static void escaped_string(const char *fmt, struct symbol *type, struct symbol *basetype, int vaidx)
@@ -468,14 +468,14 @@ static void escaped_string(const char *fmt, struct symbol *type, struct symbol *
 			sm_warning("%%pE can only be followed by a combination of [achnops]");
 	}
 	if (type->ctype.modifiers & MOD_NODEREF)
-		sm_msg("error: passing __user pointer to %%pE");
+		sm_error("passing __user pointer to %%pE");
 }
 
 static void resource_string(const char *fmt, struct symbol *type, struct symbol *basetype, int vaidx)
 {
 	assert(tolower(fmt[0]) == 'r');
 	if (!is_struct_tag(basetype, "resource")) {
-		sm_msg("error: '%%p%c' expects argument of type struct resource *, "
+		sm_error("'%%p%c' expects argument of type struct resource *, "
 			"but argument %d has type '%s'", fmt[0], vaidx, type_to_str(type));
 	}
 	if (isalnum(fmt[1]))
@@ -499,7 +499,7 @@ static void mac_address_string(const char *fmt, struct symbol *type, struct symb
 			fmt[0], vaidx, type_to_str(type));
 	}
 	if (type->ctype.modifiers & MOD_NODEREF)
-		sm_msg("error: passing __user pointer to '%%p%c'", fmt[0]);
+		sm_error("passing __user pointer to '%%p%c'", fmt[0]);
 }
 
 static void dentry_file(const char *fmt, struct symbol *type, struct symbol *basetype, int vaidx)
@@ -517,7 +517,7 @@ static void dentry_file(const char *fmt, struct symbol *type, struct symbol *bas
 	}
 
 	if (!is_struct_tag(basetype, tag))
-		sm_msg("error: '%%p%c' expects argument of type struct '%s*', argument %d has type '%s'",
+		sm_error("'%%p%c' expects argument of type struct '%s*', argument %d has type '%s'",
 			fmt[0], tag, vaidx, type_to_str(type));
 }
 
@@ -531,7 +531,7 @@ static void check_clock(const char *fmt, struct symbol *type, struct symbol *bas
 			sm_warning("'%%pC%c' cannot be followed by '%c'", fmt[1], fmt[2]);
 	}
 	if (!is_struct_tag(basetype, "clk"))
-		sm_msg("error: '%%pC' expects argument of type 'struct clk*', argument %d has type '%s'",
+		sm_error("'%%pC' expects argument of type 'struct clk*', argument %d has type '%s'",
 		       vaidx, type_to_str(type));
 }
 
@@ -541,7 +541,7 @@ static void va_format(const char *fmt, struct symbol *type, struct symbol *baset
 	if (isalnum(fmt[1]))
 		sm_warning("%%pV cannot be followed by any alphanumerics");
 	if (!is_struct_tag(basetype, "va_format"))
-		sm_msg("error: %%pV expects argument of type struct va_format*, argument %d has type '%s'", vaidx, type_to_str(type));
+		sm_error("%%pV expects argument of type struct va_format*, argument %d has type '%s'", vaidx, type_to_str(type));
 }
 
 static void netdev_feature(const char *fmt, struct symbol *type, struct symbol *basetype, int vaidx)
@@ -550,7 +550,7 @@ static void netdev_feature(const char *fmt, struct symbol *type, struct symbol *
 
 	assert(fmt[0] == 'N');
 	if (fmt[1] != 'F') {
-		sm_msg("error: %%pN must be followed by 'F'");
+		sm_error("%%pN must be followed by 'F'");
 		return;
 	}
 	if (isalnum(fmt[2]))
@@ -560,7 +560,7 @@ static void netdev_feature(const char *fmt, struct symbol *type, struct symbol *
 	if (!netdev.sym)
 		return;
 	if (basetype != netdev.sym)
-		sm_msg("error: %%pNF expects argument of type netdev_features_t*, argument %d has type '%s'",
+		sm_error("%%pNF expects argument of type netdev_features_t*, argument %d has type '%s'",
 			vaidx, type_to_str(type));
 
 }
@@ -582,17 +582,17 @@ static void address_val(const char *fmt, struct symbol *type, struct symbol *bas
 			suf = "p";
 			break;
 		default:
-			sm_msg("error: '%%pa' can only be followed by one of [dp]");
+			sm_error("'%%pa' can only be followed by one of [dp]");
 		}
 		if (isalnum(fmt[2]))
-			sm_msg("error: '%%pa%c' cannot be followed by '%c'", fmt[1], fmt[2]);
+			sm_error("'%%pa%c' cannot be followed by '%c'", fmt[1], fmt[2]);
 	}
 
 	typedef_lookup(which);
 	if (!which->sym)
 		return;
 	if (basetype != which->sym) {
-		sm_msg("error: '%%pa%s' expects argument of type '%s*', argument %d has type '%s'",
+		sm_error("'%%pa%s' expects argument of type '%s*', argument %d has type '%s'",
 			suf, which->name, vaidx, type_to_str(type));
 	}
 }
@@ -606,7 +606,7 @@ static void block_device(const char *fmt, struct symbol *type, struct symbol *ba
 		sm_warning("%%pg cannot be followed by '%c'", fmt[1]);
 	}
 	if (!is_struct_tag(basetype, tag))
-		sm_msg("error: '%%p%c' expects argument of type struct '%s*', argument %d has type '%s'",
+		sm_error("'%%p%c' expects argument of type struct '%s*', argument %d has type '%s'",
 			fmt[0], tag, vaidx, type_to_str(type));
 }
 
@@ -616,35 +616,35 @@ static void flag_string(const char *fmt, struct symbol *type, struct symbol *bas
 
 	assert(fmt[0] == 'G');
 	if (!isalnum(fmt[1])) {
-		sm_msg("error: %%pG must be followed by one of [gpv]");
+		sm_error("%%pG must be followed by one of [gpv]");
 		return;
 	}
 	switch (fmt[1]) {
 	case 'p':
 	case 'v':
 		if (basetype != &ulong_ctype)
-			sm_msg("error: '%%pG%c' expects argument of type 'unsigned long *', argument %d has type '%s'",
+			sm_error("'%%pG%c' expects argument of type 'unsigned long *', argument %d has type '%s'",
 				fmt[1], vaidx, type_to_str(type));
 		break;
 	case 'g':
 		typedef_lookup(&gfp);
 		if (basetype != gfp.sym)
-			sm_msg("error: '%%pGg' expects argument of type 'gfp_t *', argument %d has type '%s'",
+			sm_error("'%%pGg' expects argument of type 'gfp_t *', argument %d has type '%s'",
 				vaidx, type_to_str(type));
 		break;
 	default:
-		sm_msg("error: '%%pG' must be followed by one of [gpv]");
+		sm_error("'%%pG' must be followed by one of [gpv]");
 	}
 }
 
 static void device_node_string(const char *fmt, struct symbol *type, struct symbol *basetype, int vaidx)
 {
 	if (fmt[1] != 'F') {
-		sm_msg("error: %%pO can only be followed by 'F'");
+		sm_error("%%pO can only be followed by 'F'");
 		return;
 	}
 	if (!is_struct_tag(basetype, "device_node"))
-		sm_msg("error: '%%pOF' expects argument of type 'struct device_node*', argument %d has type '%s'",
+		sm_error("'%%pOF' expects argument of type 'struct device_node*', argument %d has type '%s'",
 		       vaidx, type_to_str(type));
 }
 
@@ -659,7 +659,7 @@ pointer(const char *fmt, struct expression *arg, int vaidx)
 		return;
 	}
 	if (!is_ptr_type(type)) {
-		sm_msg("error: %%p expects pointer argument, but argument %d has type '%s'",
+		sm_error("%%p expects pointer argument, but argument %d has type '%s'",
 			vaidx, type_to_str(type));
 		return;
 	}
@@ -772,7 +772,7 @@ pointer(const char *fmt, struct expression *arg, int vaidx)
 		/* 'x' is for an unhashed pointer */
 		break;
 	default:
-		sm_msg("error: unrecognized %%p extension '%c', treated as normal %%p", *fmt);
+		sm_error("unrecognized %%p extension '%c', treated as normal %%p", *fmt);
 	}
 }
 
@@ -1062,15 +1062,15 @@ do_check_printf_call(const char *caller, const char *name, struct expression *ca
 		/* 	break; */
 
 		case FORMAT_TYPE_INVALID:
-			sm_msg("error: format specifier '%.*s' invalid", read, old_fmt);
+			sm_error("format specifier '%.*s' invalid", read, old_fmt);
 			return;
 
 		case FORMAT_TYPE_FLOAT:
-			sm_msg("error: no floats in the kernel; invalid format specifier '%.*s'", read, old_fmt);
+			sm_error("no floats in the kernel; invalid format specifier '%.*s'", read, old_fmt);
 			return;
 
 		case FORMAT_TYPE_NRCHARS:
-			sm_msg("error: %%n not supported in kernel");
+			sm_error("%%n not supported in kernel");
 			return;
 
 		case FORMAT_TYPE_WIDTH:
@@ -1177,7 +1177,7 @@ check_printf_call(const char *name, struct expression *callexpr, void *_info)
 	/* Lack of format argument is a bug. */
 	fmtexpr = get_argument_from_call_expr(callexpr->args, fmtidx);
 	if (!fmtexpr) {
-		sm_msg("error: call of '%s' with no format argument", name);
+		sm_error("call of '%s' with no format argument", name);
 		return;
 	}
 
diff --git a/check_locking.c b/check_locking.c
index 711bbc6..06cc7a5 100644
--- a/check_locking.c
+++ b/check_locking.c
@@ -459,7 +459,7 @@ static void do_lock(const char *name)
 		add_tracker(&starts_unlocked, my_id, name, NULL);
 	if (sm && slist_has_state(sm->possible, &locked) &&
 			strcmp(name, "bottom_half:") != 0)
-		sm_msg("error: double lock '%s'", name);
+		sm_error("double lock '%s'", name);
 	if (sm)
 		func_has_transition = TRUE;
 	set_state(my_id, name, NULL, &locked);
@@ -491,7 +491,7 @@ static void do_unlock(const char *name)
 		add_tracker(&starts_locked, my_id, name, NULL);
 	if (sm && slist_has_state(sm->possible, &unlocked) &&
 			strcmp(name, "bottom_half:") != 0)
-		sm_msg("error: double unlock '%s'", name);
+		sm_error("double unlock '%s'", name);
 	if (sm)
 		func_has_transition = TRUE;
 	set_state(my_id, name, NULL, &unlocked);
@@ -852,7 +852,7 @@ static void check_consistency(struct symbol *sym)
 	FOR_EACH_PTR(starts_locked, tmp) {
 		if (in_tracker_list(starts_unlocked, tmp->owner, tmp->name,
 					tmp->sym))
-			sm_msg("error:  locking inconsistency.  We assume "
+			sm_error("locking inconsistency.  We assume "
 				   "'%s' is both locked and unlocked at the "
 				   "start.",
 				tmp->name);
diff --git a/check_memcpy_overflow.c b/check_memcpy_overflow.c
index 578c70f..dddc555 100644
--- a/check_memcpy_overflow.c
+++ b/check_memcpy_overflow.c
@@ -271,7 +271,7 @@ static void match_limited(const char *fn, struct expression *expr, void *_limite
 		return;
 
 	dest_name = expr_to_str(dest);
-	sm_msg("error: %s() '%s' too small (%d vs %s)", fn, dest_name, has, sval_to_str(needed));
+	sm_error("%s() '%s' too small (%d vs %s)", fn, dest_name, has, sval_to_str(needed));
 	free_string(dest_name);
 }
 
diff --git a/check_memory.c b/check_memory.c
index 776d97d..4e27497 100644
--- a/check_memory.c
+++ b/check_memory.c
@@ -201,7 +201,7 @@ static void match_assign(struct expression *expr)
 
 	if (right_name && (state = get_state(my_id, right_name, right_sym))) {
 		if (state == &isfree && !is_complex(right))
-			sm_msg("error: assigning freed pointer '%s'", right_name);
+			sm_error("assigning freed pointer '%s'", right_name);
 		set_state(my_id, right_name, right_sym, &assigned);
 	}
 
@@ -275,7 +275,7 @@ static void check_sm_is_leaked(struct sm_state *sm)
 		!is_null(sm->name, sm->sym) &&
 		!is_argument(sm->sym) && 
 		!parent_is_assigned(sm->sym))
-		sm_msg("error: memory leak of '%s'", sm->name);
+		sm_error("memory leak of '%s'", sm->name);
 }
 
 static void check_tracker_is_leaked(struct tracker *t)
diff --git a/check_memset.c b/check_memset.c
index 75413b8..0213693 100644
--- a/check_memset.c
+++ b/check_memset.c
@@ -32,7 +32,7 @@ static void match_memset(const char *fn, struct expression *expr, void *data)
 		return;
 	if (sval.value != 0)
 		return;
-	sm_msg("error: calling memset(x, y, 0);");
+	sm_error("calling memset(x, y, 0);");
 }
 
 void check_memset(int id)
diff --git a/check_snprintf_overflow.c b/check_snprintf_overflow.c
index 710c7fd..c7adba5 100644
--- a/check_snprintf_overflow.c
+++ b/check_snprintf_overflow.c
@@ -38,7 +38,7 @@ static void match_snprintf(const char *fn, struct expression *expr, void *unused
 	if (!get_implied_value(dest_size_expr, &limit_size))
 		return;
 	if (dest_size && dest_size < limit_size.value)
-		sm_msg("error: snprintf() is printing too much %s vs %d",
+		sm_error("snprintf() is printing too much %s vs %d",
 		       sval_to_str(limit_size), dest_size);
 	format = expr_to_var(format_string);
 	if (!format)
@@ -50,7 +50,7 @@ static void match_snprintf(const char *fn, struct expression *expr, void *unused
 	if (!data_size)
 		data_size = get_array_size_bytes(data);
 	if (limit_size.value < data_size)
-		sm_msg("error: snprintf() chops off the last chars of '%s': %d vs %s",
+		sm_error("snprintf() chops off the last chars of '%s': %d vs %s",
 		       data_name, data_size, sval_to_str(limit_size));
 free:
 	free_string(data_name);
diff --git a/check_sprintf_overflow.c b/check_sprintf_overflow.c
index 5330319..46d9794 100644
--- a/check_sprintf_overflow.c
+++ b/check_sprintf_overflow.c
@@ -44,7 +44,7 @@ static void match_sprintf(const char *fn, struct expression *expr, void *unused)
 	if (!data_size)
 		data_size = get_array_size_bytes(data);
 	if (dest_size < data_size)
-		sm_msg("error: sprintf() copies too much data from '%s': %d vs %d",
+		sm_error("sprintf() copies too much data from '%s': %d vs %d",
 		       data_name, data_size, dest_size);
 free:
 	free_string(data_name);
diff --git a/check_strcpy_overflow.c b/check_strcpy_overflow.c
index cc7784b..00731f9 100644
--- a/check_strcpy_overflow.c
+++ b/check_strcpy_overflow.c
@@ -46,7 +46,7 @@ static void match_strcpy(const char *fn, struct expression *expr, void *unused)
 	data_name = expr_to_str(data);
 
 	if (data_size)
-		sm_msg("error: %s() '%s' too large for '%s' (%d vs %d)",
+		sm_error("%s() '%s' too large for '%s' (%d vs %d)",
 			fn, data_name, dest_name, data_size, dest_size);
 	else if (option_spammy)
 		sm_warning("%s() '%s' of unknown size might be too large for '%s'",
diff --git a/check_string_len.c b/check_string_len.c
index 6a1bcd1..3d6fd7f 100644
--- a/check_string_len.c
+++ b/check_string_len.c
@@ -239,7 +239,7 @@ static void match_not_limited(const char *fn, struct expression *call, void *inf
 			user = 1;
 	} END_FOR_EACH_PTR(arg);
 
-	sm_msg("error: format string overflow. buf_size: %d length: %d%s",
+	sm_error("format string overflow. buf_size: %d length: %d%s",
 	       buf_size, size, user ? " [user data]": "");
 }
 
diff --git a/check_testing_index_after_use.c b/check_testing_index_after_use.c
index 453eb36..18b0fcf 100644
--- a/check_testing_index_after_use.c
+++ b/check_testing_index_after_use.c
@@ -112,7 +112,7 @@ static void match_condition(struct expression *expr)
 			char *name;
 
 			name = expr_to_var(left ? expr->right : expr->left);
-			sm_msg("error: testing array offset '%s' after use.", name);
+			sm_error("testing array offset '%s' after use.", name);
 			return;
 		}
 	} END_FOR_EACH_PTR(tmp);
diff --git a/check_type.c b/check_type.c
index 31f5eed..ac0f5b8 100644
--- a/check_type.c
+++ b/check_type.c
@@ -44,13 +44,13 @@ static void match_free(const char *fn, struct expression *expr, void *data)
 	name = expr_to_str(arg_expr);
 
 	if (!strcmp("sk_buff", type->ident->name)) {
-		sm_msg("error: use kfree_skb() here instead of kfree(%s)", name);
+		sm_error("use kfree_skb() here instead of kfree(%s)", name);
 	} else if (!strcmp("net_device", type->ident->name)) {
 		if (in_function("alloc_netdev"))
 			return;
 		if (in_function("alloc_netdev_mqs"))
 			return;
-		sm_msg("error: use free_netdev() here instead of kfree(%s)", name);
+		sm_error("use free_netdev() here instead of kfree(%s)", name);
 	}
 
 	free_string(name);
diff --git a/check_wait_for_common.c b/check_wait_for_common.c
index bd909c6..8efb457 100644
--- a/check_wait_for_common.c
+++ b/check_wait_for_common.c
@@ -26,7 +26,7 @@ static void match_wait_for_common(const char *fn, struct expression *expr, void
 	if (!expr_unsigned(expr->left))
 		return;
 	name = expr_to_str(expr->left);
-	sm_msg("error: '%s()' returns negative and '%s' is unsigned", fn, name);
+	sm_error("'%s()' returns negative and '%s' is unsigned", fn, name);
 	free_string(name);
 }
 
diff --git a/check_wine_filehandles.c b/check_wine_filehandles.c
index 6f1f92b..c4bf8a7 100644
--- a/check_wine_filehandles.c
+++ b/check_wine_filehandles.c
@@ -73,7 +73,7 @@ static void match_condition(struct expression *expr)
 		char *name;
 
 		name = expr_to_var(expr);
-		sm_msg("error: comparing a filehandle against zero '%s'", name);
+		sm_error("comparing a filehandle against zero '%s'", name);
 		set_state_expr(my_id, expr, &oktocheck);
 		free_string(name);
 	}
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 09/12] Convert some sm_msg() into more specific reporting routines.
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
                   ` (6 preceding siblings ...)
  2018-11-27 10:53 ` [PATCH 08/12] Convert sm_msg() with an error: prefix into sm_error() John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 10/12] Track sparse-level warnings and errors too, and respect them in smatch's exit code John Levon
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Signed-off-by: John Levon <levon@movementarian.org>
---
 check_kernel_printf.c | 2 +-
 smatch_slist.c        | 2 +-
 smatch_sval.c         | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/check_kernel_printf.c b/check_kernel_printf.c
index 38ae02b..c85dac1 100644
--- a/check_kernel_printf.c
+++ b/check_kernel_printf.c
@@ -855,7 +855,7 @@ check_format_string(const char *fmt, const char *caller)
 
 	f = strstr(fmt, caller);
 	if (f && strstr(f+1, caller))
-		sm_msg("note: format string contains name of enclosing function '%s' twice", caller);
+		sm_warning("format string contains name of enclosing function '%s' twice", caller);
 
 	return f != NULL;
 }
diff --git a/smatch_slist.c b/smatch_slist.c
index 0a993e9..43d9acd 100644
--- a/smatch_slist.c
+++ b/smatch_slist.c
@@ -379,7 +379,7 @@ struct sm_state *merge_sm_states(struct sm_state *one, struct sm_state *two)
 		return one;
 	if (out_of_memory()) {
 		if (!warned)
-			sm_msg("Function too hairy.  No more merges.");
+			sm_warning("Function too hairy.  No more merges.");
 		warned = 1;
 		return one;
 	}
diff --git a/smatch_sval.c b/smatch_sval.c
index 725509a..307224e 100644
--- a/smatch_sval.c
+++ b/smatch_sval.c
@@ -380,10 +380,10 @@ static sval_t sval_binop_signed(struct symbol *type, sval_t left, int op, sval_t
 		break;
 	case '/':
 		if (right.value == 0) {
-			sm_msg("debug: %s: divide by zero", __func__);
+			sm_debug("%s: divide by zero", __func__);
 			ret.value = 123456789;
 		} else if (left.value == LLONG_MIN && right.value == -1) {
-			sm_msg("debug: %s: invalid divide LLONG_MIN/-1", __func__);
+			sm_debug("%s: invalid divide LLONG_MIN/-1", __func__);
 			ret.value = 12345678;
 		} else {
 			ret.value = left.value / right.value;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 10/12] Track sparse-level warnings and errors too, and respect them in smatch's exit code.
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
                   ` (7 preceding siblings ...)
  2018-11-27 10:53 ` [PATCH 09/12] Convert some sm_msg() into more specific reporting routines John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 11/12] Add illumos projects John Levon
  2018-11-27 10:53 ` [PATCH 12/12] Add check_all_func_returns John Levon
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Signed-off-by: John Levon <levon@movementarian.org>
---
 lib.c    | 11 +++++++----
 lib.h    |  2 ++
 smatch.c |  2 +-
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/lib.c b/lib.c
index 0f3a05a..985178f 100644
--- a/lib.c
+++ b/lib.c
@@ -45,6 +45,9 @@
 #include "target.h"
 #include "version.h"
 
+int sparse_errors = 0;
+int sparse_warnings = 0;
+
 int verbose, optimize, optimize_size, preprocessing;
 int die_if_error = 0;
 int parse_error;
@@ -131,14 +134,12 @@ void info(struct position pos, const char * fmt, ...)
 
 static void do_error(struct position pos, const char * fmt, va_list args)
 {
-	static int errors = 0;
-
 	parse_error = 1;
         die_if_error = 1;
 	show_info = 1;
 	/* Shut up warnings after an error */
 	has_error |= ERROR_CURR_PHASE;
-	if (errors > 100) {
+	if (sparse_errors > 100) {
 		static int once = 0;
 		show_info = 0;
 		if (once)
@@ -148,7 +149,7 @@ static void do_error(struct position pos, const char * fmt, va_list args)
 	}
 
 	do_warn("error: ", pos, fmt, args);
-	errors++;
+	sparse_errors++;
 }	
 
 void warning(struct position pos, const char * fmt, ...)
@@ -167,6 +168,8 @@ void warning(struct position pos, const char * fmt, ...)
 		return;
 	}
 
+	sparse_warnings++;
+
 	if (!--max_warnings) {
 		show_info = 0;
 		fmt = "too many warnings";
diff --git a/lib.h b/lib.h
index d5693ed..8509dbb 100644
--- a/lib.h
+++ b/lib.h
@@ -45,6 +45,8 @@ extern int die_if_error;
 extern int parse_error;
 extern int repeat_phase, merge_phi_sources;
 extern int gcc_major, gcc_minor, gcc_patchlevel;
+extern int sparse_warnings;
+extern int sparse_errors;
 
 extern unsigned int hexval(unsigned int c);
 
diff --git a/smatch.c b/smatch.c
index 8ec103d..7a96e0f 100644
--- a/smatch.c
+++ b/smatch.c
@@ -337,7 +337,7 @@ int main(int argc, char **argv)
 	smatch(argc, argv);
 	free_string(data_dir);
 
-	if (sm_nr_errors > 0)
+	if (sm_nr_errors > 0 || sparse_errors > 0)
 		return 1;
 	if (sm_nr_checks > 0 && option_fatal_checks)
 		return 1;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 11/12] Add illumos projects
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
                   ` (8 preceding siblings ...)
  2018-11-27 10:53 ` [PATCH 10/12] Track sparse-level warnings and errors too, and respect them in smatch's exit code John Levon
@ 2018-11-27 10:53 ` John Levon
  2018-11-27 10:53 ` [PATCH 12/12] Add check_all_func_returns John Levon
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Signed-off-by: John Levon <levon@movementarian.org>
---
 smatch.c | 7 ++++++-
 smatch.h | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/smatch.c b/smatch.c
index 7a96e0f..5ec0056 100644
--- a/smatch.c
+++ b/smatch.c
@@ -234,10 +234,15 @@ void parse_args(int *argcp, char ***argvp)
 
 	if (strcmp(option_project_str, "smatch_generic") != 0)
 		option_project = PROJ_UNKNOWN;
+
 	if (strcmp(option_project_str, "kernel") == 0)
 		option_project = PROJ_KERNEL;
-	if (strcmp(option_project_str, "wine") == 0)
+	else if (strcmp(option_project_str, "wine") == 0)
 		option_project = PROJ_WINE;
+	else if (strcmp(option_project_str, "illumos_kernel") == 0)
+		option_project = PROJ_ILLUMOS_KERNEL;
+	else if (strcmp(option_project_str, "illumos_user") == 0)
+		option_project = PROJ_ILLUMOS_USER;
 }
 
 static char *read_bin_filename(void)
diff --git a/smatch.h b/smatch.h
index 737ca48..cc981bb 100644
--- a/smatch.h
+++ b/smatch.h
@@ -981,6 +981,8 @@ enum project_type {
 	PROJ_NONE,
 	PROJ_KERNEL,
 	PROJ_WINE,
+	PROJ_ILLUMOS_KERNEL,
+	PROJ_ILLUMOS_USER,
 	PROJ_UNKNOWN,
 };
 extern enum project_type option_project;
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 12/12] Add check_all_func_returns
  2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
                   ` (9 preceding siblings ...)
  2018-11-27 10:53 ` [PATCH 11/12] Add illumos projects John Levon
@ 2018-11-27 10:53 ` John Levon
  10 siblings, 0 replies; 12+ messages in thread
From: John Levon @ 2018-11-27 10:53 UTC (permalink / raw)
  To: smatch; +Cc: John Levon

Add a new check type that looks for unchecked returns on *all* functions,
mimicking the old behaviour of lint. A cast to (void) silences the warning.

Signed-off-by: John Levon <levon@movementarian.org>
---
 check_all_func_returns.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
 check_list.h             |  3 +++
 2 files changed, 69 insertions(+)
 create mode 100644 check_all_func_returns.c

diff --git a/check_all_func_returns.c b/check_all_func_returns.c
new file mode 100644
index 0000000..f4ba58d
--- /dev/null
+++ b/check_all_func_returns.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 Joyent, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
+ */
+
+/*
+ * Like lint of old, check that every return value from every function is used.
+ * Casting to (void) will silence this check.
+ */
+
+#include "smatch.h"
+#include "smatch_slist.h"
+
+static void check_func_return(struct expression *expr)
+{
+	struct symbol *sym = get_real_base_type(get_type(expr->fn));
+	const char *func = expr_to_str(expr->fn);
+	struct statement *stmt;
+
+	if (sym == NULL) {
+		sm_error("unknown type for func '%s'", func);
+		return;
+	}
+
+	/*
+	 * There is never any need to check these returns.
+	 */
+	if (strcmp(func, "memcpy") == 0 ||
+	    strcmp(func, "memmove") == 0 ||
+	    strcmp(func, "memset") == 0)
+		return;
+
+	/*
+	 * Either we got the return type already (direct call),
+	 * or we need to go one further (function pointer call)
+	 */
+	if (sym == &void_ctype || (sym->type == SYM_FN &&
+		get_real_base_type(sym) == &void_ctype))
+		return;
+
+	stmt = last_ptr_list((struct ptr_list *)big_statement_stack);
+
+	if (stmt->type == STMT_EXPRESSION && stmt->expression == expr)
+		sm_error("unchecked function return '%s'", expr_to_str(expr->fn));
+}
+
+void check_all_func_returns(int id)
+{
+	if (option_project != PROJ_ILLUMOS_KERNEL &&
+	    option_project != PROJ_ILLUMOS_USER)
+		return;
+
+	add_hook(&check_func_return, FUNCTION_CALL_HOOK);
+}
diff --git a/check_list.h b/check_list.h
index 055e630..cbe783d 100644
--- a/check_list.h
+++ b/check_list.h
@@ -192,6 +192,9 @@ CK(check_implicit_dependencies)
 CK(check_wine_filehandles)
 CK(check_wine_WtoA)
 
+/* illumos specific stuff */
+CK(check_all_func_returns)
+
 #include "check_list_local.h"
 
 CK(register_scope)
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2018-11-27 21:52 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-27 10:53 [PATCH 01/12] sparse: correctly handle "-D foo" and "-U foo" John Levon
2018-11-27 10:53 ` [PATCH 02/12] sparse: add -Wno-non-ansi-function-declaration John Levon
2018-11-27 10:53 ` [PATCH 03/12] sparse: add -Wbig-constants John Levon
2018-11-27 10:53 ` [PATCH 04/12] sparse: add -Wempty-character-constant John Levon
2018-11-27 10:53 ` [PATCH 05/12] Look across the entire compile line for smatch arguments John Levon
2018-11-27 10:53 ` [PATCH 06/12] Regularise error reporting John Levon
2018-11-27 10:53 ` [PATCH 07/12] Convert all sm_msg("warn:.." into sm_warning() John Levon
2018-11-27 10:53 ` [PATCH 08/12] Convert sm_msg() with an error: prefix into sm_error() John Levon
2018-11-27 10:53 ` [PATCH 09/12] Convert some sm_msg() into more specific reporting routines John Levon
2018-11-27 10:53 ` [PATCH 10/12] Track sparse-level warnings and errors too, and respect them in smatch's exit code John Levon
2018-11-27 10:53 ` [PATCH 11/12] Add illumos projects John Levon
2018-11-27 10:53 ` [PATCH 12/12] Add check_all_func_returns John Levon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.