2 * Copyright (C) 2014 Oracle.
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
19 #include "smatch_slist.h"
26 struct state_list
*to_check
;
28 static void set_modified(struct sm_state
*sm
, struct expression
*mod_expr
)
30 set_state(my_id
, sm
->name
, sm
->sym
, &modified
);
33 static void match_condition(struct expression
*expr
)
35 struct smatch_state
*state
;
40 if (get_value(expr
, &dummy
))
43 if (get_macro_name(expr
->pos
))
47 if (implied_condition_true(expr
))
49 else if (implied_condition_false(expr
))
54 state
= get_stored_condition(expr
);
55 if (!state
|| !state
->data
)
57 if (get_macro_name(((struct expression
*)state
->data
)->pos
))
61 * we allow double checking for NULL because people do this all the time
62 * and trying to stop them is a losers' battle.
64 if (is_pointer(expr
) && is_true
)
67 if (definitely_inside_loop()) {
73 name
= expr_to_var_sym(expr
, &sym
);
76 set_state_expr(my_id
, expr
, &checked
);
77 set_state_slist(&to_check
, my_id
, name
, sym
, &checked
);
82 name
= expr_to_str(expr
);
83 sm_msg("warn: we tested '%s' before and it was '%s'", name
, state
->name
);
87 int get_check_line(struct sm_state
*sm
)
91 FOR_EACH_PTR(sm
->possible
, tmp
) {
92 if (tmp
->state
== &checked
)
94 } END_FOR_EACH_PTR(tmp
);
99 static void after_loop(struct statement
*stmt
)
101 struct sm_state
*check
, *sm
;
103 if (!stmt
|| stmt
->type
!= STMT_ITERATOR
)
105 if (definitely_inside_loop())
110 FOR_EACH_PTR(to_check
, check
) {
112 sm
= get_sm_state(my_id
, check
->name
, check
->sym
);
116 if (slist_has_state(sm
->possible
, &modified
))
119 sm_printf("%s:%d %s() ", get_filename(), get_check_line(sm
), get_function());
120 sm_printf("warn: we tested '%s' already\n", check
->name
);
121 } END_FOR_EACH_PTR(check
);
123 free_slist(&to_check
);
126 static void match_func_end(struct symbol
*sym
)
131 sm_msg("debug: odd... found an function without an end.");
132 free_slist(&to_check
);
135 void check_double_checking(int id
)
142 add_hook(&match_condition
, CONDITION_HOOK
);
143 add_modification_hook(my_id
, &set_modified
);
144 add_hook(after_loop
, STMT_HOOK_AFTER
);
145 add_hook(&match_func_end
, END_FUNC_HOOK
);