diff options
author | Oleg Nesterov <oleg@redhat.com> | 2020-02-07 11:32:07 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-02-07 14:53:51 +0100 |
commit | f3a6f29a8ab2ac4f4892115fa3ce49b091cbee75 (patch) | |
tree | 966d7992cdee06e971ed3952787a41ce22d5f5fa | |
parent | 5778d8fe517bd147861c53e9ec4d14d93d7b7ebb (diff) | |
download | sparse-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.c | 17 |
1 files changed, 14 insertions, 3 deletions
@@ -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; } |