[PATCH 8/16] clean up the typechecking in arithmetics

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

 



* evaluate_binop() cleaned up
* evaluate_add(), evaluate_sub(), evaluate_arith() are gone

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

diff --git a/evaluate.c b/evaluate.c
index e299299..abd3b3e 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -377,6 +377,8 @@ static inline int classify_type(struct symbol *type, struct symbol **base)
 	return type_class[type->type];
 }
 
+#define is_int(class) ((class & (TYPE_NUM | TYPE_FLOAT)) == TYPE_NUM)
+
 static inline int is_string_type(struct symbol *type)
 {
 	if (type->type == SYM_NODE)
@@ -544,30 +546,6 @@ Restr:
 	goto Normal;
 }
 
-static struct symbol *evaluate_arith(struct expression *expr, int float_ok)
-{
-	struct symbol *ltype, *rtype;
-	int lclass = classify_type(expr->left->ctype, &ltype);
-	int rclass = classify_type(expr->right->ctype, &rtype);
-	struct symbol *ctype;
-
-	if (!(lclass & rclass & TYPE_NUM))
-		goto Bad;
-
-	if (!float_ok && (lclass | rclass) & TYPE_FLOAT)
-		goto Bad;
-
-	ctype = usual_conversions(expr->op, expr->left, expr->right,
-				  lclass, rclass, ltype, rtype);
-	expr->left = cast_to(expr->left, ctype);
-	expr->right = cast_to(expr->right, ctype);
-	expr->ctype = ctype;
-	return ctype;
-
-Bad:
-	return bad_expr_type(expr);
-}
-
 static inline int lvalue_expression(struct expression *expr)
 {
 	return expr->type == EXPR_PREOP && expr->op == '*';
@@ -582,20 +560,17 @@ static int ptr_object_size(struct symbol *ptr_type)
 	return ptr_type->bit_size;
 }
 
-static inline int want_int(struct expression **expr, struct symbol **ctype)
+static inline void want_int(struct expression **expr, struct symbol **ctype)
 {
 	int class = classify_type((*expr)->ctype, ctype);
 
-	if (!(class & TYPE_NUM))
-		return 0;
 	if (!(class & TYPE_RESTRICT))
-		return 1;
+		return;
 	warning((*expr)->pos, "restricted degrades to integer");
 	if (class & TYPE_FOULED)	/* unfoul it first */
 		(*ctype) = (*ctype)->ctype.base_type;
 	(*ctype) = (*ctype)->ctype.base_type;	/* get to arithmetic type */
 	*expr = cast_to(*expr, *ctype);
-	return 1;
 }
 
 static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *ctype, struct expression **ip)
@@ -604,8 +579,7 @@ static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *c
 	struct symbol *itype;
 	int bit_size;
 
-	if (!want_int(&i, &itype))
-		return bad_expr_type(expr);
+	want_int(&i, &itype);
 
 	examine_symbol_type(ctype);
 
@@ -644,20 +618,6 @@ static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *c
 	return ctype;
 }
 
