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

Reply via email to