Turn FORCE_MOD into storage class specifier (that's how it's
actually used and that makes for much simpler logics).

Introduce explicit EXPR_FORCE_CAST for forced casts; handle it
properly.

Kill the idiocy in get_as() (we end up picking the oddest things
for address space - e.g. if we have int __attribute__((address_space(1))) *p,
we'll get warnings about removal of address space when we do things like
(unsigned short)*p.  Fixed.  BTW, that had caught a bunch of very odd
bogosities in the kernel and eliminated several false positives in there.

As the result, get_as() is gone now and evaluate_cast() got simpler.

Kill the similar idiocy in handling pointer assignments; while we are at it,
fix the qualifiers check for assignments to/from void * (you can't assign
const int * to void * - qualifiers on the left side should be no less than
on the right one; for normal codepath we get that checked, but the special
case of void * skips these checks).

Signed-off-by: Al Viro <[EMAIL PROTECTED]>
---
 compile-i386.c |    1 +
 dissect.c      |    2 +-
 evaluate.c     |   91 +++++++++++++++++++++++---------------------------------
 expand.c       |    1 +
 expression.c   |   18 ++++++++---
 expression.h   |    3 +-
 inline.c       |    1 +
 linearize.c    |    1 +
 parse.c        |    7 +++-
 show-parse.c   |    1 +
 symbol.h       |    4 +-
 11 files changed, 65 insertions(+), 65 deletions(-)

diff --git a/compile-i386.c b/compile-i386.c
index 425a1bc..8526408 100644
--- a/compile-i386.c
+++ b/compile-i386.c
@@ -2351,6 +2351,7 @@ static struct storage *x86_expression(struct expression 
*expr)
                warning(expr->pos, "invalid expression after evaluation");
                return NULL;
        case EXPR_CAST:
+       case EXPR_FORCE_CAST:
        case EXPR_IMPLIED_CAST:
                return emit_cast_expr(expr);
        case EXPR_VALUE:
diff --git a/dissect.c b/dissect.c
index 9dc3df9..61240d7 100644
--- a/dissect.c
+++ b/dissect.c
@@ -317,7 +317,7 @@ again:
                do_expression(U_VOID, expr->left);
                ret = do_expression(mode, expr->right);
 
-       break; case EXPR_CAST: //case EXPR_IMPLIED_CAST:
+       break; case EXPR_CAST: case EXPR_FORCE_CAST: //case EXPR_IMPLIED_CAST:
                ret = base_type(expr->cast_type);
                do_initializer(ret, expr->cast_expression);
 
diff --git a/evaluate.c b/evaluate.c
index b97a4d7..d505007 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -1276,6 +1276,22 @@ static int compatible_assignment_types(struct expression 
*expr, struct symbol *t
                                bad_null(*rp);
                        goto Cast;
                }
+               if (sclass & TYPE_PTR && t->ctype.as == s->ctype.as) {
+                       /* we should be more lazy here */
+                       int mod1 = t->ctype.modifiers;
+                       int mod2 = s->ctype.modifiers;
+                       s = get_base_type(s);
+                       t = get_base_type(t);
+
+                       /*
+                        * assignments to/from void * are OK, provided that
+                        * we do not remove qualifiers from pointed to [C]
+                        * or mix address spaces [sparse].
+                        */
+                       if (!(mod2 & ~mod1 & (MOD_VOLATILE | MOD_CONST)))
+                               if (s == &void_ctype || t == &void_ctype)
+                                       goto Cast;
+               }
        }
 
        /* It's OK if the target is more volatile or const than the source */
@@ -1283,22 +1299,6 @@ static int compatible_assignment_types(struct expression 
*expr, struct symbol *t
        if (!typediff)
                return 1;
 
-       /* Pointer destination? */
-       if (tclass & TYPE_PTR) {
-               int source_as;
-               int target_as;
-
-               /* "void *" matches anything as long as the address space is OK 
*/
-               target_as = t->ctype.as | target->ctype.as;
-               source_as = s->ctype.as | source->ctype.as;
-               if (source_as == target_as && (s->type == SYM_PTR || s->type == 
SYM_ARRAY)) {
-                       s = get_base_type(s);
-                       t = get_base_type(t);
-                       if (s == &void_ctype || t == &void_ctype)
-                               goto Cast;
-               }
-       }
-
        warning(expr->pos, "incorrect type in %s (%s)", where, typediff);
        info(expr->pos, "   expected %s", show_typename(target));
        info(expr->pos, "   got %s", show_typename(source));
@@ -1330,6 +1330,7 @@ static void mark_assigned(struct expression *expr)
                mark_assigned(expr->right);
                return;
        case EXPR_CAST:
+       case EXPR_FORCE_CAST:
                mark_assigned(expr->cast_expression);
                return;
        case EXPR_SLICE:
@@ -2496,46 +2497,13 @@ static void evaluate_initializer(struct symbol *ctype, 
struct expression **ep)
                expression_error(*ep, "invalid initializer");
 }
 
