diff options
author | Jann Horn <jannh@google.com> | 2019-03-27 21:10:38 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-03-27 22:12:24 +0100 |
commit | 1ed0955919913ad4f314e867fcbc76535acf010c (patch) | |
tree | cf38b8d8908664d0b0c78b43a40b951e4d9b027d | |
parent | 7fd3778e2d3a7b17aefea66819bf07feb7a257d3 (diff) | |
download | sparse-1ed0955919913ad4f314e867fcbc76535acf010c.tar.gz |
evaluate: externally_visible functions don't need a declaration
sparse warns for non-static functions that don't have a separate
declaration. The kernel contains several such functions that are marked
as __attribute__((externally_visible)) to mark that they are called from
assembly code. Assembly code doesn't need a header with a declaration to
call a function. Therefore, suppress the warning for functions with
__attribute__((externally_visible)).
Signed-off-by: Jann Horn <jannh@google.com>
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | evaluate.c | 2 | ||||
-rw-r--r-- | gcc-attr-list.h | 1 | ||||
-rw-r--r-- | parse.c | 16 | ||||
-rw-r--r-- | symbol.h | 4 |
4 files changed, 19 insertions, 4 deletions
@@ -3387,7 +3387,7 @@ void check_duplicates(struct symbol *sym) } if (!declared) { unsigned long mod = sym->ctype.modifiers; - if (mod & (MOD_STATIC | MOD_REGISTER)) + if (mod & (MOD_STATIC | MOD_REGISTER | MOD_EXT_VISIBLE)) return; if (!(mod & MOD_TOPLEVEL)) return; diff --git a/gcc-attr-list.h b/gcc-attr-list.h index 8da31435..c7800175 100644 --- a/gcc-attr-list.h +++ b/gcc-attr-list.h @@ -42,7 +42,6 @@ GCC_ATTR(either) GCC_ATTR(error) GCC_ATTR(exception) GCC_ATTR(exception_handler) -GCC_ATTR(externally_visible) GCC_ATTR(far) GCC_ATTR(fast_interrupt) GCC_ATTR(fastcall) @@ -82,6 +82,7 @@ typedef struct token *attr_t(struct token *, struct symbol *, static attr_t attribute_packed, attribute_aligned, attribute_modifier, + attribute_ext_visible, attribute_bitwise, attribute_address_space, attribute_context, attribute_designated_init, @@ -373,6 +374,10 @@ static struct symbol_op attr_mod_op = { .attribute = attribute_modifier, }; +static struct symbol_op ext_visible_op = { + .attribute = attribute_ext_visible, +}; + static struct symbol_op attr_bitwise_op = { .attribute = attribute_bitwise, }; @@ -562,6 +567,8 @@ static struct init_keyword { {"const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__const", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, {"__const__", NS_KEYWORD, MOD_PURE, .op = &attr_mod_op }, + {"externally_visible", NS_KEYWORD, .op = &ext_visible_op }, + {"__externally_visible__", NS_KEYWORD, .op = &ext_visible_op }, { "mode", NS_KEYWORD, .op = &mode_op }, { "__mode__", NS_KEYWORD, .op = &mode_op }, @@ -1106,6 +1113,12 @@ static struct token *attribute_modifier(struct token *token, struct symbol *attr return token; } +static struct token *attribute_ext_visible(struct token *token, struct symbol *attr, struct decl_state *ctx) +{ + ctx->is_ext_visible = 1; + return token; +} + static struct token *attribute_bitwise(struct token *token, struct symbol *attr, struct decl_state *ctx) { if (Wbitwise) @@ -1343,7 +1356,8 @@ static unsigned long storage_modifiers(struct decl_state *ctx) [SRegister] = MOD_REGISTER }; return mod[ctx->storage_class] | (ctx->is_inline ? MOD_INLINE : 0) - | (ctx->is_tls ? MOD_TLS : 0); + | (ctx->is_tls ? MOD_TLS : 0) + | (ctx->is_ext_visible ? MOD_EXT_VISIBLE : 0); } static void set_storage_class(struct position *pos, struct decl_state *ctx, int class) @@ -110,6 +110,7 @@ struct decl_state { struct ident **ident; struct symbol_op *mode; unsigned char prefer_abstract, is_inline, storage_class, is_tls; + unsigned char is_ext_visible; }; struct symbol_op { @@ -237,6 +238,7 @@ struct symbol { #define MOD_NOCAST 0x04000000 #define MOD_NODEREF 0x08000000 #define MOD_NORETURN 0x10000000 +#define MOD_EXT_VISIBLE 0x20000000 #define MOD_ACCESS (MOD_ASSIGNED | MOD_ADDRESSABLE) @@ -246,7 +248,7 @@ struct symbol { #define MOD_LONG_ALL (MOD_LONG | MOD_LONGLONG | MOD_LONGLONGLONG) #define MOD_SPECIFIER (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL | MOD_SIGNEDNESS) #define MOD_SIZE (MOD_CHAR | MOD_SHORT | MOD_LONG_ALL) -#define MOD_IGNORE (MOD_STORAGE | MOD_ACCESS | MOD_USERTYPE | MOD_EXPLICITLY_SIGNED) +#define MOD_IGNORE (MOD_STORAGE | MOD_ACCESS | MOD_USERTYPE | MOD_EXPLICITLY_SIGNED | MOD_EXT_VISIBLE) #define MOD_QUALIFIER (MOD_CONST | MOD_VOLATILE | MOD_RESTRICT | MOD_ATOMIC) #define MOD_PTRINHERIT (MOD_QUALIFIER | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST) /* modifiers preserved by typeof() operator */ |