diff options
author | Dan Carpenter <dan.carpenter@linaro.org> | 2023-12-08 12:49:34 +0300 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2023-12-16 12:09:35 +0100 |
commit | 25e96501f249b27cb930a09aba5aeb33a047d14c (patch) | |
tree | 5cf657f7b256d5a05aaee7cf0a62125455915c48 | |
parent | dc581e62b74dafb1ef4aca1ab088e37ba6fd7c94 (diff) | |
download | sparse-dev-handle-cleanup-attr.tar.gz |
parse: handle __cleanup__ attributehandle-cleanup-attr
The kernel has recently started using the __cleanup__ attribute. Save
a pointer to cleanup function.
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | gcc-attr-list.h | 1 | ||||
-rw-r--r-- | parse.c | 31 | ||||
-rw-r--r-- | symbol.h | 2 | ||||
-rw-r--r-- | validation/parsing/attr-cleanup.c | 1 |
4 files changed, 33 insertions, 2 deletions
diff --git a/gcc-attr-list.h b/gcc-attr-list.h index c7800175..928ea388 100644 --- a/gcc-attr-list.h +++ b/gcc-attr-list.h @@ -24,7 +24,6 @@ GCC_ATTR(brk_interrupt) GCC_ATTR(callee_pop_aggregate_return) GCC_ATTR(cb) GCC_ATTR(cdecl) -GCC_ATTR(cleanup) GCC_ATTR(cmse_nonsecure_call) GCC_ATTR(cmse_nonsecure_entry) GCC_ATTR(cold) @@ -83,6 +83,7 @@ static attr_t attribute_function, attribute_bitwise, attribute_address_space, attribute_context, + attribute_cleanup, attribute_designated_init, attribute_transparent_union, ignore_attribute, attribute_mode, attribute_force; @@ -361,6 +362,10 @@ static struct symbol_op aligned_op = { .attribute = attribute_aligned, }; +static struct symbol_op cleanup_op = { + .attribute = attribute_cleanup, +}; + static struct symbol_op attr_mod_op = { .attribute = attribute_modifier, }; @@ -537,6 +542,7 @@ static struct init_keyword { /* Attributes */ D("packed", &packed_op), D("aligned", &aligned_op), + D("cleanup", &cleanup_op), D("nocast", &attr_mod_op, .mods = MOD_NOCAST), D("noderef", &attr_mod_op, .mods = MOD_NODEREF), D("safe", &attr_mod_op, .mods = MOD_SAFE), @@ -1114,6 +1120,26 @@ static struct token *attribute_aligned(struct token *token, struct symbol *attr, return token; } +static struct token *attribute_cleanup(struct token *token, struct symbol *attr, struct decl_state *ctx) +{ + struct expression *expr = NULL; + + if (match_op(token, '(')) { + token = token->next; + if (match_op(token, ')')) + sparse_error(token->pos, "an argument is expected for attribute 'cleanup'"); + else if (token_type(token) != TOKEN_IDENT) + sparse_error(token->pos, "argument is not an identifier"); + token = primary_expression(token, &expr); + if (expr && expr->type == EXPR_SYMBOL) + ctx->cleanup = expr; + return expect(token, ')', "after attribute's argument'"); + } + + sparse_error(token->pos, "an argument is expected for attribute 'cleanup'"); + return token; +} + static void apply_mod(struct position *pos, unsigned long *mods, unsigned long mod) { if (*mods & mod & ~MOD_DUP_OK) @@ -1899,6 +1925,7 @@ static struct token *declaration_list(struct token *token, struct symbol_list ** saved = ctx.ctype; for (;;) { struct symbol *decl = alloc_symbol(token->pos, SYM_NODE); + ctx.cleanup = NULL; ctx.ident = &decl->ident; token = declarator(token, &ctx); @@ -1910,6 +1937,7 @@ static struct token *declaration_list(struct token *token, struct symbol_list ** decl->ctype = ctx.ctype; decl->ctype.modifiers |= mod; + decl->cleanup = ctx.cleanup; decl->endpos = token->pos; add_symbol(list, decl); if (!match_op(token, ',')) @@ -2924,6 +2952,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis decl->ctype = ctx.ctype; decl->ctype.modifiers |= mod; + decl->cleanup = ctx.cleanup; decl->endpos = token->pos; /* Just a type declaration? */ @@ -3041,6 +3070,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis ident = NULL; decl = alloc_symbol(token->pos, SYM_NODE); ctx.ctype = saved; + ctx.cleanup = NULL; token = handle_attributes(token, &ctx); token = declarator(token, &ctx); token = handle_asm_name(token, &ctx); @@ -3048,6 +3078,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis apply_modifiers(token->pos, &ctx); decl->ctype = ctx.ctype; decl->ctype.modifiers |= mod; + decl->cleanup = ctx.cleanup; decl->endpos = token->pos; if (!ident) { sparse_error(token->pos, "expected identifier name in type definition"); @@ -107,6 +107,7 @@ struct decl_state { struct ctype ctype; struct ident **ident; struct symbol_op *mode; + struct expression *cleanup; unsigned long f_modifiers; // function attributes unsigned long storage_class; unsigned char prefer_abstract; @@ -204,6 +205,7 @@ struct symbol { struct statement *inline_stmt; struct symbol_list *inline_symbol_list; struct expression *initializer; + struct expression *cleanup; struct entrypoint *ep; struct symbol *definition; }; diff --git a/validation/parsing/attr-cleanup.c b/validation/parsing/attr-cleanup.c index 76234276..ac64649c 100644 --- a/validation/parsing/attr-cleanup.c +++ b/validation/parsing/attr-cleanup.c @@ -22,7 +22,6 @@ int test(int n) /* * check-name: attr-cleanup * check-command: sparse -Wunknown-attribute $file - * check-known-to-fail * * check-error-start parsing/attr-cleanup.c:10:17: error: argument is not an identifier |