aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2007-05-25 13:33:19 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2007-06-25 15:50:17 -0400
commit3d3763ab9fd749690e54135eef7a05f2901b3f30 (patch)
tree369903f5fc771b35fb4317c1011195deeab349c6 /evaluate.c
parent[PATCH] cleanup of evaluate_assign_op() (diff)
downloadsparse-3d3763ab9fd749690e54135eef7a05f2901b3f30.tar.gz
sparse-3d3763ab9fd749690e54135eef7a05f2901b3f30.tar.bz2
sparse-3d3763ab9fd749690e54135eef7a05f2901b3f30.zip
[PATCH] clean up the typechecking in arithmetics
* evaluate_binop() cleaned up * evaluate_add(), evaluate_sub(), evaluate_arith() are gone Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'evaluate.c')
-rw-r--r--evaluate.c171
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;