2 * smatch/smatch_function_ptrs.c
4 * Copyright (C) 2013 Oracle.
6 * Licensed under the Open Software License version 1.1
11 * Track how functions are saved as various struct members or passed as
17 #include "smatch_slist.h"
21 static char *get_array_ptr(struct expression
*expr
)
23 struct expression
*array
;
27 array
= get_array_name(expr
);
29 name
= expr_to_var(array
);
32 snprintf(buf
, sizeof(buf
), "%s[]", name
);
33 return alloc_string(buf
);
36 expr
= get_assigned_expr(expr
);
37 array
= get_array_name(expr
);
40 name
= expr_to_var(array
);
43 snprintf(buf
, sizeof(buf
), "%s[]", name
);
45 return alloc_string(buf
);
48 char *get_fnptr_name(struct expression
*expr
)
52 expr
= strip_expr(expr
);
54 /* (*ptrs[0])(a, b, c) is the same as ptrs[0](a, b, c); */
55 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*') {
56 struct expression
*unop
= strip_expr(expr
->unop
);
58 if (unop
->type
== EXPR_PREOP
&& unop
->op
== '*')
60 else if (unop
->type
== EXPR_SYMBOL
)
64 name
= get_array_ptr(expr
);
68 if (expr
->type
== EXPR_SYMBOL
) {
72 param
= get_param_num_from_sym(expr
->symbol
);
74 snprintf(buf
, sizeof(buf
), "%s param %d", get_function(), param
);
75 return alloc_string(buf
);
78 return expr_to_var(expr
);
80 name
= get_member_name(expr
);
83 return expr_to_var(expr
);
86 static void match_passes_function_pointer(struct expression
*expr
)
88 struct expression
*arg
, *tmp
;
97 FOR_EACH_PTR(expr
->args
, arg
) {
100 tmp
= strip_expr(arg
);
101 if (tmp
->type
== EXPR_PREOP
&& tmp
->op
== '&')
102 tmp
= strip_expr(tmp
->unop
);
104 type
= get_type(tmp
);
105 if (type
&& type
->type
== SYM_PTR
)
106 type
= get_real_base_type(type
);
107 if (!type
|| type
->type
!= SYM_FN
)
110 called_name
= expr_to_var(expr
->fn
);
113 fn_name
= get_fnptr_name(tmp
);
117 snprintf(ptr_name
, sizeof(ptr_name
), "%s param %d", called_name
, i
);
118 sql_insert_function_ptr(fn_name
, ptr_name
);
120 free_string(fn_name
);
121 free_string(called_name
);
122 } END_FOR_EACH_PTR(arg
);
126 static void match_function_assign(struct expression
*expr
)
128 struct expression
*right
;
133 right
= strip_expr(expr
->right
);
134 if (right
->type
== EXPR_PREOP
&& right
->op
== '&')
135 right
= strip_expr(right
->unop
);
136 if (right
->type
!= EXPR_SYMBOL
)
138 sym
= get_type(right
);
141 if (sym
->type
!= SYM_FN
&& sym
->type
!= SYM_PTR
)
143 if (sym
->type
== SYM_PTR
) {
144 sym
= get_real_base_type(sym
);
147 if (sym
->type
!= SYM_FN
&& sym
!= &void_ctype
)
151 fn_name
= get_fnptr_name(right
);
152 ptr_name
= get_fnptr_name(expr
->left
);
153 if (!fn_name
|| !ptr_name
)
156 sql_insert_function_ptr(fn_name
, ptr_name
);
159 free_string(fn_name
);
160 free_string(ptr_name
);
163 void register_function_ptrs(int id
)
170 add_hook(&match_passes_function_pointer
, FUNCTION_CALL_HOOK
);
171 add_hook(&match_function_assign
, ASSIGNMENT_HOOK
);
172 add_hook(&match_function_assign
, GLOBAL_ASSIGNMENT_HOOK
);