summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-12-12 18:30:37 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-12-12 21:10:11 +0100
commit6f9b33b07bb8e82d410bd74b0389a0ca391bde7e (patch)
tree3f54dbc598709a22ea908470cc45180ab16c3151
parent0c43faa22682ab65525638be813632b44c7a45fd (diff)
parent4bf8f31e91c88f7d2bc4e6de0c10b2b89d3093e2 (diff)
downloadsparse-6f9b33b07bb8e82d410bd74b0389a0ca391bde7e.tar.gz
Merge branch 'as-named' into tip
* prepare to identify & display the address spaces by name
-rw-r--r--evaluate.c51
-rw-r--r--parse.c49
-rw-r--r--show-parse.c24
-rw-r--r--symbol.c4
-rw-r--r--symbol.h26
-rw-r--r--tokenize.c6
-rw-r--r--validation/Waddress-space-all-attr.c24
-rw-r--r--validation/Waddress-space-strict.c12
-rw-r--r--validation/address_space.c2
-rw-r--r--validation/as-name.c17
-rw-r--r--validation/ptr-inherit.c2
11 files changed, 152 insertions, 65 deletions
diff --git a/evaluate.c b/evaluate.c
index 9c2304a7..64c02564 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -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)) {
diff --git a/parse.c b/parse.c
index da912aca..a12104f5 100644
--- a/parse.c
+++ b/parse.c
@@ -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, " )");
diff --git a/symbol.c b/symbol.c
index 2dcabe85..72ea2e4e 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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);
diff --git a/symbol.h b/symbol.h
index 5a3d7cef..87d3ce53 100644
--- a/symbol.h
+++ b/symbol.h
@@ -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 */
diff --git a/tokenize.c b/tokenize.c
index 0d17d42d..d8bbef49 100644
--- a/tokenize.c
+++ b/tokenize.c
@@ -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
*/