diff mbox

add warnings enum-to-int and int-to-enum

Message ID 200909030035.55097.kdudka@redhat.com (mailing list archive)
State Rejected, archived
Headers show

Commit Message

Kamil Dudka Sept. 2, 2009, 10:35 p.m. UTC
On Wednesday 02 of September 2009 21:19:49 Kamil Dudka wrote:
> Nope, I think we should fix it right now. And if possible ask the original
> authors for review and/or comment at the patch I am currently preparing.
> I considered it pretty broken. Just try this example:
>
> static void f(void) {
>     enum ENUM_TYPE_A { VALUE_A } var_a;
>     enum ENUM_TYPE_B { VALUE_B } var_b;
>
>     switch (var_a) {
>         case VALUE_A:
>         case VALUE_B:
>         default:
>             break;
>     }
> }
>
> It seems like this was the original intention of the calling the
> warn_for_different_enum_types() from check_case_type(). But it has been
> either not tested, or broken in the meantime.

The second holds. It's regression!

It used to work in ca1f2e9ebf33e78c77c79eb695fe88d843b4f978 - see the log 
message for a test case. The same test case is failing to issue a warning 
now, but it works again with my patch applied.

Al, Morten, can I ask you as original authors for approval of the patch?

Details about warnings (what? when? why?) are in the tests themselves. Don't 
hesitate to ask me if something is missing there :-)

> > Either one seems fine; I don't think splitting the test case helps
> > coverage, and keeping it together lets you use the same declarations for
> > the entire test case as you did in the previously attached version.
>
> This is not necessarily dedicated to choice 1), unless you are scared from
> a construction like this:
>
>     #include "enum-common.c"

Nobody has objected, so here it is. I think it'll be much easier to maintain 
this way...

Kamil

Comments

Christopher Li Sept. 3, 2009, 9:42 a.m. UTC | #1
On Wed, Sep 2, 2009 at 3:35 PM, Kamil Dudka<kdudka@redhat.com> wrote:
> On Wednesday 02 of September 2009 21:19:49 Kamil Dudka wrote:
>
> The second holds. It's regression!

I have some questions regarding your patch:

Can we just set the expression->ctype to the enum type
instead of adding the *enum_type? I think the current expr->ctype
can be reached from enum_type->ctype.base_type any way.
In other words, we do care about expression is enum type vs int type
in this patch.

After the type evaluation(and possible warning), we can convert that
enum type back to the base int type because the back end does not
care about enum.

I think fixing the regression should be a separate patch from
the this patch which adding new feature. It is easier to review
as well.

Sorry the rest of the patch will take me more time to go over.

Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kamil Dudka Sept. 3, 2009, 11:47 a.m. UTC | #2
On Thu September 3 2009 11:42:30 Christopher Li wrote:
> Can we just set the expression->ctype to the enum type
> instead of adding the *enum_type? I think the current expr->ctype
> can be reached from enum_type->ctype.base_type any way.
> In other words, we do care about expression is enum type vs int type
> in this patch.
>
> After the type evaluation(and possible warning), we can convert that
> enum type back to the base int type because the back end does not
> care about enum.

Do you want to store the correct enum type to expression->ctype and overwrite 
it later with some integral type? What's the advantage of this approach? 
(instead of preserving ABI which is already changed to 0.4.1). I don't think 
the information about type for enum constant is useful only for issuing 
warnings like this. Some SPARSE clients might also need such information.

> I think fixing the regression should be a separate patch from
> the this patch which adding new feature. It is easier to review
> as well.

Sure if anybody is able to split it... Unfortunately we have no reference for 
the "original" behavior of -Wmismatch-enum. I didn't found it documented 
anywhere and the "test-case" from the referred commit is not really useful as 
a test-case. I have not enough time for reverse engineering...

I think the tests included in the patch have good enough coverage to prevent 
you from a future regression and it sounds more important to me than 
documenting previous regressions :-)

