aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-21 03:03:15 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-21 14:49:06 +0100
commit1546f48809a43f48769c374cc58a9a0b64ccda11 (patch)
tree658c79e11f42aac343761fe80d1460d9cdcb09ec
parent9305d48da0890d578254bd0e671e55a30b77ced0 (diff)
downloadsparse-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.c23
-rw-r--r--validation/static-forward-decl.c19
2 files changed, 33 insertions, 9 deletions
diff --git a/symbol.c b/symbol.c
index 90149e5a..90190eca 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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
*/