aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-15 00:06:14 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-15 01:42:54 +0100
commit233d4e17c544e1de252aed8f409630599104dbc7 (patch)
tree83f39dd2618b8656d342a8a0bd946452e8d1f010
parentfd3528aa0409874386610ce63bb647fff8312fd9 (diff)
downloadsparse-233d4e17c544e1de252aed8f409630599104dbc7.tar.gz
function attributes apply to the function declaration
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 <john.levon@joyent.com> Reported-by: Alex Kogan <alex.kogan@oracle.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--parse.c17
-rw-r--r--symbol.h2
-rw-r--r--validation/function-attribute.c19
3 files changed, 37 insertions, 1 deletions
diff --git a/parse.c b/parse.c
index fa92fae6..37ffede7 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 4e7e437b..516b6136 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 00000000..0f2c7592
--- /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
+ */