lkml.org 
[lkml]   [2005]   [Sep]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: [sparse fix] (was Re: [PATCH] bogus cast in bio.c)
On Fri, Sep 09, 2005 at 11:15:41AM -0700, Linus Torvalds wrote:
>
>
> On Fri, 9 Sep 2005, Linus Torvalds wrote:
> >
> > Ack. Applied,
>
> Btw, I also just committed the fix to not warn for
>
> #if defined(TOKEN) && TOKEN > 1
>
> when TOKEN is undefined and -Wundef is enabled. Implemented exactly the
> way you suggested.

Cool... Speaking of sparse patches:

* generates a warning when we cast _between_ address spaces (e.g. cast from
__user to __iomem).
* optional (on -Wcast-to-as) warning when casting _TO_ address space (e.g.
when normal pointer is cast to __iomem one - that caught a lot of crap in
drivers). casts from unsigned long are still OK, so's cast from 0, so's
__force cast, of course.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
----
diff --git a/evaluate.c b/evaluate.c
--- a/evaluate.c
+++ b/evaluate.c
@@ -2049,11 +2049,27 @@ static int get_as(struct symbol *sym)
return as;
}

+static void cast_to_as(struct expression *e, int as)
+{
+ struct expression *v = e->cast_expression;
+
+ if (!Wcast_to_address_space)
+ return;
+
+ /* cast from constant 0 to pointer is OK */
+ if (v->type == EXPR_VALUE && is_int_type(v->ctype) && !v->value)
+ return;
+
+ warning(e->pos, "cast adds address space to expression (<asn:%d>)", as);
+}
+
static struct symbol *evaluate_cast(struct expression *expr)
{
struct expression *target = expr->cast_expression;
struct symbol *ctype = examine_symbol_type(expr->cast_type);
- enum type type;
+ struct symbol *t1, *t2;
+ enum type type1, type2;
+ int as1, as2;

if (!target)
return NULL;
@@ -2092,51 +2108,54 @@ static struct symbol *evaluate_cast(stru
evaluate_expression(target);
degenerate(target);

+ t1 = ctype;
+ if (t1->type == SYM_NODE)
+ t1 = t1->ctype.base_type;
+ if (t1->type == SYM_ENUM)
+ t1 = t1->ctype.base_type;
+
/*
* You can always throw a value away by casting to
* "void" - that's an implicit "force". Note that
* the same is _not_ true of "void *".
*/
- if (ctype == &void_ctype)
+ if (t1 == &void_ctype)
goto out;

- type = ctype->type;
- if (type == SYM_NODE) {
- type = ctype->ctype.base_type->type;
- if (ctype->ctype.base_type == &void_ctype)
- goto out;
- }
- if (type == SYM_ARRAY || type == SYM_UNION || type == SYM_STRUCT)
+ type1 = t1->type;
+ if (type1 == SYM_ARRAY || type1 == SYM_UNION || type1 == SYM_STRUCT)
warning(expr->pos, "cast to non-scalar");

- if (!target->ctype) {
+ t2 = target->ctype;
+ if (!t2) {
warning(expr->pos, "cast from unknown type");
goto out;
}
+ if (t2->type == SYM_NODE)
+ t2 = t2->ctype.base_type;
+ if (t2->type == SYM_ENUM)
+ t2 = t2->ctype.base_type;

- type = target->ctype->type;
- if (type == SYM_NODE)
- type = target->ctype->ctype.base_type->type;
- if (type == SYM_ARRAY || type == SYM_UNION || type == SYM_STRUCT)
+ type2 = t2->type;
+ if (type2 == SYM_ARRAY || type2 == SYM_UNION || type2 == SYM_STRUCT)
warning(expr->pos, "cast from non-scalar");

- if (!get_as(ctype) && get_as(target->ctype) > 0)
- warning(expr->pos, "cast removes address space of expression");
-
- if (!(ctype->ctype.modifiers & MOD_FORCE)) {
- struct symbol *t1 = ctype, *t2 = target->ctype;
- if (t1->type == SYM_NODE)
- t1 = t1->ctype.base_type;
- if (t2->type == SYM_NODE)
- t2 = t2->ctype.base_type;
- if (t1 != t2) {
- if (t1->type == SYM_RESTRICT)
- warning(expr->pos, "cast to restricted type");
- if (t2->type == SYM_RESTRICT)
- warning(expr->pos, "cast from restricted type");
- }
+ if (!(ctype->ctype.modifiers & MOD_FORCE) && t1 != t2) {
+ if (t1->type == SYM_RESTRICT)
+ warning(expr->pos, "cast to restricted type");
+ if (t2->type == SYM_RESTRICT)
+ warning(expr->pos, "cast from restricted type");
}

+ as1 = get_as(ctype);
+ as2 = get_as(target->ctype);
+ if (!as1 && as2 > 0)
+ warning(expr->pos, "cast removes address space of expression");
+ if (as1 > 0 && as2 > 0 && as1 != as2)
+ warning(expr->pos, "cast between address spaces (<asn:%d>-><asn:%d>)", as2, as1);
+ if (as1 > 0 && !as2)
+ cast_to_as(expr, as1);
+
/*
* Casts of constant values are special: they
* can be NULL, and thus need to be simplified
diff --git a/lib.c b/lib.c
--- a/lib.c
+++ b/lib.c
@@ -170,6 +170,7 @@ int Wtypesign = 0;
int Wcontext = 0;
int Wundefined_preprocessor = 0;
int Wptr_subtraction_blows = 0;
+int Wcast_to_address_space = 0;
int Wtransparent_union = 1;
int preprocess_only;
char *include;
@@ -295,6 +296,7 @@ static const struct warning {
const char *name;
int *flag;
} warnings[] = {
+ { "cast-to-as", &Wcast_to_address_space },
{ "ptr-subtraction-blows", &Wptr_subtraction_blows },
{ "default-bitfield-sign", &Wdefault_bitfield_sign },
{ "undef", &Wundefined_preprocessor },
diff --git a/lib.h b/lib.h
--- a/lib.h
+++ b/lib.h
@@ -79,6 +79,7 @@ extern int Wdefault_bitfield_sign;
extern int Wundefined_preprocessor;
extern int Wbitwise, Wtypesign, Wcontext;
extern int Wtransparent_union;
+extern int Wcast_to_address_space;

extern void declare_builtin_functions(void);
extern void create_builtin_stream(void);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
\
 
 \ /
  Last update: 2005-09-09 22:12    [W:0.221 / U:1.092 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site