Kamil
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christopher Li Sept. 3, 2009, 6:38 p.m. UTC | #3
On Thu, Sep 3, 2009 at 4:47 AM, Kamil Dudka<kdudka@redhat.com> wrote:
> Do you want to store the correct enum type to expression->ctype and overwrite
> it later with some integral type? What's the advantage of this approach?
> (instead of preserving ABI which is already changed to 0.4.1). I don't think
> the information about type for enum constant is useful only for issuing
> warnings like this. Some SPARSE clients might also need such information.

I think it is cleaner to have one single place to look for the ctype of
an expression.We don't have to convert it to int type. I think most of the
sparse code can deal with enum type any way. I don't like the dual personality
of expressions.

An other reason is that you increase the expression structure size for
32 bit system. Expression and symbol are the most common used
structure. It take up a good portion of the sparse memory foot print. I
want to keep them as lean as possible.

> Sure if anybody is able to split it... Unfortunately we have no reference for
> the "original" behavior of -Wmismatch-enum. I didn't found it documented
> anywhere and the "test-case" from the referred commit is not really useful as
> a test-case. I have not enough time for reverse engineering...

I don't see why it is hard to split. Can we just make the code which add
new options and issue new warnings to a separate patch? We shouldn't
need to reverse engineering the old behavior to do that.

>
> I think the tests included in the patch have good enough coverage to prevent
> you from a future regression and it sounds more important to me than
> documenting previous regressions :-)

Yes I agree the test case is always useful.

Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kamil Dudka Sept. 3, 2009, 6:54 p.m. UTC | #4
On Thursday 03 of September 2009 20:38:24 Christopher Li wrote:
> I think it is cleaner to have one single place to look for the ctype of
> an expression.We don't have to convert it to int type. I think most of the
> sparse code can deal with enum type any way. I don't like the dual
> personality of expressions.

Two personalities are still not so many ... have you ever looked to the gcc 
code? :-)

[...]

> I don't see why it is hard to split. Can we just make the code which add
> new options and issue new warnings to a separate patch? We shouldn't
> need to reverse engineering the old behavior to do that.

I didn't say hard, but actually not useful from my point of view. If it's easy 
for you to split my patch to the two pieces, you are welcome to have a go at 
that. We can still wait for opinion of the original authors. Perhaps they can 
bring some light to this problem.

Kamil
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christopher Li Sept. 3, 2009, 8:02 p.m. UTC | #5
On Thu, Sep 3, 2009 at 11:54 AM, Kamil Dudka<kdudka@redhat.com> wrote:
> Two personalities are still not so many ... have you ever looked to the gcc
> code? :-)

That is why I don't want to start a trend.

> I didn't say hard, but actually not useful from my point of view. If it's easy
> for you to split my patch to the two pieces, you are welcome to have a go at
> that. We can still wait for opinion of the original authors. Perhaps they can
> bring some light to this problem.

Fair enough .I need to spend more time to digest this patch.

Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kamil Dudka Sept. 13, 2009, 7:28 p.m. UTC | #6
On Thursday 03 of September 2009 22:02:06 Christopher Li wrote:
> On Thu, Sep 3, 2009 at 11:54 AM, Kamil Dudka<kdudka@redhat.com> wrote:
> > Two personalities are still not so many ... have you ever looked to the
> > gcc code? :-)
>
> That is why I don't want to start a trend.
>
> > I didn't say hard, but actually not useful from my point of view. If it's
> > easy for you to split my patch to the two pieces, you are welcome to have
> > a go at that. We can still wait for opinion of the original authors.
> > Perhaps they can bring some light to this problem.
>
> Fair enough .I need to spend more time to digest this patch.

Any progress here? I wouldn't like this to become another downstream patch.

I work on a generic layer [1] for processing C sources (for now) supporting 
SPARSE and gcc 4.5 plug-in as sources. The gcc plug-in [2] now works fairly 
well and I am going to make the SPARSE client fully equivalent to the 
plug-in. This will probably need a few more tiny patches for SPARSE
to implement what's missing.

Is the upstream interested to make SPARSE more useful as a library?

Kamil

[1]http://dudka.no-ip.org/cgi-bin/gitweb.cgi?p=tools;a=blob_plain;f=sl/code_listener.h
[2]http://dudka.no-ip.org/cgi-bin/gitweb.cgi?p=tools;a=blob_plain;f=sl/slplug.c
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christopher Li Sept. 13, 2009, 7:55 p.m. UTC | #7
On Sun, Sep 13, 2009 at 12:28 PM, Kamil Dudka <kdudka@redhat.com> wrote:
>
> Any progress here? I wouldn't like this to become another downstream patch.

Guilty. Too busy this week. I am going to take a look at it again tonight.

> I work on a generic layer [1] for processing C sources (for now) supporting
> SPARSE and gcc 4.5 plug-in as sources. The gcc plug-in [2] now works fairly
> well and I am going to make the SPARSE client fully equivalent to the
> plug-in. This will probably need a few more tiny patches for SPARSE
> to implement what's missing.
>
> Is the upstream interested to make SPARSE more useful as a library?

Yes. I am interested in that. If it does not cause additional slow down
or memory blow. Sure yes.

If it does because it needs to preserve more information, e.g. space and
comments it would be nice to put it under some options or even compile time
config option. I care about people don't use those feature can still run
sparse fast.

Chris
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kamil Dudka Sept. 13, 2009, 8:09 p.m. UTC | #8
On Sunday 13 of September 2009 21:55:32 Christopher Li wrote:
> On Sun, Sep 13, 2009 at 12:28 PM, Kamil Dudka <kdudka@redhat.com> wrote:
> > Any progress here? I wouldn't like this to become another downstream
> > patch.
>
> Guilty. Too busy this week. I am going to take a look at it again tonight.

Thanks for quick reply! It doesn't hurry actually. I am only trying to keep 
this thread alive :-)

> > I work on a generic layer [1] for processing C sources (for now)
> > supporting SPARSE and gcc 4.5 plug-in as sources. The gcc plug-in [2] now
> > works fairly well and I am going to make the SPARSE client fully
> > equivalent to the plug-in. This will probably need a few more tiny
> > patches for SPARSE to implement what's missing.
> >
> > Is the upstream interested to make SPARSE more useful as a library?
>
> Yes. I am interested in that. If it does not cause additional slow down
> or memory blow. Sure yes.
>
> If it does because it needs to preserve more information, e.g. space and
> comments it would be nice to put it under some options or even compile time
> config option. I care about people don't use those feature can still run
> sparse fast.

I think we'll need to add some extra items to the public SPARSE headers, not 
sure if it's good idea to #ifdef it even there. But I need to analyse what 
exactly is missing first. Now I am only asking whether the idea itself is 
welcome (before starting work on it).

Kamil
--
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

From 050663577b8832ee40f4f365bee61e2ed1bf9613 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Wed, 2 Sep 2009 23:49:09 +0200
Subject: [PATCH] add warnings enum-to-int and int-to-enum...

... and improve detection of the enum-mismatch warning. Add test case
for each of the warnings. For details about what triggers which warning
just look to the corresponding test case.

Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
 evaluate.c                 |  122 ++++++++++++++++++++++++++++++++++----------
 expression.h               |    1 +
 lib.c                      |    4 ++
 lib.h                      |    2 +
 parse.c                    |    1 +
 sparse.1                   |   13 +++++
 validation/enum-common.c   |  112 ++++++++++++++++++++++++++++++++++++++++
 validation/enum-from-int.c |   36 +++++++++++++
 validation/enum-mismatch.c |   48 +++++++++++++++++
 validation/enum-to-int.c   |   27 ++++++++++
 10 files changed, 339 insertions(+), 27 deletions(-)
 create mode 100644 validation/enum-common.c
 create mode 100644 validation/enum-from-int.c
 create mode 100644 validation/enum-mismatch.c
 create mode 100644 validation/enum-to-int.c

