All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kamil Dudka <kdudka@redhat.com>
To: Josh Triplett <josh@joshtriplett.org>
Cc: Stephen Hemminger <shemminger@vyatta.com>, linux-sparse@vger.kernel.org
Subject: [PATCH] add warnings enum-to-int and int-to-enum
Date: Tue, 1 Sep 2009 23:59:09 +0200	[thread overview]
Message-ID: <200909012359.09678.kdudka@redhat.com> (raw)
In-Reply-To: <20090831205353.GA6239@josh-work.beaverton.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 755 bytes --]

On Monday 31 of August 2009 22:53:54 Josh Triplett wrote:
> That seems quite sensible, and it even seems like something sparse
> should warn about by default.
>
> The reverse, warning about the assignment of an enum value to int, seems
> useful as well, but sparse shouldn't issue that warning by default
> because a lot of code just uses enum to define constants.
>
> Distinguishing between anonymous and named enums seems useful as well.
> An anonymous enum just creates some named constants but doesn't create a
> type to use them with, so assigning those constants to int shouldn't
> generate a warning.  (Corner case: "enum { ... } foo;".)

Here is my first take at casting from/to enum along with a simple test case. 
Any feedback welcome...

Kamil

[-- Attachment #2: test-enum.c --]
[-- Type: text/x-csrc, Size: 755 bytes --]

static void foo(void) {
    enum ENUM_TYPE_A { VALUE_A } var_a;
    enum ENUM_TYPE_B { VALUE_B } var_b;
    enum /* anon. */ { VALUE_C } anon_enum_var;
    int i;

    // always OK
    var_a = VALUE_A;
    var_a = (enum ENUM_TYPE_A) VALUE_B;
    var_b = (enum ENUM_TYPE_B) i;
    i = (int) VALUE_A;
    i = VALUE_B;
    anon_enum_var = VALUE_C;
    i = VALUE_C;
    i = anon_enum_var;

    // already caught by -Wenum-mismatch (default)
    var_a = var_b;
    var_b = anon_enum_var;
    anon_enum_var = var_a;

    // caught by -Wint-to-enum (default)
    var_a = VALUE_B;
    var_b = VALUE_C;
    anon_enum_var = VALUE_A;
    var_a = 0;
    var_b = i;
    anon_enum_var = 0;
    anon_enum_var = i;

    // caught only with -Wenum-to-int
    i = var_a;
}

[-- Attachment #3: 0001-add-warnings-enum-to-int-and-int-to-enum.patch --]
[-- Type: text/x-diff, Size: 5498 bytes --]

From a5095bbdb9694effa4a771295a87b80bf84d3230 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@redhat.com>
Date: Tue, 1 Sep 2009 23:51:29 +0200
Subject: [PATCH] add warnings enum-to-int and int-to-enum


Signed-off-by: Kamil Dudka <kdudka@redhat.com>
---
 evaluate.c   |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 expression.h |    1 +
 lib.c        |    4 +++
 lib.h        |    2 +
 parse.c      |    1 +
 sparse.1     |   12 ++++++++++
 6 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/evaluate.c b/evaluate.c
index 805ae90..47e50fb 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -235,16 +235,23 @@ static int is_same_type(struct expression *expr, struct symbol *new)
 }
 
 static void
+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 position pos,
 			       struct symbol *typea,
 			       struct symbol *typeb)
 {
 	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;
@@ -256,6 +263,54 @@ warn_for_different_enum_types (struct position pos,
 	}
 }
 
+static void
+warn_for_enum_to_int_cast (struct expression *expr, struct symbol *typeb)
+{
+	struct position pos = expr->pos;
+	struct symbol *typea = expr->ctype;
+
+	if (!Wenum_to_int)
+		return;
+
+	resolve_sym_node(&typea);
+	resolve_sym_node(&typeb);
+
+	if (typea->type != SYM_ENUM || typeb->type != SYM_BASETYPE)
+		return;
+
+	if (typea->ident) {
+		warning(pos, "cast from");
+		info(pos, "    %s to", show_typename(typea));
+		info(pos, "    %s", show_typename(typeb));
+		return;
+	}
+}
+
+static void
+warn_for_int_to_enum_cast (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 || (enum_type != typeb)) {
+		warning(pos, "cast from");
+		info(pos, "    %s to", show_typename((enum_type)
+					? enum_type
+					: typea));
+		info(pos, "    %s", show_typename(typeb));
+	}
+}
+
 /*
  * This gets called for implicit casts in assignments and
  * integer promotion. We often want to try to move the
@@ -268,6 +323,8 @@ 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_to_int_cast (old, type);
+	warn_for_int_to_enum_cast (old, type);
 
 	if (old->ctype != &null_ctype && is_same_type(old, type))
 		return old;
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..7eb0cda 100644
--- a/sparse.1
+++ b/sparse.1
@@ -149,6 +149,18 @@ Sparse issues these warnings by default.  To turn them off, use
 \fB\-Wno\-enum\-mismatch\fR.
 .
 .TP
+.B \-Wenum\-to\-int
+Warn about casting of an \fBenum\fR type to int and thus possible lost of
+information about the type.
+.
+.TP
+.B \-Wint\-to\-enum
+Warn about casting of int (or incompatible enumeration constant) to \fBenum\fR.
+
+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.
 
-- 
1.6.4.1


  reply	other threads:[~2009-09-01 22:00 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-30 22:32 sparse segv with simple test Stephen Hemminger
2009-08-30 22:53 ` Kamil Dudka
2009-08-31 15:57   ` Stephen Hemminger
2009-08-31 18:12     ` Kamil Dudka
2009-08-31 18:49       ` Stephen Hemminger
2009-08-31 19:04         ` Kamil Dudka
2009-08-31 20:53           ` Josh Triplett
2009-09-01 21:59             ` Kamil Dudka [this message]
2009-09-01 23:24               ` [PATCH] add warnings enum-to-int and int-to-enum Josh Triplett
2009-09-02  0:27                 ` Stephen Hemminger
2009-09-02 17:56                   ` Daniel Barkalow
2009-09-02 18:04                     ` Kamil Dudka
2009-09-02 18:43                       ` Daniel Barkalow
2009-09-02 18:56                         ` Josh Triplett
2009-09-02 19:19                           ` Daniel Barkalow
2009-09-02 19:58                             ` Kamil Dudka
2009-09-02 11:53                 ` Kamil Dudka
2009-09-02 15:21                   ` Josh Triplett
2009-09-02 16:23                     ` Kamil Dudka
2009-09-02 16:38                       ` Christopher Li
2009-09-02 19:03                       ` Josh Triplett
2009-09-02 19:19                         ` Kamil Dudka
2009-09-02 22:35                           ` Kamil Dudka
2009-09-03  9:42                             ` Christopher Li
2009-09-03 11:47                               ` Kamil Dudka
2009-09-03 18:38                                 ` Christopher Li
2009-09-03 18:54                                   ` Kamil Dudka
2009-09-03 20:02                                     ` Christopher Li
2009-09-13 19:28                                       ` Kamil Dudka
2009-09-13 19:55                                         ` Christopher Li
2009-09-13 20:09                                           ` Kamil Dudka

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200909012359.09678.kdudka@redhat.com \
    --to=kdudka@redhat.com \
    --cc=josh@joshtriplett.org \
    --cc=linux-sparse@vger.kernel.org \
    --cc=shemminger@vyatta.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.