mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: viro@ZenIV.linux.org.uk
To: Linus Torvalds <torvalds@osdl.org>
Cc: Andreas Schwab <schwab@suse.de>, linux-kernel@vger.kernel.org
Subject: Re: [sparse fix] (was Re: [PATCH] bogus cast in bio.c)
Date: Fri, 9 Sep 2005 21:10:18 +0100	[thread overview]
Message-ID: <20050909201018.GA9623@ZenIV.linux.org.uk> (raw)
In-Reply-To: <Pine.LNX.4.58.0509091114300.3051@g5.osdl.org>

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);

      reply	other threads:[~2005-09-09 20:10 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-09 15:53 [PATCH] bogus cast in bio.c viro
2005-09-09 16:18 ` Andreas Schwab
2005-09-09 16:36   ` viro
2005-09-09 17:29     ` [sparse fix] (was Re: [PATCH] bogus cast in bio.c) viro
2005-09-09 17:34       ` viro
2005-09-09 17:48       ` Linus Torvalds
2005-09-09 18:15         ` Linus Torvalds
2005-09-09 20:10           ` viro [this message]

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=20050909201018.GA9623@ZenIV.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=schwab@suse.de \
    --cc=torvalds@osdl.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®