kernel.return_fixes: add mipi_dsi_device_transfer(), timer_delete() and get_device()
[smatch.git] / check_double_checking.c
blobb58a973bcafdb8aec5ba8aa69b4dcad09557cbbb
1 /*
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
18 #define _GNU_SOURCE
19 #include <string.h>
20 #include "smatch.h"
21 #include "smatch_extra.h"
23 static int my_id;
25 static bool in_same_block(struct expression *one, struct expression *two)
27 struct statement *a, *b;
29 a = get_parent_stmt(one);
30 b = get_parent_stmt(two);
31 if (!a || !b)
32 return false;
33 return a->parent == b->parent;
36 static bool is_loop_condition(struct expression *expr)
38 struct statement *stmt;
41 * Two things. First of all get_stored_condition() is buggy.
42 * Secondly, even if it were not buggy there would be an
43 * issue checking the pre condition before the loop runs.
45 stmt = get_parent_stmt(expr);
46 if (stmt && stmt->type == STMT_ITERATOR)
47 return true;
48 return false;
51 static bool is_part_of_logical(struct expression *expr)
53 while ((expr = expr_get_parent_expr(expr))) {
54 if (expr->type == EXPR_PREOP) {
55 if (expr->op == '!' ||
56 expr->op == '(')
57 continue;
59 if (expr->type == EXPR_COMPARE)
60 continue;
61 if (expr->type == EXPR_LOGICAL)
62 return true;
63 return false;
65 return false;
68 static bool last_in_chain_of_else_if_statements(struct expression *expr)
70 struct statement *stmt;
72 stmt = get_parent_stmt(expr);
73 if (!stmt)
74 return false;
75 if (stmt->type != STMT_IF)
76 return false;
77 if (stmt->if_false)
78 return false;
79 stmt = stmt_get_parent_stmt(stmt);
80 if (!stmt)
81 return false;
82 if (stmt->type != STMT_IF)
83 return false;
84 return true;
87 static bool is_global(struct expression *expr)
89 struct symbol *sym;
91 sym = expr_to_sym(expr);
92 if (!sym)
93 return false;
94 return !!(sym->ctype.modifiers & MOD_TOPLEVEL);
97 static bool is_dereference(struct expression *expr)
99 expr = strip_expr(expr);
101 if (expr->type == EXPR_COMPARE ||
102 expr->type == EXPR_BINOP) {
103 if (is_dereference(expr->left) ||
104 is_dereference(expr->right))
105 return true;
106 return false;
108 if (expr->type != EXPR_DEREF)
109 return false;
110 return true;
113 static void match_condition(struct expression *expr)
115 struct expression *old_condition;
116 struct smatch_state *state;
117 struct symbol *sym;
118 char *name;
120 if (__in_fake_parameter_assign)
121 return;
123 if (get_macro_name(expr->pos))
124 return;
126 if (is_loop_condition(expr))
127 return;
129 if (is_part_of_logical(expr))
130 return;
132 if (last_in_chain_of_else_if_statements(expr))
133 return;
135 if (is_global(expr))
136 return;
138 if (is_dereference(expr))
139 return;
141 state = get_stored_condition(expr);
142 if (!state || !state->data)
143 return;
144 old_condition = state->data;
145 if (get_macro_name(old_condition->pos))
146 return;
148 if (inside_loop() && !in_same_block(old_condition, expr))
149 return;
151 name = expr_to_str_sym(expr, &sym);
152 state = get_state(my_id, name, sym);
153 if (state != &true_state && state != &false_state)
154 goto free;
156 sm_warning("duplicate check '%s' (previous on line %d)", name, old_condition->pos.line);
157 free:
158 free_string(name);
161 static bool has_array(struct expression *expr)
163 if (!expr)
164 return false;
166 if (is_array(expr))
167 return true;
168 if (expr->type == EXPR_COMPARE)
169 return is_array(expr->left);
170 return false;
173 static void match_condition_store(struct expression *expr)
175 struct symbol *sym;
176 sval_t dummy;
177 char *name;
179 if (get_value(expr, &dummy))
180 return;
182 if (has_array(expr))
183 return;
185 name = expr_to_str_sym(expr, &sym);
186 if (!name)
187 return;
189 if (sym && sym->ctype.modifiers & MOD_TOPLEVEL)
190 goto free;
192 set_true_false_states(my_id, name, sym, &true_state, &false_state);
193 free:
194 free_string(name);
197 void check_double_checking(int id)
199 my_id = id;
201 if (!option_spammy)
202 return;
204 turn_off_implications(my_id);
206 add_hook(&match_condition, CONDITION_HOOK);
207 add_hook(&match_condition_store, CONDITION_HOOK);