summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-12-03 17:50:25 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2018-12-12 18:48:52 +0100
commit2da3f3cdd4b6817553b7290806cd7f84476d8fb6 (patch)
tree46ad9e2905237cc2f45c41bde48d93c024e72422
parent69fce9f7bc6f81231953b4551e574dd90fc10e45 (diff)
downloadsparse-2da3f3cdd4b6817553b7290806cd7f84476d8fb6.tar.gz
as-name: allow ident as address_space
Currently, address space 1 is displayed as '<asn:1>' and so on. Now that address spaces can be displayed by name, the address space number should just be an implementation detail and it would make more sense the be able to 'declare' these address space directly by name, like: #define __user attribute((noderef, address_space(__user))) Since directly using the name instead of an number creates some problems internally, allow this syntax but for the moment keep the address space number and use a table to lookup the number from the name. References: https://marc.info/?l=linux-sparse&m=153627490128505 Idea-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--parse.c34
-rw-r--r--validation/as-name.c17
2 files changed, 43 insertions, 8 deletions
diff --git a/parse.c b/parse.c
index 3fef7b6b..4739d39c 100644
--- a/parse.c
+++ b/parse.c
@@ -1098,6 +1098,8 @@ 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);
}
@@ -1105,15 +1107,31 @@ static struct ident *numerical_address_space(int asn)
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 = numerical_address_space(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)
+ ctx->ctype.as = as;
+ token = expect(next, ')', "after address_space attribute");
return token;
}
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
+ */