diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-11-15 00:06:14 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-11-15 01:42:54 +0100 |
commit | 233d4e17c544e1de252aed8f409630599104dbc7 (patch) | |
tree | 83f39dd2618b8656d342a8a0bd946452e8d1f010 | |
parent | fd3528aa0409874386610ce63bb647fff8312fd9 (diff) | |
download | sparse-233d4e17c544e1de252aed8f409630599104dbc7.tar.gz |
function attributes apply to the function declaration
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@joyent.com>
Reported-by: Alex Kogan <alex.kogan@oracle.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | parse.c | 17 | ||||
-rw-r--r-- | symbol.h | 2 | ||||
-rw-r--r-- | validation/function-attribute.c | 19 |
3 files changed, 37 insertions, 1 deletions
@@ -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, ';')) { @@ -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 00000000..0f2c7592 --- /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 + */ |