Function attributes relate to the function declaration they appear in. Sparse ignore most these attributes but a few ones have a semantic value: 'pure', 'noreturn' & 'externally_visible'. Due to how Sparse parse attributes and how these attributes are stored for functions, the attributes 'pure' & 'noreturn' are applied not to the function itself but its return type if the function returns a pointer. Fix this by extracting these attributes from the declaration context and ensure they're applied to the declarator. Reported-by: John Levon <john.levon@xxxxxxxxxx> Reported-by: Alex Kogan <alex.kogan@xxxxxxxxxx> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- parse.c | 17 ++++++++++++++++- symbol.h | 2 ++ validation/function-attribute.c | 19 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 validation/function-attribute.c diff --git a/parse.c b/parse.c index fa92fae68..37ffede72 100644 --- a/parse.c +++ b/parse.c @@ -2900,6 +2900,21 @@ static struct token *toplevel_asm_declaration(struct token *token, struct symbol return token; } +static unsigned long declaration_modifiers(struct decl_state *ctx) +{ + unsigned long mods; + + // Storage modifiers only relates to the declaration + mods = storage_modifiers(ctx); + + // Function attributes also only relates to the declaration + // and must not be present in the function/return type. + mods |= ctx->ctype.modifiers & MOD_FUN_ATTR; + ctx->ctype.modifiers &=~ MOD_FUN_ATTR; + + return mods; +} + struct token *external_declaration(struct token *token, struct symbol_list **list, validate_decl_t validate_decl) { @@ -2920,7 +2935,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis /* Parse declaration-specifiers, if any */ token = declaration_specifiers(token, &ctx); - mod = storage_modifiers(&ctx); + mod = declaration_modifiers(&ctx); decl = alloc_symbol(token->pos, SYM_NODE); /* Just a type declaration? */ if (match_op(token, ';')) { diff --git a/symbol.h b/symbol.h index 4e7e437bf..516b61361 100644 --- a/symbol.h +++ b/symbol.h @@ -251,6 +251,8 @@ struct symbol { #define MOD_PTRINHERIT (MOD_QUALIFIER | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST) /* modifiers preserved by typeof() operator */ #define MOD_TYPEOF (MOD_QUALIFIER | MOD_NOCAST | MOD_SPECIFIER) +/* modifiers for funtion attributes */ +#define MOD_FUN_ATTR (MOD_PURE|MOD_NORETURN) /* Current parsing/evaluation function */ diff --git a/validation/function-attribute.c b/validation/function-attribute.c new file mode 100644 index 000000000..0f2c75922 --- /dev/null +++ b/validation/function-attribute.c @@ -0,0 +1,19 @@ +#define __pure __attribute__((pure)) + +struct s { + int x; +}; + +static __pure struct s *grab(struct s *ptr) +{ + return ptr; +} + +static void foo(struct s *ptr) +{ + struct s *ptr = grab(ptr); +} + +/* + * check-name: function-attribute + */ -- 2.24.0