[PATCH 5/8] get compatible_assignment_types() deal with all cases

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



a) pointer to _Bool is OK
b) struct to same struct or union to same union is OK; void to void etc. are not
c) to/from void * with loss of qualifiers or with different address space
   should give the right warning itself instead of "different base types"
   it would get from fallback to type_difference()

Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
---
 evaluate.c |   57 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/evaluate.c b/evaluate.c
index 91c7f74..44a4da4 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1259,11 +1259,17 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
 				goto Cast;
 			if (!restricted_value(*rp, target))
 				return 1;
+			if (s == t)
+				return 1;
 		} else if (!(sclass & TYPE_RESTRICT))
 			goto Cast;
+		typediff = "different base types";
+		goto Err;
 	}
 
-	if (tclass & TYPE_PTR) {
+	if (tclass == TYPE_PTR) {
+		unsigned long mod1, mod2;
+		struct symbol *b1, *b2;
 		// NULL pointer is always OK
 		int is_null = is_null_pointer_constant(*rp);
 		if (is_null) {
@@ -1271,29 +1277,52 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
 				bad_null(*rp);
 			goto Cast;
 		}
-		if (sclass & TYPE_PTR && t->ctype.as == s->ctype.as) {
-			/* we should be more lazy here */
-			int mod1 = t->ctype.modifiers;
-			int mod2 = s->ctype.modifiers;
-			s = get_base_type(s);
-			t = get_base_type(t);
-
+		if (!(sclass & TYPE_PTR)) {
+			typediff = "different base types";
+			goto Err;
+		}
+		/* we should be more lazy here */
+		mod1 = t->ctype.modifiers;
+		mod2 = s->ctype.modifiers;
+		b1 = get_base_type(t);
+		b2 = get_base_type(s);
+		if (b1 == &void_ctype || b2 == &void_ctype) {
 			/*
 			 * assignments to/from void * are OK, provided that
 			 * we do not remove qualifiers from pointed to [C]
 			 * or mix address spaces [sparse].
 			 */
-			if (!(mod2 & ~mod1 & (MOD_VOLATILE | MOD_CONST)))
-				if (s == &void_ctype || t == &void_ctype)
-					goto Cast;
+			if (t->ctype.as != s->ctype.as) {
+				typediff = "different address spaces";
+				goto Err;
+			}
+			if (mod2 & ~mod1 & MOD_IGN) {
+				typediff = "different modifiers";
+				goto Err;
+			}
+			goto Cast;
 		}
+		/* It's OK if the target is more volatile or const than the source */
+		typediff = type_difference(target, source,
+					   MOD_VOLATILE | MOD_CONST, 0);
+		if (typediff)
+			goto Err;
+		return 1;
 	}
 
-	/* It's OK if the target is more volatile or const than the source */
-	typediff = type_difference(target, source, MOD_VOLATILE | MOD_CONST, 0);
-	if (!typediff)
+	if ((tclass & TYPE_COMPOUND) && s == t)
 		return 1;
 
+	if (tclass & TYPE_NUM) {
+		/* XXX: need to turn into comparison with NULL */
+		if (t == &bool_ctype && (sclass & TYPE_PTR))
+			goto Cast;
+		typediff = "different base types";
+		goto Err;
+	}
+	typediff = "invalid types";
+
+Err:
 	warning(expr->pos, "incorrect type in %s (%s)", where, typediff);
 	info(expr->pos, "   expected %s", show_typename(target));
 	info(expr->pos, "   got %s", show_typename(source));
-- 
1.5.0-rc2.GIT


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

[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux