db: member_info callback should pass the sm_state instead of the state
[smatch.git] / smatch_flow.c
blob39bf57ac233a68cb2338f9945eb556d706c70f36
1 /*
2 * Copyright (C) 2006,2008 Dan Carpenter.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
18 #define _GNU_SOURCE 1
19 #include <unistd.h>
20 #include <stdio.h>
21 #include "token.h"
22 #include "scope.h"
23 #include "smatch.h"
24 #include "smatch_expression_stacks.h"
25 #include "smatch_extra.h"
26 #include "smatch_slist.h"
28 int __in_fake_assign;
29 int final_pass;
30 int __inline_call;
31 struct expression *__inline_fn;
33 static int __smatch_lineno = 0;
35 static char *base_file;
36 static const char *filename;
37 static char *pathname;
38 static char *full_filename;
39 static char *cur_func;
40 static unsigned int loop_count;
41 static int last_goto_statement_handled;
42 int __expr_stmt_count;
43 int __in_function_def;
44 static struct expression_list *switch_expr_stack = NULL;
45 static struct expression_list *post_op_stack = NULL;
47 struct expression_list *big_expression_stack;
48 struct statement_list *big_statement_stack;
49 int __in_pre_condition = 0;
50 int __bail_on_rest_of_function = 0;
51 static struct timeval fn_start_time;
52 char *get_function(void) { return cur_func; }
53 int get_lineno(void) { return __smatch_lineno; }
54 int inside_loop(void) { return !!loop_count; }
55 int definitely_inside_loop(void) { return !!(loop_count & ~0x80000000); }
56 struct expression *get_switch_expr(void) { return top_expression(switch_expr_stack); }
57 int in_expression_statement(void) { return !!__expr_stmt_count; }
59 static void split_symlist(struct symbol_list *sym_list);
60 static void split_declaration(struct symbol_list *sym_list);
61 static void split_expr_list(struct expression_list *expr_list);
62 static void add_inline_function(struct symbol *sym);
63 static void parse_inline(struct expression *expr);
65 int option_assume_loops = 0;
66 int option_known_conditions = 0;
67 int option_two_passes = 0;
68 struct symbol *cur_func_sym = NULL;
69 struct stree *global_states;
71 long long valid_ptr_min = 4096;
72 long long valid_ptr_max = 2117777777;
73 sval_t valid_ptr_min_sval = {
74 .type = &ptr_ctype,
75 {.value = 4096},
77 sval_t valid_ptr_max_sval = {
78 .type = &ptr_ctype,
79 {.value = LONG_MAX - 100000},
82 static void set_valid_ptr_max(void)
84 if (type_bits(&ptr_ctype) == 32)
85 valid_ptr_max = 2117777777;
86 else if (type_bits(&ptr_ctype) == 64)
87 valid_ptr_max = 2117777777777777777LL;
89 valid_ptr_max_sval.value = valid_ptr_max;
92 int outside_of_function(void)
94 return cur_func_sym == NULL;
97 const char *get_filename(void)
99 if (option_info)
100 return base_file;
101 if (option_full_path)
102 return full_filename;
103 return filename;
106 const char *get_base_file(void)
108 return base_file;
111 static void set_position(struct position pos)
113 int len;
114 static int prev_stream = -1;
116 if (pos.stream == 0 && pos.line == 0)
117 return;
119 __smatch_lineno = pos.line;
121 if (pos.stream == prev_stream)
122 return;
124 filename = stream_name(pos.stream);
126 free(full_filename);
127 pathname = getcwd(NULL, 0);
128 if (pathname) {
129 len = strlen(pathname) + 1 + strlen(filename) + 1;
130 full_filename = malloc(len);
131 snprintf(full_filename, len, "%s/%s", pathname, filename);
132 } else {
133 full_filename = alloc_string(filename);
135 free(pathname);
138 int is_assigned_call(struct expression *expr)
140 struct expression *tmp;
142 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
143 if (tmp->type == EXPR_ASSIGNMENT && tmp->op == '=' &&
144 strip_expr(tmp->right) == expr)
145 return 1;
146 if (tmp->pos.line < expr->pos.line)
147 return 0;
148 } END_FOR_EACH_PTR_REVERSE(tmp);
149 return 0;
152 static int is_inline_func(struct expression *expr)
154 if (expr->type != EXPR_SYMBOL || !expr->symbol)
155 return 0;
156 if (expr->symbol->ctype.modifiers & MOD_INLINE)
157 return 1;
158 return 0;
161 static int is_noreturn_func(struct expression *expr)
163 if (expr->type != EXPR_SYMBOL || !expr->symbol)
164 return 0;
165 if (expr->symbol->ctype.modifiers & MOD_NORETURN)
166 return 1;
167 return 0;
170 int inlinable(struct expression *expr)
172 struct symbol *sym;
174 if (__inline_fn) /* don't nest */
175 return 0;
177 if (expr->type != EXPR_SYMBOL || !expr->symbol)
178 return 0;
179 if (is_no_inline_function(expr->symbol->ident->name))
180 return 0;
181 sym = get_base_type(expr->symbol);
182 if (sym->stmt && sym->stmt->type == STMT_COMPOUND) {
183 if (ptr_list_size((struct ptr_list *)sym->stmt->stmts) <= 10)
184 return 1;
185 return 0;
187 if (sym->inline_stmt && sym->inline_stmt->type == STMT_COMPOUND) {
188 if (ptr_list_size((struct ptr_list *)sym->inline_stmt->stmts) <= 10)
189 return 1;
190 return 0;
192 return 0;
195 void __process_post_op_stack(void)
197 struct expression *expr;
199 FOR_EACH_PTR(post_op_stack, expr) {
200 __pass_to_client(expr, OP_HOOK);
201 } END_FOR_EACH_PTR(expr);
203 __free_ptr_list((struct ptr_list **)&post_op_stack);
206 static int handle_comma_assigns(struct expression *expr)
208 struct expression *right;
209 struct expression *assign;
211 right = strip_expr(expr->right);
212 if (right->type != EXPR_COMMA)
213 return 0;
215 __split_expr(right->left);
216 __process_post_op_stack();
218 assign = assign_expression(expr->left, right->right);
219 __split_expr(assign);
221 return 1;
224 void __split_expr(struct expression *expr)
226 if (!expr)
227 return;
229 // sm_msg(" Debug expr_type %d %s", expr->type, show_special(expr->op));
231 if (__in_fake_assign && expr->type != EXPR_ASSIGNMENT)
232 return;
233 if (__in_fake_assign >= 4) /* don't allow too much nesting */
234 return;
236 push_expression(&big_expression_stack, expr);
237 set_position(expr->pos);
238 __pass_to_client(expr, EXPR_HOOK);
240 switch (expr->type) {
241 case EXPR_PREOP:
242 if (expr->op == '*')
243 __pass_to_client(expr, DEREF_HOOK);
244 __split_expr(expr->unop);
245 __pass_to_client(expr, OP_HOOK);
246 break;
247 case EXPR_POSTOP:
248 __split_expr(expr->unop);
249 push_expression(&post_op_stack, expr);
250 break;
251 case EXPR_STATEMENT:
252 __expr_stmt_count++;
253 __split_stmt(expr->statement);
254 __expr_stmt_count--;
255 break;
256 case EXPR_LOGICAL:
257 case EXPR_COMPARE:
258 __pass_to_client(expr, LOGIC_HOOK);
259 __handle_logic(expr);
260 break;
261 case EXPR_BINOP:
262 __pass_to_client(expr, BINOP_HOOK);
263 case EXPR_COMMA:
264 __split_expr(expr->left);
265 __process_post_op_stack();
266 __split_expr(expr->right);
267 break;
268 case EXPR_ASSIGNMENT: {
269 struct expression *tmp;
271 if (!expr->right)
272 break;
274 __pass_to_client(expr, RAW_ASSIGNMENT_HOOK);
276 /* foo = !bar() */
277 if (__handle_condition_assigns(expr))
278 break;
279 /* foo = (x < 5 ? foo : 5); */
280 if (__handle_select_assigns(expr))
281 break;
282 /* foo = ({frob(); frob(); frob(); 1;}) */
283 if (__handle_expr_statement_assigns(expr))
284 break;
285 /* foo = (3, 4); */
286 if (handle_comma_assigns(expr))
287 break;
289 __split_expr(expr->right);
290 if (outside_of_function())
291 __pass_to_client(expr, GLOBAL_ASSIGNMENT_HOOK);
292 else
293 __pass_to_client(expr, ASSIGNMENT_HOOK);
295 __fake_struct_member_assignments(expr);
297 tmp = strip_expr(expr->right);
298 if (expr->op == '=' && tmp->type == EXPR_CALL) {
299 __pass_to_client(expr, CALL_ASSIGNMENT_HOOK);
300 if (!is_fake_call(tmp))
301 __pass_to_client(tmp, FUNCTION_CALL_HOOK_AFTER);
303 if (get_macro_name(tmp->pos) &&
304 get_macro_name(expr->pos) != get_macro_name(tmp->pos))
305 __pass_to_client(expr, MACRO_ASSIGNMENT_HOOK);
306 __split_expr(expr->left);
307 break;
309 case EXPR_DEREF:
310 __pass_to_client(expr, DEREF_HOOK);
311 __split_expr(expr->deref);
312 break;
313 case EXPR_SLICE:
314 __split_expr(expr->base);
315 break;
316 case EXPR_CAST:
317 case EXPR_FORCE_CAST:
318 __pass_to_client(expr, CAST_HOOK);
319 __split_expr(expr->cast_expression);
320 break;
321 case EXPR_SIZEOF:
322 if (expr->cast_expression)
323 __pass_to_client(strip_parens(expr->cast_expression),
324 SIZEOF_HOOK);
325 break;
326 case EXPR_OFFSETOF:
327 case EXPR_ALIGNOF:
328 evaluate_expression(expr);
329 break;
330 case EXPR_CONDITIONAL:
331 case EXPR_SELECT:
332 if (known_condition_true(expr->conditional)) {
333 __split_expr(expr->cond_true);
334 break;
336 if (known_condition_false(expr->conditional)) {
337 __split_expr(expr->cond_false);
338 break;
340 __pass_to_client(expr, SELECT_HOOK);
341 __split_whole_condition(expr->conditional);
342 __split_expr(expr->cond_true);
343 __push_true_states();
344 __use_false_states();
345 __split_expr(expr->cond_false);
346 __merge_true_states();
347 break;
348 case EXPR_CALL:
349 if (sym_name_is("__builtin_constant_p", expr->fn))
350 break;
351 split_expr_list(expr->args);
352 __split_expr(expr->fn);
353 if (is_inline_func(expr->fn))
354 add_inline_function(expr->fn->symbol);
355 if (inlinable(expr->fn))
356 __inline_call = 1;
357 __process_post_op_stack();
358 __pass_to_client(expr, FUNCTION_CALL_HOOK);
359 __inline_call = 0;
360 if (inlinable(expr->fn)) {
361 parse_inline(expr);
363 __pass_to_client(expr, CALL_HOOK_AFTER_INLINE);
364 if (!is_assigned_call(expr))
365 __pass_to_client(expr, FUNCTION_CALL_HOOK_AFTER);
366 if (is_noreturn_func(expr->fn))
367 nullify_path();
368 break;
369 case EXPR_INITIALIZER:
370 split_expr_list(expr->expr_list);
371 break;
372 case EXPR_IDENTIFIER:
373 __split_expr(expr->ident_expression);
374 break;
375 case EXPR_INDEX:
376 __split_expr(expr->idx_expression);
377 break;
378 case EXPR_POS:
379 __split_expr(expr->init_expr);
380 break;
381 case EXPR_SYMBOL:
382 __pass_to_client(expr, SYM_HOOK);
383 break;
384 case EXPR_STRING:
385 __pass_to_client(expr, STRING_HOOK);
386 break;
387 default:
388 break;
390 pop_expression(&big_expression_stack);
393 static int is_forever_loop(struct statement *stmt)
395 struct expression *expr;
397 expr = strip_expr(stmt->iterator_pre_condition);
398 if (!expr)
399 expr = stmt->iterator_post_condition;
400 if (!expr) {
401 /* this is a for(;;) loop... */
402 return 1;
405 if (expr->type == EXPR_VALUE && expr->value == 1)
406 return 1;
408 return 0;
411 static int loop_num;
412 static char *get_loop_name(int num)
414 char buf[256];
416 snprintf(buf, 255, "-loop%d", num);
417 buf[255] = '\0';
418 return alloc_sname(buf);
422 * Pre Loops are while and for loops.
424 static void handle_pre_loop(struct statement *stmt)
426 int once_through; /* we go through the loop at least once */
427 struct sm_state *extra_sm = NULL;
428 int unchanged = 0;
429 char *loop_name;
430 struct stree *stree = NULL;
431 struct sm_state *sm = NULL;
433 loop_name = get_loop_name(loop_num);
434 loop_num++;
436 __split_stmt(stmt->iterator_pre_statement);
438 once_through = implied_condition_true(stmt->iterator_pre_condition);
440 loop_count++;
441 __push_continues();
442 __push_breaks();
444 __merge_gotos(loop_name);
446 extra_sm = __extra_handle_canonical_loops(stmt, &stree);
447 __in_pre_condition++;
448 __pass_to_client(stmt, PRELOOP_HOOK);
449 __split_whole_condition(stmt->iterator_pre_condition);
450 __in_pre_condition--;
451 FOR_EACH_SM(stree, sm) {
452 set_state(sm->owner, sm->name, sm->sym, sm->state);
453 } END_FOR_EACH_SM(sm);
454 free_stree(&stree);
455 if (extra_sm)
456 extra_sm = get_sm_state(extra_sm->owner, extra_sm->name, extra_sm->sym);
458 if (option_assume_loops)
459 once_through = 1;
461 __split_stmt(stmt->iterator_statement);
462 __warn_on_silly_pre_loops();
463 if (is_forever_loop(stmt)) {
464 __merge_continues();
465 __save_gotos(loop_name);
467 __push_fake_cur_stree();
468 __split_stmt(stmt->iterator_post_statement);
469 stree = __pop_fake_cur_stree();
471 __discard_false_states();
472 __use_breaks();
474 if (!__path_is_null())
475 __merge_stree_into_cur(stree);
476 free_stree(&stree);
477 } else {
478 __merge_continues();
479 unchanged = __iterator_unchanged(extra_sm);
480 __split_stmt(stmt->iterator_post_statement);
481 __save_gotos(loop_name);
482 __in_pre_condition++;
483 __split_whole_condition(stmt->iterator_pre_condition);
484 __in_pre_condition--;
485 nullify_path();
486 __merge_false_states();
487 if (once_through)
488 __discard_false_states();
489 else
490 __merge_false_states();
492 if (extra_sm && unchanged)
493 __extra_pre_loop_hook_after(extra_sm,
494 stmt->iterator_post_statement,
495 stmt->iterator_pre_condition);
496 __merge_breaks();
498 loop_count--;
502 * Post loops are do {} while();
504 static void handle_post_loop(struct statement *stmt)
506 char *loop_name;
508 loop_name = get_loop_name(loop_num);
509 loop_num++;
510 loop_count++;
512 __push_continues();
513 __push_breaks();
514 __merge_gotos(loop_name);
515 __split_stmt(stmt->iterator_statement);
516 __merge_continues();
517 if (!is_zero(stmt->iterator_post_condition))
518 __save_gotos(loop_name);
520 if (is_forever_loop(stmt)) {
521 __use_breaks();
522 } else {
523 __split_whole_condition(stmt->iterator_post_condition);
524 __use_false_states();
525 __merge_breaks();
527 loop_count--;
530 static int empty_statement(struct statement *stmt)
532 if (!stmt)
533 return 0;
534 if (stmt->type == STMT_EXPRESSION && !stmt->expression)
535 return 1;
536 return 0;
539 static int last_stmt_on_same_line(void)
541 struct statement *stmt;
542 int i = 0;
544 FOR_EACH_PTR_REVERSE(big_statement_stack, stmt) {
545 if (!i++)
546 continue;
547 if (stmt->pos.line == get_lineno())
548 return 1;
549 return 0;
550 } END_FOR_EACH_PTR_REVERSE(stmt);
551 return 0;
554 static void split_asm_constraints(struct expression_list *expr_list)
556 struct expression *expr;
557 int state = 0;
559 FOR_EACH_PTR(expr_list, expr) {
560 switch (state) {
561 case 0: /* identifier */
562 case 1: /* constraint */
563 state++;
564 continue;
565 case 2: /* expression */
566 state = 0;
567 __split_expr(expr);
568 continue;
570 } END_FOR_EACH_PTR(expr);
573 static int is_case_val(struct statement *stmt, sval_t sval)
575 sval_t case_sval;
577 if (stmt->type != STMT_CASE)
578 return 0;
579 if (!stmt->case_expression) {
580 __set_default();
581 return 1;
583 if (!get_value(stmt->case_expression, &case_sval))
584 return 0;
585 if (case_sval.value == sval.value)
586 return 1;
587 return 0;
590 static void split_known_switch(struct statement *stmt, sval_t sval)
592 struct statement *tmp;
594 __split_expr(stmt->switch_expression);
596 push_expression(&switch_expr_stack, stmt->switch_expression);
597 __save_switch_states(top_expression(switch_expr_stack));
598 nullify_path();
599 __push_default();
600 __push_breaks();
602 stmt = stmt->switch_statement;
604 __push_scope_hooks();
605 FOR_EACH_PTR(stmt->stmts, tmp) {
606 __smatch_lineno = tmp->pos.line;
607 if (is_case_val(tmp, sval)) {
608 __merge_switches(top_expression(switch_expr_stack),
609 stmt->case_expression);
610 __pass_case_to_client(top_expression(switch_expr_stack),
611 stmt->case_expression);
613 if (__path_is_null())
614 continue;
615 __split_stmt(tmp);
616 if (__path_is_null()) {
617 __set_default();
618 goto out;
620 } END_FOR_EACH_PTR(tmp);
621 out:
622 __call_scope_hooks();
623 if (!__pop_default())
624 __merge_switches(top_expression(switch_expr_stack),
625 NULL);
626 __discard_switches();
627 __merge_breaks();
628 pop_expression(&switch_expr_stack);
631 static int taking_too_long(void)
633 int ms;
635 ms = ms_since(&fn_start_time);
636 if (ms > 1000 * 60 * 5) /* five minutes */
637 return 1;
638 return 0;
641 static int is_last_stmt(struct statement *cur_stmt)
643 struct symbol *fn = get_base_type(cur_func_sym);
644 struct statement *stmt;
646 if (!fn)
647 return 0;
648 stmt = fn->stmt;
649 if (!stmt)
650 stmt = fn->inline_stmt;
651 if (!stmt || stmt->type != STMT_COMPOUND)
652 return 0;
653 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
654 if (stmt && stmt->type == STMT_LABEL)
655 stmt = stmt->label_statement;
656 if (stmt == cur_stmt)
657 return 1;
658 return 0;
661 static void handle_backward_goto(struct statement *goto_stmt)
663 const char *goto_name, *label_name;
664 struct statement *func_stmt;
665 struct symbol *base_type = get_base_type(cur_func_sym);
666 struct statement *tmp;
667 int found = 0;
669 if (!option_info)
670 return;
671 if (last_goto_statement_handled)
672 return;
673 last_goto_statement_handled = 1;
675 if (!goto_stmt->goto_label ||
676 goto_stmt->goto_label->type != SYM_LABEL ||
677 !goto_stmt->goto_label->ident)
678 return;
679 goto_name = goto_stmt->goto_label->ident->name;
681 func_stmt = base_type->stmt;
682 if (!func_stmt)
683 func_stmt = base_type->inline_stmt;
684 if (!func_stmt)
685 return;
686 if (func_stmt->type != STMT_COMPOUND)
687 return;
689 FOR_EACH_PTR(func_stmt->stmts, tmp) {
690 if (!found) {
691 if (tmp->type != STMT_LABEL)
692 continue;
693 if (!tmp->label_identifier ||
694 tmp->label_identifier->type != SYM_LABEL ||
695 !tmp->label_identifier->ident)
696 continue;
697 label_name = tmp->label_identifier->ident->name;
698 if (strcmp(goto_name, label_name) != 0)
699 continue;
700 found = 1;
702 __split_stmt(tmp);
703 } END_FOR_EACH_PTR(tmp);
706 static void fake_a_return(void)
708 struct symbol *return_type;
710 nullify_path();
711 __unnullify_path();
713 return_type = get_real_base_type(cur_func_sym);
714 return_type = get_real_base_type(return_type);
715 if (return_type != &void_ctype) {
716 __pass_to_client(unknown_value_expression(NULL), RETURN_HOOK);
717 nullify_path();
720 __pass_to_client(cur_func_sym, END_FUNC_HOOK);
721 __pass_to_client(cur_func_sym, AFTER_FUNC_HOOK);
724 void __split_stmt(struct statement *stmt)
726 sval_t sval;
728 if (!stmt)
729 goto out;
731 if (__bail_on_rest_of_function || out_of_memory() || taking_too_long()) {
732 static char *printed = NULL;
734 __bail_on_rest_of_function = 1;
735 if (printed != cur_func)
736 sm_msg("Function too hairy. Giving up.");
737 fake_a_return();
738 final_pass = 0; /* turn off sm_msg() from here */
739 printed = cur_func;
740 return;
743 add_ptr_list(&big_statement_stack, stmt);
744 free_expression_stack(&big_expression_stack);
745 set_position(stmt->pos);
746 __pass_to_client(stmt, STMT_HOOK);
748 switch (stmt->type) {
749 case STMT_DECLARATION:
750 split_declaration(stmt->declaration);
751 break;
752 case STMT_RETURN:
753 __split_expr(stmt->ret_value);
754 __pass_to_client(stmt->ret_value, RETURN_HOOK);
755 __process_post_op_stack();
756 nullify_path();
757 break;
758 case STMT_EXPRESSION:
759 __split_expr(stmt->expression);
760 break;
761 case STMT_COMPOUND: {
762 struct statement *tmp;
764 __push_scope_hooks();
765 FOR_EACH_PTR(stmt->stmts, tmp) {
766 __split_stmt(tmp);
767 } END_FOR_EACH_PTR(tmp);
768 __call_scope_hooks();
769 break;
771 case STMT_IF:
772 if (known_condition_true(stmt->if_conditional)) {
773 __split_stmt(stmt->if_true);
774 break;
776 if (known_condition_false(stmt->if_conditional)) {
777 __split_stmt(stmt->if_false);
778 break;
780 if (option_known_conditions &&
781 implied_condition_true(stmt->if_conditional)) {
782 sm_info("this condition is true.");
783 __split_stmt(stmt->if_true);
784 break;
786 if (option_known_conditions &&
787 implied_condition_false(stmt->if_conditional)) {
788 sm_info("this condition is false.");
789 __split_stmt(stmt->if_false);
790 break;
792 __split_whole_condition(stmt->if_conditional);
793 __split_stmt(stmt->if_true);
794 if (empty_statement(stmt->if_true) &&
795 last_stmt_on_same_line() &&
796 !get_macro_name(stmt->if_true->pos))
797 sm_msg("warn: if();");
798 __push_true_states();
799 __use_false_states();
800 __split_stmt(stmt->if_false);
801 __merge_true_states();
802 break;
803 case STMT_ITERATOR:
804 if (stmt->iterator_pre_condition)
805 handle_pre_loop(stmt);
806 else if (stmt->iterator_post_condition)
807 handle_post_loop(stmt);
808 else {
809 // these are for(;;) type loops.
810 handle_pre_loop(stmt);
812 break;
813 case STMT_SWITCH:
814 if (get_value(stmt->switch_expression, &sval)) {
815 split_known_switch(stmt, sval);
816 break;
818 __split_expr(stmt->switch_expression);
819 push_expression(&switch_expr_stack, stmt->switch_expression);
820 __save_switch_states(top_expression(switch_expr_stack));
821 nullify_path();
822 __push_default();
823 __push_breaks();
824 __split_stmt(stmt->switch_statement);
825 if (!__pop_default())
826 __merge_switches(top_expression(switch_expr_stack),
827 NULL);
828 __discard_switches();
829 __merge_breaks();
830 pop_expression(&switch_expr_stack);
831 break;
832 case STMT_CASE:
833 __merge_switches(top_expression(switch_expr_stack),
834 stmt->case_expression);
835 __pass_case_to_client(top_expression(switch_expr_stack),
836 stmt->case_expression);
837 if (!stmt->case_expression)
838 __set_default();
839 __split_expr(stmt->case_expression);
840 __split_expr(stmt->case_to);
841 __split_stmt(stmt->case_statement);
842 break;
843 case STMT_LABEL:
844 if (stmt->label_identifier &&
845 stmt->label_identifier->type == SYM_LABEL &&
846 stmt->label_identifier->ident) {
847 loop_count |= 0x80000000;
848 __merge_gotos(stmt->label_identifier->ident->name);
850 __split_stmt(stmt->label_statement);
851 break;
852 case STMT_GOTO:
853 __split_expr(stmt->goto_expression);
854 if (stmt->goto_label && stmt->goto_label->type == SYM_NODE) {
855 if (!strcmp(stmt->goto_label->ident->name, "break")) {
856 __process_breaks();
857 } else if (!strcmp(stmt->goto_label->ident->name,
858 "continue")) {
859 __process_continues();
861 } else if (stmt->goto_label &&
862 stmt->goto_label->type == SYM_LABEL &&
863 stmt->goto_label->ident) {
864 __save_gotos(stmt->goto_label->ident->name);
866 nullify_path();
867 if (is_last_stmt(stmt))
868 handle_backward_goto(stmt);
869 break;
870 case STMT_NONE:
871 break;
872 case STMT_ASM:
873 __pass_to_client(stmt, ASM_HOOK);
874 __split_expr(stmt->asm_string);
875 split_asm_constraints(stmt->asm_outputs);
876 split_asm_constraints(stmt->asm_inputs);
877 split_asm_constraints(stmt->asm_clobbers);
878 break;
879 case STMT_CONTEXT:
880 break;
881 case STMT_RANGE:
882 __split_expr(stmt->range_expression);
883 __split_expr(stmt->range_low);
884 __split_expr(stmt->range_high);
885 break;
887 __pass_to_client(stmt, STMT_HOOK_AFTER);
888 out:
889 __process_post_op_stack();
892 static void split_expr_list(struct expression_list *expr_list)
894 struct expression *expr;
896 FOR_EACH_PTR(expr_list, expr) {
897 __split_expr(expr);
898 __process_post_op_stack();
899 } END_FOR_EACH_PTR(expr);
902 static void split_sym(struct symbol *sym)
904 if (!sym)
905 return;
906 if (!(sym->namespace & NS_SYMBOL))
907 return;
909 __split_stmt(sym->stmt);
910 __split_expr(sym->array_size);
911 split_symlist(sym->arguments);
912 split_symlist(sym->symbol_list);
913 __split_stmt(sym->inline_stmt);
914 split_symlist(sym->inline_symbol_list);
917 static void split_symlist(struct symbol_list *sym_list)
919 struct symbol *sym;
921 FOR_EACH_PTR(sym_list, sym) {
922 split_sym(sym);
923 } END_FOR_EACH_PTR(sym);
926 typedef void (fake_cb)(struct expression *expr);
928 static int member_to_number(struct expression *expr, struct ident *member)
930 struct symbol *type, *tmp;
931 char *name;
932 int i;
934 if (!member)
935 return -1;
936 name = member->name;
938 type = get_type(expr);
939 if (!type || type->type != SYM_STRUCT)
940 return -1;
942 i = -1;
943 FOR_EACH_PTR(type->symbol_list, tmp) {
944 i++;
945 if (!tmp->ident)
946 continue;
947 if (strcmp(name, tmp->ident->name) == 0)
948 return i;
949 } END_FOR_EACH_PTR(tmp);
950 return -1;
953 static struct ident *number_to_member(struct expression *expr, int num)
955 struct symbol *type, *member;
956 int i = 0;
958 type = get_type(expr);
959 if (!type || type->type != SYM_STRUCT)
960 return NULL;
962 FOR_EACH_PTR(type->symbol_list, member) {
963 if (i == num)
964 return member->ident;
965 i++;
966 } END_FOR_EACH_PTR(member);
967 return NULL;
970 static void fake_element_assigns_helper(struct expression *array, struct expression_list *expr_list, fake_cb *fake_cb);
972 struct member_set {
973 struct ident *ident;
974 int set;
977 static struct member_set *alloc_member_set(struct symbol *type)
979 struct member_set *member_set;
980 struct symbol *member;
981 int member_count;
982 int member_idx;
984 member_count = ptr_list_size((struct ptr_list *)type->symbol_list);
985 member_set = malloc(member_count * sizeof(*member_set));
986 member_idx = 0;
987 FOR_EACH_PTR(type->symbol_list, member) {
988 member_set[member_idx].ident = member->ident;
989 member_set[member_idx].set = 0;
990 member_idx++;
991 } END_FOR_EACH_PTR(member);
993 return member_set;
996 static void mark_member_as_set(struct symbol *type, struct member_set *member_set, struct ident *ident)
998 int member_count = ptr_list_size((struct ptr_list *)type->symbol_list);
999 int i;
1001 for (i = 0; i < member_count; i++) {
1002 if (member_set[i].ident == ident) {
1003 member_set[i].set = 1;
1004 return;
1007 // crap. this is buggy.
1008 // sm_msg("internal smatch error in initializer %s.%s", type->ident->name, ident->name);
1011 static void set_unset_to_zero(struct expression *symbol, struct symbol *type, struct member_set *member_set)
1013 struct expression *deref, *assign;
1014 struct symbol *member, *member_type;
1015 int member_idx;
1017 member_idx = 0;
1018 FOR_EACH_PTR(type->symbol_list, member) {
1019 if (!member->ident || member_set[member_idx].set) {
1020 member_idx++;
1021 continue;
1023 member_type = get_real_base_type(member);
1024 if (!member_type || member_type->type == SYM_ARRAY) {
1025 member_idx++;
1026 continue;
1028 /* TODO: this should be handled recursively and not ignored */
1029 if (member_type->type == SYM_STRUCT || member_type->type == SYM_UNION) {
1030 member_idx++;
1031 continue;
1033 deref = member_expression(symbol, '.', member->ident);
1034 assign = assign_expression(deref, zero_expr());
1035 __split_expr(assign);
1036 member_idx++;
1037 } END_FOR_EACH_PTR(member);
1041 static void fake_member_assigns_helper(struct expression *symbol, struct expression_list *members, fake_cb *fake_cb)
1043 struct expression *deref, *assign, *tmp;
1044 struct symbol *struct_type, *type;
1045 struct ident *member;
1046 int member_idx;
1047 struct member_set *member_set;
1049 struct_type = get_type(symbol);
1050 if (!struct_type ||
1051 (struct_type->type != SYM_STRUCT && struct_type->type != SYM_UNION))
1052 return;
1054 member_set = alloc_member_set(struct_type);
1056 member_idx = 0;
1057 FOR_EACH_PTR(members, tmp) {
1058 member = number_to_member(symbol, member_idx);
1059 while (tmp->type == EXPR_IDENTIFIER) {
1060 member = tmp->expr_ident;
1061 member_idx = member_to_number(symbol, member);
1062 tmp = tmp->ident_expression;
1064 mark_member_as_set(struct_type, member_set, member);
1065 member_idx++;
1066 deref = member_expression(symbol, '.', member);
1067 if (tmp->type == EXPR_INITIALIZER) {
1068 type = get_type(deref);
1069 if (type && type->type == SYM_ARRAY)
1070 fake_element_assigns_helper(deref, tmp->expr_list, fake_cb);
1071 else
1072 fake_member_assigns_helper(deref, tmp->expr_list, fake_cb);
1073 } else {
1074 assign = assign_expression(deref, tmp);
1075 fake_cb(assign);
1077 } END_FOR_EACH_PTR(tmp);
1079 set_unset_to_zero(symbol, struct_type, member_set);
1082 static void fake_member_assigns(struct symbol *sym, fake_cb *fake_cb)
1084 fake_member_assigns_helper(symbol_expression(sym),
1085 sym->initializer->expr_list, fake_cb);
1088 static void fake_element_assigns_helper(struct expression *array, struct expression_list *expr_list, fake_cb *fake_cb)
1090 struct expression *offset, *binop, *assign, *tmp;
1091 struct symbol *type;
1092 int idx;
1094 idx = 0;
1095 FOR_EACH_PTR(expr_list, tmp) {
1096 if (tmp->type == EXPR_INDEX) {
1097 if (tmp->idx_from != tmp->idx_to)
1098 return;
1099 idx = tmp->idx_from;
1100 if (!tmp->idx_expression)
1101 goto next;
1102 tmp = tmp->idx_expression;
1104 offset = value_expr(idx);
1105 binop = array_element_expression(array, offset);
1106 if (tmp->type == EXPR_INITIALIZER) {
1107 type = get_type(binop);
1108 if (type && type->type == SYM_ARRAY)
1109 fake_element_assigns_helper(binop, tmp->expr_list, fake_cb);
1110 else
1111 fake_member_assigns_helper(binop, tmp->expr_list, fake_cb);
1112 } else {
1113 assign = assign_expression(binop, tmp);
1114 fake_cb(assign);
1116 next:
1117 idx++;
1118 } END_FOR_EACH_PTR(tmp);
1121 static void fake_element_assigns(struct symbol *sym, fake_cb *fake_cb)
1123 fake_element_assigns_helper(symbol_expression(sym), sym->initializer->expr_list, fake_cb);
1126 static void fake_assign_expr(struct symbol *sym)
1128 struct expression *assign, *symbol;
1130 symbol = symbol_expression(sym);
1131 assign = assign_expression(symbol, sym->initializer);
1132 __split_expr(assign);
1135 static void call_split_expr(struct expression *expr)
1137 __split_expr(expr);
1140 static void do_initializer_stuff(struct symbol *sym)
1142 if (!sym->initializer)
1143 return;
1145 if (sym->initializer->type == EXPR_INITIALIZER) {
1146 if (get_real_base_type(sym)->type == SYM_ARRAY)
1147 fake_element_assigns(sym, call_split_expr);
1148 else
1149 fake_member_assigns(sym, call_split_expr);
1150 } else {
1151 fake_assign_expr(sym);
1155 static void split_declaration(struct symbol_list *sym_list)
1157 struct symbol *sym;
1159 FOR_EACH_PTR(sym_list, sym) {
1160 __pass_to_client(sym, DECLARATION_HOOK);
1161 do_initializer_stuff(sym);
1162 split_sym(sym);
1163 } END_FOR_EACH_PTR(sym);
1166 static void call_global_assign_hooks(struct expression *assign)
1168 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1171 static void fake_global_assign(struct symbol *sym)
1173 struct expression *assign, *symbol;
1175 if (get_real_base_type(sym)->type == SYM_ARRAY) {
1176 if (sym->initializer && sym->initializer->type == EXPR_INITIALIZER) {
1177 fake_element_assigns(sym, call_global_assign_hooks);
1178 } else if (sym->initializer) {
1179 symbol = symbol_expression(sym);
1180 assign = assign_expression(symbol, sym->initializer);
1181 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1182 } else {
1183 fake_element_assigns_helper(symbol_expression(sym), NULL, call_global_assign_hooks);
1185 } else if (get_real_base_type(sym)->type == SYM_STRUCT) {
1186 if (sym->initializer && sym->initializer->type == EXPR_INITIALIZER) {
1187 fake_member_assigns(sym, call_global_assign_hooks);
1188 } else if (sym->initializer) {
1189 symbol = symbol_expression(sym);
1190 assign = assign_expression(symbol, sym->initializer);
1191 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1192 } else {
1193 fake_member_assigns_helper(symbol_expression(sym), NULL, call_global_assign_hooks);
1195 } else {
1196 symbol = symbol_expression(sym);
1197 if (sym->initializer)
1198 assign = assign_expression(symbol, sym->initializer);
1199 else
1200 assign = assign_expression(symbol, zero_expr());
1201 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1205 static void start_function_definition(struct symbol *sym)
1207 __in_function_def = 1;
1208 __pass_to_client(sym, FUNC_DEF_HOOK);
1209 __in_function_def = 0;
1210 __pass_to_client(sym, AFTER_DEF_HOOK);
1214 static void split_function(struct symbol *sym)
1216 struct symbol *base_type = get_base_type(sym);
1218 if (!base_type->stmt && !base_type->inline_stmt)
1219 return;
1221 gettimeofday(&fn_start_time, NULL);
1222 cur_func_sym = sym;
1223 if (sym->ident)
1224 cur_func = sym->ident->name;
1225 __smatch_lineno = sym->pos.line;
1226 loop_count = 0;
1227 last_goto_statement_handled = 0;
1228 sm_debug("new function: %s\n", cur_func);
1229 __stree_id = 0;
1230 if (option_two_passes) {
1231 __unnullify_path();
1232 loop_num = 0;
1233 final_pass = 0;
1234 start_function_definition(sym);
1235 __split_stmt(base_type->stmt);
1236 __split_stmt(base_type->inline_stmt);
1237 nullify_path();
1239 __unnullify_path();
1240 loop_num = 0;
1241 final_pass = 1;
1242 start_function_definition(sym);
1243 __split_stmt(base_type->stmt);
1244 __split_stmt(base_type->inline_stmt);
1245 __pass_to_client(sym, END_FUNC_HOOK);
1246 __pass_to_client(sym, AFTER_FUNC_HOOK);
1248 cur_func_sym = NULL;
1249 cur_func = NULL;
1250 clear_all_states();
1251 free_data_info_allocs();
1252 free_expression_stack(&switch_expr_stack);
1253 __free_ptr_list((struct ptr_list **)&big_statement_stack);
1254 __bail_on_rest_of_function = 0;
1257 static void parse_inline(struct expression *call)
1259 struct symbol *base_type;
1260 int loop_num_bak = loop_num;
1261 int final_pass_bak = final_pass;
1262 char *cur_func_bak = cur_func;
1263 struct statement_list *big_statement_stack_bak = big_statement_stack;
1264 struct expression_list *big_expression_stack_bak = big_expression_stack;
1265 struct expression_list *switch_expr_stack_bak = switch_expr_stack;
1266 struct symbol *cur_func_sym_bak = cur_func_sym;
1268 __pass_to_client(call, INLINE_FN_START);
1269 final_pass = 0; /* don't print anything */
1270 __inline_fn = call;
1272 base_type = get_base_type(call->fn->symbol);
1273 cur_func_sym = call->fn->symbol;
1274 if (call->fn->symbol->ident)
1275 cur_func = call->fn->symbol->ident->name;
1276 else
1277 cur_func = NULL;
1278 set_position(call->fn->symbol->pos);
1280 save_all_states();
1281 big_statement_stack = NULL;
1282 big_expression_stack = NULL;
1283 switch_expr_stack = NULL;
1285 sm_debug("inline function: %s\n", cur_func);
1286 __unnullify_path();
1287 loop_num = 0;
1288 start_function_definition(call->fn->symbol);
1289 __split_stmt(base_type->stmt);
1290 __split_stmt(base_type->inline_stmt);
1291 __pass_to_client(call->fn->symbol, END_FUNC_HOOK);
1292 __pass_to_client(call->fn->symbol, AFTER_FUNC_HOOK);
1294 free_expression_stack(&switch_expr_stack);
1295 __free_ptr_list((struct ptr_list **)&big_statement_stack);
1296 nullify_path();
1297 free_goto_stack();
1299 loop_num = loop_num_bak;
1300 final_pass = final_pass_bak;
1301 cur_func_sym = cur_func_sym_bak;
1302 cur_func = cur_func_bak;
1303 big_statement_stack = big_statement_stack_bak;
1304 big_expression_stack = big_expression_stack_bak;
1305 switch_expr_stack = switch_expr_stack_bak;
1307 restore_all_states();
1308 set_position(call->pos);
1309 __inline_fn = NULL;
1310 __pass_to_client(call, INLINE_FN_END);
1313 static struct symbol_list *inlines_called;
1314 static void add_inline_function(struct symbol *sym)
1316 static struct symbol_list *already_added;
1317 struct symbol *tmp;
1319 FOR_EACH_PTR(already_added, tmp) {
1320 if (tmp == sym)
1321 return;
1322 } END_FOR_EACH_PTR(tmp);
1324 add_ptr_list(&already_added, sym);
1325 add_ptr_list(&inlines_called, sym);
1328 static void process_inlines(void)
1330 struct symbol *tmp;
1332 FOR_EACH_PTR(inlines_called, tmp) {
1333 split_function(tmp);
1334 } END_FOR_EACH_PTR(tmp);
1335 free_ptr_list(&inlines_called);
1338 static struct symbol *get_last_scoped_symbol(struct symbol_list *big_list, int use_static)
1340 struct symbol *sym;
1342 FOR_EACH_PTR_REVERSE(big_list, sym) {
1343 if (!sym->scope)
1344 continue;
1345 if (use_static && sym->ctype.modifiers & MOD_STATIC)
1346 return sym;
1347 if (!use_static && !(sym->ctype.modifiers & MOD_STATIC))
1348 return sym;
1349 } END_FOR_EACH_PTR_REVERSE(sym);
1351 return NULL;
1354 static void split_inlines_in_scope(struct symbol *sym)
1356 struct symbol *base;
1357 struct symbol_list *scope_list;
1358 int stream;
1360 scope_list = sym->scope->symbols;
1361 stream = sym->pos.stream;
1363 /* find the last static symbol in the file */
1364 FOR_EACH_PTR_REVERSE(scope_list, sym) {
1365 if (sym->pos.stream != stream)
1366 continue;
1367 if (sym->type != SYM_NODE)
1368 continue;
1369 base = get_base_type(sym);
1370 if (!base)
1371 continue;
1372 if (base->type != SYM_FN)
1373 continue;
1374 if (!base->inline_stmt)
1375 continue;
1376 add_inline_function(sym);
1377 } END_FOR_EACH_PTR_REVERSE(sym);
1379 process_inlines();
1382 static void split_inlines(struct symbol_list *sym_list)
1384 struct symbol *sym;
1386 sym = get_last_scoped_symbol(sym_list, 0);
1387 if (sym)
1388 split_inlines_in_scope(sym);
1389 sym = get_last_scoped_symbol(sym_list, 1);
1390 if (sym)
1391 split_inlines_in_scope(sym);
1394 static struct stree *clone_estates_perm(struct stree *orig)
1396 struct stree *ret = NULL;
1397 struct sm_state *tmp;
1399 FOR_EACH_SM(orig, tmp) {
1400 set_state_stree_perm(&ret, tmp->owner, tmp->name, tmp->sym, clone_estate_perm(tmp->state));
1401 } END_FOR_EACH_SM(tmp);
1403 return ret;
1406 static void split_functions(struct symbol_list *sym_list)
1408 struct symbol *sym;
1410 __unnullify_path();
1411 FOR_EACH_PTR(sym_list, sym) {
1412 set_position(sym->pos);
1413 if (sym->type != SYM_NODE || get_base_type(sym)->type != SYM_FN) {
1414 __pass_to_client(sym, BASE_HOOK);
1415 fake_global_assign(sym);
1417 } END_FOR_EACH_PTR(sym);
1418 global_states = clone_estates_perm(get_all_states_stree(SMATCH_EXTRA));
1419 nullify_path();
1421 FOR_EACH_PTR(sym_list, sym) {
1422 set_position(sym->pos);
1423 if (sym->type == SYM_NODE && get_base_type(sym)->type == SYM_FN) {
1424 split_function(sym);
1425 process_inlines();
1427 } END_FOR_EACH_PTR(sym);
1428 split_inlines(sym_list);
1429 __pass_to_client(sym_list, END_FILE_HOOK);
1432 void smatch(int argc, char **argv)
1435 struct string_list *filelist = NULL;
1436 struct symbol_list *sym_list;
1438 if (argc < 2) {
1439 printf("Usage: smatch [--debug] <filename.c>\n");
1440 exit(1);
1442 sparse_initialize(argc, argv, &filelist);
1443 set_valid_ptr_max();
1444 FOR_EACH_PTR_NOTAG(filelist, base_file) {
1445 if (option_file_output) {
1446 char buf[256];
1448 snprintf(buf, sizeof(buf), "%s.smatch", base_file);
1449 sm_outfd = fopen(buf, "w");
1450 if (!sm_outfd) {
1451 printf("Error: Cannot open %s\n", base_file);
1452 exit(1);
1455 sym_list = sparse_keep_tokens(base_file);
1456 split_functions(sym_list);
1457 } END_FOR_EACH_PTR_NOTAG(base_file);