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 <[EMAIL PROTECTED]>
---
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 [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html