|
|
|
[PATCH] add warnings enum-to-int and int-to-enum | |
| [Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] | |
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
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;
}
From a5095bbdb9694effa4a771295a87b80bf84d3230 Mon Sep 17 00:00:00 2001
From: Kamil Dudka <kdudka@xxxxxxxxxx>
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@xxxxxxxxxx>
---
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
[Newbies FAQ] [Kernel List] [Site Home] [IETF Annouce] [DCCP] [Netdev] [Networking] [Security] [Bugtraq] [Photo] [Yosemite] [MIPS Linux] [ARM Linux] [Linux Security] [Linux RAID] [Linux SCSI] [DDR & Rambus] [Trinity Fuzzer Tool]