From 25e96501f249b27cb930a09aba5aeb33a047d14c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 8 Dec 2023 12:49:34 +0300 Subject: [PATCH] parse: handle __cleanup__ attribute The kernel has recently started using the __cleanup__ attribute. Save a pointer to cleanup function. Signed-off-by: Dan Carpenter Signed-off-by: Luc Van Oostenryck --- gcc-attr-list.h | 1 - parse.c | 31 +++++++++++++++++++++++++++++++ symbol.h | 2 ++ 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) diff --git a/parse.c b/parse.c index 3d6fef7c..f868bf63 100644 --- a/parse.c +++ b/parse.c @@ -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"); diff --git a/symbol.h b/symbol.h index 5270fcd7..88130c15 100644 --- a/symbol.h +++ b/symbol.h @@ -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 -- 2.11.4.GIT