Add some strip_expr() calls to the function hooks.
[smatch.git] / smatch_flow.c
blob07fc99286f3f2890525e1ab87ff76ae7526b8844
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"
16 static int __smatch_lineno = 0;
18 static char *filename;
19 static char *cur_func;
20 static int line_func_start;
21 static struct expression_stack *switch_expr_stack = NULL;
23 char *get_filename(void) { return filename; }
24 char *get_function(void) { return cur_func; }
25 int get_lineno(void) { return __smatch_lineno; }
26 int get_func_pos(void) { return __smatch_lineno - line_func_start; }
28 static void split_symlist(struct symbol_list *sym_list);
29 static void split_declaration(struct symbol_list *sym_list);
30 static void split_expr_list(struct expression_list *expr_list);
32 int option_assume_loops = 0;
33 int option_known_conditions = 0;
35 void __split_expr(struct expression *expr)
37 if (!expr)
38 return;
40 // printf("%d Debug expr_type %d %s\n", get_lineno(), expr->type, show_special(expr->op));
42 __smatch_lineno = expr->pos.line;
43 __pass_to_client(expr, EXPR_HOOK);
45 switch (expr->type) {
46 case EXPR_PREOP:
47 case EXPR_POSTOP:
48 __pass_to_client(expr, OP_HOOK);
49 __split_expr(expr->unop);
50 return;
51 case EXPR_STATEMENT:
52 __split_statements(expr->statement);
53 return;
54 case EXPR_LOGICAL:
55 __split_whole_condition(expr);
56 __push_true_states();
57 __use_false_states();
58 __merge_true_states();
59 __pop_false_only_stack();
60 return;
62 return;
63 case EXPR_BINOP:
64 case EXPR_COMMA:
65 case EXPR_COMPARE:
66 __split_expr(expr->left);
67 __split_expr(expr->right);
68 return;
69 case EXPR_ASSIGNMENT: {
70 struct expression *tmp;
72 __split_expr(expr->right);
73 __pass_to_client(expr, ASSIGNMENT_HOOK);
74 tmp = strip_expr(expr->right);
75 if (tmp->type == EXPR_CALL)
76 __pass_to_client(expr, CALL_ASSIGNMENT_HOOK);
77 __split_expr(expr->left);
78 return;
80 case EXPR_DEREF:
81 __pass_to_client(expr, DEREF_HOOK);
82 __split_expr(expr->deref);
83 return;
84 case EXPR_SLICE:
85 __split_expr(expr->base);
86 return;
87 case EXPR_CAST:
88 __split_expr(expr->cast_expression);
89 return;
90 case EXPR_SIZEOF:
91 /* there isn't anything to pass a client from inside a sizeof() */
92 return;
93 case EXPR_CONDITIONAL:
94 case EXPR_SELECT:
95 __split_whole_condition(expr->conditional);
96 __split_expr(expr->cond_true);
97 __push_true_states();
98 __use_false_states();
99 __split_expr(expr->cond_false);
100 __merge_true_states();
101 __pop_false_only_stack();
102 return;
103 case EXPR_CALL:
104 split_expr_list(expr->args);
105 __split_expr(expr->fn);
106 __pass_to_client(expr, FUNCTION_CALL_HOOK);
107 return;
108 case EXPR_INITIALIZER:
109 split_expr_list(expr->expr_list);
110 return;
111 case EXPR_IDENTIFIER:
112 __split_expr(expr->ident_expression);
113 return;
114 case EXPR_INDEX:
115 __split_expr(expr->idx_expression);
116 return;
117 case EXPR_POS:
118 __split_expr(expr->init_expr);
119 return;
120 default:
121 return;
125 static int is_forever_loop(struct statement *stmt)
128 struct expression *expr;
130 expr = strip_expr(stmt->iterator_pre_condition);
131 if (!expr)
132 expr = stmt->iterator_post_condition;
133 if (!expr) {
134 /* this is a for(;;) loop... */
135 return 1;
138 if (expr->type == EXPR_VALUE && expr->value == 1) {
139 return 1;
142 return 0;
146 * Pre Loops are while and for loops.
149 static void handle_pre_loop(struct statement *stmt)
151 int once_through; /* we go through the loop at least once */
152 struct sm_state *extra_state = NULL;
153 int unchanged = 0;
156 __split_statements(stmt->iterator_pre_statement);
158 once_through = implied_condition_true(stmt->iterator_pre_condition);
160 __push_continues();
161 __push_breaks();
163 __split_whole_condition(stmt->iterator_pre_condition);
164 if (once_through)
165 extra_state = __extra_pre_loop_hook_before(stmt->iterator_pre_statement);
166 if (option_assume_loops)
167 once_through = 1;
168 __split_statements(stmt->iterator_statement);
170 __warn_on_silly_pre_loops();
171 if (is_forever_loop(stmt)) {
172 __pop_false_only_stack();
173 /* forever loops don't have an iterator_post_statement */
174 __pop_continues();
175 __pop_false_states();
176 __use_breaks();
177 } else if (once_through) {
178 __merge_continues();
179 if (extra_state)
180 unchanged = __iterator_unchanged(extra_state, stmt->iterator_post_statement);
181 __split_statements(stmt->iterator_post_statement);
182 __split_whole_condition(stmt->iterator_pre_condition);
183 nullify_path();
184 __merge_false_states();
185 if (extra_state && unchanged)
186 __extra_pre_loop_hook_after(extra_state,
187 stmt->iterator_post_statement, stmt->iterator_pre_condition);
188 __pop_false_states();
189 __pop_false_only_stack();
190 __pop_false_only_stack();
191 __merge_breaks();
192 } else {
193 __merge_continues();
194 __split_statements(stmt->iterator_post_statement);
195 __merge_false_states();
196 __use_false_only_stack();
197 __merge_breaks();
202 * Post loops are do {} while();
204 static void handle_post_loop(struct statement *stmt)
206 __push_continues();
207 __push_breaks();
208 __split_statements(stmt->iterator_statement);
209 if (is_forever_loop(stmt)) {
210 __pop_continues();
211 __use_breaks();
213 } else {
214 __merge_continues();
215 __split_whole_condition(stmt->iterator_post_condition);
216 __use_false_states();
217 __merge_breaks();
219 __pop_false_only_stack();
222 static void print_unreached(struct statement *stmt)
226 * GCC insists on a return statement even where it is never
227 * reached. Also BUG() sometimes is a forever loop and
228 * sometimes not so people put code after a BUG(). There
229 * are way to many false positives.
231 #ifdef KERNEL
232 return;
233 #endif
234 if (__path_is_null()) {
235 switch(stmt->type) {
236 case STMT_COMPOUND: /* after a switch before a case stmt */
237 case STMT_CASE:
238 case STMT_LABEL:
239 case STMT_DECLARATION: /* switch(x) { int a; case foo: ... */
240 break;
241 default:
242 smatch_msg("unreachable code. %d", stmt->type);
247 void __split_statements(struct statement *stmt)
249 if (!stmt)
250 return;
252 if (out_of_memory()) {
253 static char *printed = NULL;
255 if (printed != cur_func)
256 smatch_msg("Function too big. Giving up.");
257 printed = cur_func;
258 return;
261 __smatch_lineno = stmt->pos.line;
262 print_unreached(stmt);
263 __pass_to_client(stmt, STMT_HOOK);
265 switch (stmt->type) {
266 case STMT_DECLARATION:
267 split_declaration(stmt->declaration);
268 return;
269 case STMT_RETURN:
270 __split_expr(stmt->ret_value);
271 __pass_to_client(stmt, RETURN_HOOK);
272 nullify_path();
273 return;
274 case STMT_EXPRESSION:
275 __split_expr(stmt->expression);
276 return;
277 case STMT_COMPOUND: {
278 struct statement *s;
279 __push_scope_hooks();
280 FOR_EACH_PTR(stmt->stmts, s) {
281 __split_statements(s);
282 } END_FOR_EACH_PTR(s);
283 __call_scope_hooks();
284 return;
286 case STMT_IF:
287 if (known_condition_true(stmt->if_conditional)) {
288 __split_statements(stmt->if_true);
289 return;
291 if (known_condition_false(stmt->if_conditional)) {
292 __split_statements(stmt->if_false);
293 return;
295 if (option_known_conditions &&
296 implied_condition_true(stmt->if_conditional)) {
297 smatch_msg("info: this condition is true.");
298 __split_statements(stmt->if_true);
299 return;
301 if (option_known_conditions &&
302 implied_condition_false(stmt->if_conditional)) {
303 smatch_msg("info: this condition is false.");
304 __split_statements(stmt->if_false);
305 return;
307 __split_whole_condition(stmt->if_conditional);
308 __split_statements(stmt->if_true);
309 __push_true_states();
310 __use_false_states();
311 __split_statements(stmt->if_false);
312 __merge_true_states();
313 __pop_false_only_stack();
314 return;
315 case STMT_ITERATOR:
316 if (stmt->iterator_pre_condition)
317 handle_pre_loop(stmt);
318 else if (stmt->iterator_post_condition)
319 handle_post_loop(stmt);
320 else {
321 // these are for(;;) type loops.
322 handle_pre_loop(stmt);
324 return;
325 case STMT_SWITCH:
326 __split_expr(stmt->switch_expression);
327 push_expression(&switch_expr_stack, stmt->switch_expression);
328 __save_switch_states(top_expression(switch_expr_stack));
329 nullify_path();
330 __push_default();
331 __push_breaks();
332 __split_statements(stmt->switch_statement);
333 if (!__pop_default())
334 __merge_switches(top_expression(switch_expr_stack),
335 NULL);
336 __pop_switches();
337 __merge_breaks();
338 pop_expression(&switch_expr_stack);
339 return;
340 case STMT_CASE:
341 __merge_switches(top_expression(switch_expr_stack),
342 stmt->case_expression);
343 __pass_case_to_client(top_expression(switch_expr_stack),
344 stmt->case_expression);
345 if (!stmt->case_expression)
346 __set_default();
347 __split_expr(stmt->case_expression);
348 __split_expr(stmt->case_to);
349 __split_statements(stmt->case_statement);
350 return;
351 case STMT_LABEL:
352 if (stmt->label &&
353 stmt->label->type == SYM_LABEL &&
354 stmt->label->ident) {
355 __merge_gotos(stmt->label->ident->name);
357 __split_statements(stmt->label_statement);
358 return;
359 case STMT_GOTO:
360 __split_expr(stmt->goto_expression);
361 if (stmt->goto_label && stmt->goto_label->type == SYM_NODE) {
362 if (!strcmp(stmt->goto_label->ident->name, "break")) {
363 __process_breaks();
364 } else if (!strcmp(stmt->goto_label->ident->name,
365 "continue")) {
366 __process_continues();
368 } else if (stmt->goto_label &&
369 stmt->goto_label->type == SYM_LABEL &&
370 stmt->goto_label->ident) {
371 __save_gotos(stmt->goto_label->ident->name);
373 nullify_path();
374 return;
375 case STMT_NONE:
376 return;
377 case STMT_ASM:
378 __split_expr(stmt->asm_string);
379 //__split_expr(stmt->asm_outputs);
380 //__split_expr(stmt->asm_inputs);
381 //__split_expr(stmt->asm_clobbers);
382 return;
383 case STMT_CONTEXT:
384 return;
385 case STMT_RANGE:
386 __split_expr(stmt->range_expression);
387 __split_expr(stmt->range_low);
388 __split_expr(stmt->range_high);
389 return;
393 static void split_expr_list(struct expression_list *expr_list)
395 struct expression *expr;
396 FOR_EACH_PTR(expr_list, expr) {
397 __split_expr(expr);
398 } END_FOR_EACH_PTR(expr);
402 static void split_sym(struct symbol *sym)
404 if (!sym)
405 return;
406 if (!(sym->namespace & NS_SYMBOL))
407 return;
409 __pass_to_client(sym, SYM_HOOK);
410 __split_statements(sym->stmt);
411 __split_expr(sym->array_size);
412 split_symlist(sym->arguments);
413 split_symlist(sym->symbol_list);
414 __split_statements(sym->inline_stmt);
415 split_symlist(sym->inline_symbol_list);
416 __split_expr(sym->initializer);
419 static void split_symlist(struct symbol_list *sym_list)
421 struct symbol *sym;
423 FOR_EACH_PTR(sym_list, sym) {
424 split_sym(sym);
425 } END_FOR_EACH_PTR(sym);
428 static void split_declaration(struct symbol_list *sym_list)
430 struct symbol *sym;
432 FOR_EACH_PTR(sym_list, sym) {
433 __pass_to_client(sym, DECLARATION_HOOK);
434 __split_expr(sym->initializer);
435 if(sym->initializer && sym->initializer->type == EXPR_CALL) {
436 __match_initializer_call(sym);
438 split_sym(sym);
439 } END_FOR_EACH_PTR(sym);
442 static void split_functions(struct symbol_list *sym_list)
444 struct symbol *sym;
446 FOR_EACH_PTR(sym_list, sym) {
447 struct symbol *base_type;
448 base_type = get_base_type(sym);
449 if (sym->type == SYM_NODE && base_type->type == SYM_FN) {
450 if (base_type->stmt)
451 line_func_start = base_type->stmt->pos.line;
452 if (sym->ident)
453 cur_func = sym->ident->name;
454 __smatch_lineno = sym->pos.line;
455 SM_DEBUG("new function: %s\n", cur_func);
456 __unnullify_path();
457 __pass_to_client(sym, FUNC_DEF_HOOK);
458 __split_statements(base_type->stmt);
459 __pass_to_client(sym, END_FUNC_HOOK);
460 cur_func = NULL;
461 line_func_start = 0;
462 clear_all_states();
463 free_expression_stack(&switch_expr_stack);
464 } else {
465 __pass_to_client(sym, BASE_HOOK);
467 } END_FOR_EACH_PTR(sym);
468 __pass_to_client_no_data(END_FILE_HOOK);
471 void smatch (int argc, char **argv)
474 struct string_list *filelist = NULL;
475 struct symbol_list *sym_list;
477 if (argc < 2) {
478 printf("Usage: smatch [--debug] <filename.c>\n");
479 exit(1);
481 sparse_initialize(argc, argv, &filelist);
482 FOR_EACH_PTR_NOTAG(filelist, filename) {
483 sym_list = __sparse(filename);
484 split_functions(sym_list);
485 } END_FOR_EACH_PTR_NOTAG(filename);