[PATCH] function attributes apply to the function declaration

Luc Van Oostenryck <[email protected]>
Newsgroups org.kernel.vger.smatch
Message-ID <[email protected]>
Function attributes relate to the function declaration they
appear in. Sparse ignore most these attributes but a few ones
have a semantic value: 'pure', 'noreturn' & 'externally_visible'.

Due to how Sparse parse attributes and how these attributes
are stored for functions, the attributes 'pure' & 'noreturn'
are applied not to the function itself but its return type
if the function returns a pointer.

Fix this by extracting these attributes from the declaration
context and ensure they're applied to the declarator.

Reported-by: John Levon <[email protected]>
Reported-by: Alex Kogan <[email protected]>
Signed-off-by: Luc Van Oostenryck <[email protected]>
---
 parse.c                         | 17 ++++++++++++++++-
 symbol.h                        |  2 ++
 validation/function-attribute.c | 19 +++++++++++++++++++
 3 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 validation/function-attribute.c

diff --git a/parse.c b/parse.c
index fa92fae68..37ffede72 100644
--- a/parse.c
+++ b/parse.c
@@ -2900,6 +2900,21 @@ static struct token *toplevel_asm_declaration(struct token *token, struct symbol
 	return token;
 }
 
+static unsigned long declaration_modifiers(struct decl_state *ctx)
+{
+	unsigned long mods;
+
+	// Storage modifiers only relates to the declaration
+	mods = storage_modifiers(ctx);
+
+	// Function attributes also only relates to the declaration
+	// and must not be present in the function/return type.
+	mods |= ctx->ctype.modifiers & MOD_FUN_ATTR;
+	ctx->ctype.modifiers &=~ MOD_FUN_ATTR;
+
+	return mods;
+}
+
 struct token *external_declaration(struct token *token, struct symbol_list **list,
 		validate_decl_t validate_decl)
 {
@@ -2920,7 +2935,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 = declaration_modifiers(&ctx);
 	decl = alloc_symbol(token->pos, SYM_NODE);
 	/* Just a type declaration? */
 	if (match_op(token, ';')) {
diff --git a/symbol.h b/symbol.h
index 4e7e437bf..516b61361 100644
--- a/symbol.h
+++ b/symbol.h
@@ -251,6 +251,8 @@ struct symbol {
 #define MOD_PTRINHERIT	(MOD_QUALIFIER | MOD_NODEREF | MOD_NORETURN | MOD_NOCAST)
 /* modifiers preserved by typeof() operator */
 #define MOD_TYPEOF	(MOD_QUALIFIER | MOD_NOCAST | MOD_SPECIFIER)
+/* modifiers for funtion attributes */
+#define MOD_FUN_ATTR	(MOD_PURE|MOD_NORETURN)
 
 
 /* Current parsing/evaluation function */
diff --git a/validation/function-attribute.c b/validation/function-attribute.c
new file mode 100644
index 000000000..0f2c75922
--- /dev/null
+++ b/validation/function-attribute.c
@@ -0,0 +1,19 @@
+#define __pure __attribute__((pure))
+
+struct s {
+	int x;
+};
+
+static __pure struct s *grab(struct s *ptr)
+{
+	return ptr;
+}
+
+static void foo(struct s *ptr)
+{
+	struct s *ptr = grab(ptr);
+}
+
+/*
+ * check-name: function-attribute
+ */
-- 
2.24.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.