Implied ranges. Part #1.
[smatch.git] / smatch_flow.c
blob9de013e187daa29dcd6b93bb89b6deaf0deae5a7
1 /*
2 * sparse/smatch_flow.c
4 * Copyright (C) 2006,2008 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include <stdio.h>
11 #include "token.h"
12 #include "smatch.h"
14 static int __smatch_lineno = 0;
16 static char *filename;
17 static char *cur_func;
18 static int line_func_start;
20 char *get_filename(void) { return filename; }
21 char *get_function(void) { return cur_func; }
22 int get_lineno(void) { return __smatch_lineno; }
23 int get_func_pos(void) { return __smatch_lineno - line_func_start; }
25 static void split_symlist(struct symbol_list *sym_list);
26 static void split_declaration(struct symbol_list *sym_list);
27 static void split_expr_list(struct expression_list *expr_list);
29 unsigned int __get_allocations();
31 int option_assume_loops = 0;
32 int option_known_conditions = 0;
34 void __split_expr(struct expression *expr)
36 if (!expr)
37 return;
39 // printf("%d Debug expr_type %d\n", get_lineno(), expr->type);
41 __smatch_lineno = expr->pos.line;
42 __pass_to_client(expr, EXPR_HOOK);
44 switch (expr->type) {
45 case EXPR_PREOP:
46 case EXPR_POSTOP:
47 __pass_to_client(expr, OP_HOOK);
48 __split_expr(expr->unop);
49 return;
50 case EXPR_STATEMENT:
51 __split_statements(expr->statement);
52 return;
53 case EXPR_LOGICAL:
54 __split_whole_condition(expr);
55 __push_true_states();
56 __use_false_states();
57 __merge_true_states();
58 __pop_false_only_stack();
59 return;
61 return;
62 case EXPR_BINOP:
63 case EXPR_COMMA:
64 case EXPR_COMPARE:
65 __split_expr(expr->left);
66 __split_expr(expr->right);
67 return;
68 case EXPR_ASSIGNMENT: {
69 struct expression *tmp;
71 __split_expr(expr->right);
72 __pass_to_client(expr, ASSIGNMENT_HOOK);
73 tmp = strip_expr(expr->right);
74 if (tmp->type == EXPR_CALL)
75 __pass_to_client(expr, CALL_ASSIGNMENT_HOOK);
76 __split_expr(expr->left);
77 return;
79 case EXPR_DEREF:
80 __pass_to_client(expr, DEREF_HOOK);
81 __split_expr(expr->deref);
82 return;
83 case EXPR_SLICE:
84 __split_expr(expr->base);
85 return;
86 case EXPR_CAST:
87 __split_expr(expr->cast_expression);
88 return;
89 case EXPR_SIZEOF:
90 /* there isn't anything to pass a client from inside a sizeof() */
91 return;
92 case EXPR_CONDITIONAL:
93 case EXPR_SELECT:
94 __split_whole_condition(expr->conditional);
95 __split_expr(expr->cond_true);
96 __push_true_states();
97 __use_false_states();
98 __split_expr(expr->cond_false);
99 __merge_true_states();
100 __pop_false_only_stack();
101 return;
102 case EXPR_CALL:
103 split_expr_list(expr->args);
104 __split_expr(expr->fn);
105 __pass_to_client(expr, FUNCTION_CALL_HOOK);
106 return;
107 case EXPR_INITIALIZER:
108 split_expr_list(expr->expr_list);
109 return;
110 case EXPR_IDENTIFIER:
111 __split_expr(expr->ident_expression);
112 return;
113 case EXPR_INDEX:
114 __split_expr(expr->idx_expression);
115 return;
116 case EXPR_POS:
117 __split_expr(expr->init_expr);
118 return;
119 default:
120 return;
124 static int is_forever_loop(struct statement *stmt)
127 struct expression *expr;
129 expr = strip_expr(stmt->iterator_pre_condition);
130 if (!expr)
131 expr = stmt->iterator_post_condition;
132 if (!expr) {
133 /* this is a for(;;) loop... */
134 return 1;
137 if (expr->type == EXPR_VALUE && expr->value == 1) {
138 return 1;
141 return 0;
145 * Pre Loops are while and for loops.
148 static void handle_pre_loop(struct statement *stmt)
150 int once_through; /* we go through the loop at least once */
152 __split_statements(stmt->iterator_pre_statement);
154 once_through = known_condition_true(stmt->iterator_pre_condition);
155 if (option_assume_loops)
156 once_through = 1;
158 __push_continues();
159 __push_breaks();
161 __split_whole_condition(stmt->iterator_pre_condition);
163 __split_statements(stmt->iterator_statement);
164 __warn_on_silly_pre_loops();
165 if (is_forever_loop(stmt)) {
166 __pop_false_only_stack();
167 /* forever loops don't have an iterator_post_statement */
168 __pop_continues();
169 __pop_false_states();
170 __use_breaks();
171 } else if (once_through) {
172 __merge_continues();
173 __split_statements(stmt->iterator_post_statement);
174 __pop_false_states();
175 __use_false_only_stack();
176 __merge_breaks();
177 } else {
178 __merge_continues();
179 __split_statements(stmt->iterator_post_statement);
180 __merge_false_states();
181 __use_false_only_stack();
182 __merge_breaks();
187 * Post loops are do {} while();
189 static void handle_post_loop(struct statement *stmt)
191 __push_continues();
192 __push_breaks();
193 __split_statements(stmt->iterator_statement);
194 if (is_forever_loop(stmt)) {
195 __pop_continues();
196 __use_breaks();
198 } else {
199 __merge_continues();
200 __split_whole_condition(stmt->iterator_post_condition);
201 __use_false_states();
202 __merge_breaks();
204 __pop_false_only_stack();
207 static void print_unreached(struct statement *stmt)
211 * GCC insists on a return statement even where it is never
212 * reached. Also BUG() sometimes is a forever loop and
213 * sometimes not so people put code after a BUG(). There
214 * are way to many false positives.
216 #ifdef KERNEL
217 return;
218 #endif
219 if (__path_is_null()) {
220 switch(stmt->type) {
221 case STMT_COMPOUND: /* after a switch before a case stmt */
222 case STMT_CASE:
223 case STMT_LABEL:
224 case STMT_DECLARATION: /* switch(x) { int a; case foo: ... */
225 break;
226 default:
227 smatch_msg("unreachable code. %d", stmt->type);
232 void __split_statements(struct statement *stmt)
234 if (!stmt)
235 return;
237 if (__get_allocations() > MAXSMSTATES) {
238 static char *printed = NULL;
240 if (printed != cur_func)
241 smatch_msg("Function too big. Giving up.");
242 printed = cur_func;
243 return;
246 __smatch_lineno = stmt->pos.line;
247 print_unreached(stmt);
248 __pass_to_client(stmt, STMT_HOOK);
250 switch (stmt->type) {
251 case STMT_DECLARATION:
252 split_declaration(stmt->declaration);
253 return;
254 case STMT_RETURN:
255 __split_expr(stmt->ret_value);
256 __pass_to_client(stmt, RETURN_HOOK);
257 nullify_path();
258 return;
259 case STMT_EXPRESSION:
260 __split_expr(stmt->expression);
261 return;
262 case STMT_COMPOUND: {
263 struct statement *s;
264 FOR_EACH_PTR(stmt->stmts, s) {
265 __split_statements(s);
266 } END_FOR_EACH_PTR(s);
267 return;
269 case STMT_IF:
270 if (option_known_conditions &&
271 known_condition_true(stmt->if_conditional)) {
272 smatch_msg("info: this condition is true.");
273 __split_statements(stmt->if_true);
274 return;
276 if (option_known_conditions &&
277 known_condition_false(stmt->if_conditional)) {
278 smatch_msg("info: this condition is false.");
279 __split_statements(stmt->if_false);
280 return;
282 __split_whole_condition(stmt->if_conditional);
283 __split_statements(stmt->if_true);
284 __push_true_states();
285 __use_false_states();
286 __split_statements(stmt->if_false);
287 __merge_true_states();
288 __pop_false_only_stack();
289 return;
290 case STMT_ITERATOR:
291 if (stmt->iterator_pre_condition)
292 handle_pre_loop(stmt);
293 else if (stmt->iterator_post_condition)
294 handle_post_loop(stmt);
295 else {
296 // these are for(;;) type loops.
297 handle_pre_loop(stmt);
299 return;
300 case STMT_SWITCH:
301 __split_expr(stmt->switch_expression);
302 __save_switch_states();
303 __push_default();
304 __push_breaks();
305 __split_statements(stmt->switch_statement);
306 if (!__pop_default())
307 __merge_switches();
308 __pop_switches();
309 __merge_breaks();
310 return;
311 case STMT_CASE:
312 __merge_switches();
313 if (!stmt->case_expression)
314 __set_default();
315 __split_expr(stmt->case_expression);
316 __split_expr(stmt->case_to);
317 __split_statements(stmt->case_statement);
318 return;
319 case STMT_LABEL:
320 if (stmt->label &&
321 stmt->label->type == SYM_LABEL &&
322 stmt->label->ident) {
323 __merge_gotos(stmt->label->ident->name);
325 __split_statements(stmt->label_statement);
326 return;
327 case STMT_GOTO:
328 __split_expr(stmt->goto_expression);
329 if (stmt->goto_label && stmt->goto_label->type == SYM_NODE) {
330 if (!strcmp(stmt->goto_label->ident->name, "break")) {
331 __process_breaks();
332 } else if (!strcmp(stmt->goto_label->ident->name,
333 "continue")) {
334 __process_continues();
336 } else if (stmt->goto_label &&
337 stmt->goto_label->type == SYM_LABEL &&
338 stmt->goto_label->ident) {
339 __save_gotos(stmt->goto_label->ident->name);
341 nullify_path();
342 return;
343 case STMT_NONE:
344 return;
345 case STMT_ASM:
346 __split_expr(stmt->asm_string);
347 //__split_expr(stmt->asm_outputs);
348 //__split_expr(stmt->asm_inputs);
349 //__split_expr(stmt->asm_clobbers);
350 return;
351 case STMT_CONTEXT:
352 return;
353 case STMT_RANGE:
354 __split_expr(stmt->range_expression);
355 __split_expr(stmt->range_low);
356 __split_expr(stmt->range_high);
357 return;
361 static void split_expr_list(struct expression_list *expr_list)
363 struct expression *expr;
364 FOR_EACH_PTR(expr_list, expr) {
365 __split_expr(expr);
366 } END_FOR_EACH_PTR(expr);
370 static void split_sym(struct symbol *sym)
372 if (!sym)
373 return;
374 if (!(sym->namespace & NS_SYMBOL))
375 return;
377 __pass_to_client(sym, SYM_HOOK);
378 __split_statements(sym->stmt);
379 __split_expr(sym->array_size);
380 split_symlist(sym->arguments);
381 split_symlist(sym->symbol_list);
382 __split_statements(sym->inline_stmt);
383 split_symlist(sym->inline_symbol_list);
384 __split_expr(sym->initializer);
387 static void split_symlist(struct symbol_list *sym_list)
389 struct symbol *sym;
391 FOR_EACH_PTR(sym_list, sym) {
392 split_sym(sym);
393 } END_FOR_EACH_PTR(sym);
396 static void split_declaration(struct symbol_list *sym_list)
398 struct symbol *sym;
400 FOR_EACH_PTR(sym_list, sym) {
401 __pass_to_client(sym, DECLARATION_HOOK);
402 __split_expr(sym->initializer);
403 if(sym->initializer && sym->initializer->type == EXPR_CALL) {
404 __match_initializer_call(sym);
406 split_sym(sym);
407 } END_FOR_EACH_PTR(sym);
410 static void split_functions(struct symbol_list *sym_list)
412 struct symbol *sym;
414 FOR_EACH_PTR(sym_list, sym) {
415 struct symbol *base_type;
416 base_type = get_base_type(sym);
417 if (sym->type == SYM_NODE && base_type->type == SYM_FN) {
418 if (base_type->stmt)
419 line_func_start = base_type->stmt->pos.line;
420 if (sym->ident)
421 cur_func = sym->ident->name;
422 __smatch_lineno = sym->pos.line;
423 SM_DEBUG("new function: %s\n", cur_func);
424 __unnullify_path();
425 __pass_to_client(sym, FUNC_DEF_HOOK);
426 __split_statements(base_type->stmt);
427 __pass_to_client(sym, END_FUNC_HOOK);
428 cur_func = NULL;
429 line_func_start = 0;
430 clear_all_states();
432 } else {
433 __pass_to_client(sym, BASE_HOOK);
435 } END_FOR_EACH_PTR(sym);
436 __pass_to_client_no_data(END_FILE_HOOK);
439 void smatch (int argc, char **argv)
442 struct string_list *filelist = NULL;
443 struct symbol_list *sym_list;
445 if (argc < 2) {
446 printf("Usage: smatch [--debug] <filename.c>\n");
447 exit(1);
449 sparse_initialize(argc, argv, &filelist);
450 FOR_EACH_PTR_NOTAG(filelist, filename) {
451 sym_list = __sparse(filename);
452 split_functions(sym_list);
453 } END_FOR_EACH_PTR_NOTAG(filename);