function_ptrs: track parameters as well
[smatch.git] / smatch_function_ptrs.c
blob3524fb19cc86b23dbb6221d4e3ffe7627b9383d3
1 /*
2 * smatch/smatch_function_ptrs.c
4 * Copyright (C) 2013 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
11 * Track how functions are saved as various struct members or passed as
12 * parameters.
16 #include "smatch.h"
17 #include "smatch_slist.h"
19 static int my_id;
21 static void match_passes_function_pointer(struct expression *expr)
23 struct expression *arg, *tmp;
24 struct symbol *type;
25 char *called_name;
26 char *fn_name;
27 char ptr_name[256];
28 int i;
31 i = -1;
32 FOR_EACH_PTR(expr->args, arg) {
33 i++;
35 tmp = strip_expr(arg);
36 if (tmp->type == EXPR_PREOP && tmp->op == '&')
37 tmp = strip_expr(tmp->unop);
38 type = get_type(tmp);
39 if (!type || type->type != SYM_FN)
40 continue;
42 called_name = expr_to_var(expr->fn);
43 if (!called_name)
44 return;
45 fn_name = expr_to_var(tmp);
46 if (!fn_name)
47 goto free;
49 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i);
50 sql_insert_function_ptr(fn_name, ptr_name);
51 free:
52 free_string(fn_name);
53 free_string(called_name);
54 } END_FOR_EACH_PTR(arg);
58 static void match_function_assign(struct expression *expr)
60 struct expression *right = expr->right;
61 struct symbol *sym;
62 char *fn_name;
63 char *ptr_name;
65 if (right->type == EXPR_PREOP && right->op == '&')
66 right = strip_expr(right->unop);
67 if (right->type != EXPR_SYMBOL)
68 return;
69 sym = get_type(right);
70 if (!sym || sym->type != SYM_FN)
71 return;
73 fn_name = expr_to_var(right);
74 ptr_name = get_fnptr_name(expr->left);
75 if (!fn_name || !ptr_name)
76 goto free;
78 sql_insert_function_ptr(fn_name, ptr_name);
80 free:
81 free_string(fn_name);
82 free_string(ptr_name);
85 void register_function_ptrs(int id)
87 my_id = id;
89 if (!option_info)
90 return;
92 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK);
93 add_hook(&match_function_assign, ASSIGNMENT_HOOK);