If you dereference a function pointer, you get a function pointer back. AFAICS there are >=69 places in the kernel that unnecessarily dereference a function pointer before calling through it. Output of testcase when applied to previous version: ============================================= $ ./test-suite single linear/fn-ptr-deref.c TEST dereference function pointer (linear/fn-ptr-deref.c) error: actual output text does not match expected output text. error: see linear/fn-ptr-deref.c.output.* for further investigation. --- linear/fn-ptr-deref.c.output.expected 2018-02-22 01:26:20.592985408 +0100 +++ linear/fn-ptr-deref.c.output.got 2018-02-22 01:26:20.588985440 +0100 @@ -2,7 +2,8 @@ .L0: <entry-point> call func_a - call func_a + load %r4 <- 0[func_a] + call VOID ret linear/fn-ptr-deref.c failed ! ============================================= Signed-off-by: Jann Horn <jannh@xxxxxxxxxx> --- evaluate.c | 6 ++++++ validation/linear/fn-ptr-deref.c | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 validation/linear/fn-ptr-deref.c diff --git a/evaluate.c b/evaluate.c index b96696d..3859bfc 100644 --- a/evaluate.c +++ b/evaluate.c @@ -1776,6 +1776,12 @@ static struct symbol *evaluate_dereference(struct expression *expr) if (ctype->type == SYM_NODE) ctype = ctype->ctype.base_type; + /* Dereferencing a function pointer does nothing. */ + if (ctype->type == SYM_PTR && ctype->ctype.base_type->type == SYM_FN) { + *expr = *op; + return expr->ctype; + } + node = alloc_symbol(expr->pos, SYM_NODE); target = ctype->ctype.base_type; diff --git a/validation/linear/fn-ptr-deref.c b/validation/linear/fn-ptr-deref.c new file mode 100644 index 0000000..9352d1e --- /dev/null +++ b/validation/linear/fn-ptr-deref.c @@ -0,0 +1,22 @@ +void func_a(void); +static void function_foobar(int n) +{ + void (*indir_func_var)(void) = func_a; + indir_func_var(); + (*indir_func_var)(); +} +/* + * check-name: dereference function pointer + * check-command: test-linearize $file + * + * check-output-start +function_foobar: +.L0: + <entry-point> + call func_a + call func_a + ret + + + * check-output-end + */ -- 2.16.1.291.g4437f3f132-goog -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html