-static struct symbol *evaluate_add(struct expression *expr)
-{
-	struct expression *left = expr->left, *right = expr->right;
-	struct symbol *ltype = left->ctype, *rtype = right->ctype;
-
-	if (is_ptr_type(ltype))
-		return evaluate_ptr_add(expr, degenerate(left), &expr->right);
-
-	if (is_ptr_type(rtype))
-		return evaluate_ptr_add(expr, degenerate(right), &expr->left);
-		
-	return evaluate_arith(expr, 1);
-}
-
 const char * type_difference(struct symbol *target, struct symbol *source,
 	unsigned long target_mod_ignore, unsigned long source_mod_ignore)
 {
@@ -836,23 +796,17 @@ static int is_null_ptr(struct expression *expr)
  */
 #define MOD_IGN (MOD_VOLATILE | MOD_CONST)
 
-static struct symbol *evaluate_ptr_sub(struct expression *expr, struct expression *l)
+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;
 
 	ltype = degenerate(l);
 	rtype = degenerate(r);
 
-	/*
-	 * If it is an integer subtract: the ptr add case will do the
-	 * right thing.
-	 */
-	if (!is_ptr_type(rtype))
-		return evaluate_ptr_add(expr, degenerate(l), &expr->right);
-
 	ctype = ltype;
 	typediff = type_difference(ltype, rtype, ~MOD_SIZE, ~MOD_SIZE);
 	if (typediff)
@@ -896,17 +850,6 @@ static struct symbol *evaluate_ptr_sub(struct expression *expr, struct expressio
 	return ssize_t_ctype;
 }
 
-static struct symbol *evaluate_sub(struct expression *expr)
-{
-	struct expression *left = expr->left;
-	struct symbol *ltype = left->ctype;
-
-	if (is_ptr_type(ltype))
-		return evaluate_ptr_sub(expr, left);
-
-	return evaluate_arith(expr, 1);
-}
-
 #define is_safe_type(type) ((type)->ctype.modifiers & MOD_SAFE)
 
 static struct symbol *evaluate_conditional(struct expression *expr, int iterator)
@@ -942,42 +885,64 @@ static struct symbol *evaluate_logical(struct expression *expr)
 static struct symbol *evaluate_shift(struct expression *expr)
 {
 	struct symbol *ltype, *rtype;
+	struct symbol *ctype;
 
-	if (want_int(&expr->left, &ltype) && want_int(&expr->right, &rtype)) {
-		struct symbol *ctype = integer_promotion(ltype);
-		expr->left = cast_to(expr->left, ctype);
-		expr->ctype = ctype;
-		ctype = integer_promotion(rtype);
-		expr->right = cast_to(expr->right, ctype);
-		return expr->ctype;
-	}
-	return bad_expr_type(expr);
+	want_int(&expr->left, &ltype);
+	want_int(&expr->right, &rtype);
+	ctype = integer_promotion(ltype);
+	expr->left = cast_to(expr->left, ctype);
+	expr->ctype = ctype;
+	ctype = integer_promotion(rtype);
+	expr->right = cast_to(expr->right, ctype);
+	return expr->ctype;
 }
 
 static struct symbol *evaluate_binop(struct expression *expr)
 {
-	switch (expr->op) {
-	// addition can take ptr+int, fp and int
-	case '+':
-		return evaluate_add(expr);
-
-	// subtraction can take ptr-ptr, fp and int
-	case '-':
-		return evaluate_sub(expr);
+	struct symbol *ltype, *rtype, *ctype;
+	int lclass = classify_type(expr->left->ctype, &ltype);
+	int rclass = classify_type(expr->right->ctype, &rtype);
+	int op = expr->op;
 
-	// Arithmetic operations can take fp and int
-	case '*': case '/':
-		return evaluate_arith(expr, 1);
+	/* number op number */
+	if (lclass & rclass & TYPE_NUM) {
+		if ((lclass | rclass) & TYPE_FLOAT) {
+			switch (op) {
+			case '+': case '-': case '*': case '/':
+				break;
+			default:
+				return bad_expr_type(expr);
+			}
+		}
 
-	// shifts do integer promotions, but that's it.
-	case SPECIAL_LEFTSHIFT: case SPECIAL_RIGHTSHIFT:
-		return evaluate_shift(expr);
+		// shifts do integer promotions, but that's it.
+		if (op == SPECIAL_LEFTSHIFT || op == SPECIAL_RIGHTSHIFT)
+			return evaluate_shift(expr);
 
-	// The rest are integer operations
-	// '%', '&', '^', '|'
-	default:
-		return evaluate_arith(expr, 0);
+		// The rest do usual conversions
+		ctype = usual_conversions(op, expr->left, expr->right,
+					  lclass, rclass, ltype, rtype);
+		expr->left = cast_to(expr->left, ctype);
+		expr->right = cast_to(expr->right, ctype);
+		expr->ctype = ctype;
+		return ctype;
 	}
+
+	/* pointer (+|-) integer */
+	if (lclass & TYPE_PTR && is_int(rclass) && (op == '+' || op == '-'))
+		return evaluate_ptr_add(expr, degenerate(expr->left),
+					&expr->right);
+
+	/* integer + pointer */
+	if (rclass & TYPE_PTR && is_int(lclass) && op == '+')
+		return evaluate_ptr_add(expr, degenerate(expr->right),
+					&expr->left);
+
+	/* pointer - pointer */
+	if (lclass & rclass & TYPE_PTR && expr->op == '-')
+		return evaluate_ptr_sub(expr);
+
+	return bad_expr_type(expr);
 }
 
 static struct symbol *evaluate_comma(struct expression *expr)
@@ -1004,6 +969,7 @@ static struct symbol *evaluate_compare(struct expression *expr)
 	struct expression *left = expr->left, *right = expr->right;
 	struct symbol *ltype = left->ctype, *rtype = right->ctype;
 	struct symbol *ctype;
+	int lclass, rclass;
 
 	/* Type types? */
 	if (is_type_type(ltype) && is_type_type(rtype))
@@ -1012,18 +978,27 @@ static struct symbol *evaluate_compare(struct expression *expr)
 	if (is_safe_type(ltype) || is_safe_type(rtype))
 		warning(expr->pos, "testing a 'safe expression'");
 
+	lclass = classify_type(ltype, &ltype);
+	rclass = classify_type(rtype, &rtype);
+
 	/* Pointer types? */
-	if (is_ptr_type(ltype) || is_ptr_type(rtype)) {
+	if ((lclass | rclass) & TYPE_PTR) {
 		// FIXME! Check the types for compatibility
 		expr->op = modify_for_unsigned(expr->op);
 		goto OK;
 	}
 
-	ctype = evaluate_arith(expr, 1);
-	if (ctype) {
-		if (ctype->ctype.modifiers & MOD_UNSIGNED)
-			expr->op = modify_for_unsigned(expr->op);
-	}
+	/* Both should be numbers */
+	if (!(lclass & rclass & TYPE_NUM))
+		return bad_expr_type(expr);
+
+	ctype = usual_conversions(expr->op, expr->left, expr->right,
+				  lclass, rclass, ltype, rtype);
+	expr->left = cast_to(expr->left, ctype);
+	expr->right = cast_to(expr->right, ctype);
+	if (ctype->ctype.modifiers & MOD_UNSIGNED)
+		expr->op = modify_for_unsigned(expr->op);
+
 OK:
 	expr->ctype = &bool_ctype;
 	return &bool_ctype;
@@ -1151,7 +1126,7 @@ static int evaluate_assign_op(struct expression *expr)
 		expr->right = cast_to(expr->right, target);
 		return 0;
 	}
-	if (tclass & TYPE_PTR) {
+	if (tclass & TYPE_PTR && is_int(sclass)) {
 		if (op == SPECIAL_ADD_ASSIGN || op == SPECIAL_SUB_ASSIGN) {
 			evaluate_ptr_add(expr, target, &expr->right);
 			return 1;
-- 
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