db: remove return_implies table and related code
[smatch.git] / smatch_param_limit.c
blob778845e650558086b77dc4b36fad410616ea5cc8
1 /*
2 * sparse/smatch_param_limit.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "scope.h"
11 #include "smatch.h"
12 #include "smatch_extra.h"
14 static int orig_id;
15 static int modify_id;
16 static int side_effects;
18 STATE(modified);
20 static struct smatch_state *unmatched_state(struct sm_state *sm)
22 return extra_undefined(estate_type(sm->state));
25 int was_modified_sym(struct symbol *sym)
27 if (!side_effects)
28 return 0;
29 if (!sym || !sym->ident)
30 return 1; /* safer to say it was modified? */
31 if (get_state(modify_id, sym->ident->name, sym))
32 return 1;
33 return 0;
36 static int is_local(struct symbol *sym)
38 if (!sym->scope || !sym->scope->token)
39 return 0;
40 return 1;
43 static void check_expr(struct expression *expr)
45 struct smatch_state *state;
46 struct symbol *sym;
47 char *name;
49 name = get_variable_from_expr_complex(expr, &sym);
50 if (!sym) {
51 side_effects = 1;
52 goto free;
55 if (!is_local(sym))
56 side_effects = 1;
59 * Pointers are so tricky to handle just bail.
61 if (get_real_base_type(sym)->type == SYM_PTR)
62 side_effects = 1;
65 * TODO: it should only do this if we modify something that's not on the
66 * stack.
68 if (get_param_num_from_sym(sym) >= 0) {
69 side_effects = 1;
70 if (!get_state_expr(orig_id, expr)) {
71 state = get_implied_estate(expr);
72 set_state_expr(orig_id, expr, state);
76 set_state_expr(modify_id, expr, &modified);
77 free:
78 free_string(name);
81 static void match_assign(struct expression *expr)
83 check_expr(expr->left);
86 static void unop_expr(struct expression *expr)
88 if (expr->op != SPECIAL_DECREMENT && expr->op != SPECIAL_INCREMENT)
89 return;
91 expr = strip_expr(expr->unop);
92 check_expr(expr);
95 static int no_effect_func;
96 static int db_no_effect_func(void *unused, int argc, char **argv, char **azColName)
98 no_effect_func = 1;
99 return 0;
102 static int is_no_side_effect_func(struct expression *fn)
104 static char sql_filter[1024];
106 if (fn->type != EXPR_SYMBOL || !fn->symbol)
107 return 0;
109 if (fn->symbol->ctype.modifiers & MOD_STATIC) {
110 snprintf(sql_filter, 1024, "file = '%s' and function = '%s';",
111 get_filename(), fn->symbol->ident->name);
112 } else {
113 snprintf(sql_filter, 1024, "function = '%s' and static = 0;",
114 fn->symbol->ident->name);
117 no_effect_func = 0;
118 run_sql(db_no_effect_func, "select * from no_side_effects where %s", sql_filter);
120 return no_effect_func;
123 static void match_call(struct expression *expr)
125 struct expression *arg, *tmp;
127 if (!is_no_side_effect_func(expr->fn))
128 side_effects = 1;
130 FOR_EACH_PTR(expr->args, arg) {
131 tmp = strip_expr(arg);
132 if (tmp->type != EXPR_PREOP || tmp->op != '&')
133 continue;
134 tmp = strip_expr(tmp->unop);
135 check_expr(expr);
136 } END_FOR_EACH_PTR(arg);
139 static void asm_expr(struct statement *stmt)
142 struct expression *expr;
143 int state = 0;
145 FOR_EACH_PTR(stmt->asm_outputs, expr) {
146 switch (state) {
147 case 0: /* identifier */
148 case 1: /* constraint */
149 state++;
150 continue;
151 case 2: /* expression */
152 state = 0;
153 check_expr(expr);
154 continue;
156 } END_FOR_EACH_PTR(expr);
159 struct smatch_state *get_orig_estate(struct symbol *sym)
161 struct smatch_state *state;
163 if (!sym->ident || !sym->ident->name)
164 return NULL;
166 state = get_state(orig_id, sym->ident->name, sym);
167 if (state)
168 return state;
170 return get_state(SMATCH_EXTRA, sym->ident->name, sym);
173 static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr, struct state_list *slist)
175 struct smatch_state *state;
176 struct symbol *tmp;
177 int param;
179 param = -1;
180 FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, tmp) {
181 param++;
182 state = get_orig_estate(tmp);
183 if (!state)
184 continue;
185 sm_msg("info: return_limited_param %d %d '%s' '$$' '%s' %s",
186 return_id, param, return_ranges,
187 state->name, global_static());
188 } END_FOR_EACH_PTR(tmp);
191 static void match_end_func(struct symbol *sym)
193 if (option_info && !side_effects)
194 sm_msg("info: no_side_effects %s", global_static());
195 side_effects = 0;
198 void register_param_limit(int id)
200 modify_id = id;
202 add_hook(&match_assign, ASSIGNMENT_HOOK);
203 add_hook(&unop_expr, OP_HOOK);
204 add_hook(&match_call, FUNCTION_CALL_HOOK);
205 add_hook(&asm_expr, ASM_HOOK);
206 add_hook(&match_end_func, END_FUNC_HOOK);
207 add_returned_state_callback(&print_return_value_param);
210 void register_param_limit2(int id)
212 orig_id = id;
213 add_merge_hook(orig_id, &merge_estates);
214 add_unmatched_state_hook(orig_id, &unmatched_state);