[PATCH 3/16] mechanically split compatible_assignment_types()

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

 



Pure assignment and <op>= cases are different enough to make it easier handling
them in separate functions.  For now just split compatible_assignment_types()
in two; the next patches will clean each up.

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

diff --git a/evaluate.c b/evaluate.c
index be67fa8..febfad2 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1130,19 +1130,16 @@ out:
 /* FP assignments can not do modulo or bit operations */
 static int compatible_float_op(int op)
 {
-	return	op == '=' ||
-		op == SPECIAL_ADD_ASSIGN ||
+	return	op == SPECIAL_ADD_ASSIGN ||
 		op == SPECIAL_SUB_ASSIGN ||
 		op == SPECIAL_MUL_ASSIGN ||
 		op == SPECIAL_DIV_ASSIGN;
 }
 
-static int compatible_assignment_types(struct expression *expr, struct symbol *target,
-	struct expression **rp, struct symbol *source, const char *where, int op)
+static int evaluate_assign_op(struct expression *expr, struct symbol *target,
+	struct expression **rp, struct symbol *source, int op)
 {
-	const char *typediff;
 	struct symbol *t, *s;
-	int target_as;
 	int tclass = classify_type(target, &t);
 	int sclass = classify_type(source, &s);
 
@@ -1163,20 +1160,49 @@ static int compatible_assignment_types(struct expression *expr, struct symbol *t
 				return 1;
 		} else if (!(sclass & TYPE_RESTRICT))
 			goto Cast;
+		/* source and target would better be identical restricted */
+		if (t == s)
+			return 1;
+		warning(expr->pos, "invalid restricted assignment");
+		*rp = cast_to(*rp, target);
+		return 0;
 	} else if (tclass & TYPE_PTR) {
 		if (op == SPECIAL_ADD_ASSIGN || op == SPECIAL_SUB_ASSIGN) {
 			evaluate_ptr_add(expr, target, rp);
 			return 1;
 		}
-		if (op != '=') {
-			expression_error(expr, "invalid pointer assignment");
-			return 0;
-		}
-	} else if (op != '=') {
+		expression_error(expr, "invalid pointer assignment");
+		return 0;
+	} else {
 		expression_error(expr, "invalid assignment");
 		return 0;
 	}
 
+Cast:
+	*rp = cast_to(*rp, target);
+	return 1;
+}
+
+static int compatible_assignment_types(struct expression *expr, struct symbol *target,
+	struct expression **rp, struct symbol *source, const char *where)
+{
+	const char *typediff;
+	struct symbol *t, *s;
+	int target_as;
+	int tclass = classify_type(target, &t);
+	int sclass = classify_type(source, &s);
+
+	if (tclass & sclass & TYPE_NUM) {
+		if (tclass & TYPE_RESTRICT) {
+			/* allowed assignments unfoul */
+			if (sclass & TYPE_FOULED && s->ctype.base_type == t)
+				goto Cast;
+			if (!restricted_value(*rp, target))
+				return 1;
+		} else if (!(sclass & TYPE_RESTRICT))
+			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)
@@ -1268,8 +1294,13 @@ static struct symbol *evaluate_assignment(struct expression *expr)
 
 	rtype = degenerate(right);
 
-	if (!compatible_assignment_types(where, ltype, &where->right, rtype, "assignment", expr->op))
-		return NULL;
+	if (expr->op != '=') {
+		if (!evaluate_assign_op(where, ltype, &where->right, rtype, expr->op))
+			return NULL;
+	} else {
+		if (!compatible_assignment_types(where, ltype, &where->right, rtype, "assignment"))
+			return NULL;
+	}
 
 	evaluate_assign_to(left, ltype);
 
@@ -1918,7 +1949,7 @@ static int evaluate_arguments(struct symbol *f, struct symbol *fn, struct expres
 			static char where[30];
 			examine_symbol_type(target);
 			sprintf(where, "argument %d", i);
-			compatible_assignment_types(expr, target, p, ctype, where, '=');
+			compatible_assignment_types(expr, target, p, ctype, where);
 		}
 
 		i++;
@@ -2307,7 +2338,7 @@ static int handle_simple_initializer(struct expression **ep, int nested,
 		if (!e->ctype)
 			return 1;
 		compatible_assignment_types(e, ctype, ep, degenerate(e),
-					    "initializer", '=');
+					    "initializer");
 		return 1;
 	}
 
@@ -2805,7 +2836,7 @@ static struct symbol *evaluate_return_expression(struct statement *stmt)
 	}
 	if (!ctype)
 		return NULL;
-	compatible_assignment_types(expr, fntype, &stmt->expression, ctype, "return expression", '=');
+	compatible_assignment_types(expr, fntype, &stmt->expression, ctype, "return expression");
 	return NULL;
 }
 
-- 
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