flow: add a new expr->parent struct member
[smatch.git] / smatch_flow.c
blobd444d575c5904147486c8de75d6a5f14c967b136
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 struct statement *__prev_stmt;
50 struct statement *__cur_stmt;
51 struct statement *__next_stmt;
52 int __in_pre_condition = 0;
53 int __bail_on_rest_of_function = 0;
54 static struct timeval fn_start_time;
55 char *get_function(void) { return cur_func; }
56 int get_lineno(void) { return __smatch_lineno; }
57 int inside_loop(void) { return !!loop_count; }
58 int definitely_inside_loop(void) { return !!(loop_count & ~0x80000000); }
59 struct expression *get_switch_expr(void) { return top_expression(switch_expr_stack); }
60 int in_expression_statement(void) { return !!__expr_stmt_count; }
62 static void split_symlist(struct symbol_list *sym_list);
63 static void split_declaration(struct symbol_list *sym_list);
64 static void split_expr_list(struct expression_list *expr_list, struct expression *parent);
65 static void add_inline_function(struct symbol *sym);
66 static void parse_inline(struct expression *expr);
68 int option_assume_loops = 0;
69 int option_known_conditions = 0;
70 int option_two_passes = 0;
71 struct symbol *cur_func_sym = NULL;
72 struct stree *global_states;
74 long long valid_ptr_min = 4096;
75 long long valid_ptr_max = 2117777777;
76 sval_t valid_ptr_min_sval = {
77 .type = &ptr_ctype,
78 {.value = 4096},
80 sval_t valid_ptr_max_sval = {
81 .type = &ptr_ctype,
82 {.value = LONG_MAX - 100000},
85 static void set_valid_ptr_max(void)
87 if (type_bits(&ptr_ctype) == 32)
88 valid_ptr_max = 2117777777;
89 else if (type_bits(&ptr_ctype) == 64)
90 valid_ptr_max = 2117777777777777777LL;
92 valid_ptr_max_sval.value = valid_ptr_max;
95 int outside_of_function(void)
97 return cur_func_sym == NULL;
100 const char *get_filename(void)
102 if (option_info)
103 return base_file;
104 if (option_full_path)
105 return full_filename;
106 return filename;
109 const char *get_base_file(void)
111 return base_file;
114 static void set_position(struct position pos)
116 int len;
117 static int prev_stream = -1;
119 if (pos.stream == 0 && pos.line == 0)
120 return;
122 __smatch_lineno = pos.line;
124 if (pos.stream == prev_stream)
125 return;
127 filename = stream_name(pos.stream);
129 free(full_filename);
130 pathname = getcwd(NULL, 0);
131 if (pathname) {
132 len = strlen(pathname) + 1 + strlen(filename) + 1;
133 full_filename = malloc(len);
134 snprintf(full_filename, len, "%s/%s", pathname, filename);
135 } else {
136 full_filename = alloc_string(filename);
138 free(pathname);
141 static void set_parent(struct expression *expr, struct expression *parent)
143 if (!expr)
144 return;
145 expr->parent = parent;
148 int is_assigned_call(struct expression *expr)
150 struct expression *tmp;
152 FOR_EACH_PTR_REVERSE(big_expression_stack, tmp) {
153 if (tmp->type == EXPR_ASSIGNMENT && tmp->op == '=' &&
154 strip_expr(tmp->right) == expr)
155 return 1;
156 if (tmp->pos.line < expr->pos.line)
157 return 0;
158 } END_FOR_EACH_PTR_REVERSE(tmp);
159 return 0;
162 static int is_inline_func(struct expression *expr)
164 if (expr->type != EXPR_SYMBOL || !expr->symbol)
165 return 0;
166 if (expr->symbol->ctype.modifiers & MOD_INLINE)
167 return 1;
168 return 0;
171 static int is_noreturn_func(struct expression *expr)
173 if (expr->type != EXPR_SYMBOL || !expr->symbol)
174 return 0;
175 if (expr->symbol->ctype.modifiers & MOD_NORETURN)
176 return 1;
177 return 0;
180 int inlinable(struct expression *expr)
182 struct symbol *sym;
183 struct statement *last_stmt = NULL;
185 if (__inline_fn) /* don't nest */
186 return 0;
188 if (expr->type != EXPR_SYMBOL || !expr->symbol)
189 return 0;
190 if (is_no_inline_function(expr->symbol->ident->name))
191 return 0;
192 sym = get_base_type(expr->symbol);
193 if (sym->stmt && sym->stmt->type == STMT_COMPOUND) {
194 if (ptr_list_size((struct ptr_list *)sym->stmt->stmts) > 10)
195 return 0;
196 if (sym->stmt->type != STMT_COMPOUND)
197 return 0;
198 last_stmt = last_ptr_list((struct ptr_list *)sym->stmt->stmts);
200 if (sym->inline_stmt && sym->inline_stmt->type == STMT_COMPOUND) {
201 if (ptr_list_size((struct ptr_list *)sym->inline_stmt->stmts) > 10)
202 return 0;
203 if (sym->inline_stmt->type != STMT_COMPOUND)
204 return 0;
205 last_stmt = last_ptr_list((struct ptr_list *)sym->inline_stmt->stmts);
208 if (!last_stmt)
209 return 0;
211 /* the magic numbers in this function are pulled out of my bum. */
212 if (last_stmt->pos.line > sym->pos.line + 20)
213 return 0;
215 return 1;
218 void __process_post_op_stack(void)
220 struct expression *expr;
222 FOR_EACH_PTR(post_op_stack, expr) {
223 __pass_to_client(expr, OP_HOOK);
224 } END_FOR_EACH_PTR(expr);
226 __free_ptr_list((struct ptr_list **)&post_op_stack);
229 static int handle_comma_assigns(struct expression *expr)
231 struct expression *right;
232 struct expression *assign;
234 right = strip_expr(expr->right);
235 if (right->type != EXPR_COMMA)
236 return 0;
238 __split_expr(right->left);
239 __process_post_op_stack();
241 assign = assign_expression(expr->left, right->right);
242 __split_expr(assign);
244 return 1;
247 void __split_expr(struct expression *expr)
249 if (!expr)
250 return;
252 // sm_msg(" Debug expr_type %d %s", expr->type, show_special(expr->op));
254 if (__in_fake_assign && expr->type != EXPR_ASSIGNMENT)
255 return;
256 if (__in_fake_assign >= 4) /* don't allow too much nesting */
257 return;
259 push_expression(&big_expression_stack, expr);
260 set_position(expr->pos);
261 __pass_to_client(expr, EXPR_HOOK);
263 switch (expr->type) {
264 case EXPR_PREOP:
265 set_parent(expr->unop, expr);
267 if (expr->op == '*')
268 __pass_to_client(expr, DEREF_HOOK);
269 __split_expr(expr->unop);
270 __pass_to_client(expr, OP_HOOK);
271 break;
272 case EXPR_POSTOP:
273 set_parent(expr->unop, expr);
275 __split_expr(expr->unop);
276 push_expression(&post_op_stack, expr);
277 break;
278 case EXPR_STATEMENT:
279 __expr_stmt_count++;
280 __split_stmt(expr->statement);
281 __expr_stmt_count--;
282 break;
283 case EXPR_LOGICAL:
284 case EXPR_COMPARE:
285 set_parent(expr->left, expr);
286 set_parent(expr->right, expr);
288 __pass_to_client(expr, LOGIC_HOOK);
289 __handle_logic(expr);
290 break;
291 case EXPR_BINOP:
292 set_parent(expr->left, expr);
293 set_parent(expr->right, expr);
295 __pass_to_client(expr, BINOP_HOOK);
296 case EXPR_COMMA:
297 set_parent(expr->left, expr);
298 set_parent(expr->right, expr);
300 __split_expr(expr->left);
301 __process_post_op_stack();
302 __split_expr(expr->right);
303 break;
304 case EXPR_ASSIGNMENT: {
305 struct expression *tmp;
307 set_parent(expr->left, expr);
308 set_parent(expr->right, expr);
310 if (!expr->right)
311 break;
313 __pass_to_client(expr, RAW_ASSIGNMENT_HOOK);
315 /* foo = !bar() */
316 if (__handle_condition_assigns(expr))
317 break;
318 /* foo = (x < 5 ? foo : 5); */
319 if (__handle_select_assigns(expr))
320 break;
321 /* foo = ({frob(); frob(); frob(); 1;}) */
322 if (__handle_expr_statement_assigns(expr))
323 break;
324 /* foo = (3, 4); */
325 if (handle_comma_assigns(expr))
326 break;
328 __split_expr(expr->right);
329 if (outside_of_function())
330 __pass_to_client(expr, GLOBAL_ASSIGNMENT_HOOK);
331 else
332 __pass_to_client(expr, ASSIGNMENT_HOOK);
334 __fake_struct_member_assignments(expr);
336 tmp = strip_expr(expr->right);
337 if (expr->op == '=' && tmp->type == EXPR_CALL) {
338 __pass_to_client(expr, CALL_ASSIGNMENT_HOOK);
339 if (!is_fake_call(tmp))
340 __pass_to_client(tmp, FUNCTION_CALL_HOOK_AFTER);
342 if (get_macro_name(tmp->pos) &&
343 get_macro_name(expr->pos) != get_macro_name(tmp->pos))
344 __pass_to_client(expr, MACRO_ASSIGNMENT_HOOK);
345 __split_expr(expr->left);
346 break;
348 case EXPR_DEREF:
349 set_parent(expr->deref, expr);
351 __pass_to_client(expr, DEREF_HOOK);
352 __split_expr(expr->deref);
353 break;
354 case EXPR_SLICE:
355 set_parent(expr->base, expr);
357 __split_expr(expr->base);
358 break;
359 case EXPR_CAST:
360 case EXPR_FORCE_CAST:
361 set_parent(expr->cast_expression, expr);
363 __pass_to_client(expr, CAST_HOOK);
364 __split_expr(expr->cast_expression);
365 break;
366 case EXPR_SIZEOF:
367 if (expr->cast_expression)
368 __pass_to_client(strip_parens(expr->cast_expression),
369 SIZEOF_HOOK);
370 break;
371 case EXPR_OFFSETOF:
372 case EXPR_ALIGNOF:
373 evaluate_expression(expr);
374 break;
375 case EXPR_CONDITIONAL:
376 case EXPR_SELECT:
377 set_parent(expr->conditional, expr);
378 set_parent(expr->cond_true, expr);
379 set_parent(expr->cond_false, expr);
381 if (known_condition_true(expr->conditional)) {
382 __split_expr(expr->cond_true);
383 break;
385 if (known_condition_false(expr->conditional)) {
386 __split_expr(expr->cond_false);
387 break;
389 __pass_to_client(expr, SELECT_HOOK);
390 __split_whole_condition(expr->conditional);
391 __split_expr(expr->cond_true);
392 __push_true_states();
393 __use_false_states();
394 __split_expr(expr->cond_false);
395 __merge_true_states();
396 break;
397 case EXPR_CALL:
398 set_parent(expr->fn, expr);
400 if (sym_name_is("__builtin_constant_p", expr->fn))
401 break;
402 split_expr_list(expr->args, expr);
403 __split_expr(expr->fn);
404 if (is_inline_func(expr->fn))
405 add_inline_function(expr->fn->symbol);
406 if (inlinable(expr->fn))
407 __inline_call = 1;
408 __process_post_op_stack();
409 __pass_to_client(expr, FUNCTION_CALL_HOOK);
410 __inline_call = 0;
411 if (inlinable(expr->fn)) {
412 parse_inline(expr);
414 __pass_to_client(expr, CALL_HOOK_AFTER_INLINE);
415 if (!is_assigned_call(expr))
416 __pass_to_client(expr, FUNCTION_CALL_HOOK_AFTER);
417 if (is_noreturn_func(expr->fn))
418 nullify_path();
419 break;
420 case EXPR_INITIALIZER:
421 split_expr_list(expr->expr_list, expr);
422 break;
423 case EXPR_IDENTIFIER:
424 set_parent(expr->ident_expression, expr);
425 __split_expr(expr->ident_expression);
426 break;
427 case EXPR_INDEX:
428 set_parent(expr->idx_expression, expr);
429 __split_expr(expr->idx_expression);
430 break;
431 case EXPR_POS:
432 set_parent(expr->init_expr, expr);
433 __split_expr(expr->init_expr);
434 break;
435 case EXPR_SYMBOL:
436 __pass_to_client(expr, SYM_HOOK);
437 break;
438 case EXPR_STRING:
439 __pass_to_client(expr, STRING_HOOK);
440 break;
441 default:
442 break;
444 pop_expression(&big_expression_stack);
447 static int is_forever_loop(struct statement *stmt)
449 struct expression *expr;
451 expr = strip_expr(stmt->iterator_pre_condition);
452 if (!expr)
453 expr = stmt->iterator_post_condition;
454 if (!expr) {
455 /* this is a for(;;) loop... */
456 return 1;
459 if (expr->type == EXPR_VALUE && expr->value == 1)
460 return 1;
462 return 0;
465 static int loop_num;
466 static char *get_loop_name(int num)
468 char buf[256];
470 snprintf(buf, 255, "-loop%d", num);
471 buf[255] = '\0';
472 return alloc_sname(buf);
476 * Pre Loops are while and for loops.
478 static void handle_pre_loop(struct statement *stmt)
480 int once_through; /* we go through the loop at least once */
481 struct sm_state *extra_sm = NULL;
482 int unchanged = 0;
483 char *loop_name;
484 struct stree *stree = NULL;
485 struct sm_state *sm = NULL;
487 loop_name = get_loop_name(loop_num);
488 loop_num++;
490 __split_stmt(stmt->iterator_pre_statement);
491 __prev_stmt = stmt->iterator_pre_statement;
493 once_through = implied_condition_true(stmt->iterator_pre_condition);
495 loop_count++;
496 __push_continues();
497 __push_breaks();
499 __merge_gotos(loop_name);
501 extra_sm = __extra_handle_canonical_loops(stmt, &stree);
502 __in_pre_condition++;
503 __pass_to_client(stmt, PRELOOP_HOOK);
504 __split_whole_condition(stmt->iterator_pre_condition);
505 __in_pre_condition--;
506 FOR_EACH_SM(stree, sm) {
507 set_state(sm->owner, sm->name, sm->sym, sm->state);
508 } END_FOR_EACH_SM(sm);
509 free_stree(&stree);
510 if (extra_sm)
511 extra_sm = get_sm_state(extra_sm->owner, extra_sm->name, extra_sm->sym);
513 if (option_assume_loops)
514 once_through = 1;
516 __split_stmt(stmt->iterator_statement);
517 __warn_on_silly_pre_loops();
518 if (is_forever_loop(stmt)) {
519 __merge_continues();
520 __save_gotos(loop_name);
522 __push_fake_cur_stree();
523 __split_stmt(stmt->iterator_post_statement);
524 stree = __pop_fake_cur_stree();
526 __discard_false_states();
527 __use_breaks();
529 if (!__path_is_null())
530 __merge_stree_into_cur(stree);
531 free_stree(&stree);
532 } else {
533 __merge_continues();
534 unchanged = __iterator_unchanged(extra_sm);
535 __split_stmt(stmt->iterator_post_statement);
536 __prev_stmt = stmt->iterator_post_statement;
537 __cur_stmt = stmt;
539 __save_gotos(loop_name);
540 __in_pre_condition++;
541 __split_whole_condition(stmt->iterator_pre_condition);
542 __in_pre_condition--;
543 nullify_path();
544 __merge_false_states();
545 if (once_through)
546 __discard_false_states();
547 else
548 __merge_false_states();
550 if (extra_sm && unchanged)
551 __extra_pre_loop_hook_after(extra_sm,
552 stmt->iterator_post_statement,
553 stmt->iterator_pre_condition);
554 __merge_breaks();
556 loop_count--;
560 * Post loops are do {} while();
562 static void handle_post_loop(struct statement *stmt)
564 char *loop_name;
566 loop_name = get_loop_name(loop_num);
567 loop_num++;
568 loop_count++;
570 __push_continues();
571 __push_breaks();
572 __merge_gotos(loop_name);
573 __split_stmt(stmt->iterator_statement);
574 __merge_continues();
575 if (!is_zero(stmt->iterator_post_condition))
576 __save_gotos(loop_name);
578 if (is_forever_loop(stmt)) {
579 __use_breaks();
580 } else {
581 __split_whole_condition(stmt->iterator_post_condition);
582 __use_false_states();
583 __merge_breaks();
585 loop_count--;
588 static int empty_statement(struct statement *stmt)
590 if (!stmt)
591 return 0;
592 if (stmt->type == STMT_EXPRESSION && !stmt->expression)
593 return 1;
594 return 0;
597 static int last_stmt_on_same_line(void)
599 struct statement *stmt;
600 int i = 0;
602 FOR_EACH_PTR_REVERSE(big_statement_stack, stmt) {
603 if (!i++)
604 continue;
605 if (stmt->pos.line == get_lineno())
606 return 1;
607 return 0;
608 } END_FOR_EACH_PTR_REVERSE(stmt);
609 return 0;
612 static void split_asm_constraints(struct expression_list *expr_list)
614 struct expression *expr;
615 int state = 0;
617 FOR_EACH_PTR(expr_list, expr) {
618 switch (state) {
619 case 0: /* identifier */
620 case 1: /* constraint */
621 state++;
622 continue;
623 case 2: /* expression */
624 state = 0;
625 __split_expr(expr);
626 continue;
628 } END_FOR_EACH_PTR(expr);
631 static int is_case_val(struct statement *stmt, sval_t sval)
633 sval_t case_sval;
635 if (stmt->type != STMT_CASE)
636 return 0;
637 if (!stmt->case_expression) {
638 __set_default();
639 return 1;
641 if (!get_value(stmt->case_expression, &case_sval))
642 return 0;
643 if (case_sval.value == sval.value)
644 return 1;
645 return 0;
648 static void split_known_switch(struct statement *stmt, sval_t sval)
650 struct statement *tmp;
652 __split_expr(stmt->switch_expression);
654 push_expression(&switch_expr_stack, stmt->switch_expression);
655 __save_switch_states(top_expression(switch_expr_stack));
656 nullify_path();
657 __push_default();
658 __push_breaks();
660 stmt = stmt->switch_statement;
662 __push_scope_hooks();
663 FOR_EACH_PTR(stmt->stmts, tmp) {
664 __smatch_lineno = tmp->pos.line;
665 if (is_case_val(tmp, sval)) {
666 __merge_switches(top_expression(switch_expr_stack),
667 stmt->case_expression);
668 __pass_case_to_client(top_expression(switch_expr_stack),
669 stmt->case_expression);
671 if (__path_is_null())
672 continue;
673 __split_stmt(tmp);
674 if (__path_is_null()) {
675 __set_default();
676 goto out;
678 } END_FOR_EACH_PTR(tmp);
679 out:
680 __call_scope_hooks();
681 if (!__pop_default())
682 __merge_switches(top_expression(switch_expr_stack),
683 NULL);
684 __discard_switches();
685 __merge_breaks();
686 pop_expression(&switch_expr_stack);
689 static int taking_too_long(void)
691 int ms;
693 ms = ms_since(&fn_start_time);
694 if (ms > 1000 * 60 * 5) /* five minutes */
695 return 1;
696 return 0;
699 static int is_last_stmt(struct statement *cur_stmt)
701 struct symbol *fn = get_base_type(cur_func_sym);
702 struct statement *stmt;
704 if (!fn)
705 return 0;
706 stmt = fn->stmt;
707 if (!stmt)
708 stmt = fn->inline_stmt;
709 if (!stmt || stmt->type != STMT_COMPOUND)
710 return 0;
711 stmt = last_ptr_list((struct ptr_list *)stmt->stmts);
712 if (stmt && stmt->type == STMT_LABEL)
713 stmt = stmt->label_statement;
714 if (stmt == cur_stmt)
715 return 1;
716 return 0;
719 static void handle_backward_goto(struct statement *goto_stmt)
721 const char *goto_name, *label_name;
722 struct statement *func_stmt;
723 struct symbol *base_type = get_base_type(cur_func_sym);
724 struct statement *tmp;
725 int found = 0;
727 if (!option_info)
728 return;
729 if (last_goto_statement_handled)
730 return;
731 last_goto_statement_handled = 1;
733 if (!goto_stmt->goto_label ||
734 goto_stmt->goto_label->type != SYM_LABEL ||
735 !goto_stmt->goto_label->ident)
736 return;
737 goto_name = goto_stmt->goto_label->ident->name;
739 func_stmt = base_type->stmt;
740 if (!func_stmt)
741 func_stmt = base_type->inline_stmt;
742 if (!func_stmt)
743 return;
744 if (func_stmt->type != STMT_COMPOUND)
745 return;
747 FOR_EACH_PTR(func_stmt->stmts, tmp) {
748 if (!found) {
749 if (tmp->type != STMT_LABEL)
750 continue;
751 if (!tmp->label_identifier ||
752 tmp->label_identifier->type != SYM_LABEL ||
753 !tmp->label_identifier->ident)
754 continue;
755 label_name = tmp->label_identifier->ident->name;
756 if (strcmp(goto_name, label_name) != 0)
757 continue;
758 found = 1;
760 __split_stmt(tmp);
761 } END_FOR_EACH_PTR(tmp);
764 static void fake_a_return(void)
766 struct symbol *return_type;
768 nullify_path();
769 __unnullify_path();
771 return_type = get_real_base_type(cur_func_sym);
772 return_type = get_real_base_type(return_type);
773 if (return_type != &void_ctype) {
774 __pass_to_client(unknown_value_expression(NULL), RETURN_HOOK);
775 nullify_path();
778 __pass_to_client(cur_func_sym, END_FUNC_HOOK);
779 __pass_to_client(cur_func_sym, AFTER_FUNC_HOOK);
782 static void split_compound(struct statement *stmt)
784 struct statement *prev = NULL;
785 struct statement *cur = NULL;
786 struct statement *next;
788 __push_scope_hooks();
790 FOR_EACH_PTR(stmt->stmts, next) {
791 if (cur) {
792 __prev_stmt = prev;
793 __next_stmt = next;
794 __cur_stmt = cur;
795 __split_stmt(cur);
797 prev = cur;
798 cur = next;
799 } END_FOR_EACH_PTR(next);
800 if (cur) {
801 __prev_stmt = prev;
802 __cur_stmt = cur;
803 __next_stmt = NULL;
804 __split_stmt(cur);
807 __call_scope_hooks();
810 void __split_stmt(struct statement *stmt)
812 sval_t sval;
814 if (!stmt)
815 goto out;
817 if (__bail_on_rest_of_function || out_of_memory() || taking_too_long()) {
818 static char *printed = NULL;
820 __bail_on_rest_of_function = 1;
821 if (printed != cur_func)
822 sm_msg("Function too hairy. Giving up.");
823 fake_a_return();
824 final_pass = 0; /* turn off sm_msg() from here */
825 printed = cur_func;
826 return;
829 add_ptr_list(&big_statement_stack, stmt);
830 free_expression_stack(&big_expression_stack);
831 set_position(stmt->pos);
832 __pass_to_client(stmt, STMT_HOOK);
834 switch (stmt->type) {
835 case STMT_DECLARATION:
836 split_declaration(stmt->declaration);
837 break;
838 case STMT_RETURN:
839 __split_expr(stmt->ret_value);
840 __pass_to_client(stmt->ret_value, RETURN_HOOK);
841 __process_post_op_stack();
842 nullify_path();
843 break;
844 case STMT_EXPRESSION:
845 __split_expr(stmt->expression);
846 break;
847 case STMT_COMPOUND:
848 split_compound(stmt);
849 break;
850 case STMT_IF:
851 if (known_condition_true(stmt->if_conditional)) {
852 __split_stmt(stmt->if_true);
853 break;
855 if (known_condition_false(stmt->if_conditional)) {
856 __split_stmt(stmt->if_false);
857 break;
859 if (option_known_conditions &&
860 implied_condition_true(stmt->if_conditional)) {
861 sm_info("this condition is true.");
862 __split_stmt(stmt->if_true);
863 break;
865 if (option_known_conditions &&
866 implied_condition_false(stmt->if_conditional)) {
867 sm_info("this condition is false.");
868 __split_stmt(stmt->if_false);
869 break;
871 __split_whole_condition(stmt->if_conditional);
872 __split_stmt(stmt->if_true);
873 if (empty_statement(stmt->if_true) &&
874 last_stmt_on_same_line() &&
875 !get_macro_name(stmt->if_true->pos))
876 sm_msg("warn: if();");
877 __push_true_states();
878 __use_false_states();
879 __split_stmt(stmt->if_false);
880 __merge_true_states();
881 break;
882 case STMT_ITERATOR:
883 if (stmt->iterator_pre_condition)
884 handle_pre_loop(stmt);
885 else if (stmt->iterator_post_condition)
886 handle_post_loop(stmt);
887 else {
888 // these are for(;;) type loops.
889 handle_pre_loop(stmt);
891 break;
892 case STMT_SWITCH:
893 if (get_value(stmt->switch_expression, &sval)) {
894 split_known_switch(stmt, sval);
895 break;
897 __split_expr(stmt->switch_expression);
898 push_expression(&switch_expr_stack, stmt->switch_expression);
899 __save_switch_states(top_expression(switch_expr_stack));
900 nullify_path();
901 __push_default();
902 __push_breaks();
903 __split_stmt(stmt->switch_statement);
904 if (!__pop_default())
905 __merge_switches(top_expression(switch_expr_stack),
906 NULL);
907 __discard_switches();
908 __merge_breaks();
909 pop_expression(&switch_expr_stack);
910 break;
911 case STMT_CASE:
912 __merge_switches(top_expression(switch_expr_stack),
913 stmt->case_expression);
914 __pass_case_to_client(top_expression(switch_expr_stack),
915 stmt->case_expression);
916 if (!stmt->case_expression)
917 __set_default();
918 __split_expr(stmt->case_expression);
919 __split_expr(stmt->case_to);
920 __split_stmt(stmt->case_statement);
921 break;
922 case STMT_LABEL:
923 if (stmt->label_identifier &&
924 stmt->label_identifier->type == SYM_LABEL &&
925 stmt->label_identifier->ident) {
926 loop_count |= 0x80000000;
927 __merge_gotos(stmt->label_identifier->ident->name);
929 __split_stmt(stmt->label_statement);
930 break;
931 case STMT_GOTO:
932 __split_expr(stmt->goto_expression);
933 if (stmt->goto_label && stmt->goto_label->type == SYM_NODE) {
934 if (!strcmp(stmt->goto_label->ident->name, "break")) {
935 __process_breaks();
936 } else if (!strcmp(stmt->goto_label->ident->name,
937 "continue")) {
938 __process_continues();
940 } else if (stmt->goto_label &&
941 stmt->goto_label->type == SYM_LABEL &&
942 stmt->goto_label->ident) {
943 __save_gotos(stmt->goto_label->ident->name);
945 nullify_path();
946 if (is_last_stmt(stmt))
947 handle_backward_goto(stmt);
948 break;
949 case STMT_NONE:
950 break;
951 case STMT_ASM:
952 __pass_to_client(stmt, ASM_HOOK);
953 __split_expr(stmt->asm_string);
954 split_asm_constraints(stmt->asm_outputs);
955 split_asm_constraints(stmt->asm_inputs);
956 split_asm_constraints(stmt->asm_clobbers);
957 break;
958 case STMT_CONTEXT:
959 break;
960 case STMT_RANGE:
961 __split_expr(stmt->range_expression);
962 __split_expr(stmt->range_low);
963 __split_expr(stmt->range_high);
964 break;
966 __pass_to_client(stmt, STMT_HOOK_AFTER);
967 out:
968 __process_post_op_stack();
971 static void split_expr_list(struct expression_list *expr_list, struct expression *parent)
973 struct expression *expr;
975 FOR_EACH_PTR(expr_list, expr) {
976 set_parent(expr, parent);
977 __split_expr(expr);
978 __process_post_op_stack();
979 } END_FOR_EACH_PTR(expr);
982 static void split_sym(struct symbol *sym)
984 if (!sym)
985 return;
986 if (!(sym->namespace & NS_SYMBOL))
987 return;
989 __split_stmt(sym->stmt);
990 __split_expr(sym->array_size);
991 split_symlist(sym->arguments);
992 split_symlist(sym->symbol_list);
993 __split_stmt(sym->inline_stmt);
994 split_symlist(sym->inline_symbol_list);
997 static void split_symlist(struct symbol_list *sym_list)
999 struct symbol *sym;
1001 FOR_EACH_PTR(sym_list, sym) {
1002 split_sym(sym);
1003 } END_FOR_EACH_PTR(sym);
1006 typedef void (fake_cb)(struct expression *expr);
1008 static int member_to_number(struct expression *expr, struct ident *member)
1010 struct symbol *type, *tmp;
1011 char *name;
1012 int i;
1014 if (!member)
1015 return -1;
1016 name = member->name;
1018 type = get_type(expr);
1019 if (!type || type->type != SYM_STRUCT)
1020 return -1;
1022 i = -1;
1023 FOR_EACH_PTR(type->symbol_list, tmp) {
1024 i++;
1025 if (!tmp->ident)
1026 continue;
1027 if (strcmp(name, tmp->ident->name) == 0)
1028 return i;
1029 } END_FOR_EACH_PTR(tmp);
1030 return -1;
1033 static struct ident *number_to_member(struct expression *expr, int num)
1035 struct symbol *type, *member;
1036 int i = 0;
1038 type = get_type(expr);
1039 if (!type || type->type != SYM_STRUCT)
1040 return NULL;
1042 FOR_EACH_PTR(type->symbol_list, member) {
1043 if (i == num)
1044 return member->ident;
1045 i++;
1046 } END_FOR_EACH_PTR(member);
1047 return NULL;
1050 static void fake_element_assigns_helper(struct expression *array, struct expression_list *expr_list, fake_cb *fake_cb);
1052 struct member_set {
1053 struct ident *ident;
1054 int set;
1057 static struct member_set *alloc_member_set(struct symbol *type)
1059 struct member_set *member_set;
1060 struct symbol *member;
1061 int member_count;
1062 int member_idx;
1064 member_count = ptr_list_size((struct ptr_list *)type->symbol_list);
1065 member_set = malloc(member_count * sizeof(*member_set));
1066 member_idx = 0;
1067 FOR_EACH_PTR(type->symbol_list, member) {
1068 member_set[member_idx].ident = member->ident;
1069 member_set[member_idx].set = 0;
1070 member_idx++;
1071 } END_FOR_EACH_PTR(member);
1073 return member_set;
1076 static void mark_member_as_set(struct symbol *type, struct member_set *member_set, struct ident *ident)
1078 int member_count = ptr_list_size((struct ptr_list *)type->symbol_list);
1079 int i;
1081 for (i = 0; i < member_count; i++) {
1082 if (member_set[i].ident == ident) {
1083 member_set[i].set = 1;
1084 return;
1087 // crap. this is buggy.
1088 // sm_msg("internal smatch error in initializer %s.%s", type->ident->name, ident->name);
1091 static void set_inner_struct_members(struct expression *expr, struct symbol *member)
1093 struct expression *edge_member, *assign;
1094 struct symbol *base = get_real_base_type(member);
1095 struct symbol *tmp;
1097 if (member->ident)
1098 expr = member_expression(expr, '.', member->ident);
1100 FOR_EACH_PTR(base->symbol_list, tmp) {
1101 struct symbol *type;
1103 type = get_real_base_type(tmp);
1104 if (!type)
1105 continue;
1107 if (tmp->ident) {
1108 edge_member = member_expression(expr, '.', tmp->ident);
1109 if (get_state_expr(SMATCH_EXTRA, edge_member))
1110 continue;
1113 if (type->type == SYM_UNION || type->type == SYM_STRUCT) {
1114 set_inner_struct_members(expr, tmp);
1115 continue;
1118 if (!tmp->ident)
1119 continue;
1121 assign = assign_expression(edge_member, zero_expr());
1122 __split_expr(assign);
1123 } END_FOR_EACH_PTR(tmp);
1128 static void set_unset_to_zero(struct symbol *type, struct expression *expr)
1130 struct symbol *tmp;
1131 struct expression *member, *assign;
1132 int op = '*';
1134 if (expr->type == EXPR_PREOP && expr->op == '&') {
1135 expr = strip_expr(expr->unop);
1136 op = '.';
1139 FOR_EACH_PTR(type->symbol_list, tmp) {
1140 type = get_real_base_type(tmp);
1141 if (!type)
1142 continue;
1144 if (tmp->ident) {
1145 member = member_expression(expr, op, tmp->ident);
1146 if (get_state_expr(SMATCH_EXTRA, member))
1147 continue;
1150 if (type->type == SYM_UNION || type->type == SYM_STRUCT) {
1151 set_inner_struct_members(expr, tmp);
1152 continue;
1154 if (type->type == SYM_ARRAY)
1155 continue;
1156 if (!tmp->ident)
1157 continue;
1159 assign = assign_expression(member, zero_expr());
1160 __split_expr(assign);
1161 } END_FOR_EACH_PTR(tmp);
1164 static void fake_member_assigns_helper(struct expression *symbol, struct expression_list *members, fake_cb *fake_cb)
1166 struct expression *deref, *assign, *tmp;
1167 struct symbol *struct_type, *type;
1168 struct ident *member;
1169 int member_idx;
1170 struct member_set *member_set;
1172 struct_type = get_type(symbol);
1173 if (!struct_type ||
1174 (struct_type->type != SYM_STRUCT && struct_type->type != SYM_UNION))
1175 return;
1177 member_set = alloc_member_set(struct_type);
1179 member_idx = 0;
1180 FOR_EACH_PTR(members, tmp) {
1181 member = number_to_member(symbol, member_idx);
1182 while (tmp->type == EXPR_IDENTIFIER) {
1183 member = tmp->expr_ident;
1184 member_idx = member_to_number(symbol, member);
1185 tmp = tmp->ident_expression;
1187 mark_member_as_set(struct_type, member_set, member);
1188 member_idx++;
1189 deref = member_expression(symbol, '.', member);
1190 if (tmp->type == EXPR_INITIALIZER) {
1191 type = get_type(deref);
1192 if (type && type->type == SYM_ARRAY)
1193 fake_element_assigns_helper(deref, tmp->expr_list, fake_cb);
1194 else
1195 fake_member_assigns_helper(deref, tmp->expr_list, fake_cb);
1196 } else {
1197 assign = assign_expression(deref, tmp);
1198 fake_cb(assign);
1200 } END_FOR_EACH_PTR(tmp);
1202 set_unset_to_zero(struct_type, symbol);
1205 static void fake_member_assigns(struct symbol *sym, fake_cb *fake_cb)
1207 fake_member_assigns_helper(symbol_expression(sym),
1208 sym->initializer->expr_list, fake_cb);
1211 static void fake_element_assigns_helper(struct expression *array, struct expression_list *expr_list, fake_cb *fake_cb)
1213 struct expression *offset, *binop, *assign, *tmp;
1214 struct symbol *type;
1215 int idx;
1217 idx = 0;
1218 FOR_EACH_PTR(expr_list, tmp) {
1219 if (tmp->type == EXPR_INDEX) {
1220 if (tmp->idx_from != tmp->idx_to)
1221 return;
1222 idx = tmp->idx_from;
1223 if (!tmp->idx_expression)
1224 goto next;
1225 tmp = tmp->idx_expression;
1227 offset = value_expr(idx);
1228 binop = array_element_expression(array, offset);
1229 if (tmp->type == EXPR_INITIALIZER) {
1230 type = get_type(binop);
1231 if (type && type->type == SYM_ARRAY)
1232 fake_element_assigns_helper(binop, tmp->expr_list, fake_cb);
1233 else
1234 fake_member_assigns_helper(binop, tmp->expr_list, fake_cb);
1235 } else {
1236 assign = assign_expression(binop, tmp);
1237 fake_cb(assign);
1239 next:
1240 idx++;
1241 } END_FOR_EACH_PTR(tmp);
1244 static void fake_element_assigns(struct symbol *sym, fake_cb *fake_cb)
1246 fake_element_assigns_helper(symbol_expression(sym), sym->initializer->expr_list, fake_cb);
1249 static void fake_assign_expr(struct symbol *sym)
1251 struct expression *assign, *symbol;
1253 symbol = symbol_expression(sym);
1254 assign = assign_expression(symbol, sym->initializer);
1255 __split_expr(assign);
1258 static void call_split_expr(struct expression *expr)
1260 __split_expr(expr);
1263 static void do_initializer_stuff(struct symbol *sym)
1265 if (!sym->initializer)
1266 return;
1268 if (sym->initializer->type == EXPR_INITIALIZER) {
1269 if (get_real_base_type(sym)->type == SYM_ARRAY)
1270 fake_element_assigns(sym, call_split_expr);
1271 else
1272 fake_member_assigns(sym, call_split_expr);
1273 } else {
1274 fake_assign_expr(sym);
1278 static void split_declaration(struct symbol_list *sym_list)
1280 struct symbol *sym;
1282 FOR_EACH_PTR(sym_list, sym) {
1283 __pass_to_client(sym, DECLARATION_HOOK);
1284 do_initializer_stuff(sym);
1285 split_sym(sym);
1286 } END_FOR_EACH_PTR(sym);
1289 static void call_global_assign_hooks(struct expression *assign)
1291 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1294 static void fake_global_assign(struct symbol *sym)
1296 struct expression *assign, *symbol;
1298 if (get_real_base_type(sym)->type == SYM_ARRAY) {
1299 if (sym->initializer && sym->initializer->type == EXPR_INITIALIZER) {
1300 fake_element_assigns(sym, call_global_assign_hooks);
1301 } else if (sym->initializer) {
1302 symbol = symbol_expression(sym);
1303 assign = assign_expression(symbol, sym->initializer);
1304 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1305 } else {
1306 fake_element_assigns_helper(symbol_expression(sym), NULL, call_global_assign_hooks);
1308 } else if (get_real_base_type(sym)->type == SYM_STRUCT) {
1309 if (sym->initializer && sym->initializer->type == EXPR_INITIALIZER) {
1310 fake_member_assigns(sym, call_global_assign_hooks);
1311 } else if (sym->initializer) {
1312 symbol = symbol_expression(sym);
1313 assign = assign_expression(symbol, sym->initializer);
1314 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1315 } else {
1316 fake_member_assigns_helper(symbol_expression(sym), NULL, call_global_assign_hooks);
1318 } else {
1319 symbol = symbol_expression(sym);
1320 if (sym->initializer)
1321 assign = assign_expression(symbol, sym->initializer);
1322 else
1323 assign = assign_expression(symbol, zero_expr());
1324 __pass_to_client(assign, GLOBAL_ASSIGNMENT_HOOK);
1328 static void start_function_definition(struct symbol *sym)
1330 __in_function_def = 1;
1331 __pass_to_client(sym, FUNC_DEF_HOOK);
1332 __in_function_def = 0;
1333 __pass_to_client(sym, AFTER_DEF_HOOK);
1337 static void split_function(struct symbol *sym)
1339 struct symbol *base_type = get_base_type(sym);
1341 if (!base_type->stmt && !base_type->inline_stmt)
1342 return;
1344 gettimeofday(&fn_start_time, NULL);
1345 cur_func_sym = sym;
1346 if (sym->ident)
1347 cur_func = sym->ident->name;
1348 __smatch_lineno = sym->pos.line;
1349 loop_count = 0;
1350 last_goto_statement_handled = 0;
1351 sm_debug("new function: %s\n", cur_func);
1352 __stree_id = 0;
1353 if (option_two_passes) {
1354 __unnullify_path();
1355 loop_num = 0;
1356 final_pass = 0;
1357 start_function_definition(sym);
1358 __split_stmt(base_type->stmt);
1359 __split_stmt(base_type->inline_stmt);
1360 nullify_path();
1362 __unnullify_path();
1363 loop_num = 0;
1364 final_pass = 1;
1365 start_function_definition(sym);
1366 __split_stmt(base_type->stmt);
1367 __split_stmt(base_type->inline_stmt);
1368 __pass_to_client(sym, END_FUNC_HOOK);
1369 __pass_to_client(sym, AFTER_FUNC_HOOK);
1371 clear_all_states();
1372 cur_func_sym = NULL;
1373 cur_func = NULL;
1374 free_data_info_allocs();
1375 free_expression_stack(&switch_expr_stack);
1376 __free_ptr_list((struct ptr_list **)&big_statement_stack);
1377 __bail_on_rest_of_function = 0;
1380 static void parse_inline(struct expression *call)
1382 struct symbol *base_type;
1383 int loop_num_bak = loop_num;
1384 int final_pass_bak = final_pass;
1385 char *cur_func_bak = cur_func;
1386 struct statement_list *big_statement_stack_bak = big_statement_stack;
1387 struct expression_list *big_expression_stack_bak = big_expression_stack;
1388 struct expression_list *switch_expr_stack_bak = switch_expr_stack;
1389 struct symbol *cur_func_sym_bak = cur_func_sym;
1391 __pass_to_client(call, INLINE_FN_START);
1392 final_pass = 0; /* don't print anything */
1393 __inline_fn = call;
1395 base_type = get_base_type(call->fn->symbol);
1396 cur_func_sym = call->fn->symbol;
1397 if (call->fn->symbol->ident)
1398 cur_func = call->fn->symbol->ident->name;
1399 else
1400 cur_func = NULL;
1401 set_position(call->fn->symbol->pos);
1403 save_all_states();
1404 big_statement_stack = NULL;
1405 big_expression_stack = NULL;
1406 switch_expr_stack = NULL;
1408 sm_debug("inline function: %s\n", cur_func);
1409 __unnullify_path();
1410 loop_num = 0;
1411 start_function_definition(call->fn->symbol);
1412 __split_stmt(base_type->stmt);
1413 __split_stmt(base_type->inline_stmt);
1414 __pass_to_client(call->fn->symbol, END_FUNC_HOOK);
1415 __pass_to_client(call->fn->symbol, AFTER_FUNC_HOOK);
1417 free_expression_stack(&switch_expr_stack);
1418 __free_ptr_list((struct ptr_list **)&big_statement_stack);
1419 nullify_path();
1420 free_goto_stack();
1422 loop_num = loop_num_bak;
1423 final_pass = final_pass_bak;
1424 cur_func_sym = cur_func_sym_bak;
1425 cur_func = cur_func_bak;
1426 big_statement_stack = big_statement_stack_bak;
1427 big_expression_stack = big_expression_stack_bak;
1428 switch_expr_stack = switch_expr_stack_bak;
1430 restore_all_states();
1431 set_position(call->pos);
1432 __inline_fn = NULL;
1433 __pass_to_client(call, INLINE_FN_END);
1436 static struct symbol_list *inlines_called;
1437 static void add_inline_function(struct symbol *sym)
1439 static struct symbol_list *already_added;
1440 struct symbol *tmp;
1442 FOR_EACH_PTR(already_added, tmp) {
1443 if (tmp == sym)
1444 return;
1445 } END_FOR_EACH_PTR(tmp);
1447 add_ptr_list(&already_added, sym);
1448 add_ptr_list(&inlines_called, sym);
1451 static void process_inlines(void)
1453 struct symbol *tmp;
1455 FOR_EACH_PTR(inlines_called, tmp) {
1456 split_function(tmp);
1457 } END_FOR_EACH_PTR(tmp);
1458 free_ptr_list(&inlines_called);
1461 static struct symbol *get_last_scoped_symbol(struct symbol_list *big_list, int use_static)
1463 struct symbol *sym;
1465 FOR_EACH_PTR_REVERSE(big_list, sym) {
1466 if (!sym->scope)
1467 continue;
1468 if (use_static && sym->ctype.modifiers & MOD_STATIC)
1469 return sym;
1470 if (!use_static && !(sym->ctype.modifiers & MOD_STATIC))
1471 return sym;
1472 } END_FOR_EACH_PTR_REVERSE(sym);
1474 return NULL;
1477 static void split_inlines_in_scope(struct symbol *sym)
1479 struct symbol *base;
1480 struct symbol_list *scope_list;
1481 int stream;
1483 scope_list = sym->scope->symbols;
1484 stream = sym->pos.stream;
1486 /* find the last static symbol in the file */
1487 FOR_EACH_PTR_REVERSE(scope_list, sym) {
1488 if (sym->pos.stream != stream)
1489 continue;
1490 if (sym->type != SYM_NODE)
1491 continue;
1492 base = get_base_type(sym);
1493 if (!base)
1494 continue;
1495 if (base->type != SYM_FN)
1496 continue;
1497 if (!base->inline_stmt)
1498 continue;
1499 add_inline_function(sym);
1500 } END_FOR_EACH_PTR_REVERSE(sym);
1502 process_inlines();
1505 static void split_inlines(struct symbol_list *sym_list)
1507 struct symbol *sym;
1509 sym = get_last_scoped_symbol(sym_list, 0);
1510 if (sym)
1511 split_inlines_in_scope(sym);
1512 sym = get_last_scoped_symbol(sym_list, 1);
1513 if (sym)
1514 split_inlines_in_scope(sym);
1517 static struct stree *clone_estates_perm(struct stree *orig)
1519 struct stree *ret = NULL;
1520 struct sm_state *tmp;
1522 FOR_EACH_SM(orig, tmp) {
1523 set_state_stree_perm(&ret, tmp->owner, tmp->name, tmp->sym, clone_estate_perm(tmp->state));
1524 } END_FOR_EACH_SM(tmp);
1526 return ret;
1529 static void split_functions(struct symbol_list *sym_list)
1531 struct symbol *sym;
1533 __unnullify_path();
1534 FOR_EACH_PTR(sym_list, sym) {
1535 set_position(sym->pos);
1536 if (sym->type != SYM_NODE || get_base_type(sym)->type != SYM_FN) {
1537 __pass_to_client(sym, BASE_HOOK);
1538 fake_global_assign(sym);
1540 } END_FOR_EACH_PTR(sym);
1541 global_states = clone_estates_perm(get_all_states_stree(SMATCH_EXTRA));
1542 nullify_path();
1544 FOR_EACH_PTR(sym_list, sym) {
1545 set_position(sym->pos);
1546 if (sym->type == SYM_NODE && get_base_type(sym)->type == SYM_FN) {
1547 split_function(sym);
1548 process_inlines();
1550 } END_FOR_EACH_PTR(sym);
1551 split_inlines(sym_list);
1552 __pass_to_client(sym_list, END_FILE_HOOK);
1555 void smatch(int argc, char **argv)
1558 struct string_list *filelist = NULL;
1559 struct symbol_list *sym_list;
1561 if (argc < 2) {
1562 printf("Usage: smatch [--debug] <filename.c>\n");
1563 exit(1);
1565 sparse_initialize(argc, argv, &filelist);
1566 set_valid_ptr_max();
1567 FOR_EACH_PTR_NOTAG(filelist, base_file) {
1568 if (option_file_output) {
1569 char buf[256];
1571 snprintf(buf, sizeof(buf), "%s.smatch", base_file);
1572 sm_outfd = fopen(buf, "w");
1573 if (!sm_outfd) {
1574 printf("Error: Cannot open %s\n", base_file);
1575 exit(1);
1578 sym_list = sparse_keep_tokens(base_file);
1579 split_functions(sym_list);
1580 } END_FOR_EACH_PTR_NOTAG(base_file);