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
);
62 } END_FOR_EACH_PTR(tmp
);
65 static void match_assign(struct expression
*expr
)
67 struct expression
*left
;
71 left
= strip_expr(expr
->left
);
72 name
= get_variable_from_expr(left
, &sym
);
75 set_state(name
, my_id
, sym
, alloc_state(get_value(expr
->right
)));
78 static void undef_expr(struct expression
*expr
)
83 name
= get_variable_from_expr(expr
->unop
, &sym
);
86 if (!get_state(name
, my_id
, sym
)) {
90 set_state(name
, my_id
, sym
, &undefined
);
93 static void match_declarations(struct symbol
*sym
)
98 name
= sym
->ident
->name
;
99 if (sym
->initializer
) {
100 set_state(name
, my_id
, sym
, alloc_state(get_value(sym
->initializer
)));
105 static void match_unop(struct expression
*expr
)
112 name
= get_variable_from_expr(expr
->unop
, &sym
);
116 tmp
= show_special(expr
->op
);
117 if ((!strcmp(tmp
, "--")) || (!strcmp(tmp
, "++")))
118 set_state(name
, my_id
, sym
, &undefined
);
121 void register_smatch_extra(int id
)
124 add_hook(&undef_expr
, OP_HOOK
);
125 add_hook(&match_function_call_after
, FUNCTION_CALL_AFTER_HOOK
);
126 add_hook(&match_assign
, ASSIGNMENT_AFTER_HOOK
);
127 add_hook(&match_declarations
, DECLARATION_HOOK
);
128 add_hook(&match_unop
, OP_HOOK
);
131 static int expr_to_val(struct expression
*expr
)
133 struct smatch_state
*state
;
138 val
= get_value(expr
);
139 if (val
!= UNDEFINED
)
142 name
= get_variable_from_expr(expr
, &sym
);
145 state
= get_state(name
, my_id
, sym
);
147 if (!state
|| !state
->data
)
149 return *(int *)state
->data
;
152 static int true_comparison(int left
, int comparison
, int right
)
156 case SPECIAL_UNSIGNED_LT
:
160 case SPECIAL_UNSIGNED_LTE
:
168 case SPECIAL_UNSIGNED_GTE
:
173 case SPECIAL_UNSIGNED_GT
:
177 case SPECIAL_NOTEQUAL
:
182 smatch_msg("unhandled comparison %d\n", comparison
);
187 static int compare_true(struct expression
*expr
)
189 int left
, right
, ret
;
191 if ((left
= expr_to_val(expr
->left
)) == UNDEFINED
)
194 if ((right
= expr_to_val(expr
->right
)) == UNDEFINED
)
197 ret
= true_comparison(left
, expr
->op
, right
);
199 SM_DEBUG("%d known condition: %d %s %d => true", get_lineno(),
200 left
, show_special(expr
->op
), right
);
202 smatch_msg("known condition: %d %s %d => false", left
,
203 show_special(expr
->op
), right
);
209 struct statement
*get_block_thing(struct expression
*expr
)
211 /* What are those things called? if (({....; ret;})) { ...*/
213 if (expr
->type
!= EXPR_PREOP
)
217 if (expr
->unop
->type
!= EXPR_STATEMENT
)
219 if (expr
->unop
->statement
->type
!= STMT_COMPOUND
)
221 return expr
->unop
->statement
;
224 int block_thing_true(struct statement
*stmt
)
226 struct expression
*expr
;
228 stmt
= last_ptr_list((struct ptr_list
*)stmt
->stmts
);
229 if (stmt
->type
!= STMT_EXPRESSION
)
231 expr
= stmt
->expression
;
232 if (get_value(expr
) == 1)
237 int known_condition_true(struct expression
*expr
)
244 return compare_true(expr
);
246 struct statement
*stmt
;
247 struct expression
*tmp
;
249 stmt
= get_block_thing(expr
);
251 return block_thing_true(stmt
);
252 tmp
= strip_expr(expr
);
254 return known_condition_true(tmp
);