aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linearize.c
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-11-29 10:51:08 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-12-21 01:53:52 +0100
commit2be50b1451d954b4ea4579bcb7173e57d8a07161 (patch)
treedb616322c39b4b1326575e181ee4b4ce289060d7 /linearize.c
parentc2f4b9f69159eb8604f6371687a796d40920f093 (diff)
downloadsparse-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.c10
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 {