smdb: don't use "like" where it isnt necessary
[smatch.git] / check_double_checking.c
blobaf08d888c2d37caf9eeab6f1aad3bba864f05b71
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 char *name;
119 if (__in_fake_parameter_assign)
120 return;
122 if (get_macro_name(expr->pos))
123 return;
125 if (is_loop_condition(expr))
126 return;
128 if (is_part_of_logical(expr))
129 return;
131 if (last_in_chain_of_else_if_statements(expr))
132 return;
134 if (is_global(expr))
135 return;
137 if (is_dereference(expr))
138 return;
140 state = get_stored_condition(expr);
141 if (!state || !state->data)
142 return;
143 old_condition = state->data;
144 if (get_macro_name(old_condition->pos))
145 return;
147 if (inside_loop() && !in_same_block(old_condition, expr))
148 return;
150 name = expr_to_str(expr);
151 sm_warning("duplicate check '%s' (previous on line %d)", name, old_condition->pos.line);
152 free_string(name);
155 void check_double_checking(int id)
157 my_id = id;
159 if (!option_spammy)
160 return;
162 add_hook(&match_condition, CONDITION_HOOK);