diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-11-21 03:03:15 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-11-21 14:49:06 +0100 |
commit | 1546f48809a43f48769c374cc58a9a0b64ccda11 (patch) | |
tree | 658c79e11f42aac343761fe80d1460d9cdcb09ec | |
parent | 9305d48da0890d578254bd0e671e55a30b77ced0 (diff) | |
download | sparse-1546f48809a43f48769c374cc58a9a0b64ccda11.tar.gz |
allow 'static' forward declaration
A function or an object can be forward-declared as
'static' and then defining with the keyword 'static'
omitted. This is perfectly legal and relatively common.
However, Sparse complains that the definition is not
declared and asks to the dev if should not be static.
This is weird because the function or object *is*
declared and *is* static (or at least should be following
the standard or GCC's rules).
Fix this by letting a new declaration or definition
'inherit' the 'static-ness' of the previous declarations.
This is a bit more complicated than simply copying
MOD_STATIC and must be done when binding the new symbol
because static or extern objects have different scopes.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | symbol.c | 23 | ||||
-rw-r--r-- | validation/static-forward-decl.c | 19 |
2 files changed, 33 insertions, 9 deletions
@@ -618,6 +618,27 @@ void check_declaration(struct symbol *sym) } } +static void inherit_static(struct symbol *sym) +{ + struct symbol *prev; + + // only 'plain' symbols are concerned + if (sym->ctype.modifiers & (MOD_STATIC|MOD_EXTERN)) + return; + + for (prev = sym->next_id; prev; prev = prev->next_id) { + if (prev->namespace != NS_SYMBOL) + continue; + if (prev->scope != file_scope) + continue; + + sym->ctype.modifiers |= prev->ctype.modifiers & MOD_STATIC; + + // previous declarations are already converted + return; + } +} + void bind_symbol(struct symbol *sym, struct ident *ident, enum namespace ns) { struct scope *scope; @@ -641,6 +662,8 @@ void bind_symbol(struct symbol *sym, struct ident *ident, enum namespace ns) if (ns == NS_SYMBOL && toplevel(scope)) { unsigned mod = MOD_ADDRESSABLE | MOD_TOPLEVEL; + inherit_static(sym); + scope = global_scope; if (sym->ctype.modifiers & MOD_STATIC || is_extern_inline(sym)) { diff --git a/validation/static-forward-decl.c b/validation/static-forward-decl.c index daad1ecb..d25d8152 100644 --- a/validation/static-forward-decl.c +++ b/validation/static-forward-decl.c @@ -1,13 +1,14 @@ -static int f(void); +int fref(void); +int fref(void) { return 0; } + +static +int floc(void); +int floc(void) { return 0; } + +static +int oloc; +int oloc = 0; -int f(void) -{ - return 0; -} /* * check-name: static forward declaration - * - * check-error-start -static-forward-decl.c:3:5: warning: symbol 'f' was not declared. Should it be static? - * check-error-end */ |