smatch_clear_buffer: make a function static
[smatch.git] / smatch_function_ptrs.c
blob9173f721954d439cb9de4577300ca3454b716360
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 char *name;
26 char buf[256];
28 array = get_array_name(expr);
29 if (array) {
30 name = expr_to_var(array);
31 if (!name)
32 return NULL;
33 snprintf(buf, sizeof(buf), "%s[]", name);
34 return alloc_string(buf);
37 expr = get_assigned_expr(expr);
38 array = get_array_name(expr);
39 if (!array)
40 return NULL;
41 name = expr_to_var(array);
42 if (!name)
43 return NULL;
44 snprintf(buf, sizeof(buf), "%s[]", name);
45 free_string(name);
46 return alloc_string(buf);
49 static int is_local_symbol(struct symbol *sym)
51 if (!sym || !sym->scope || !sym->scope->token)
52 return 0;
53 if (positions_eq(sym->scope->token->pos, cur_func_sym->pos))
54 return 1;
55 return 0;
58 static char *ptr_prefix(struct symbol *sym)
60 static char buf[128];
63 if (is_local_symbol(sym))
64 snprintf(buf, sizeof(buf), "%s ptr", get_function());
65 else if (sym && toplevel(sym->scope))
66 snprintf(buf, sizeof(buf), "%s ptr", get_base_file());
67 else
68 snprintf(buf, sizeof(buf), "ptr");
70 return buf;
73 char *get_fnptr_name(struct expression *expr)
75 char *name;
77 expr = strip_expr(expr);
79 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
80 if (expr->type == EXPR_PREOP && expr->op == '*') {
81 struct expression *unop = strip_expr(expr->unop);
83 if (unop->type == EXPR_PREOP && unop->op == '*')
84 expr = unop;
85 else if (unop->type == EXPR_SYMBOL)
86 expr = unop;
89 name = get_array_ptr(expr);
90 if (name)
91 return name;
93 if (expr->type == EXPR_SYMBOL) {
94 int param;
95 char buf[256];
96 struct symbol *sym;
97 struct symbol *type;
99 param = get_param_num_from_sym(expr->symbol);
100 if (param >= 0) {
101 snprintf(buf, sizeof(buf), "%s param %d", get_function(), param);
102 return alloc_string(buf);
105 name = expr_to_var_sym(expr, &sym);
106 if (!name)
107 return NULL;
108 type = get_type(expr);
109 if (type && type->type == SYM_PTR) {
110 snprintf(buf, sizeof(buf), "%s %s", ptr_prefix(sym), name);
111 free_string(name);
112 return alloc_string(buf);
114 return name;
116 name = get_member_name(expr);
117 if (name)
118 return name;
119 return expr_to_var(expr);
122 static void match_passes_function_pointer(struct expression *expr)
124 struct expression *arg, *tmp;
125 struct symbol *type;
126 char *called_name;
127 char *fn_name;
128 char ptr_name[256];
129 int i;
132 i = -1;
133 FOR_EACH_PTR(expr->args, arg) {
134 i++;
136 tmp = strip_expr(arg);
137 if (tmp->type == EXPR_PREOP && tmp->op == '&')
138 tmp = strip_expr(tmp->unop);
140 type = get_type(tmp);
141 if (type && type->type == SYM_PTR)
142 type = get_real_base_type(type);
143 if (!type || type->type != SYM_FN)
144 continue;
146 called_name = expr_to_var(expr->fn);
147 if (!called_name)
148 return;
149 fn_name = get_fnptr_name(tmp);
150 if (!fn_name)
151 goto free;
153 snprintf(ptr_name, sizeof(ptr_name), "%s param %d", called_name, i);
154 sql_insert_function_ptr(fn_name, ptr_name);
155 free:
156 free_string(fn_name);
157 free_string(called_name);
158 } END_FOR_EACH_PTR(arg);
162 static void match_function_assign(struct expression *expr)
164 struct expression *right;
165 struct symbol *sym;
166 char *fn_name;
167 char *ptr_name;
169 right = strip_expr(expr->right);
170 if (right->type == EXPR_PREOP && right->op == '&')
171 right = strip_expr(right->unop);
172 if (right->type != EXPR_SYMBOL && right->type != EXPR_DEREF)
173 return;
174 sym = get_type(right);
175 if (!sym)
176 return;
177 if (sym->type != SYM_FN && sym->type != SYM_PTR)
178 return;
179 if (sym->type == SYM_PTR) {
180 sym = get_real_base_type(sym);
181 if (!sym)
182 return;
183 if (sym->type != SYM_FN && sym != &void_ctype)
184 return;
187 fn_name = get_fnptr_name(right);
188 ptr_name = get_fnptr_name(expr->left);
189 if (!fn_name || !ptr_name)
190 goto free;
192 sql_insert_function_ptr(fn_name, ptr_name);
194 free:
195 free_string(fn_name);
196 free_string(ptr_name);
199 void register_function_ptrs(int id)
201 my_id = id;
203 if (!option_info)
204 return;
206 add_hook(&match_passes_function_pointer, FUNCTION_CALL_HOOK);
207 add_hook(&match_function_assign, ASSIGNMENT_HOOK);
208 add_hook(&match_function_assign, GLOBAL_ASSIGNMENT_HOOK);