small clean up.
[smatch.git] / smatch_flow.c
bloba6fb70537f88246474a88ae4d493e92f8a785665
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"
13 #include "smatch_expression_stacks.h"
14 #include "smatch_extra.h"
15 #include "smatch_slist.h" // just for sname.
17 int final_pass;
19 static int __smatch_lineno = 0;
21 static char *filename;
22 static char *cur_func;
23 static int line_func_start;
24 static struct expression_stack *switch_expr_stack = NULL;
26 char *get_filename(void) { return filename; }
27 char *get_function(void) { return cur_func; }
28 int get_lineno(void) { return __smatch_lineno; }
29 int get_func_pos(void) { return __smatch_lineno - line_func_start; }
31 static void split_symlist(struct symbol_list *sym_list);
32 static void split_declaration(struct symbol_list *sym_list);
33 static void split_expr_list(struct expression_list *expr_list);
35 int option_assume_loops = 0;
36 int option_known_conditions = 0;
37 int option_two_passes = 0;
39 void __split_expr(struct expression *expr)
41 if (!expr)
42 return;
44 // printf("%d Debug expr_type %d %s\n", get_lineno(), expr->type, show_special(expr->op));
46 __smatch_lineno = expr->pos.line;
47 __pass_to_client(expr, EXPR_HOOK);
49 switch (expr->type) {
50 case EXPR_PREOP:
51 case EXPR_POSTOP:
52 __pass_to_client(expr, OP_HOOK);
53 __split_expr(expr->unop);
54 return;
55 case EXPR_STATEMENT:
56 __split_statements(expr->statement);
57 return;
58 case EXPR_LOGICAL:
59 __split_whole_condition(expr);
60 __push_true_states();
61 __use_false_states();
62 __merge_true_states();
63 __pop_false_only_stack();
64 return;
66 return;
67 case EXPR_BINOP:
68 case EXPR_COMMA:
69 case EXPR_COMPARE:
70 __split_expr(expr->left);
71 __split_expr(expr->right);
72 return;
73 case EXPR_ASSIGNMENT: {
74 struct expression *tmp;
76 __split_expr(expr->right);
77 __pass_to_client(expr, ASSIGNMENT_HOOK);
78 tmp = strip_expr(expr->right);
79 if (tmp->type == EXPR_CALL)
80 __pass_to_client(expr, CALL_ASSIGNMENT_HOOK);
81 __split_expr(expr->left);
82 return;
84 case EXPR_DEREF:
85 __pass_to_client(expr, DEREF_HOOK);
86 __split_expr(expr->deref);
87 return;
88 case EXPR_SLICE:
89 __split_expr(expr->base);
90 return;
91 case EXPR_CAST:
92 __split_expr(expr->cast_expression);
93 return;
94 case EXPR_SIZEOF:
95 /* there isn't anything to pass a client from inside a sizeof() */
96 return;
97 case EXPR_CONDITIONAL:
98 case EXPR_SELECT:
99 __split_whole_condition(expr->conditional);
100 __split_expr(expr->cond_true);
101 __push_true_states();
102 __use_false_states();
103 __split_expr(expr->cond_false);
104 __merge_true_states();
105 __pop_false_only_stack();
106 return;
107 case EXPR_CALL:
108 split_expr_list(expr->args);
109 __split_expr(expr->fn);
110 __pass_to_client(expr, FUNCTION_CALL_HOOK);
111 return;
112 case EXPR_INITIALIZER:
113 split_expr_list(expr->expr_list);
114 return;
115 case EXPR_IDENTIFIER:
116 __split_expr(expr->ident_expression);
117 return;
118 case EXPR_INDEX:
119 __split_expr(expr->idx_expression);
120 return;
121 case EXPR_POS:
122 __split_expr(expr->init_expr);
123 return;
124 default:
125 return;
129 static int is_forever_loop(struct statement *stmt)
132 struct expression *expr;
134 expr = strip_expr(stmt->iterator_pre_condition);
135 if (!expr)
136 expr = stmt->iterator_post_condition;
137 if (!expr) {
138 /* this is a for(;;) loop... */
139 return 1;
142 if (expr->type == EXPR_VALUE && expr->value == 1) {
143 return 1;
146 return 0;
149 static int loop_num;
150 static char *get_loop_name(int num)
152 char buf[256];
154 snprintf(buf, 255, "-loop%d", num);
155 buf[255] = '\0';
156 return alloc_sname(buf);;
160 * Pre Loops are while and for loops.
163 static void handle_pre_loop(struct statement *stmt)
165 int once_through; /* we go through the loop at least once */
166 struct sm_state *extra_state = NULL;
167 int unchanged = 0;
168 char *loop_name;
170 loop_name = get_loop_name(loop_num);
171 loop_num++;
173 __split_statements(stmt->iterator_pre_statement);
175 once_through = implied_condition_true(stmt->iterator_pre_condition);
177 __push_continues();
178 __push_breaks();
180 __merge_gotos(loop_name);
181 __split_whole_condition(stmt->iterator_pre_condition);
182 if (once_through)
183 extra_state = __extra_pre_loop_hook_before(stmt->iterator_pre_statement);
184 if (option_assume_loops)
185 once_through = 1;
186 __split_statements(stmt->iterator_statement);
188 __warn_on_silly_pre_loops();
189 if (is_forever_loop(stmt)) {
190 __save_gotos(loop_name);
191 __pop_false_only_stack();
192 /* forever loops don't have an iterator_post_statement */
193 __pop_continues();
194 __pop_false_states();
195 __use_breaks();
196 } else if (once_through) {
197 __merge_continues();
198 if (extra_state)
199 unchanged = __iterator_unchanged(extra_state, stmt->iterator_post_statement);
200 __split_statements(stmt->iterator_post_statement);
201 __save_gotos(loop_name);
202 __split_whole_condition(stmt->iterator_pre_condition);
203 nullify_path();
204 __merge_false_states();
205 if (extra_state && unchanged)
206 __extra_pre_loop_hook_after(extra_state,
207 stmt->iterator_post_statement, stmt->iterator_pre_condition);
208 __pop_false_states();
209 __pop_false_only_stack();
210 __pop_false_only_stack();
211 __merge_breaks();
212 } else {
213 __merge_continues();
214 __split_statements(stmt->iterator_post_statement);
215 __save_gotos(loop_name);
216 __merge_false_states();
217 __use_false_only_stack();
218 __merge_breaks();
223 * Post loops are do {} while();
225 static void handle_post_loop(struct statement *stmt)
227 char *loop_name;
229 loop_name = get_loop_name(loop_num);
230 loop_num++;
232 __push_continues();
233 __push_breaks();
234 __merge_gotos(loop_name);
235 __split_statements(stmt->iterator_statement);
236 __merge_continues();
237 if (!is_zero(stmt->iterator_post_condition))
238 __save_gotos(loop_name);
240 if (is_forever_loop(stmt)) {
241 __use_breaks();
242 } else {
243 __split_whole_condition(stmt->iterator_post_condition);
244 __use_false_states();
245 __merge_breaks();
247 __pop_false_only_stack();
250 static void print_unreached(struct statement *stmt)
254 * GCC insists on a return statement even where it is never
255 * reached. Also BUG() sometimes is a forever loop and
256 * sometimes not so people put code after a BUG(). There
257 * are way to many false positives.
259 #ifdef KERNEL
260 return;
261 #endif
262 if (__path_is_null()) {
263 switch(stmt->type) {
264 case STMT_COMPOUND: /* after a switch before a case stmt */
265 case STMT_CASE:
266 case STMT_LABEL:
267 case STMT_DECLARATION: /* switch(x) { int a; case foo: ... */
268 break;
269 default:
270 sm_msg("unreachable code. %d", stmt->type);
275 void __split_statements(struct statement *stmt)
277 if (!stmt)
278 return;
280 if (out_of_memory()) {
281 static char *printed = NULL;
283 if (printed != cur_func)
284 sm_msg("Function too big. Giving up.");
285 printed = cur_func;
286 return;
289 __smatch_lineno = stmt->pos.line;
290 print_unreached(stmt);
291 __pass_to_client(stmt, STMT_HOOK);
293 switch (stmt->type) {
294 case STMT_DECLARATION:
295 split_declaration(stmt->declaration);
296 return;
297 case STMT_RETURN:
298 __split_expr(stmt->ret_value);
299 __pass_to_client(stmt, RETURN_HOOK);
300 nullify_path();
301 return;
302 case STMT_EXPRESSION:
303 __split_expr(stmt->expression);
304 return;
305 case STMT_COMPOUND: {
306 struct statement *s;
307 __push_scope_hooks();
308 FOR_EACH_PTR(stmt->stmts, s) {
309 __split_statements(s);
310 } END_FOR_EACH_PTR(s);
311 __call_scope_hooks();
312 return;
314 case STMT_IF:
315 if (known_condition_true(stmt->if_conditional)) {
316 __split_statements(stmt->if_true);
317 return;
319 if (known_condition_false(stmt->if_conditional)) {
320 __split_statements(stmt->if_false);
321 return;
323 if (option_known_conditions &&
324 implied_condition_true(stmt->if_conditional)) {
325 sm_msg("info: this condition is true.");
326 __split_statements(stmt->if_true);
327 return;
329 if (option_known_conditions &&
330 implied_condition_false(stmt->if_conditional)) {
331 sm_msg("info: this condition is false.");
332 __split_statements(stmt->if_false);
333 return;
335 __split_whole_condition(stmt->if_conditional);
336 __split_statements(stmt->if_true);
337 __push_true_states();
338 __use_false_states();
339 __split_statements(stmt->if_false);
340 __merge_true_states();
341 __pop_false_only_stack();
342 return;
343 case STMT_ITERATOR:
344 if (stmt->iterator_pre_condition)
345 handle_pre_loop(stmt);
346 else if (stmt->iterator_post_condition)
347 handle_post_loop(stmt);
348 else {
349 // these are for(;;) type loops.
350 handle_pre_loop(stmt);
352 return;
353 case STMT_SWITCH:
354 __split_expr(stmt->switch_expression);
355 push_expression(&switch_expr_stack, stmt->switch_expression);
356 __save_switch_states(top_expression(switch_expr_stack));
357 nullify_path();
358 __push_default();
359 __push_breaks();
360 __split_statements(stmt->switch_statement);
361 if (!__pop_default())
362 __merge_switches(top_expression(switch_expr_stack),
363 NULL);
364 __pop_switches();
365 __merge_breaks();
366 pop_expression(&switch_expr_stack);
367 return;
368 case STMT_CASE:
369 __merge_switches(top_expression(switch_expr_stack),
370 stmt->case_expression);
371 __pass_case_to_client(top_expression(switch_expr_stack),
372 stmt->case_expression);
373 if (!stmt->case_expression)
374 __set_default();
375 __split_expr(stmt->case_expression);
376 __split_expr(stmt->case_to);
377 __split_statements(stmt->case_statement);
378 return;
379 case STMT_LABEL:
380 if (stmt->label &&
381 stmt->label->type == SYM_LABEL &&
382 stmt->label->ident) {
383 __merge_gotos(stmt->label->ident->name);
385 __split_statements(stmt->label_statement);
386 return;
387 case STMT_GOTO:
388 __split_expr(stmt->goto_expression);
389 if (stmt->goto_label && stmt->goto_label->type == SYM_NODE) {
390 if (!strcmp(stmt->goto_label->ident->name, "break")) {
391 __process_breaks();
392 } else if (!strcmp(stmt->goto_label->ident->name,
393 "continue")) {
394 __process_continues();
396 } else if (stmt->goto_label &&
397 stmt->goto_label->type == SYM_LABEL &&
398 stmt->goto_label->ident) {
399 __save_gotos(stmt->goto_label->ident->name);
401 nullify_path();
402 return;
403 case STMT_NONE:
404 return;
405 case STMT_ASM:
406 __split_expr(stmt->asm_string);
407 //__split_expr(stmt->asm_outputs);
408 //__split_expr(stmt->asm_inputs);
409 //__split_expr(stmt->asm_clobbers);
410 return;
411 case STMT_CONTEXT:
412 return;
413 case STMT_RANGE:
414 __split_expr(stmt->range_expression);
415 __split_expr(stmt->range_low);
416 __split_expr(stmt->range_high);
417 return;
421 static void split_expr_list(struct expression_list *expr_list)
423 struct expression *expr;
424 FOR_EACH_PTR(expr_list, expr) {
425 __split_expr(expr);
426 } END_FOR_EACH_PTR(expr);
430 static void split_sym(struct symbol *sym)
432 if (!sym)
433 return;
434 if (!(sym->namespace & NS_SYMBOL))
435 return;
437 __pass_to_client(sym, SYM_HOOK);
438 __split_statements(sym->stmt);
439 __split_expr(sym->array_size);
440 split_symlist(sym->arguments);
441 split_symlist(sym->symbol_list);
442 __split_statements(sym->inline_stmt);
443 split_symlist(sym->inline_symbol_list);
444 __split_expr(sym->initializer);
447 static void split_symlist(struct symbol_list *sym_list)
449 struct symbol *sym;
451 FOR_EACH_PTR(sym_list, sym) {
452 split_sym(sym);
453 } END_FOR_EACH_PTR(sym);
456 static void split_declaration(struct symbol_list *sym_list)
458 struct symbol *sym;
460 FOR_EACH_PTR(sym_list, sym) {
461 __pass_to_client(sym, DECLARATION_HOOK);
462 __split_expr(sym->initializer);
463 if(sym->initializer && sym->initializer->type == EXPR_CALL) {
464 __match_initializer_call(sym);
466 split_sym(sym);
467 } END_FOR_EACH_PTR(sym);
470 static void split_functions(struct symbol_list *sym_list)
472 struct symbol *sym;
474 FOR_EACH_PTR(sym_list, sym) {
475 struct symbol *base_type;
476 base_type = get_base_type(sym);
477 if (sym->type == SYM_NODE && base_type->type == SYM_FN) {
478 if (base_type->stmt)
479 line_func_start = base_type->stmt->pos.line;
480 if (sym->ident)
481 cur_func = sym->ident->name;
482 __smatch_lineno = sym->pos.line;
483 sm_debug("new function: %s\n", cur_func);
484 if (option_two_passes) {
485 __unnullify_path();
486 loop_num = 0;
487 final_pass = 0;
488 __pass_to_client(sym, FUNC_DEF_HOOK);
489 __split_statements(base_type->stmt);
490 nullify_path();
492 __unnullify_path();
493 loop_num = 0;
494 final_pass = 1;
495 __pass_to_client(sym, FUNC_DEF_HOOK);
496 __split_statements(base_type->stmt);
497 __pass_to_client(sym, END_FUNC_HOOK);
498 cur_func = NULL;
499 line_func_start = 0;
500 clear_all_states();
501 free_expression_stack(&switch_expr_stack);
502 } else {
503 __pass_to_client(sym, BASE_HOOK);
505 } END_FOR_EACH_PTR(sym);
506 __pass_to_client_no_data(END_FILE_HOOK);
509 void smatch (int argc, char **argv)
512 struct string_list *filelist = NULL;
513 struct symbol_list *sym_list;
515 if (argc < 2) {
516 printf("Usage: smatch [--debug] <filename.c>\n");
517 exit(1);
519 sparse_initialize(argc, argv, &filelist);
520 FOR_EACH_PTR_NOTAG(filelist, filename) {
521 sym_list = __sparse(filename);
522 split_functions(sym_list);
523 } END_FOR_EACH_PTR_NOTAG(filename);