2 * sparse/smatch_extra.c
4 * Copyright (C) 2008 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
19 static struct smatch_state zero
= {
24 static struct smatch_state one
= {
29 static struct smatch_state
*alloc_state(int val
)
31 struct smatch_state
*state
;
40 state
= malloc(sizeof(*state
));
41 state
->name
= "value";
42 state
->data
= malloc(sizeof(int));
43 *(int *)state
->data
= val
;
47 static void match_function_call_after(struct expression
*expr
)
49 struct expression
*tmp
;
54 FOR_EACH_PTR(expr
->args
, tmp
) {
56 name
= get_variable_from_expr(tmp
->unop
, &sym
);
58 set_state(name
, my_id
, sym
, &undefined
);
63 } END_FOR_EACH_PTR(tmp
);
66 static void match_assign(struct expression
*expr
)
68 struct expression
*left
;
72 left
= strip_expr(expr
->left
);
73 name
= get_variable_from_expr(left
, &sym
);
76 set_state(name
, my_id
, sym
, alloc_state(get_value(expr
->right
)));
80 static void undef_expr(struct expression
*expr
)
85 name
= get_variable_from_expr(expr
->unop
, &sym
);
88 if (!get_state(name
, my_id
, sym
)) {
92 set_state(name
, my_id
, sym
, &undefined
);
96 static void match_declarations(struct symbol
*sym
)
101 name
= sym
->ident
->name
;
102 if (sym
->initializer
) {
103 set_state(name
, my_id
, sym
, alloc_state(get_value(sym
->initializer
)));
105 set_state(name
, my_id
, sym
, &undefined
);
110 static void match_function_def(struct symbol
*sym
)
114 FOR_EACH_PTR(sym
->ctype
.base_type
->arguments
, arg
) {
118 set_state(arg
->ident
->name
, my_id
, arg
, &undefined
);
119 } END_FOR_EACH_PTR(arg
);
122 static void match_unop(struct expression
*expr
)
129 name
= get_variable_from_expr(expr
->unop
, &sym
);
133 tmp
= show_special(expr
->op
);
134 if ((!strcmp(tmp
, "--")) || (!strcmp(tmp
, "++")))
135 set_state(name
, my_id
, sym
, &undefined
);
139 static int expr_to_val(struct expression
*expr
)
141 struct smatch_state
*state
;
146 val
= get_value(expr
);
147 if (val
!= UNDEFINED
)
150 name
= get_variable_from_expr(expr
, &sym
);
153 state
= get_state(name
, my_id
, sym
);
155 if (!state
|| !state
->data
)
157 return *(int *)state
->data
;
160 int true_comparison(int left
, int comparison
, int right
)
164 case SPECIAL_UNSIGNED_LT
:
168 case SPECIAL_UNSIGNED_LTE
:
176 case SPECIAL_UNSIGNED_GTE
:
181 case SPECIAL_UNSIGNED_GT
:
185 case SPECIAL_NOTEQUAL
:
190 smatch_msg("unhandled comparison %d\n", comparison
);
196 static int do_comparison(struct expression
*expr
)
198 int left
, right
, ret
;
200 if ((left
= expr_to_val(expr
->left
)) == UNDEFINED
)
203 if ((right
= expr_to_val(expr
->right
)) == UNDEFINED
)
206 ret
= true_comparison(left
, expr
->op
, right
);
208 SM_DEBUG("%d known condition: %d %s %d => true\n",
209 get_lineno(), left
, show_special(expr
->op
), right
);
210 } else if (ret
== 0) {
211 SM_DEBUG("%d known condition: %d %s %d => false\n",
212 get_lineno(), left
, show_special(expr
->op
), right
);
217 int last_stmt_val(struct statement
*stmt
)
219 struct expression
*expr
;
221 stmt
= last_ptr_list((struct ptr_list
*)stmt
->stmts
);
222 if (stmt
->type
!= STMT_EXPRESSION
)
224 expr
= stmt
->expression
;
225 return get_value(expr
);
228 static int variable_non_zero(struct expression
*expr
)
232 struct smatch_state
*state
;
235 name
= get_variable_from_expr(expr
, &sym
);
238 state
= get_state(name
, my_id
, sym
);
239 if (!state
|| !state
->data
)
241 ret
= true_comparison(*(int *)state
->data
, SPECIAL_NOTEQUAL
, 0);
247 int known_condition_true(struct expression
*expr
)
249 struct statement
*stmt
;
255 tmp
= get_value(expr
);
256 if (tmp
&& tmp
!= UNDEFINED
)
259 expr
= strip_expr(expr
);
262 if (do_comparison(expr
) == 1)
266 if (expr
->op
== '!') {
267 if (known_condition_false(expr
->unop
))
271 stmt
= get_block_thing(expr
);
272 if (stmt
&& (last_stmt_val(stmt
) == 1))
276 if (variable_non_zero(expr
) == 1)
283 int known_condition_false(struct expression
*expr
)
285 struct statement
*stmt
;
286 struct expression
*tmp
;
296 if (do_comparison(expr
) == 0)
299 if (expr
->op
== '!') {
300 if (known_condition_true(expr
->unop
))
304 stmt
= get_block_thing(expr
);
305 if (stmt
&& (last_stmt_val(stmt
) == 0))
307 tmp
= strip_expr(expr
);
309 return known_condition_false(tmp
);
312 if (variable_non_zero(expr
) == 0)
319 void register_smatch_extra(int id
)
322 add_hook(&undef_expr
, OP_HOOK
);
323 add_hook(&match_function_def
, FUNC_DEF_HOOK
);
324 add_hook(&match_function_call_after
, FUNCTION_CALL_AFTER_HOOK
);
325 add_hook(&match_assign
, ASSIGNMENT_AFTER_HOOK
);
326 add_hook(&match_declarations
, DECLARATION_HOOK
);
327 add_hook(&match_unop
, OP_HOOK
);