diff --git a/evaluate.c b/evaluate.c
index 805ae90..0d5e93b 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -235,27 +235,105 @@  static int is_same_type(struct expression *expr, struct symbol *new)
 }
 
 static void
-warn_for_different_enum_types (struct position pos,
-			       struct symbol *typea,
-			       struct symbol *typeb)
+resolve_sym_node (struct symbol **psym)
 {
+	struct symbol *sym = *psym;
+	if (sym->type == SYM_NODE)
+		*psym = sym->ctype.base_type;
+}
+
+static void
+warn_for_different_enum_types (struct expression *expr, struct symbol *typeb)
+{
+	struct position pos = expr->pos;
+	struct symbol *typea = expr->ctype;
+	struct symbol *enum_type = expr->enum_type;
+	enum type ttypea;
+
 	if (!Wenum_mismatch)
 		return;
-	if (typea->type == SYM_NODE)
-		typea = typea->ctype.base_type;
-	if (typeb->type == SYM_NODE)
-		typeb = typeb->ctype.base_type;
+
+	resolve_sym_node(&typea);
+	resolve_sym_node(&typeb);
 
 	if (typea == typeb)
 		return;
+	if (typeb->type != SYM_ENUM)
+		return;
 
-	if (typea->type == SYM_ENUM && typeb->type == SYM_ENUM) {
+	ttypea = typea->type;
+	if (ttypea == SYM_ENUM || (ttypea == SYM_BASETYPE
+					&& enum_type && enum_type != typeb))
+	{
 		warning(pos, "mixing different enum types");
-		info(pos, "    %s versus", show_typename(typea));
+		info(pos, "    %s versus", show_typename((ttypea == SYM_ENUM)
+					? typea
+					: enum_type));
 		info(pos, "    %s", show_typename(typeb));
 	}
 }
 
+static void
+issue_conversion_warning(struct position pos,
+			 struct symbol *typea,
+			 struct symbol *typeb)
+{
+	warning(pos, "conversion of");
+	info(pos, "    %s to", show_typename(typea));
+	info(pos, "    %s", show_typename(typeb));
+}
+
+static void
+warn_for_enum_to_int_conversion (struct expression *expr, struct symbol *typeb)
+{
+	struct position pos = expr->pos;
+	struct symbol *typea = expr->ctype;
+	struct symbol *enum_type = expr->enum_type;
+
+	if (!Wenum_to_int)
+		return;
+
+	resolve_sym_node(&typea);
+	resolve_sym_node(&typeb);
+
+	if (typeb->type != SYM_BASETYPE)
+		return;
+
+	if (typea->type == SYM_ENUM && typea->ident)
+		issue_conversion_warning(pos, typea, typeb);
+
+	if (typea->type == SYM_BASETYPE && enum_type && enum_type->ident)
+		issue_conversion_warning(pos, enum_type, typeb);
+}
+
+static void
+warn_for_int_to_enum_conversion (struct expression *expr, struct symbol *typeb)
+{
+	struct position pos = expr->pos;
+	struct symbol *typea = expr->ctype;
+	struct symbol *enum_type = expr->enum_type;
+
+	if (!Wint_to_enum)
+		return;
+
+	resolve_sym_node(&typea);
+	resolve_sym_node(&typeb);
+
+	if (typea->type != SYM_BASETYPE || typeb->type != SYM_ENUM)
+		return;
+
+	if (!enum_type)
+		issue_conversion_warning(pos, typea, typeb);
+}
+
+static void
+warn_for_enum_conversions(struct expression *expr, struct symbol *type)
+{
+	warn_for_different_enum_types (expr, type);
+	warn_for_enum_to_int_conversion (expr, type);
+	warn_for_int_to_enum_conversion (expr, type);
+}
+
 /*
  * This gets called for implicit casts in assignments and
  * integer promotion. We often want to try to move the
@@ -267,7 +345,7 @@  static struct expression * cast_to(struct expression *old, struct symbol *type)
 {
 	struct expression *expr;
 
-	warn_for_different_enum_types (old->pos, old->ctype, type);
+	warn_for_enum_conversions(old, type);
 
 	if (old->ctype != &null_ctype && is_same_type(old, type))
 		return old;
@@ -287,8 +365,6 @@  static struct expression * cast_to(struct expression *old, struct symbol *type)
 		break;
 
 	case EXPR_IMPLIED_CAST:
-		warn_for_different_enum_types(old->pos, old->ctype, type);
-
 		if (old->ctype->bit_size >= type->bit_size) {
 			struct expression *orig = old->cast_expression;
 			if (same_cast_type(orig->ctype, type))
@@ -498,7 +574,8 @@  static struct symbol *usual_conversions(int op,
 {
 	struct symbol *ctype;
 
-	warn_for_different_enum_types(right->pos, left->ctype, right->ctype);
+	/* FIXME: we should either write a test-case for it or delete it */
+	warn_for_enum_conversions(left, right->ctype);
 
 	if ((lclass | rclass) & TYPE_RESTRICT)
 		goto Restr;
@@ -3225,8 +3302,7 @@  static void evaluate_case_statement(struct statement *stmt)
 }
 
 static void check_case_type(struct expression *switch_expr,
-			    struct expression *case_expr,
-			    struct expression **enumcase)
+			    struct expression *case_expr)
 {
 	struct symbol *switch_type, *case_type;
 	int sclass, cclass;
@@ -3239,12 +3315,8 @@  static void check_case_type(struct expression *switch_expr,
 
 	if (!switch_type || !case_type)
 		goto Bad;
-	if (enumcase) {
-		if (*enumcase)
-			warn_for_different_enum_types(case_expr->pos, case_type, (*enumcase)->ctype);
-		else if (is_enum_type(case_type))
-			*enumcase = case_expr;
-	}
+
+	warn_for_enum_conversions(case_expr, switch_type);
 
 	sclass = classify_type(switch_type, &switch_type);
 	cclass = classify_type(case_type, &case_type);
@@ -3275,21 +3347,17 @@  Bad:
 static void evaluate_switch_statement(struct statement *stmt)
 {
 	struct symbol *sym;
-	struct expression *enumcase = NULL;
-	struct expression **enumcase_holder = &enumcase;
 	struct expression *sel = stmt->switch_expression;
 
 	evaluate_expression(sel);
 	evaluate_statement(stmt->switch_statement);
 	if (!sel)
 		return;
-	if (sel->ctype && is_enum_type(sel->ctype))
-		enumcase_holder = NULL; /* Only check cases against switch */
 
 	FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
 		struct statement *case_stmt = sym->stmt;
-		check_case_type(sel, case_stmt->case_expression, enumcase_holder);
-		check_case_type(sel, case_stmt->case_to, enumcase_holder);
+		check_case_type(sel, case_stmt->case_expression);
+		check_case_type(sel, case_stmt->case_to);
 	} END_FOR_EACH_PTR(sym);
 }
 
diff --git a/expression.h b/expression.h
index 631224f..81f70ad 100644
--- a/expression.h
+++ b/expression.h
@@ -70,6 +70,7 @@  struct expression {
 		struct {
 			unsigned long long value;
 			unsigned taint;
+			struct symbol *enum_type;
 		};
 
 		// EXPR_FVALUE
diff --git a/lib.c b/lib.c
index 600939b..2f78bd5 100644
--- a/lib.c
+++ b/lib.c
@@ -199,6 +199,8 @@  int Wdecl = 1;
 int Wdefault_bitfield_sign = 0;
 int Wdo_while = 0;
 int Wenum_mismatch = 1;
+int Wenum_to_int = 0;
+int Wint_to_enum = 1;
 int Wnon_pointer_null = 1;
 int Wold_initializer = 1;
 int Wone_bit_signed_bitfield = 1;
@@ -380,6 +382,8 @@  static const struct warning {
 	{ "default-bitfield-sign", &Wdefault_bitfield_sign },
 	{ "do-while", &Wdo_while },
 	{ "enum-mismatch", &Wenum_mismatch },
+	{ "enum-to-int", &Wenum_to_int },
+	{ "int-to-enum", &Wint_to_enum },
 	{ "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 b22fa93..962d49d 100644
--- a/lib.h
+++ b/lib.h
@@ -96,6 +96,8 @@  extern int Wdecl;
 extern int Wdefault_bitfield_sign;
 extern int Wdo_while;
 extern int Wenum_mismatch;
+extern int Wenum_to_int;
+extern int Wint_to_enum;
 extern int Wnon_pointer_null;
 extern int Wold_initializer;
 extern int Wone_bit_signed_bitfield;
diff --git a/parse.c b/parse.c
index 5e75242..76d4c58 100644
--- a/parse.c
+++ b/parse.c
@@ -791,6 +791,7 @@  static void cast_enum_list(struct symbol_list *list, struct symbol *base_type)
 		if (expr->type != EXPR_VALUE)
 			continue;
 		ctype = expr->ctype;
+		expr->enum_type = sym->ctype.base_type;
 		if (ctype->bit_size == base_type->bit_size)
 			continue;
 		cast_value(expr, base_type, expr, ctype);
diff --git a/sparse.1 b/sparse.1
index d7fe444..288b3a8 100644
--- a/sparse.1
+++ b/sparse.1
@@ -149,6 +149,19 @@  Sparse issues these warnings by default.  To turn them off, use
 \fB\-Wno\-enum\-mismatch\fR.
 .
 .TP
+.B \-Wenum\-to\-int
+Warn about converting an \fBenum\fR type to int. An explicit cast to int will
+suppress this warning.
+.
+.TP
+.B \-Wint\-to\-enum
+Warn about converting int to \fBenum\fR type. An explicit cast to the right
+\fBenum\fR type will suppress this warning.
+
+Sparse issues these warnings by default.  To turn them off, use
+\fB\-Wno\-int\-to\-enum\fR.
+.
+.TP
 .B \-Wnon\-pointer\-null
 Warn about the use of 0 as a NULL pointer.
 
diff --git a/validation/enum-common.c b/validation/enum-common.c
new file mode 100644
index 0000000..f940fef
--- /dev/null
+++ b/validation/enum-common.c
@@ -0,0 +1,112 @@ 
+static enum ENUM_TYPE_A { VALUE_A } var_a;
+static enum ENUM_TYPE_B { VALUE_B } var_b;
+static enum /* anon. */ { VALUE_C } anon_enum_var;
+static int i;
+
+static void take_enum_of_type_a(enum ENUM_TYPE_A arg_enum)
+{
+	(void) arg_enum;
+}
+
+static void take_int(int arg_int)
+{
+	(void) arg_int;
+}
+
+static void always_ok(void)
+{
+	var_a ++;
+	var_a = VALUE_A;
+	var_a = (enum ENUM_TYPE_A) VALUE_B;
+	var_b = (enum ENUM_TYPE_B) i;
+	i = (int) VALUE_A;
+	anon_enum_var = VALUE_C;
+	i = VALUE_C;
+	i = anon_enum_var;
+	i = 7;
+	var_a = (enum ENUM_TYPE_A) 0;
+	anon_enum_var = (__typeof__(anon_enum_var)) 0;
+	anon_enum_var = (__typeof__(anon_enum_var)) VALUE_A;
+
+	switch (var_a) {
+		case VALUE_A:
+		default:
+			take_enum_of_type_a(var_a);
+			take_enum_of_type_a(VALUE_A);
+	}
+
+	switch (anon_enum_var) {
+		case VALUE_C:
+		default:
+			take_int(anon_enum_var);
+	}
+
+	switch (i) {
+		case VALUE_C:
+		default:
+			take_int(VALUE_C);
+	}
+}
+
+static void trigger_enum_mismatch(void)
+{
+	switch (var_a) {
+		case VALUE_B:
+		case VALUE_C:
+		default:
+			take_enum_of_type_a(var_b);
+			take_enum_of_type_a(VALUE_B);
+	}
+
+	switch (anon_enum_var) {
+		case VALUE_A:
+		default:
+			take_enum_of_type_a(anon_enum_var);
+			take_enum_of_type_a(VALUE_C);
+	}
+
+	// this has been already working in sparse 0.4.1
+	var_a = var_b;
+	var_b = anon_enum_var;
+	anon_enum_var = var_a;
+
+	// implemented after sparse 0.4.1
+	var_a = VALUE_B;
+	var_b = VALUE_C;
+	anon_enum_var = VALUE_A;
+}
+
+static void trigger_int_to_enum_conversion(void)
+{
+	switch (var_a) {
+		case 0:
+		default:
+			take_enum_of_type_a(i);
+			take_enum_of_type_a(7);
+	}
+	var_a = 0;
+	var_b = i;
+	anon_enum_var = 0;
+	anon_enum_var = i;
+	var_a = (int) VALUE_A;
+	var_a = (int) VALUE_B;
+}
+
+static void trigger_enum_to_int_conversion(void)
+{
+	i = var_a;
+	i = VALUE_B;
+	switch (i) {
+		case VALUE_A:
+		case VALUE_B:
+		default:
+			take_int(var_a);
+			take_int(VALUE_B);
+	}
+}
+
+/*
+ * check-name: enum-common
+ * check-description: common part of the test for -Wenum-mismatch, -Wenum-to-int and -Wint-to-enum
+ * check-command: sparse -Wno-enum-mismatch -Wno-int-to-enum $file
+ */
diff --git a/validation/enum-from-int.c b/validation/enum-from-int.c
new file mode 100644
index 0000000..15b1e4d
--- /dev/null
+++ b/validation/enum-from-int.c
@@ -0,0 +1,36 @@ 
+#include "enum-common.c"
+
+/*
+ * check-name: -Wint-to-enum
+ * check-command: sparse -Wno-enum-mismatch $file
+ *
+ * check-error-start
+enum-common.c:84:45: warning: conversion of
+enum-common.c:84:45:     int to
+enum-common.c:84:45:     int enum ENUM_TYPE_A 
+enum-common.c:85:45: warning: conversion of
+enum-common.c:85:45:     int to
+enum-common.c:85:45:     int enum ENUM_TYPE_A 
+enum-common.c:82:22: warning: conversion of
+enum-common.c:82:22:     int to
+enum-common.c:82:22:     int enum ENUM_TYPE_A 
+enum-common.c:87:17: warning: conversion of
+enum-common.c:87:17:     int to
+enum-common.c:87:17:     int enum ENUM_TYPE_A 
+enum-common.c:88:17: warning: conversion of
+enum-common.c:88:17:     int to
+enum-common.c:88:17:     int enum ENUM_TYPE_B 
+enum-common.c:89:25: warning: conversion of
+enum-common.c:89:25:     int to
+enum-common.c:89:25:     int enum <noident> 
+enum-common.c:90:25: warning: conversion of
+enum-common.c:90:25:     int to
+enum-common.c:90:25:     int enum <noident> 
+enum-common.c:91:18: warning: conversion of
+enum-common.c:91:18:     int to
+enum-common.c:91:18:     int enum ENUM_TYPE_A 
+enum-common.c:92:18: warning: conversion of
+enum-common.c:92:18:     int to
+enum-common.c:92:18:     int enum ENUM_TYPE_A 
+ * check-error-end
+ */
diff --git a/validation/enum-mismatch.c b/validation/enum-mismatch.c
new file mode 100644
index 0000000..6db016f
--- /dev/null
+++ b/validation/enum-mismatch.c
@@ -0,0 +1,48 @@ 
+#include "enum-common.c"
+
+/*
+ * check-name: -Wenum-mismatch
+ * check-command: sparse -Wenum-mismatch -Wno-int-to-enum $file
+ *
+ * check-error-start
+enum-common.c:57:45: warning: mixing different enum types
+enum-common.c:57:45:     int enum ENUM_TYPE_B  versus
+enum-common.c:57:45:     int enum ENUM_TYPE_A 
+enum-common.c:58:45: warning: mixing different enum types
+enum-common.c:58:45:     int enum ENUM_TYPE_B  versus
+enum-common.c:58:45:     int enum ENUM_TYPE_A 
+enum-common.c:54:22: warning: mixing different enum types
+enum-common.c:54:22:     int enum ENUM_TYPE_B  versus
+enum-common.c:54:22:     int enum ENUM_TYPE_A 
+enum-common.c:55:22: warning: mixing different enum types
+enum-common.c:55:22:     int enum <noident>  versus
+enum-common.c:55:22:     int enum ENUM_TYPE_A 
+enum-common.c:64:45: warning: mixing different enum types
+enum-common.c:64:45:     int enum <noident>  versus
+enum-common.c:64:45:     int enum ENUM_TYPE_A 
+enum-common.c:65:45: warning: mixing different enum types
+enum-common.c:65:45:     int enum <noident>  versus
+enum-common.c:65:45:     int enum ENUM_TYPE_A 
+enum-common.c:62:22: warning: mixing different enum types
+enum-common.c:62:22:     int enum ENUM_TYPE_A  versus
+enum-common.c:62:22:     int enum <noident> 
+enum-common.c:69:17: warning: mixing different enum types
+enum-common.c:69:17:     int enum ENUM_TYPE_B  versus
+enum-common.c:69:17:     int enum ENUM_TYPE_A 
+enum-common.c:70:17: warning: mixing different enum types
+enum-common.c:70:17:     int enum <noident>  versus
+enum-common.c:70:17:     int enum ENUM_TYPE_B 
+enum-common.c:71:25: warning: mixing different enum types
+enum-common.c:71:25:     int enum ENUM_TYPE_A  versus
+enum-common.c:71:25:     int enum <noident> 
+enum-common.c:74:17: warning: mixing different enum types
+enum-common.c:74:17:     int enum ENUM_TYPE_B  versus
+enum-common.c:74:17:     int enum ENUM_TYPE_A 
+enum-common.c:75:17: warning: mixing different enum types
+enum-common.c:75:17:     int enum <noident>  versus
+enum-common.c:75:17:     int enum ENUM_TYPE_B 
+enum-common.c:76:25: warning: mixing different enum types
+enum-common.c:76:25:     int enum ENUM_TYPE_A  versus
+enum-common.c:76:25:     int enum <noident> 
+ * check-error-end
+ */
diff --git a/validation/enum-to-int.c b/validation/enum-to-int.c
new file mode 100644
index 0000000..a981ce5
--- /dev/null
+++ b/validation/enum-to-int.c
@@ -0,0 +1,27 @@ 
+#include "enum-common.c"
+
+/*
+ * check-name: -Wenum-to-int
+ * check-command: sparse -Wenum-to-int -Wno-enum-mismatch -Wno-int-to-enum $file
+ *
+ * check-error-start
+enum-common.c:97:13: warning: conversion of
+enum-common.c:97:13:     int enum ENUM_TYPE_A  to
+enum-common.c:97:13:     int
+enum-common.c:98:13: warning: conversion of
+enum-common.c:98:13:     int enum ENUM_TYPE_B  to
+enum-common.c:98:13:     int
+enum-common.c:103:34: warning: conversion of
+enum-common.c:103:34:     int enum ENUM_TYPE_A  to
+enum-common.c:103:34:     int
+enum-common.c:104:34: warning: conversion of
+enum-common.c:104:34:     int enum ENUM_TYPE_B  to
+enum-common.c:104:34:     int
+enum-common.c:100:22: warning: conversion of
+enum-common.c:100:22:     int enum ENUM_TYPE_A  to
+enum-common.c:100:22:     int
+enum-common.c:101:22: warning: conversion of
+enum-common.c:101:22:     int enum ENUM_TYPE_B  to
+enum-common.c:101:22:     int
+ * check-error-end
+ */
-- 
1.6.4.1