[PATCH 8/8] deal correctly with qualifiers on arrays

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

 



* new helper: examine_pointer_target().  Examine target, find address_space
et.al.  If the target is SYM_NODE - merge it, etc.
* new helper: target_qualifiers().  Pointers to any array are considered
as pointers to unqualified type as far as implicit conversions are
concerned; handle that right.
* SYM_TYPEOF can be handled sanely now: don't copy the node, just convert
SYM_TYPEOF to SYM_NODE and examine that.

Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
---
 evaluate.c |   71 +++++++++++++++++++++++++++++++----------------------------
 symbol.c   |   37 ++++++++++++++++---------------
 symbol.h   |    1 +
 3 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/evaluate.c b/evaluate.c
index 213039b..db33442 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -703,12 +703,12 @@ const char *type_difference(struct ctype *c1, struct ctype *c2,
 			if ((mod1 ^ mod2) & ~MOD_IGNORE & ~MOD_SPECIFIER)
 				return "different modifiers";
 			/* we could be lazier here */
+			base1 = examine_pointer_target(t1);
+			base2 = examine_pointer_target(t2);
 			mod1 = t1->ctype.modifiers;
 			as1 = t1->ctype.as;
 			mod2 = t2->ctype.modifiers;
 			as2 = t2->ctype.as;
-			base1 = examine_symbol_type(base1);
-			base2 = examine_symbol_type(base2);
 			break;
 		case SYM_FN: {
 			struct symbol *arg1, *arg2;
@@ -801,10 +801,17 @@ static void bad_null(struct expression *expr)
 		warning(expr->pos, "Using plain integer as NULL pointer");
 }
 
+static unsigned long target_qualifiers(struct symbol *type)
+{
+	unsigned long mod = type->ctype.modifiers & MOD_IGN;
+	if (type->ctype.base_type && type->ctype.base_type->type == SYM_ARRAY)
+		mod = 0;
+	return mod;
+}
+
 static struct symbol *evaluate_ptr_sub(struct expression *expr)
 {
 	const char *typediff;
-	struct symbol *ctype;
 	struct symbol *ltype, *rtype;
 	struct expression *l = expr->left;
 	struct expression *r = expr->right;
@@ -813,28 +820,25 @@ static struct symbol *evaluate_ptr_sub(struct expression *expr)
 	classify_type(degenerate(l), &ltype);
 	classify_type(degenerate(r), &rtype);
 
-	lbase = get_base_type(ltype);
-	rbase = get_base_type(rtype);
+	lbase = examine_pointer_target(ltype);
+	rbase = examine_pointer_target(rtype);
 	typediff = type_difference(&ltype->ctype, &rtype->ctype,
-				   MOD_IGN, MOD_IGN);
+				   target_qualifiers(rtype),
+				   target_qualifiers(ltype));
 	if (typediff)
 		expression_error(expr, "subtraction of different types can't work (%s)", typediff);
 
-	ctype = lbase;
-	/* Figure out the base type we point to */
-	if (ctype->type == SYM_NODE)
-		ctype = ctype->ctype.base_type;
-	if (ctype->type == SYM_FN) {
+	if (lbase->type == SYM_FN) {
 		expression_error(expr, "subtraction of functions? Share your drugs");
 		return NULL;
 	}
 
 	expr->ctype = ssize_t_ctype;
-	if (ctype->bit_size > bits_in_char) {
+	if (lbase->bit_size > bits_in_char) {
 		struct expression *sub = alloc_expression(expr->pos, EXPR_BINOP);
 		struct expression *div = expr;
 		struct expression *val = alloc_expression(expr->pos, EXPR_VALUE);
-		unsigned long value = ctype->bit_size >> 3;
+		unsigned long value = lbase->bit_size >> 3;
 
 		val->ctype = size_t_ctype;
 		val->value = value;
@@ -1050,8 +1054,8 @@ static struct symbol *evaluate_compare(struct expression *expr)
 		return bad_expr_type(expr);
 	expr->op = modify_for_unsigned(expr->op);
 
-	lbase = get_base_type(ltype);
-	rbase = get_base_type(rtype);
+	lbase = examine_pointer_target(ltype);
+	rbase = examine_pointer_target(rtype);
 
 	/* they also have special treatment for pointers to void */
 	if (expr->op == SPECIAL_EQUAL || expr->op == SPECIAL_NOTEQUAL) {
@@ -1068,7 +1072,8 @@ static struct symbol *evaluate_compare(struct expression *expr)
 	}
 
 	typediff = type_difference(&ltype->ctype, &rtype->ctype,
-				   MOD_IGN, MOD_IGN);
+				   target_qualifiers(rtype),
+				   target_qualifiers(ltype));
 	if (!typediff)
 		goto OK;
 
@@ -1164,10 +1169,9 @@ static struct symbol *evaluate_conditional_expression(struct expression *expr)
 		}
 
 		/* need to be lazier here */
-		lbase = get_base_type(ltype);
-		rbase = get_base_type(rtype);
-		qual = ltype->ctype.modifiers | rtype->ctype.modifiers;
-		qual &= MOD_CONST | MOD_VOLATILE;
+		lbase = examine_pointer_target(ltype);
+		rbase = examine_pointer_target(rtype);
+		qual = target_qualifiers(ltype) | target_qualifiers(rtype);
 
 		if (lbase == &void_ctype) {
 			/* XXX: pointers to function should warn here */
@@ -1183,7 +1187,7 @@ static struct symbol *evaluate_conditional_expression(struct expression *expr)
 		/* XXX: that should be pointer to composite */
 		ctype = ltype;
 		typediff = type_difference(&ltype->ctype, &rtype->ctype,
-					   MOD_IGN, MOD_IGN);
+					   qual, qual);
 		if (!typediff)
 			goto Qual;
 		goto Err;
@@ -1314,11 +1318,10 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
 			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);
+		b1 = examine_pointer_target(t);
+		b2 = examine_pointer_target(s);
+		mod1 = target_qualifiers(t);
+		mod2 = target_qualifiers(s);
 		if (b1 == &void_ctype || b2 == &void_ctype) {
 			/*
 			 * assignments to/from void * are OK, provided that
@@ -1329,15 +1332,14 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
 				typediff = "different address spaces";
 				goto Err;
 			}
-			if (mod2 & ~mod1 & MOD_IGN) {
+			if (mod2 & ~mod1) {
 				typediff = "different modifiers";
 				goto Err;
 			}
 			goto Cast;
 		}
 		/* It's OK if the target is more volatile or const than the source */
-		typediff = type_difference(&t->ctype, &s->ctype,
-					   0, mod1 & MOD_IGN);
+		typediff = type_difference(&t->ctype, &s->ctype, 0, mod1);
 		if (typediff)
 			goto Err;
 		return 1;
@@ -2623,9 +2625,6 @@ static struct symbol *evaluate_cast(struct expression *expr)
 	if (class1 & TYPE_COMPOUND)
 		warning(expr->pos, "cast to non-scalar");
 
-	if (class1 == TYPE_PTR)
-		get_base_type(t1);
-
 	t2 = target->ctype;
 	if (!t2) {
 		expression_error(expr, "cast from unknown type");
@@ -2652,13 +2651,17 @@ static struct symbol *evaluate_cast(struct expression *expr)
 
 	if (t1 == &ulong_ctype)
 		as1 = -1;
-	else if (class1 == TYPE_PTR)
+	else if (class1 == TYPE_PTR) {
+		examine_pointer_target(t1);
 		as1 = t1->ctype.as;
+	}
 
 	if (t2 == &ulong_ctype)
 		as2 = -1;
-	else if (class2 == TYPE_PTR)
+	else if (class2 == TYPE_PTR) {
+		examine_pointer_target(t2);
 		as2 = t2->ctype.as;
+	}
 
 	if (!as1 && as2 > 0)
 		warning(expr->pos, "cast removes address space of expression");
diff --git a/symbol.c b/symbol.c
index 9dfeb41..a64815c 100644
--- a/symbol.c
+++ b/symbol.c
@@ -193,13 +193,16 @@ static struct symbol *examine_base_type(struct symbol *sym)
 	struct symbol *base_type;
 
 	/* Check the base type */
-	base_type = sym->ctype.base_type;
-	if (base_type) {
-		base_type = examine_symbol_type(base_type);
-
-		/* "typeof" can cause this */
-		if (base_type && base_type->type == SYM_NODE)
-			merge_type(sym, base_type);
+	base_type = examine_symbol_type(sym->ctype.base_type);
+	if (!base_type || base_type->type == SYM_PTR)
+		return base_type;
+	sym->ctype.as |= base_type->ctype.as;
+	sym->ctype.modifiers |= base_type->ctype.modifiers & MOD_PTRINHERIT;
+	concat_ptr_list((struct ptr_list *)base_type->ctype.contexts,
+			(struct ptr_list **)&sym->ctype.contexts);
+	if (base_type->type == SYM_NODE) {
+		base_type = base_type->ctype.base_type;
+		sym->ctype.base_type = base_type;
 	}
 	return base_type;
 }
@@ -410,17 +413,10 @@ struct symbol *examine_symbol_type(struct symbol * sym)
 				warning(base->pos, "typeof applied to bitfield type");
 			if (base->type == SYM_NODE)
 				base = base->ctype.base_type;
-			switch (base->type) {
-			case SYM_RESTRICT:
-			case SYM_UNION:
-			case SYM_STRUCT:
-				sym->type = SYM_NODE;
-				sym->ctype.modifiers = 0;
-				sym->ctype.base_type = base;
-				return examine_node_type(sym);
-			}
-			*sym = *base;
-			break;
+			sym->type = SYM_NODE;
+			sym->ctype.modifiers = 0;
+			sym->ctype.base_type = base;
+			return examine_node_type(sym);
 		}
 		break;
 	}
@@ -443,6 +439,11 @@ struct symbol *examine_symbol_type(struct symbol * sym)
 	return sym;
 }
 
+struct symbol *examine_pointer_target(struct symbol *sym)
+{
+	return examine_base_type(sym);
+}
+
 static struct symbol_list *restr, *fouled;
 
 void create_fouled(struct symbol *type)
diff --git a/symbol.h b/symbol.h
index bf5b675..9b24f40 100644
--- a/symbol.h
+++ b/symbol.h
@@ -263,6 +263,7 @@ extern void add_symbol(struct symbol_list **, struct symbol *);
 extern void bind_symbol(struct symbol *, struct ident *, enum namespace);
 
 extern struct symbol *examine_symbol_type(struct symbol *);
+extern struct symbol *examine_pointer_target(struct symbol *);
 extern void examine_simple_symbol_type(struct symbol *);
 extern const char *show_typename(struct symbol *sym);
 extern const char *builtin_typename(struct symbol *sym);
-- 
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