2 * Copyright (C) 2013 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * Track how functions are saved as various struct members or passed as
26 #include "smatch_slist.h"
30 static char *get_array_ptr(struct expression
*expr
)
32 struct expression
*array
;
37 array
= get_array_name(expr
);
40 name
= get_member_name(array
);
45 /* FIXME: is_array() should probably be is_array_element() */
46 type
= get_type(expr
);
47 if (!array
&& type
&& type
->type
== SYM_ARRAY
)
50 name
= expr_to_var(array
);
53 snprintf(buf
, sizeof(buf
), "%s[]", name
);
54 return alloc_string(buf
);
57 expr
= get_assigned_expr(expr
);
58 array
= get_array_name(expr
);
61 name
= expr_to_var(array
);
64 snprintf(buf
, sizeof(buf
), "%s[]", name
);
66 return alloc_string(buf
);
69 static int is_local_symbol(struct symbol
*sym
)
71 if (!sym
|| !sym
->scope
|| !sym
->scope
->token
)
73 if (positions_eq(sym
->scope
->token
->pos
, cur_func_sym
->pos
))
78 static char *ptr_prefix(struct symbol
*sym
)
83 if (is_local_symbol(sym
))
84 snprintf(buf
, sizeof(buf
), "%s ptr", get_function());
85 else if (sym
&& toplevel(sym
->scope
))
86 snprintf(buf
, sizeof(buf
), "%s ptr", get_base_file());
88 snprintf(buf
, sizeof(buf
), "ptr");
93 char *get_returned_ptr(struct expression
*expr
)
99 if (expr
->type
!= EXPR_CALL
)
101 if (!expr
->fn
|| expr
->fn
->type
!= EXPR_SYMBOL
)
104 type
= get_type(expr
);
105 if (type
&& type
->type
== SYM_PTR
)
106 type
= get_real_base_type(type
);
107 if (!type
|| type
->type
!= SYM_FN
)
110 name
= expr_to_var(expr
->fn
);
113 snprintf(buf
, sizeof(buf
), "r %s()", name
);
115 return alloc_string(buf
);
118 char *get_fnptr_name(struct expression
*expr
)
122 expr
= strip_expr(expr
);
124 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
125 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*') {
126 struct expression
*unop
= strip_expr(expr
->unop
);
128 if (unop
->type
== EXPR_PREOP
&& unop
->op
== '*')
130 else if (unop
->type
== EXPR_SYMBOL
)
134 name
= get_array_ptr(expr
);
138 name
= get_returned_ptr(expr
);
142 name
= get_member_name(expr
);
146 if (expr
->type
== EXPR_SYMBOL
) {
152 param
= get_param_num_from_sym(expr
->symbol
);
154 snprintf(buf
, sizeof(buf
), "%s param %d", get_function(), param
);
155 return alloc_string(buf
);
158 name
= expr_to_var_sym(expr
, &sym
);
161 type
= get_type(expr
);
162 if (type
&& type
->type
== SYM_PTR
) {
163 snprintf(buf
, sizeof(buf
), "%s %s", ptr_prefix(sym
), name
);
165 return alloc_string(buf
);
169 return expr_to_var(expr
);
172 static void match_passes_function_pointer(struct expression
*expr
)
174 struct expression
*arg
, *tmp
;
183 FOR_EACH_PTR(expr
->args
, arg
) {
186 tmp
= strip_expr(arg
);
187 if (tmp
->type
== EXPR_PREOP
&& tmp
->op
== '&')
188 tmp
= strip_expr(tmp
->unop
);
190 type
= get_type(tmp
);
191 if (type
&& type
->type
== SYM_PTR
)
192 type
= get_real_base_type(type
);
193 if (!type
|| type
->type
!= SYM_FN
)
196 called_name
= expr_to_var(expr
->fn
);
199 fn_name
= get_fnptr_name(tmp
);
203 snprintf(ptr_name
, sizeof(ptr_name
), "%s param %d", called_name
, i
);
204 sql_insert_function_ptr(fn_name
, ptr_name
);
206 free_string(fn_name
);
207 free_string(called_name
);
208 } END_FOR_EACH_PTR(arg
);
212 static void match_function_assign(struct expression
*expr
)
214 struct expression
*right
;
219 if (__in_fake_assign
)
222 right
= strip_expr(expr
->right
);
223 if (right
->type
== EXPR_PREOP
&& right
->op
== '&')
224 right
= strip_expr(right
->unop
);
225 if (right
->type
!= EXPR_SYMBOL
&& right
->type
!= EXPR_DEREF
&& right
->type
!= EXPR_CALL
)
227 sym
= get_type(right
);
230 if (sym
->type
!= SYM_FN
&& sym
->type
!= SYM_PTR
&& sym
->type
!= SYM_ARRAY
)
232 if (sym
->type
== SYM_PTR
) {
233 sym
= get_real_base_type(sym
);
236 if (sym
->type
!= SYM_FN
&& sym
!= &void_ctype
)
240 fn_name
= get_fnptr_name(right
);
241 ptr_name
= get_fnptr_name(expr
->left
);
242 if (!fn_name
|| !ptr_name
)
244 if (strcmp(fn_name
, ptr_name
) == 0)
247 sql_insert_function_ptr(fn_name
, ptr_name
);
250 free_string(fn_name
);
251 free_string(ptr_name
);
254 static void match_returns_function_pointer(struct expression
*expr
)
263 type
= get_real_base_type(cur_func_sym
);
264 if (!type
|| type
->type
!= SYM_FN
)
266 type
= get_real_base_type(type
);
267 if (!type
|| type
->type
!= SYM_PTR
)
269 type
= get_real_base_type(type
);
270 if (!type
|| type
->type
!= SYM_FN
)
273 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '&')
274 expr
= strip_expr(expr
->unop
);
276 fn_name
= get_fnptr_name(expr
);
279 snprintf(ptr_name
, sizeof(ptr_name
), "r %s()", get_function());
280 sql_insert_function_ptr(fn_name
, ptr_name
);
283 void register_function_ptrs(int id
)
290 add_hook(&match_passes_function_pointer
, FUNCTION_CALL_HOOK
);
291 add_hook(&match_returns_function_pointer
, RETURN_HOOK
);
292 add_hook(&match_function_assign
, ASSIGNMENT_HOOK
);
293 add_hook(&match_function_assign
, GLOBAL_ASSIGNMENT_HOOK
);