diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-05-21 17:40:33 +0200 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-05-21 17:40:33 +0200 |
commit | 18351292096b1b90ed7f3bc34459d371aa095588 (patch) | |
tree | e8d2bed28aab5770089cdd882bba3701bef2e5dd | |
parent | 386baba96aa18c8419c1ecea21a907ccc526a5fa (diff) | |
parent | d1c0ce0393cab5442bdfbe8e03fd748d8dcdb2ed (diff) | |
download | sparse-18351292096b1b90ed7f3bc34459d371aa095588.tar.gz |
Merge branch 'fun-attr'
* improve handling of function attributes
* separate modifiers into type/declaration
* add support for attributes 'unused' & 'gnu_inline'
* simplify parsing of inline/__tls/__visible
-rw-r--r-- | parse.c | 58 | ||||
-rw-r--r-- | show-parse.c | 28 | ||||
-rw-r--r-- | symbol.h | 14 | ||||
-rw-r--r-- | validation/attr-visible.c | 1 | ||||
-rw-r--r-- | validation/attr-visible2.c | 1 | ||||
-rw-r--r-- | validation/cond_expr2.c | 2 | ||||
-rw-r--r-- | validation/function-redecl.c | 6 |
7 files changed, 55 insertions, 55 deletions
@@ -84,7 +84,6 @@ typedef struct token *attr_t(struct token *, struct symbol *, static attr_t attribute_packed, attribute_aligned, attribute_modifier, attribute_function, - attribute_ext_visible, attribute_bitwise, attribute_address_space, attribute_context, attribute_designated_init, @@ -389,10 +388,6 @@ static struct symbol_op attr_fun_op = { .attribute = attribute_function, }; -static struct symbol_op ext_visible_op = { - .attribute = attribute_ext_visible, -}; - static struct symbol_op attr_bitwise_op = { .attribute = attribute_bitwise, }; @@ -571,6 +566,10 @@ static struct init_keyword { { "__noderef__",NS_KEYWORD, MOD_NODEREF, .op = &attr_mod_op }, { "safe", NS_KEYWORD, MOD_SAFE, .op = &attr_mod_op }, { "__safe__", NS_KEYWORD, MOD_SAFE, .op = &attr_mod_op }, + { "unused", NS_KEYWORD, MOD_UNUSED, .op = &attr_mod_op }, + { "__unused__", NS_KEYWORD, MOD_UNUSED, .op = &attr_mod_op }, + { "externally_visible", NS_KEYWORD, MOD_EXT_VISIBLE,.op = &attr_mod_op }, + { "__externally_visible__", NS_KEYWORD,MOD_EXT_VISIBLE,.op = &attr_mod_op }, { "force", NS_KEYWORD, .op = &attr_force_op }, { "__force__", NS_KEYWORD, .op = &attr_force_op }, { "bitwise", NS_KEYWORD, MOD_BITWISE, .op = &attr_bitwise_op }, @@ -588,8 +587,8 @@ static struct init_keyword { {"const", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op }, {"__const", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op }, {"__const__", NS_KEYWORD, MOD_PURE, .op = &attr_fun_op }, - {"externally_visible", NS_KEYWORD, .op = &ext_visible_op }, - {"__externally_visible__", NS_KEYWORD, .op = &ext_visible_op }, + {"gnu_inline", NS_KEYWORD, MOD_GNU_INLINE, .op = &attr_fun_op }, + {"__gnu_inline__",NS_KEYWORD, MOD_GNU_INLINE, .op = &attr_fun_op }, { "mode", NS_KEYWORD, .op = &mode_op }, { "__mode__", NS_KEYWORD, .op = &mode_op }, @@ -1127,11 +1126,16 @@ static struct token *attribute_aligned(struct token *token, struct symbol *attr, return token; } +static void apply_mod(struct position *pos, unsigned long *mods, unsigned long mod) +{ + if (*mods & mod & ~MOD_DUP_OK) + warning(*pos, "duplicate %s", modifier_string(mod)); + *mods |= mod; +} + static void apply_qualifier(struct position *pos, struct ctype *ctx, unsigned long qual) { - if (ctx->modifiers & qual) - warning(*pos, "duplicate %s", modifier_string(qual)); - ctx->modifiers |= qual; + apply_mod(pos, &ctx->modifiers, qual); } static struct token *attribute_modifier(struct token *token, struct symbol *attr, struct decl_state *ctx) @@ -1142,16 +1146,7 @@ static struct token *attribute_modifier(struct token *token, struct symbol *attr static struct token *attribute_function(struct token *token, struct symbol *attr, struct decl_state *ctx) { - unsigned long mod = attr->ctype.modifiers; - if (ctx->f_modifiers & mod) - warning(token->pos, "duplicate %s", modifier_string(mod)); - ctx->f_modifiers |= mod; - return token; -} - -static struct token *attribute_ext_visible(struct token *token, struct symbol *attr, struct decl_state *ctx) -{ - ctx->is_ext_visible = 1; + apply_mod(&token->pos, &ctx->f_modifiers, attr->ctype.modifiers); return token; } @@ -1382,7 +1377,7 @@ static const char *storage_class[] = [SForced] = "[force]" }; -static unsigned long storage_modifiers(struct decl_state *ctx) +static unsigned long decl_modifiers(struct decl_state *ctx) { static unsigned long mod[SMax] = { @@ -1391,15 +1386,16 @@ static unsigned long storage_modifiers(struct decl_state *ctx) [SStatic] = MOD_STATIC, [SRegister] = MOD_REGISTER }; - return mod[ctx->storage_class] | (ctx->is_inline ? MOD_INLINE : 0) - | (ctx->is_tls ? MOD_TLS : 0) - | (ctx->is_ext_visible ? MOD_EXT_VISIBLE : 0); + unsigned long mods = ctx->ctype.modifiers & MOD_DECLARE; + ctx->ctype.modifiers &= ~MOD_DECLARE; + return mod[ctx->storage_class] | mods; } static void set_storage_class(struct position *pos, struct decl_state *ctx, int class) { + int is_tls = ctx->ctype.modifiers & MOD_TLS; /* __thread can be used alone, or with extern or static */ - if (ctx->is_tls && (class != SStatic && class != SExtern)) { + if (is_tls && (class != SStatic && class != SExtern)) { sparse_error(*pos, "__thread can only be used alone, or with " "extern or static"); return; @@ -1450,7 +1446,7 @@ static struct token *thread_specifier(struct token *next, struct decl_state *ctx /* This GCC extension can be used alone, or with extern or static */ if (!ctx->storage_class || ctx->storage_class == SStatic || ctx->storage_class == SExtern) { - ctx->is_tls = 1; + apply_qualifier(&next->pos, &ctx->ctype, MOD_TLS); } else { sparse_error(next->pos, "__thread can only be used alone, or " "with extern or static"); @@ -1467,7 +1463,7 @@ static struct token *attribute_force(struct token *token, struct symbol *attr, s static struct token *inline_specifier(struct token *next, struct decl_state *ctx) { - ctx->is_inline = 1; + apply_qualifier(&next->pos, &ctx->ctype, MOD_INLINE); return next; } @@ -1670,7 +1666,7 @@ static struct token *declaration_specifiers(struct token *token, struct decl_sta } } token = token->next; - if (s->op->declarator) + if (s->op->declarator) // Note: this eats attributes token = s->op->declarator(token, ctx); if (s->op->type & KW_EXACT) { ctx->ctype.base_type = s->ctype.base_type; @@ -1997,7 +1993,7 @@ static struct token *declaration_list(struct token *token, struct symbol_list ** unsigned long mod; token = declaration_specifiers(token, &ctx); - mod = storage_modifiers(&ctx); + mod = decl_modifiers(&ctx); saved = ctx.ctype; for (;;) { struct symbol *decl = alloc_symbol(token->pos, SYM_NODE); @@ -2050,7 +2046,7 @@ static struct token *parameter_declaration(struct token *token, struct symbol *s token = handle_attributes(token, &ctx, KW_ATTRIBUTE); apply_modifiers(token->pos, &ctx); sym->ctype = ctx.ctype; - sym->ctype.modifiers |= storage_modifiers(&ctx); + sym->ctype.modifiers |= decl_modifiers(&ctx); sym->endpos = token->pos; sym->forced_arg = ctx.storage_class == SForced; return token; @@ -2953,7 +2949,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 = decl_modifiers(&ctx); decl = alloc_symbol(token->pos, SYM_NODE); /* Just a type declaration? */ if (match_op(token, ';')) { diff --git a/show-parse.c b/show-parse.c index 8a145b88..eb71b650 100644 --- a/show-parse.c +++ b/show-parse.c @@ -119,28 +119,30 @@ const char *modifier_string(unsigned long mod) static struct mod_name mod_names[] = { {MOD_AUTO, "auto"}, + {MOD_EXTERN, "extern"}, {MOD_REGISTER, "register"}, {MOD_STATIC, "static"}, - {MOD_EXTERN, "extern"}, + {MOD_INLINE, "inline"}, {MOD_CONST, "const"}, - {MOD_VOLATILE, "volatile"}, {MOD_RESTRICT, "restrict"}, - {MOD_ATOMIC, "[atomic]"}, - {MOD_SIGNED, "[signed]"}, - {MOD_UNSIGNED, "[unsigned]"}, - {MOD_TLS, "[tls]"}, - {MOD_INLINE, "inline"}, + {MOD_VOLATILE, "volatile"}, {MOD_ADDRESSABLE, "[addressable]"}, + {MOD_ASSIGNED, "[assigned]"}, + {MOD_ATOMIC, "[atomic]"}, + {MOD_BITWISE, "[bitwise]"}, + {MOD_EXPLICITLY_SIGNED, "[explicitly-signed]"}, + {MOD_GNU_INLINE, "[gnu_inline]"}, {MOD_NOCAST, "[nocast]"}, {MOD_NODEREF, "[noderef]"}, - {MOD_TOPLEVEL, "[toplevel]"}, - {MOD_ASSIGNED, "[assigned]"}, - {MOD_SAFE, "[safe]"}, - {MOD_USERTYPE, "[usertype]"}, {MOD_NORETURN, "[noreturn]"}, - {MOD_EXPLICITLY_SIGNED, "[explicitly-signed]"}, - {MOD_BITWISE, "[bitwise]"}, {MOD_PURE, "[pure]"}, + {MOD_SAFE, "[safe]"}, + {MOD_SIGNED, "[signed]"}, + {MOD_TLS, "[tls]"}, + {MOD_TOPLEVEL, "[toplevel]"}, + {MOD_UNSIGNED, "[unsigned]"}, + {MOD_UNUSED, "[unused]"}, + {MOD_USERTYPE, "[usertype]"}, }; for (i = 0; i < ARRAY_SIZE(mod_names); i++) { @@ -108,8 +108,7 @@ struct decl_state { struct ident **ident; struct symbol_op *mode; unsigned long f_modifiers; // function attributes - unsigned char prefer_abstract, is_inline, storage_class, is_tls; - unsigned char is_ext_visible; + unsigned char prefer_abstract, storage_class; unsigned char autotype; }; @@ -229,14 +228,14 @@ struct symbol { #define MOD_UNSIGNED 0x00004000 #define MOD_EXPLICITLY_SIGNED 0x00008000 - // MOD UNUSED 0x00010000 +#define MOD_GNU_INLINE 0x00010000 #define MOD_USERTYPE 0x00020000 // MOD UNUSED 0x00040000 // MOD UNUSED 0x00080000 // MOD UNUSED 0x00100000 // MOD UNUSED 0x00200000 - // MOD UNUSED 0x00400000 +#define MOD_UNUSED 0x00400000 #define MOD_SAFE 0x00800000 // non-null/non-trapping pointer #define MOD_PURE 0x01000000 #define MOD_BITWISE 0x02000000 @@ -252,7 +251,7 @@ struct symbol { #define MOD_ESIGNED (MOD_SIGNED | MOD_EXPLICITLY_SIGNED) #define MOD_SIGNEDNESS (MOD_SIGNED | MOD_UNSIGNED | MOD_EXPLICITLY_SIGNED) #define MOD_SPECIFIER MOD_SIGNEDNESS -#define MOD_IGNORE (MOD_STORAGE | MOD_ACCESS | MOD_USERTYPE | MOD_EXPLICITLY_SIGNED | MOD_EXT_VISIBLE) +#define MOD_IGNORE (MOD_STORAGE | MOD_ACCESS | MOD_USERTYPE | MOD_EXPLICITLY_SIGNED | MOD_EXT_VISIBLE | MOD_UNUSED | MOD_GNU_INLINE) #define MOD_QUALIFIER (MOD_CONST | MOD_VOLATILE | MOD_RESTRICT) #define MOD_PTRINHERIT (MOD_QUALIFIER | MOD_ATOMIC | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST) /* modifiers preserved by typeof() operator */ @@ -261,6 +260,11 @@ struct symbol { #define MOD_FUN_ATTR (MOD_PURE|MOD_NORETURN) /* like cvr-qualifiers but 'reversed' (OK: source <= target) */ #define MOD_REV_QUAL (MOD_PURE|MOD_NORETURN) +/* do not warn when these are duplicated */ +#define MOD_DUP_OK (MOD_UNUSED|MOD_GNU_INLINE) +/* must be part of the declared symbol, not its type */ +#define MOD_DECLARE (MOD_STORAGE|MOD_INLINE|MOD_TLS|MOD_GNU_INLINE|MOD_UNUSED|MOD_PURE|MOD_NORETURN|MOD_EXT_VISIBLE) + /* Current parsing/evaluation function */ diff --git a/validation/attr-visible.c b/validation/attr-visible.c index 38ee8575..ce35e4e5 100644 --- a/validation/attr-visible.c +++ b/validation/attr-visible.c @@ -9,5 +9,4 @@ int flag __visible; /* * check-name: attr-visible * check-command: sparse -Wdecl $file - * check-known-to-fail */ diff --git a/validation/attr-visible2.c b/validation/attr-visible2.c index 62949b47..98918169 100644 --- a/validation/attr-visible2.c +++ b/validation/attr-visible2.c @@ -6,5 +6,4 @@ int arr[2] __visible; /* * check-name: attr-visible-after * check-command: sparse -Wdecl $file - * check-known-to-fail */ diff --git a/validation/cond_expr2.c b/validation/cond_expr2.c index 5e974cfa..a5d96576 100644 --- a/validation/cond_expr2.c +++ b/validation/cond_expr2.c @@ -16,7 +16,7 @@ cond_expr2.c:6:11: warning: incorrect type in assignment (different modifiers) cond_expr2.c:6:11: expected void volatile *extern [addressable] [toplevel] q cond_expr2.c:6:11: got void const volatile * cond_expr2.c:8:11: warning: incorrect type in assignment (different modifiers) -cond_expr2.c:8:11: expected int volatile *extern [addressable] [toplevel] [assigned] r +cond_expr2.c:8:11: expected int volatile *extern [addressable] [assigned] [toplevel] r cond_expr2.c:8:11: got int const volatile * * check-error-end */ diff --git a/validation/function-redecl.c b/validation/function-redecl.c index 03151359..d0d844a5 100644 --- a/validation/function-redecl.c +++ b/validation/function-redecl.c @@ -51,11 +51,11 @@ void arg_vararg(int a, ...) { } /* check-should-fail */ function-redecl.c:5:6: error: symbol 'ret_type' redeclared with different type (different base types): function-redecl.c:5:6: void extern [addressable] [toplevel] ret_type( ... ) function-redecl.c:4:5: note: previously declared as: -function-redecl.c:4:5: int extern [signed] [addressable] [toplevel] ret_type( ... ) +function-redecl.c:4:5: int extern [addressable] [signed] [toplevel] ret_type( ... ) function-redecl.c:9:11: error: symbol 'ret_const' redeclared with different type (different modifiers): -function-redecl.c:9:11: int extern const [signed] [addressable] [toplevel] ret_const( ... ) +function-redecl.c:9:11: int extern const [addressable] [signed] [toplevel] ret_const( ... ) function-redecl.c:8:5: note: previously declared as: -function-redecl.c:8:5: int extern [signed] [addressable] [toplevel] ret_const( ... ) +function-redecl.c:8:5: int extern [addressable] [signed] [toplevel] ret_const( ... ) function-redecl.c:13:13: error: symbol 'ret_as' redeclared with different type (different address spaces): function-redecl.c:13:13: void <asn:1> *extern [addressable] [toplevel] ret_as( ... ) function-redecl.c:12:6: note: previously declared as: |