On Wed, Dec 13, 2023 at 01:14:29PM +0300, Dan Carpenter wrote: > On Tue, Dec 12, 2023 at 12:39:40PM +0300, Dan Carpenter wrote: > > > > @@ -2924,6 +2945,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis > > > > > > > > decl->ctype = ctx.ctype; > > > > decl->ctype.modifiers |= mod; > > > > + decl->cleanup = ctx.cleanup; > > > > > > Similarly, the attribute should only be applied to automatic variables, > > > so this should not be needed/should be detected as an error. > > > > > > > Yeah. There are a couple other "cleanup" lines later in the function > > that should be deleted as well, I see. > > Hm... Something went wrong. When I remove this assignment then the > cleanup function isn't saved here: Mmmmhh yes, my bad. I thought that the parsing functions followed closely the names of the C grammar in the spec. They largely do but not in this case (they can't because some context is needed to distinguish between 'declaration' and 'function-definition'). Would the following patch be OK for you when applied on top of your v2? It contains: - the attribute can be removed from the list of ignored attributes - I prefer to add the "attribute_cleanup," on its own line - I added some checks and a few corresponding testcases - the s/D("__cleanup__"/D("cleanup"/ - and the removal of 'sym->cleanup = ctx.cleanup;' from typename() which I think is still unneeded. Best regards, -- Luc diff --git a/gcc-attr-list.h b/gcc-attr-list.h index c78001757229..928ea3889e01 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) diff --git a/parse.c b/parse.c index e5b5e6acc062..f868bf63a0f5 100644 --- a/parse.c +++ b/parse.c @@ -79,11 +79,11 @@ typedef struct token *attr_t(struct token *, struct symbol *, struct decl_state *); static attr_t - attribute_packed, attribute_aligned, attribute_cleanup, - attribute_modifier, + attribute_packed, attribute_aligned, attribute_modifier, attribute_function, attribute_bitwise, attribute_address_space, attribute_context, + attribute_cleanup, attribute_designated_init, attribute_transparent_union, ignore_attribute, attribute_mode, attribute_force; @@ -542,7 +542,7 @@ static struct init_keyword { /* Attributes */ D("packed", &packed_op), D("aligned", &aligned_op), - D("__cleanup__", &cleanup_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), @@ -1125,10 +1125,18 @@ static struct token *attribute_cleanup(struct token *token, struct symbol *attr, struct expression *expr = NULL; if (match_op(token, '(')) { - token = parens_expression(token, &expr, "in attribute"); + 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; } @@ -1984,7 +1992,6 @@ struct token *typename(struct token *token, struct symbol **p, int *forced) token = declarator(token, &ctx); apply_modifiers(token->pos, &ctx); sym->ctype = ctx.ctype; - sym->cleanup = ctx.cleanup; sym->endpos = token->pos; class = ctx.storage_class; if (forced) diff --git a/validation/parsing/attr-cleanup.c b/validation/parsing/attr-cleanup.c new file mode 100644 index 000000000000..ac64649c2ac1 --- /dev/null +++ b/validation/parsing/attr-cleanup.c @@ -0,0 +1,33 @@ +#define __cleanup(F) __attribute__((__cleanup__(F))) + +void fun(int *ptr); + +int test(int n); +int test(int n) +{ + int var __attribute__((cleanup(fun))) = 1; + int alt __cleanup(fun) = 2; + int mis __cleanup(0) = 3; + int non __attribute__((cleanup)); + int mis __attribute__((cleanup())); + int two __attribute__((cleanup(fun, fun))); + + for (int i __cleanup(fun) = 0; i < n; i++) + ; + + var = 5; + return 0; +} + +/* + * check-name: attr-cleanup + * check-command: sparse -Wunknown-attribute $file + * + * check-error-start +parsing/attr-cleanup.c:10:17: error: argument is not an identifier +parsing/attr-cleanup.c:11:39: error: an argument is expected for attribute 'cleanup' +parsing/attr-cleanup.c:12:40: error: an argument is expected for attribute 'cleanup' +parsing/attr-cleanup.c:13:43: error: Expected ) after attribute's argument' +parsing/attr-cleanup.c:13:43: error: got , + * check-error-end + */