-static int get_as(struct symbol *sym)
-{
-       int as;
-       unsigned long mod;
-
-       if (!sym)
-               return 0;
-       as = sym->ctype.as;
-       mod = sym->ctype.modifiers;
-       if (sym->type == SYM_NODE) {
-               sym = sym->ctype.base_type;
-               as |= sym->ctype.as;
-               mod |= sym->ctype.modifiers;
-       }
-
-       /*
-        * At least for now, allow casting to a "unsigned long".
-        * That's how we do things like pointer arithmetic and
-        * store pointers to registers.
-        */
-       if (sym == &ulong_ctype)
-               return -1;
-
-       if (sym && sym->type == SYM_PTR) {
-               sym = get_base_type(sym);
-               as |= sym->ctype.as;
-               mod |= sym->ctype.modifiers;
-       }
-       if (mod & MOD_FORCE)
-               return -1;
-       return as;
-}
-
 static struct symbol *evaluate_cast(struct expression *expr)
 {
        struct expression *target = expr->cast_expression;
        struct symbol *ctype;
        struct symbol *t1, *t2;
        int class1, class2;
-       int as1, as2;
+       int as1 = 0, as2 = 0;
 
        if (!target)
                return NULL;
@@ -2596,6 +2564,9 @@ static struct symbol *evaluate_cast(struct expression 
*expr)
        if (class1 & TYPE_COMPOUND)
                warning(expr->pos, "cast to non-scalar");
 
+       if (class1 == TYPE_PTR)
+               get_base_type(t1);
+
        t2 = target->ctype;
        if (!t2) {
                expression_error(expr, "cast from unknown type");
@@ -2606,19 +2577,30 @@ static struct symbol *evaluate_cast(struct expression 
*expr)
        if (class2 & TYPE_COMPOUND)
                warning(expr->pos, "cast from non-scalar");
 
+       if (expr->type == EXPR_FORCE_CAST)
+               goto out;
+
        /* allowed cast unfouls */
        if (class2 & TYPE_FOULED)
                t2 = t2->ctype.base_type;
 
-       if (!(ctype->ctype.modifiers & MOD_FORCE) && t1 != t2) {
+       if (t1 != t2) {
                if (class1 & TYPE_RESTRICT)
                        warning(expr->pos, "cast to restricted type");
                if (class2 & TYPE_RESTRICT)
                        warning(expr->pos, "cast from restricted type");
        }
 
-       as1 = get_as(ctype);
-       as2 = get_as(target->ctype);
+       if (t1 == &ulong_ctype)
+               as1 = -1;
+       else if (class1 == TYPE_PTR)
+               as1 = t1->ctype.as;
+
+       if (t2 == &ulong_ctype)
+               as2 = -1;
+       else if (class2 == TYPE_PTR)
+               as2 = t2->ctype.as;
+
        if (!as1 && as2 > 0)
                warning(expr->pos, "cast removes address space of expression");
        if (as1 > 0 && as2 > 0 && as1 != as2)
@@ -2628,7 +2610,7 @@ static struct symbol *evaluate_cast(struct expression 
*expr)
                warning(expr->pos,
                        "cast adds address space to expression (<asn:%d>)", 
as1);
 
-       if (!(ctype->ctype.modifiers & MOD_PTRINHERIT) && class1 == TYPE_PTR &&
+       if (!(t1->ctype.modifiers & MOD_PTRINHERIT) && class1 == TYPE_PTR &&
            !as1 && (target->flags & Int_const_expr)) {
                if (t1->ctype.base_type == &void_ctype) {
                        if (is_zero_constant(target)) {
@@ -2860,6 +2842,7 @@ struct symbol *evaluate_expression(struct expression 
*expr)
                        return NULL;
                return evaluate_postop(expr);
        case EXPR_CAST:
+       case EXPR_FORCE_CAST:
        case EXPR_IMPLIED_CAST:
                return evaluate_cast(expr);
        case EXPR_SIZEOF:
diff --git a/expand.c b/expand.c
index b2eeef8..06b8127 100644
--- a/expand.c
+++ b/expand.c
@@ -955,6 +955,7 @@ static int expand_expression(struct expression *expr)
                return expand_postop(expr);
 
        case EXPR_CAST:
+       case EXPR_FORCE_CAST:
        case EXPR_IMPLIED_CAST:
                return expand_cast(expr);
 
diff --git a/expression.c b/expression.c
index 65f959e..77d665d 100644
--- a/expression.c
+++ b/expression.c
@@ -118,7 +118,7 @@ static struct token *parse_type(struct token *token, struct 
expression **tree)
        struct symbol *sym;
        *tree = alloc_expression(token->pos, EXPR_TYPE);
        (*tree)->flags = Int_const_expr; /* sic */
-       token = typename(token, &sym);
+       token = typename(token, &sym, 0);
        if (sym->ident)
                sparse_error(token->pos,
                             "type expression should not include identifier "
@@ -167,7 +167,7 @@ static struct token *builtin_offsetof_expr(struct token 
*token,
                return expect(token, '(', "after __builtin_offset");
 
        token = token->next;
-       token = typename(token, &sym);
+       token = typename(token, &sym, 0);
        if (sym->ident)
                sparse_error(token->pos,
                             "type expression should not include identifier "
@@ -482,7 +482,7 @@ struct token *primary_expression(struct token *token, 
struct expression **tree)
                if (token->special == '[' && lookup_type(token->next)) {
                        expr = alloc_expression(token->pos, EXPR_TYPE);
                        expr->flags = Int_const_expr; /* sic */
-                       token = typename(token->next, &expr->symbol);
+                       token = typename(token->next, &expr->symbol, 0);
                        token = expect(token, ']', "in type expression");
                        break;
                }
@@ -600,7 +600,7 @@ static struct token *type_info_expression(struct token 
*token,
        token = token->next;
        if (!match_op(token, '(') || !lookup_type(token->next))
                return unary_expression(token, &expr->cast_expression);
-       token = typename(token->next, &expr->cast_type);
+       token = typename(token->next, &expr->cast_type, 0);
 
        if (!match_op(token, ')')) {
                static const char * error[] = {
@@ -715,15 +715,23 @@ static struct token *cast_expression(struct token *token, 
struct expression **tr
                        struct expression *cast = alloc_expression(next->pos, 
EXPR_CAST);
                        struct expression *v;
                        struct symbol *sym;
+                       int is_force;
 
-                       token = typename(next, &sym);
+                       token = typename(next, &sym, MOD_FORCE);
                        cast->cast_type = sym;
+                       is_force = sym->ctype.modifiers & MOD_FORCE;
+                       sym->ctype.modifiers &= ~MOD_FORCE;
                        token = expect(token, ')', "at end of cast operator");
                        if (match_op(token, '{')) {
+                               if (is_force)
+                                       warning(sym->pos,
+                                               "[force] in compound literal");
                                token = initializer(&cast->cast_expression, 
token);
                                return postfix_expression(token, tree, cast);
                        }
                        *tree = cast;
+                       if (is_force)
+                               cast->type = EXPR_FORCE_CAST;
                        token = cast_expression(token, &v);
                        if (!v)
                                return token;
diff --git a/expression.h b/expression.h
index 02eec02..fa5039a 100644
--- a/expression.h
+++ b/expression.h
@@ -27,6 +27,7 @@ enum expression_type {
        EXPR_PREOP,
        EXPR_POSTOP,
        EXPR_CAST,
+       EXPR_FORCE_CAST,
        EXPR_IMPLIED_CAST,
        EXPR_SIZEOF,
        EXPR_ALIGNOF,
@@ -190,7 +191,7 @@ static inline struct expression 
*alloc_const_expression(struct position pos, int
 }
 
 /* Type name parsing */
-struct token *typename(struct token *, struct symbol **);
+struct token *typename(struct token *, struct symbol **, int);
 
 static inline int lookup_type(struct token *token)
 {
diff --git a/inline.c b/inline.c
index 061261a..860c0ee 100644
--- a/inline.c
+++ b/inline.c
@@ -145,6 +145,7 @@ static struct expression * copy_expression(struct 
expression *expr)
                        *expr->cast_type = *sym;
                        break;
                }
+       case EXPR_FORCE_CAST:
        case EXPR_IMPLIED_CAST:
        case EXPR_SIZEOF: 
        case EXPR_PTRSIZEOF:
diff --git a/linearize.c b/linearize.c
index 3a07823..8a68f05 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1581,6 +1581,7 @@ pseudo_t linearize_expression(struct entrypoint *ep, 
struct expression *expr)
                return linearize_postop(ep, expr);
 
        case EXPR_CAST:
+       case EXPR_FORCE_CAST:
        case EXPR_IMPLIED_CAST:
                return linearize_cast(ep, expr);
        
diff --git a/parse.c b/parse.c
index ab3a096..68f1dac 100644
--- a/parse.c
+++ b/parse.c
@@ -768,7 +768,7 @@ static struct token *typeof_specifier(struct token *token, 
struct ctype *ctype)
                return token;
        }
        if (lookup_type(token->next)) {
-               token = typename(token->next, &sym);
+               token = typename(token->next, &sym, 0);
                *ctype = sym->ctype;
        } else {
                struct symbol *typeof_sym = alloc_symbol(token->pos, 
SYM_TYPEOF);
@@ -1343,13 +1343,16 @@ static struct token *parameter_declaration(struct token 
*token, struct symbol **
        return token;
 }
 
-struct token *typename(struct token *token, struct symbol **p)
+struct token *typename(struct token *token, struct symbol **p, int mod)
 {
        struct symbol *sym = alloc_symbol(token->pos, SYM_NODE);
        *p = sym;
        token = declaration_specifiers(token, &sym->ctype, 0);
        token = declarator(token, sym, NULL);
        apply_modifiers(token->pos, &sym->ctype);
+       if (sym->ctype.modifiers & MOD_STORAGE & ~mod)
+               warning(sym->pos, "storage class in typename (%s)",
+                       show_typename(sym));
        return token;
 }
 
diff --git a/show-parse.c b/show-parse.c
index 07ee763..aae8b74 100644
--- a/show-parse.c
+++ b/show-parse.c
@@ -1053,6 +1053,7 @@ int show_expression(struct expression *expr)
                warning(expr->pos, "invalid expression after evaluation");
                return 0;
        case EXPR_CAST:
+       case EXPR_FORCE_CAST:
        case EXPR_IMPLIED_CAST:
                return show_cast_expr(expr);
        case EXPR_VALUE:
diff --git a/symbol.h b/symbol.h
index a59feee..4d8d328 100644
--- a/symbol.h
+++ b/symbol.h
@@ -204,12 +204,12 @@ struct symbol {
 #define MOD_BITWISE    0x80000000
 
 #define MOD_NONLOCAL   (MOD_EXTERN | MOD_TOPLEVEL)
-#define MOD_STORAGE    (MOD_AUTO | MOD_REGISTER | MOD_STATIC | MOD_EXTERN | 
MOD_INLINE | MOD_TOPLEVEL)
+#define MOD_STORAGE    (MOD_AUTO | MOD_REGISTER | MOD_STATIC | MOD_EXTERN | 
MOD_INLINE | MOD_TOPLEVEL | MOD_FORCE)
 #define MOD_SIGNEDNESS (MOD_SIGNED | MOD_UNSIGNED | MOD_EXPLICITLY_SIGNED)
 #define MOD_SPECIFIER  (MOD_CHAR | MOD_SHORT | MOD_LONG | MOD_LONGLONG | 
MOD_SIGNEDNESS)
 #define MOD_SIZE       (MOD_CHAR | MOD_SHORT | MOD_LONG | MOD_LONGLONG)
 #define MOD_IGNORE (MOD_TOPLEVEL | MOD_STORAGE | MOD_ADDRESSABLE |     \
-       MOD_ASSIGNED | MOD_USERTYPE | MOD_FORCE | MOD_ACCESSED | 
MOD_EXPLICITLY_SIGNED)
+       MOD_ASSIGNED | MOD_USERTYPE | MOD_ACCESSED | MOD_EXPLICITLY_SIGNED)
 #define MOD_PTRINHERIT (MOD_VOLATILE | MOD_CONST | MOD_NODEREF | MOD_STORAGE)
 
 
-- 
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