type_value: typo meant the u64max was translated to 0x3fffffffffffffff
[smatch.git] / smatch_function_ptrs.c
bloba0eecc3d09d50d5064598336f9b17d48df1129c2
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 "scope.h"
17 #include "smatch.h"
18 #include "smatch_slist.h"
20 static int my_id;
22 static char *get_array_ptr(struct expression *expr)
24 struct expression *array;
25 struct symbol *type;
26 char *name;
27 char buf[256];
29 array = get_array_name(expr);
30 /* FIXME: is_array() should probably be is_array_element() */
31 type = get_type(expr);
32 if (!array && type && type->type == SYM_ARRAY)
33 array = expr;
34 if (array) {
35 name = expr_to_var(array);
36 if (!name)
37 return NULL;
38 snprintf(buf, sizeof(buf), "%s[]", name);
39 return alloc_string(buf);
42 expr = get_assigned_expr(expr);
43 array = get_array_name(expr);
44 if (!array)
45 return NULL;
46 name = expr_to_var(array);
47 if (!name)
48 return NULL;
49 snprintf(buf, sizeof(buf), "%s[]", name);
50 free_string(name);
51 return alloc_string(buf);
54 static int is_local_symbol(struct symbol *sym)
56 if (!sym || !sym->scope || !sym->scope->token)
57 return 0;
58 if (positions_eq(sym->scope->token->pos, cur_func_sym->pos))
59 return 1;
60 return 0;
63 static char *ptr_prefix(struct symbol *sym)
65 static char buf[128];
68 if (is_local_symbol(sym))
69 snprintf(buf, sizeof(buf), "%s ptr", get_function());
70 else if (sym && toplevel(sym->scope))
71 snprintf(buf, sizeof(buf), "%s ptr", get_base_file());
72 else
73 snprintf(buf, sizeof(buf), "ptr");
75 return buf;
78 char *get_fnptr_name(struct expression *expr)
80 char *name;
82 expr = strip_expr(expr);
84 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
85 if (expr->type == EXPR_PREOP && expr->op == '*') {
86 struct expression *unop = strip_expr(expr->unop);
88 if (unop->type == EXPR_PREOP && unop->op == '*')
89 expr = unop;
90 else if (unop->type == EXPR_SYMBOL)
91 expr = unop;
94 name = get_array_ptr(expr);
95 if (name)
96 return name;
98 if (expr->type == EXPR_SYMBOL) {
99 int param;
100 char buf[256];
101 struct symbol *sym;
102 struct symbol *type;
104 param = get_param_num_from_sym(expr->symbol);
105 if (param >= 0) {
106 snprintf(buf, sizeof(buf), "%s param %d", get_function(), param);
107 return alloc_string(buf);
110 name = expr_to_var_sym(expr, &sym);
111 if (!name)
112 return NULL;
113 type = get_type(expr);
114 if (type && type->type == SYM_PTR) {
115 snprintf(buf, sizeof(buf), "%s %s", ptr_prefix(sym), name);
116 free_string(name);
117 return alloc_string(buf);
119 return name;
121 name = get_member_name(expr);
122 if (name)
123 return name;
124 return expr_to_var(expr);
127 static void match_passes_function_pointer(struct expression *expr)
129 struct expression *arg, *tmp;
130 struct symbol *type;
131 char *called_name;
132 char *fn_name;
133 char ptr_name[256];
134 int i;
137 i = -1;
138 FOR_EACH_PTR(expr->args, arg) {
139 i++;
141 tmp = strip_expr(arg);
142 if (tmp->type == EXPR_PREOP && tmp->op == '&')
143 tmp = strip_expr(tmp->unop);
145 type = get_type(tmp);
146 if (type && type->type == SYM_PTR)
147 type = get_real_base_type(type);
148 if (!type || type->type != SYM_FN)
149 continue;
151 called_name = expr_to_var(expr->fn);
152 if (!called_name)
153 return;
154 fn_name = get_fnptr_name(tmp);
155 if (!fn_name)
156 goto free;
158 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i);
159 sql_insert_function_ptr(fn_name, ptr_name);
160 free:
161 free_string(fn_name);
162 free_string(called_name);
163 } END_FOR_EACH_PTR(arg);
167 static void match_function_assign(struct expression *expr)
169 struct expression *right;
170 struct symbol *sym;
171 char *fn_name;
172 char *ptr_name;
174 if (__in_fake_assign)
175 return;
177 right = strip_expr(expr->right);
178 if (right->type == EXPR_PREOP && right->op == '&')
179 right = strip_expr(right->unop);
180 if (right->type != EXPR_SYMBOL && right->type != EXPR_DEREF)
181 return;
182 sym = get_type(right);
183 if (!sym)
184 return;
185 if (sym->type != SYM_FN && sym->type != SYM_PTR && sym->type != SYM_ARRAY)
186 return;
187 if (sym->type == SYM_PTR) {
188 sym = get_real_base_type(sym);
189 if (!sym)
190 return;
191 if (sym->type != SYM_FN && sym != &void_ctype)
192 return;
195 fn_name = get_fnptr_name(right);
196 ptr_name = get_fnptr_name(expr->left);
197 if (!fn_name || !ptr_name)
198 goto free;
199 if (strcmp(fn_name, ptr_name) == 0)
200 goto free;
202 sql_insert_function_ptr(fn_name, ptr_name);
204 free:
205 free_string(fn_name);
206 free_string(ptr_name);
209 void register_function_ptrs(int id)
211 my_id = id;
213 if (!option_info)
214 return;
216 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK);
217 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
218 add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK);