[PATCH] allow 'static' forward declaration

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 symbol.c                         | 23 +++++++++++++++++++++++
 validation/static-forward-decl.c | 19 ++++++++++---------
 2 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/symbol.c b/symbol.c
index 90149e5ae..90190eca1 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 daad1ecb1..d25d8152a 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
  */
-- 
2.24.0




[Index of Archives]     [Newbies FAQ]     [LKML]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Trinity Fuzzer Tool]

  Powered by Linux