aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2020-02-07 11:32:07 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-02-07 14:53:51 +0100
commitf3a6f29a8ab2ac4f4892115fa3ce49b091cbee75 (patch)
tree966d7992cdee06e971ed3952787a41ce22d5f5fa
parent5778d8fe517bd147861c53e9ec4d14d93d7b7ebb (diff)
downloadsparse-f3a6f29a8ab2ac4f4892115fa3ce49b091cbee75.tar.gz
dissect: change do_symbol(SYM_FN) to check base_type->stmt != NULL
examine_fn_arguments() silently degenerates function arguments into pointers but dissect doesn't do evaluate_symbol_list(), that is why do_sym_list(type->arguments) can report the bogus definitions. Test case: void extf(int MUST_NOT_BE_REPORTED); typedef void (fptr_t)(int MUST_NOT_BE_REPORTED); void func1(fptr_t fptr) {} void func2(typeof(extf) fptr) {} void func3(void) { typeof(extf) fptr; }; void func4(void (fptr)(int MUST_NOT_BE_REPORTED)) {} without this patch: 4:6 def func1 void ( ... ) 4:12 func1 def fptr void ( ... ) 2:23 fptr def MUST_NOT_BE_REPORTED int 5:6 def func2 void ( ... ) 5:19 func2 --- extf void ( ... ) 5:12 func2 def fptr void ( ... ) 1:11 fptr def MUST_NOT_BE_REPORTED int 6:6 def func3 void ( ... ) 6:27 func3 --- extf void ( ... ) 6:33 func3 def fptr void ( ... ) 1:11 fptr def MUST_NOT_BE_REPORTED int 7:6 def func4 void ( ... ) 7:12 func4 def fptr void ( ... ) 7:24 fptr def MUST_NOT_BE_REPORTED int Signed-off-by: Oleg Nesterov <oleg@redhat.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--dissect.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/dissect.c b/dissect.c
index 54e11d2f..b48cd852 100644
--- a/dissect.c
+++ b/dissect.c
@@ -589,6 +589,7 @@ static inline struct symbol *do_symbol(struct symbol *sym)
{
struct symbol *type = base_type(sym);
struct symbol *dctx = dissect_ctx;
+ struct statement *stmt;
reporter->r_symdef(sym);
@@ -603,12 +604,22 @@ static inline struct symbol *do_symbol(struct symbol *sym)
dissect_ctx = dctx;
break; case SYM_FN:
+ stmt = sym->ctype.modifiers & MOD_INLINE
+ ? type->inline_stmt
+ : type->stmt;
+ if (!stmt)
+ break;
+
+ if (dctx)
+ sparse_error(dctx->pos,
+ "dissect_ctx change %.*s -> %s",
+ dctx->ident->len, dctx->ident->name,
+ show_ident(sym->ident));
+
dissect_ctx = sym;
return_type = base_type(type);
do_sym_list(type->arguments);
- do_statement(U_VOID, sym->ctype.modifiers & MOD_INLINE
- ? type->inline_stmt
- : type->stmt);
+ do_statement(U_VOID, stmt);
dissect_ctx = dctx;
return_type = NULL;
}