flow: expressions: don't try updating to uninitialized position
[smatch.git] / smatch_function_ptrs.c
blob2600e3f0e53c30bcc36469d7e89b9a73d5bc7bba
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 char *get_fnptr_name(struct expression *expr)
23 char *name;
25 expr = strip_expr(expr);
26 if (expr->type == EXPR_SYMBOL) {
27 int param;
28 char buf[256];
30 param = get_param_num_from_sym(expr->symbol);
31 if (param >= 0) {
32 snprintf(buf, sizeof(buf), "%s param %d", get_function(), param);
33 return alloc_string(buf);
36 return expr_to_var(expr);
38 name = get_member_name(expr);
39 if (name)
40 return name;
41 return expr_to_var(expr);
44 static void match_passes_function_pointer(struct expression *expr)
46 struct expression *arg, *tmp;
47 struct symbol *type;
48 char *called_name;
49 char *fn_name;
50 char ptr_name[256];
51 int i;
54 i = -1;
55 FOR_EACH_PTR(expr->args, arg) {
56 i++;
58 tmp = strip_expr(arg);
59 if (tmp->type == EXPR_PREOP && tmp->op == '&')
60 tmp = strip_expr(tmp->unop);
62 type = get_type(tmp);
63 if (type && type->type == SYM_PTR)
64 type = get_real_base_type(type);
65 if (!type || type->type != SYM_FN)
66 continue;
68 called_name = expr_to_var(expr->fn);
69 if (!called_name)
70 return;
71 fn_name = get_fnptr_name(tmp);
72 if (!fn_name)
73 goto free;
75 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i);
76 sql_insert_function_ptr(fn_name, ptr_name);
77 free:
78 free_string(fn_name);
79 free_string(called_name);
80 } END_FOR_EACH_PTR(arg);
84 static void match_function_assign(struct expression *expr)
86 struct expression *right;
87 struct symbol *sym;
88 char *fn_name;
89 char *ptr_name;
91 right = strip_expr(expr->right);
92 if (right->type == EXPR_PREOP && right->op == '&')
93 right = strip_expr(right->unop);
94 if (right->type != EXPR_SYMBOL)
95 return;
96 sym = get_type(right);
97 if (!sym || sym->type != SYM_FN)
98 return;
100 fn_name = expr_to_var(right);
101 ptr_name = get_fnptr_name(expr->left);
102 if (!fn_name || !ptr_name)
103 goto free;
105 sql_insert_function_ptr(fn_name, ptr_name);
107 free:
108 free_string(fn_name);
109 free_string(ptr_name);
112 void register_function_ptrs(int id)
114 my_id = id;
116 if (!option_info)
117 return;
119 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK);
120 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
121 add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK);