This adds -W[no-]declaration-after-statement, which makes warnings about
declarations after statements a command-line option. (The code to implement
the warning was already in there via a #define; the patch just exposes it
at runtime.) Rationale: C99 allows them, C89 doesn't.

Signed-off-by: Geoff Johnstone <geoffSHEEP.johnstoneFROG@googlemail.com>

diff --git a/lib.c b/lib.c
index 75afdb7..0abcc9a 100644
--- a/lib.c
+++ b/lib.c
@@ -208,6 +208,7 @@ int Wtransparent_union = 1;
 int Wtypesign = 0;
 int Wundef = 0;
 int Wuninitialized = 1;
+int Wdeclarationafterstatement = -1;
 
 int dbg_entry = 0;
 int dbg_dead = 0;
@@ -372,6 +373,7 @@ static const struct warning {
 	{ "typesign", &Wtypesign },
 	{ "undef", &Wundef },
 	{ "uninitialized", &Wuninitialized },
+	{ "declaration-after-statement", &Wdeclarationafterstatement },
 };
 
 enum {
@@ -456,6 +458,28 @@ static void handle_onoff_switch_finalize(const struct warning warnings[], int n)
 static void handle_switch_W_finalize(void)
 {
 	handle_onoff_switch_finalize(warnings, sizeof(warnings) / sizeof(warnings[0]));
+
+	/* default Wdeclarationafterstatement based on the C dialect */
+	if (-1 == Wdeclarationafterstatement)
+	{
+		switch (standard)
+		{
+			case STANDARD_C89:
+			case STANDARD_C94:
+				Wdeclarationafterstatement = 1;
+				break;
+
+			case STANDARD_C99:
+			case STANDARD_GNU89:
+			case STANDARD_GNU99:
+				Wdeclarationafterstatement = 0;
+				break;
+
+			default:
+				assert (0);
+		}
+
+	}
 }
 
 static void handle_switch_v_finalize(void)
diff --git a/lib.h b/lib.h
index cef4ab8..42a3396 100644
--- a/lib.h
+++ b/lib.h
@@ -108,6 +108,7 @@ extern int Wtransparent_union;
 extern int Wtypesign;
 extern int Wundef;
 extern int Wuninitialized;
+extern int Wdeclarationafterstatement;
 
 extern int dbg_entry;
 extern int dbg_dead;
diff --git a/parse.c b/parse.c
index 6255737..8346fe2 100644
--- a/parse.c
+++ b/parse.c
@@ -28,8 +28,6 @@
 #include "expression.h"
 #include "target.h"
 
-#define warn_on_mixed (1)
-
 static struct symbol_list **function_symbol_list;
 struct symbol_list *function_computed_target_list;
 struct statement_list *function_computed_goto_list;
@@ -1810,7 +1808,7 @@ static struct token * statement_list(struct token *token, struct statement_list
 			stmt = alloc_statement(token->pos, STMT_DECLARATION);
 			token = external_declaration(token, &stmt->declaration);
 		} else {
-			seen_statement = warn_on_mixed;
+			seen_statement = Wdeclarationafterstatement;
 			token = statement(token, &stmt);
 		}
 		add_statement(list, stmt);
diff --git a/sparse.1 b/sparse.1
index 7a39d85..0f9131d 100644
--- a/sparse.1
+++ b/sparse.1
@@ -112,6 +112,16 @@ Sparse issues these warnings by default.  To turn them off, use
 \fB\-Wno\-decl\fR.
 .
 .TP
+.B \-Wdeclaration-after-statement
+Warn about declarations that are not at the start of a block.
+
+These declarations are permitted in C99 but not in C89.
+
+Sparse issues these warnings by default only when the C dialect is
+C89 (i.e. -ansi or -std=c89).  To turn them off, use
+\fB\-Wno\-declaration\-after\-statement\fR.
+.
+.TP
 .B \-Wdefault\-bitfield\-sign
 Warn about any bitfield with no explicit signedness.
 
diff --git a/validation/declaration-after-statement-ansi.c b/validation/declaration-after-statement-ansi.c
new file mode 100644
index 0000000..333410b
--- /dev/null
+++ b/validation/declaration-after-statement-ansi.c
@@ -0,0 +1,12 @@
+static void func (int i)
+{
+	i;
+	int j = i;
+}
+/*
+ * check-name: declaration after statement (ANSI)
+ * check-command: sparse -ansi $file
+ * check-error-start
+declaration-after-statement-ansi.c:4:2: warning: mixing declarations and code
+ * check-error-end
+ */
diff --git a/validation/declaration-after-statement-c89.c b/validation/declaration-after-statement-c89.c
new file mode 100644
index 0000000..78632cd
--- /dev/null
+++ b/validation/declaration-after-statement-c89.c
@@ -0,0 +1,12 @@
+static void func (int i)
+{
+	i;
+	int j = i;
+}
+/*
+ * check-name: declaration after statement (C89)
+ * check-command: sparse -std=c89 $file
+ * check-error-start
+declaration-after-statement-c89.c:4:2: warning: mixing declarations and code
+ * check-error-end
+ */
diff --git a/validation/declaration-after-statement-c99.c b/validation/declaration-after-statement-c99.c
new file mode 100644
index 0000000..dd36e6e
--- /dev/null
+++ b/validation/declaration-after-statement-c99.c
@@ -0,0 +1,9 @@
+static void func (int i)
+{
+	i;
+	int j = i;
+}
+/*
+ * check-name: declaration after statement (C99)
+ * check-command: sparse -std=c99 $file
+ */
diff --git a/validation/declaration-after-statement-default.c b/validation/declaration-after-statement-default.c
new file mode 100644
index 0000000..c3fe2cd
--- /dev/null
+++ b/validation/declaration-after-statement-default.c
@@ -0,0 +1,9 @@
+static void func (int i)
+{
+	i;
+	int j = i;
+}
+/*
+ * check-name: declaration after statement (default)
+ * check-command: sparse $file
+ */
