diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-11-29 10:51:08 +0100 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-12-21 01:53:52 +0100 |
| commit | 2be50b1451d954b4ea4579bcb7173e57d8a07161 (patch) | |
| tree | db616322c39b4b1326575e181ee4b4ce289060d7 /linearize.c | |
| parent | c2f4b9f69159eb8604f6371687a796d40920f093 (diff) | |
| download | sparse-dev-2be50b1451d954b4ea4579bcb7173e57d8a07161.tar.gz | |
fix linearize (*fun)()
A function call via a function pointer can be written like:
fp(), (fp)() or (*fp)()
In the latter case the dereference is unneeded but legal and
idiomatic.
However, the linearization doesn't handle this unneeded deref
and leads to the generation of a load of the pointer:
int foo(int a, int (*fun)(int))
{
(*fun)(a);
}
gives something like:
foo:
load %r2 <- 0[%arg2]
call.32 %r3 <- %r2, %arg1
ret.32 %r3
This happens because, at linearization, the deref is dropped
but only if the sub-expression is a symbol and the test for
node is not done.
Fix this by using is_func_type() to test the type of all call
expressions.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Diffstat (limited to 'linearize.c')
| -rw-r--r-- | linearize.c | 10 |
1 files changed, 3 insertions, 7 deletions
diff --git a/linearize.c b/linearize.c index 7ad348c0..2e146de7 100644 --- a/linearize.c +++ b/linearize.c @@ -1291,13 +1291,9 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi add_symbol(&insn->fntypes, arg->ctype); } END_FOR_EACH_PTR(arg); - if (fn->type == EXPR_PREOP) { - if (fn->unop->type == EXPR_SYMBOL) { - struct symbol *sym = fn->unop->symbol; - if (sym->ctype.base_type->type == SYM_FN) - fn = fn->unop; - } - } + if (fn->type == EXPR_PREOP && fn->op == '*' && is_func_type(fn->ctype)) + fn = fn->unop; + if (fn->type == EXPR_SYMBOL) { call = symbol_pseudo(ep, fn->symbol); } else { |
