aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2020-02-19 17:29:34 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-02-20 01:41:46 +0100
commite078774555c66004ab404097bfd58523c2e78f86 (patch)
tree9ccd44659a843ae7e3b78c7043668a2a8b027664
parent9ac20e9e3c06918665aada812b0452d88d835291 (diff)
downloadsparse-e078774555c66004ab404097bfd58523c2e78f86.tar.gz
dissect: fix sym_is_local(SYM_STRUCT/UNION/ENUM)
Now that struct_union_enum_specifier() always sets sym->scope we can simplify sym_is_local(sym) and rely on toplevel() even if sym is type. Test-case: // copied from linux kernel # define __force __attribute__((force)) #define WRITE_ONCE(x, val) \ ({ \ union { typeof(x) __val; char __c[1]; } __u = \ { .__val = (__force typeof(x)) (val) }; \ __write_once_size(&(x), __u.__c, sizeof(x)); \ __u.__val; \ }) void func(int *p) { WRITE_ONCE(*p, 0); } before this patch the widely used WRITE_ONCE() generates a lot of spam which can't be filtered out using sym_is_local(), 11:6 def f func void ( ... ) 11:11 func def . v p int * 13:9 def s :__u 13:9 --- . v p int * 13:9 def m :__u.__val int 13:9 def m :__u.__c char [1] 13:9 func def . v __u union :__u 13:9 func -w- . v __u union :__u 13:9 func -w- m :__u.__val int 13:9 func --- . v p int * 13:9 func --r f __write_once_size bad type 13:9 func -r- . v p int * 13:9 func -r- . v __u union :__u 13:9 func m-- m :__u.__c char [1] 13:9 func --- . v p int * 13:9 func --- . v __u union :__u 13:9 func --- m :__u.__val int plus it triggers warning("no context") in test-dissect.c. With this patch the only "nonlocal" report is __write_once_size() call. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--dissect.c4
-rw-r--r--dissect.h3
2 files changed, 4 insertions, 3 deletions
diff --git a/dissect.c b/dissect.c
index 40baf64f..c48214b9 100644
--- a/dissect.c
+++ b/dissect.c
@@ -152,7 +152,6 @@ static inline struct symbol *expr_symbol(struct expression *expr)
if (!sym) {
sym = alloc_symbol(expr->pos, SYM_BAD);
bind_symbol(sym, expr->symbol_name, NS_SYMBOL);
- sym->ctype.modifiers = MOD_EXTERN | MOD_TOPLEVEL;
sym->kind = expr->op ?: 'v'; /* see EXPR_CALL */
}
}
@@ -238,7 +237,8 @@ static void examine_sym_node(struct symbol *node, struct symbol *parent)
return;
dctx = dissect_ctx;
- dissect_ctx = NULL;
+ if (toplevel(base->scope))
+ dissect_ctx = NULL;
if (base->ident || deanon(base, name, parent))
reporter->r_symdef(base);
diff --git a/dissect.h b/dissect.h
index 326d3dc3..a77a9328 100644
--- a/dissect.h
+++ b/dissect.h
@@ -4,6 +4,7 @@
#include <stdio.h>
#include "parse.h"
#include "expression.h"
+#include "scope.h"
#define U_SHIFT 8
@@ -29,7 +30,7 @@ extern struct symbol *dissect_ctx;
static inline bool sym_is_local(struct symbol *sym)
{
- return sym->kind == 'v' && !(sym->ctype.modifiers & MOD_TOPLEVEL);
+ return !toplevel(sym->scope);
}
extern void dissect(struct reporter *, struct string_list *);