diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-12-12 18:30:37 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-12-12 21:10:11 +0100 |
commit | 6f9b33b07bb8e82d410bd74b0389a0ca391bde7e (patch) | |
tree | 3f54dbc598709a22ea908470cc45180ab16c3151 | |
parent | 0c43faa22682ab65525638be813632b44c7a45fd (diff) | |
parent | 4bf8f31e91c88f7d2bc4e6de0c10b2b89d3093e2 (diff) | |
download | sparse-6f9b33b07bb8e82d410bd74b0389a0ca391bde7e.tar.gz |
Merge branch 'as-named' into tip
* prepare to identify & display the address spaces by name
-rw-r--r-- | evaluate.c | 51 | ||||
-rw-r--r-- | parse.c | 49 | ||||
-rw-r--r-- | show-parse.c | 24 | ||||
-rw-r--r-- | symbol.c | 4 | ||||
-rw-r--r-- | symbol.h | 26 | ||||
-rw-r--r-- | tokenize.c | 6 | ||||
-rw-r--r-- | validation/Waddress-space-all-attr.c | 24 | ||||
-rw-r--r-- | validation/Waddress-space-strict.c | 12 | ||||
-rw-r--r-- | validation/address_space.c | 2 | ||||
-rw-r--r-- | validation/as-name.c | 17 | ||||
-rw-r--r-- | validation/ptr-inherit.c | 2 |
11 files changed, 152 insertions, 65 deletions
@@ -45,6 +45,8 @@ struct symbol *current_fn; +struct ident bad_address_space = { .len = 6, .name = "bad AS", }; + static struct symbol *degenerate(struct expression *expr); static struct symbol *evaluate_symbol(struct symbol *sym); @@ -208,14 +210,14 @@ static int same_cast_type(struct symbol *orig, struct symbol *new) orig->bit_offset == new->bit_offset; } -static struct symbol *base_type(struct symbol *node, unsigned long *modp, unsigned long *asp) +static struct symbol *base_type(struct symbol *node, unsigned long *modp, struct ident **asp) { - unsigned long mod, as; + unsigned long mod = 0; + struct ident *as = NULL; - mod = 0; as = 0; while (node) { mod |= node->ctype.modifiers; - as |= node->ctype.as; + combine_address_space(node->pos, &as, node->ctype.as); if (node->type == SYM_NODE) { node = node->ctype.base_type; continue; @@ -230,7 +232,8 @@ static struct symbol *base_type(struct symbol *node, unsigned long *modp, unsign static int is_same_type(struct expression *expr, struct symbol *new) { struct symbol *old = expr->ctype; - unsigned long oldmod, newmod, oldas, newas; + unsigned long oldmod, newmod; + struct ident *oldas, *newas; old = base_type(old, &oldmod, &oldas); new = base_type(new, &newmod, &newas); @@ -660,7 +663,7 @@ static void examine_fn_arguments(struct symbol *fn); const char *type_difference(struct ctype *c1, struct ctype *c2, unsigned long mod1, unsigned long mod2) { - unsigned long as1 = c1->as, as2 = c2->as; + struct ident *as1 = c1->as, *as2 = c2->as; struct symbol *t1 = c1->base_type; struct symbol *t2 = c2->base_type; int move1 = 1, move2 = 1; @@ -678,7 +681,7 @@ const char *type_difference(struct ctype *c1, struct ctype *c2, if (move1) { if (t1 && t1->type != SYM_PTR) { mod1 |= t1->ctype.modifiers; - as1 |= t1->ctype.as; + combine_address_space(t1->pos, &as1, t1->ctype.as); } move1 = 0; } @@ -686,7 +689,7 @@ const char *type_difference(struct ctype *c1, struct ctype *c2, if (move2) { if (t2 && t2->type != SYM_PTR) { mod2 |= t2->ctype.modifiers; - as2 |= t2->ctype.as; + combine_address_space(t2->pos, &as2, t2->ctype.as); } move2 = 0; } @@ -1609,11 +1612,11 @@ static void examine_fn_arguments(struct symbol *fn) ptr->ctype = arg->ctype; else ptr->ctype.base_type = arg; - ptr->ctype.as |= s->ctype.as; + combine_address_space(s->pos, &ptr->ctype.as, s->ctype.as); ptr->ctype.modifiers |= s->ctype.modifiers & MOD_PTRINHERIT; s->ctype.base_type = ptr; - s->ctype.as = 0; + s->ctype.as = NULL; s->ctype.modifiers &= ~MOD_PTRINHERIT; s->bit_size = 0; s->examined = 0; @@ -1627,7 +1630,7 @@ static void examine_fn_arguments(struct symbol *fn) } END_FOR_EACH_PTR(s); } -static struct symbol *convert_to_as_mod(struct symbol *sym, int as, int mod) +static struct symbol *convert_to_as_mod(struct symbol *sym, struct ident *as, int mod) { /* Take the modifiers of the pointer, and apply them to the member */ mod |= sym->ctype.modifiers; @@ -1659,12 +1662,12 @@ static struct symbol *create_pointer(struct expression *expr, struct symbol *sym sym->ctype.modifiers &= ~MOD_REGISTER; } if (sym->type == SYM_NODE) { - ptr->ctype.as |= sym->ctype.as; + combine_address_space(sym->pos, &ptr->ctype.as, sym->ctype.as); ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT; sym = sym->ctype.base_type; } if (degenerate && sym->type == SYM_ARRAY) { - ptr->ctype.as |= sym->ctype.as; + combine_address_space(sym->pos, &ptr->ctype.as, sym->ctype.as); ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT; sym = sym->ctype.base_type; } @@ -2051,8 +2054,8 @@ static struct symbol *evaluate_member_dereference(struct expression *expr) struct symbol *ctype, *member; struct expression *deref = expr->deref, *add; struct ident *ident = expr->member; + struct ident *address_space; unsigned int mod; - int address_space; if (!evaluate_expression(deref)) return NULL; @@ -2067,7 +2070,7 @@ static struct symbol *evaluate_member_dereference(struct expression *expr) mod = ctype->ctype.modifiers; if (ctype->type == SYM_NODE) { ctype = ctype->ctype.base_type; - address_space |= ctype->ctype.as; + combine_address_space(deref->pos, &address_space, ctype->ctype.as); mod |= ctype->ctype.modifiers; } if (!ctype || (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION)) { @@ -2913,7 +2916,7 @@ static struct symbol *evaluate_cast(struct expression *expr) struct symbol *ctype; struct symbol *ttype, *stype; int tclass, sclass; - int tas = 0, sas = 0; + struct ident *tas = NULL, *sas = NULL; if (!source) return NULL; @@ -3004,27 +3007,27 @@ static struct symbol *evaluate_cast(struct expression *expr) } if (ttype == &ulong_ctype && !Wcast_from_as) - tas = -1; + tas = &bad_address_space; else if (tclass == TYPE_PTR) { examine_pointer_target(ttype); tas = ttype->ctype.as; } if (stype == &ulong_ctype && !Wcast_from_as) - sas = -1; + sas = &bad_address_space; else if (sclass == TYPE_PTR) { examine_pointer_target(stype); sas = stype->ctype.as; } - if (!tas && sas > 0) - warning(expr->pos, "cast removes address space of expression (<asn:%d>)", sas); - if (tas > 0 && sas > 0 && tas != sas) - warning(expr->pos, "cast between address spaces (<asn:%d>-><asn:%d>)", sas, tas); - if (tas > 0 && !sas && + if (!tas && valid_as(sas)) + warning(expr->pos, "cast removes address space '%s' of expression", show_as(sas)); + if (valid_as(tas) && valid_as(sas) && tas != sas) + warning(expr->pos, "cast between address spaces (%s -> %s)", show_as(sas), show_as(tas)); + if (valid_as(tas) && !sas && !is_null_pointer_constant(source) && Wcast_to_as) warning(expr->pos, - "cast adds address space to expression (<asn:%d>)", tas); + "cast adds address space '%s' to expression", show_as(tas)); if (!(ttype->ctype.modifiers & MOD_PTRINHERIT) && tclass == TYPE_PTR && !tas && (source->flags & CEF_ICE)) { @@ -1094,18 +1094,49 @@ static struct token *attribute_bitwise(struct token *token, struct symbol *attr, return token; } +static struct ident *numerical_address_space(int asn) +{ + char buff[32]; + + if (!asn) + return NULL; + sprintf(buff, "<asn:%d>", asn); + return built_in_ident(buff); +} + static struct token *attribute_address_space(struct token *token, struct symbol *attr, struct decl_state *ctx) { struct expression *expr = NULL; - int as; + struct ident *as = NULL; + struct token *next; + token = expect(token, '(', "after address_space attribute"); - token = conditional_expression(token, &expr); - if (expr) { - as = const_expression_value(expr); - if (Waddress_space && as) - ctx->ctype.as = as; - } - token = expect(token, ')', "after address_space attribute"); + switch (token_type(token)) { + case TOKEN_NUMBER: + next = primary_expression(token, &expr); + if (expr->type != EXPR_VALUE) + goto invalid; + as = numerical_address_space(expr->value); + break; + case TOKEN_IDENT: + next = token->next; + as = token->ident; + break; + default: + next = token->next; + invalid: + as = NULL; + warning(token->pos, "invalid address space name"); + } + + if (Waddress_space && as) { + if (ctx->ctype.as) + sparse_error(token->pos, + "multiple address space given: %s & %s", + show_as(ctx->ctype.as), show_as(as)); + ctx->ctype.as = as; + } + token = expect(next, ')', "after address_space attribute"); return token; } @@ -1825,7 +1856,7 @@ static struct token *pointer(struct token *token, struct decl_state *ctx) ptr->ctype.contexts = ctx->ctype.contexts; ctx->ctype.modifiers = 0; ctx->ctype.base_type = ptr; - ctx->ctype.as = 0; + ctx->ctype.as = NULL; ctx->ctype.contexts = NULL; ctx->ctype.alignment = 0; diff --git a/show-parse.c b/show-parse.c index 6328439c..b892c189 100644 --- a/show-parse.c +++ b/show-parse.c @@ -72,10 +72,11 @@ static void do_debug_symbol(struct symbol *sym, int indent) if (!sym) return; - fprintf(stderr, "%.*s%s%3d:%lu %s %s (as: %d) %p (%s:%d:%d) %s\n", + fprintf(stderr, "%.*s%s%3d:%lu %s %s (as: %s) %p (%s:%d:%d) %s\n", indent, indent_string, typestr[sym->type], sym->bit_size, sym->ctype.alignment, - modifier_string(sym->ctype.modifiers), show_ident(sym->ident), sym->ctype.as, + modifier_string(sym->ctype.modifiers), show_ident(sym->ident), + show_as(sym->ctype.as), sym, stream_name(sym->pos.stream), sym->pos.line, sym->pos.pos, builtin_typename(sym) ?: ""); i = 0; @@ -182,6 +183,13 @@ void show_symbol_list(struct symbol_list *list, const char *sep) } END_FOR_EACH_PTR(sym); } +const char *show_as(struct ident *as) +{ + if (!as) + return ""; + return show_ident(as); +} + struct type_name { char *start; char *end; @@ -276,7 +284,7 @@ static void do_show_type(struct symbol *sym, struct type_name *name) { const char *typename; unsigned long mod = 0; - int as = 0; + struct ident *as = NULL; int was_ptr = 0; int restr = 0; int fouled = 0; @@ -288,14 +296,14 @@ deeper: size_t len; if (as) - prepend(name, "<asn:%d>", as); + prepend(name, "%s ", show_as(as)); s = modifier_string(mod); len = strlen(s); name->start -= len; memcpy(name->start, s, len); mod = 0; - as = 0; + as = NULL; } if (!sym) @@ -347,12 +355,12 @@ deeper: case SYM_NODE: append(name, "%s", show_ident(sym->ident)); mod |= sym->ctype.modifiers; - as |= sym->ctype.as; + combine_address_space(sym->pos, &as, sym->ctype.as); break; case SYM_BITFIELD: mod |= sym->ctype.modifiers; - as |= sym->ctype.as; + combine_address_space(sym->pos, &as, sym->ctype.as); append(name, ":%d", sym->bit_size); break; @@ -362,7 +370,7 @@ deeper: case SYM_ARRAY: mod |= sym->ctype.modifiers; - as |= sym->ctype.as; + combine_address_space(sym->pos, &as, sym->ctype.as); if (was_ptr) { prepend(name, "( "); append(name, " )"); @@ -214,7 +214,7 @@ static struct symbol *examine_base_type(struct symbol *sym) base_type = examine_symbol_type(sym->ctype.base_type); if (!base_type || base_type->type == SYM_PTR) return base_type; - sym->ctype.as |= base_type->ctype.as; + combine_address_space(sym->pos, &sym->ctype.as, base_type->ctype.as); sym->ctype.modifiers |= base_type->ctype.modifiers & MOD_PTRINHERIT; concat_ptr_list((struct ptr_list *)base_type->ctype.contexts, (struct ptr_list **)&sym->ctype.contexts); @@ -278,7 +278,7 @@ static struct symbol *examine_bitfield_type(struct symbol *sym) */ void merge_type(struct symbol *sym, struct symbol *base_type) { - sym->ctype.as |= base_type->ctype.as; + combine_address_space(sym->pos, &sym->ctype.as, base_type->ctype.as); sym->ctype.modifiers |= (base_type->ctype.modifiers & ~MOD_STORAGE); concat_ptr_list((struct ptr_list *)base_type->ctype.contexts, (struct ptr_list **)&sym->ctype.contexts); @@ -101,7 +101,7 @@ struct ctype { unsigned long modifiers; unsigned long alignment; struct context_list *contexts; - unsigned int as; + struct ident *as; struct symbol *base_type; }; @@ -315,6 +315,7 @@ extern void bind_symbol(struct symbol *, struct ident *, enum namespace); extern struct symbol *examine_symbol_type(struct symbol *); extern struct symbol *examine_pointer_target(struct symbol *); +extern const char *show_as(struct ident *as); extern const char *show_typename(struct symbol *sym); extern const char *builtin_typename(struct symbol *sym); extern const char *builtin_ctypename(struct ctype *ctype); @@ -499,4 +500,27 @@ static inline struct symbol *lookup_keyword(struct ident *ident, enum namespace void create_fouled(struct symbol *type); struct symbol *befoul(struct symbol *type); + +extern struct ident bad_address_space; + +static inline bool valid_as(struct ident *as) +{ + return as && as != &bad_address_space; +} + +static inline void combine_address_space(struct position pos, + struct ident **tas, struct ident *sas) +{ + struct ident *as; + if (!sas) + return; + as = *tas; + if (!as) + *tas = sas; + else if (as != sas) { + *tas = &bad_address_space; + sparse_error(pos, "multiple address spaces given"); + } +} + #endif /* SYMBOL_H */ @@ -88,9 +88,13 @@ const char *show_special(int val) const char *show_ident(const struct ident *ident) { - static char buffer[256]; + static char buff[4][256]; + static int n; + char *buffer; + if (!ident) return "<noident>"; + buffer = buff[3 & ++n]; sprintf(buffer, "%.*s", ident->len, ident->name); return buffer; } diff --git a/validation/Waddress-space-all-attr.c b/validation/Waddress-space-all-attr.c index 46b70953..5b2d0f92 100644 --- a/validation/Waddress-space-all-attr.c +++ b/validation/Waddress-space-all-attr.c @@ -44,17 +44,17 @@ static void expl(obj_t __kernel *k, obj_t __iomem *o, * check-command: sparse -Wcast-from-as -Wcast-to-as $file * * check-error-start -Waddress-space-all-attr.c:21:10: warning: cast removes address space of expression (<asn:2>) -Waddress-space-all-attr.c:22:10: warning: cast removes address space of expression (<asn:2>) -Waddress-space-all-attr.c:23:10: warning: cast removes address space of expression (<asn:2>) -Waddress-space-all-attr.c:26:10: warning: cast removes address space of expression (<asn:1>) -Waddress-space-all-attr.c:27:10: warning: cast removes address space of expression (<asn:1>) -Waddress-space-all-attr.c:28:10: warning: cast removes address space of expression (<asn:1>) -Waddress-space-all-attr.c:31:10: warning: cast removes address space of expression (<asn:3>) -Waddress-space-all-attr.c:32:10: warning: cast removes address space of expression (<asn:3>) -Waddress-space-all-attr.c:33:10: warning: cast removes address space of expression (<asn:3>) -Waddress-space-all-attr.c:36:10: warning: cast removes address space of expression (<asn:4>) -Waddress-space-all-attr.c:37:10: warning: cast removes address space of expression (<asn:4>) -Waddress-space-all-attr.c:38:10: warning: cast removes address space of expression (<asn:4>) +Waddress-space-all-attr.c:21:10: warning: cast removes address space '<asn:2>' of expression +Waddress-space-all-attr.c:22:10: warning: cast removes address space '<asn:2>' of expression +Waddress-space-all-attr.c:23:10: warning: cast removes address space '<asn:2>' of expression +Waddress-space-all-attr.c:26:10: warning: cast removes address space '<asn:1>' of expression +Waddress-space-all-attr.c:27:10: warning: cast removes address space '<asn:1>' of expression +Waddress-space-all-attr.c:28:10: warning: cast removes address space '<asn:1>' of expression +Waddress-space-all-attr.c:31:10: warning: cast removes address space '<asn:3>' of expression +Waddress-space-all-attr.c:32:10: warning: cast removes address space '<asn:3>' of expression +Waddress-space-all-attr.c:33:10: warning: cast removes address space '<asn:3>' of expression +Waddress-space-all-attr.c:36:10: warning: cast removes address space '<asn:4>' of expression +Waddress-space-all-attr.c:37:10: warning: cast removes address space '<asn:4>' of expression +Waddress-space-all-attr.c:38:10: warning: cast removes address space '<asn:4>' of expression * check-error-end */ diff --git a/validation/Waddress-space-strict.c b/validation/Waddress-space-strict.c index 807965f6..7987eb1d 100644 --- a/validation/Waddress-space-strict.c +++ b/validation/Waddress-space-strict.c @@ -27,11 +27,11 @@ static void expl(ulong u, void *v, obj_t *o, obj_t __user *p) * check-command: sparse -Wcast-from-as -Wcast-to-as $file * * check-error-start -Waddress-space-strict.c:9:10: warning: cast adds address space to expression (<asn:1>) -Waddress-space-strict.c:12:10: warning: cast adds address space to expression (<asn:1>) -Waddress-space-strict.c:17:10: warning: cast adds address space to expression (<asn:1>) -Waddress-space-strict.c:19:10: warning: cast removes address space of expression (<asn:1>) -Waddress-space-strict.c:20:10: warning: cast removes address space of expression (<asn:1>) -Waddress-space-strict.c:21:10: warning: cast removes address space of expression (<asn:1>) +Waddress-space-strict.c:9:10: warning: cast adds address space '<asn:1>' to expression +Waddress-space-strict.c:12:10: warning: cast adds address space '<asn:1>' to expression +Waddress-space-strict.c:17:10: warning: cast adds address space '<asn:1>' to expression +Waddress-space-strict.c:19:10: warning: cast removes address space '<asn:1>' of expression +Waddress-space-strict.c:20:10: warning: cast removes address space '<asn:1>' of expression +Waddress-space-strict.c:21:10: warning: cast removes address space '<asn:1>' of expression * check-error-end */ diff --git a/validation/address_space.c b/validation/address_space.c index c55b78df..a0c8bf5d 100644 --- a/validation/address_space.c +++ b/validation/address_space.c @@ -12,6 +12,6 @@ static int sys_do_stuff(void __user *user_addr) * check-error-start address_space.c:7:28: warning: incorrect type in argument 1 (different address spaces) address_space.c:7:28: expected void *addr -address_space.c:7:28: got void <asn:1>*user_addr +address_space.c:7:28: got void <asn:1> *user_addr * check-error-end */ diff --git a/validation/as-name.c b/validation/as-name.c new file mode 100644 index 00000000..4dd65798 --- /dev/null +++ b/validation/as-name.c @@ -0,0 +1,17 @@ +#define __user __attribute__((address_space(__user))) + +extern void fun(void *addr); + +static void foo(void __user *ptr) +{ + return fun(ptr); +} +/* + * check-name: as-name attribute + * + * check-error-start +as-name.c:7:20: warning: incorrect type in argument 1 (different address spaces) +as-name.c:7:20: expected void *addr +as-name.c:7:20: got void __user *ptr + * check-error-end + */ diff --git a/validation/ptr-inherit.c b/validation/ptr-inherit.c index 58524a71..87330567 100644 --- a/validation/ptr-inherit.c +++ b/validation/ptr-inherit.c @@ -75,6 +75,6 @@ ptr-inherit.c:30:19: expected int *p ptr-inherit.c:30:19: got restricted int *<noident> ptr-inherit.c:36:19: warning: incorrect type in initializer (different address spaces) ptr-inherit.c:36:19: expected int *p -ptr-inherit.c:36:19: got int <asn:1>*<noident> +ptr-inherit.c:36:19: got int <asn:1> *<noident> * check-error-end */ |