db/fixup_kernel.sh: fix clear_user() handling
[smatch.git] / check_or_vs_and.c
blobc06015d888e56a53ee10c698176d6f6e360b906f
1 /*
2 * Copyright (C) 2012 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 #include "smatch.h"
19 #include "smatch_function_hashtable.h"
21 static int my_id;
23 static int does_inc_dec(struct expression *expr)
25 if (expr->type == EXPR_PREOP || expr->type == EXPR_POSTOP) {
26 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
27 return 1;
28 return does_inc_dec(expr->unop);
30 return 0;
33 static int expr_equiv_no_inc_dec(struct expression *one, struct expression *two)
35 sval_t dummy;
37 if (does_inc_dec(one) || does_inc_dec(two))
38 return 0;
39 if (get_value(one, &dummy) &&
40 get_value(two, &dummy))
41 return 0;
43 return expr_equiv(one, two);
46 static int inconsistent_check(struct expression *left, struct expression *right)
48 sval_t sval;
50 if (get_value(left->left, &sval)) {
51 if (get_value(right->left, &sval))
52 return expr_equiv_no_inc_dec(left->right, right->right);
53 if (get_value(right->right, &sval))
54 return expr_equiv_no_inc_dec(left->right, right->left);
55 return 0;
57 if (get_value(left->right, &sval)) {
58 if (get_value(right->left, &sval))
59 return expr_equiv_no_inc_dec(left->left, right->right);
60 if (get_value(right->right, &sval))
61 return expr_equiv_no_inc_dec(left->left, right->left);
62 return 0;
65 return 0;
68 static void check_or(struct expression *expr)
70 struct expression *left, *right;
72 left = strip_expr(expr->left);
73 right = strip_expr(expr->right);
75 if (left->type != EXPR_COMPARE || left->op != SPECIAL_NOTEQUAL)
76 return;
77 if (right->type != EXPR_COMPARE || right->op != SPECIAL_NOTEQUAL)
78 return;
79 if (!inconsistent_check(left, right))
80 return;
82 sm_warning("was && intended here instead of ||?");
85 static int is_kernel_min_macro(struct expression *expr)
87 char *macro;
89 if (option_project != PROJ_KERNEL)
90 return 0;
91 macro = get_macro_name(expr->pos);
92 if (!macro)
93 return 0;
94 if (strcmp(macro, "min") == 0 ||
95 strcmp(macro, "min_t") == 0 ||
96 strcmp(macro, "max") == 0 ||
97 strcmp(macro, "max_t") == 0)
98 return 1;
99 return 0;
102 static void check_and(struct expression *expr)
104 struct expression *left, *right;
106 if (is_kernel_min_macro(expr))
107 return;
109 left = strip_expr(expr->left);
110 right = strip_expr(expr->right);
112 if (left->type != EXPR_COMPARE || left->op != SPECIAL_EQUAL)
113 return;
114 if (right->type != EXPR_COMPARE || right->op != SPECIAL_EQUAL)
115 return;
116 if (!inconsistent_check(left, right))
117 return;
119 sm_warning("was || intended here instead of &&?");
122 static void match_logic(struct expression *expr)
124 if (expr->type != EXPR_LOGICAL)
125 return;
127 if (expr->op == SPECIAL_LOGICAL_OR)
128 check_or(expr);
129 if (expr->op == SPECIAL_LOGICAL_AND)
130 check_and(expr);
133 static void match_condition(struct expression *expr)
135 sval_t sval;
137 if (expr->type != EXPR_BINOP)
138 return;
139 if (expr->op == '|') {
140 if (get_value(expr->left, &sval) || get_value(expr->right, &sval))
141 sm_warning("suspicious bitop condition");
142 return;
145 if (expr->op != '&')
146 return;
148 if (get_macro_name(expr->pos))
149 return;
150 if (is_unconstant_macro(expr->left) || is_unconstant_macro(expr->right))
151 return;
153 if ((get_value(expr->left, &sval) && sval.value == 0) ||
154 (get_value(expr->right, &sval) && sval.value == 0))
155 sm_warning("bitwise AND condition is false here");
158 static void match_binop(struct expression *expr)
160 sval_t left, right, sval;
162 if (expr->op != '&')
163 return;
164 if (!get_value(expr, &sval) || sval.value != 0)
165 return;
166 if (get_macro_name(expr->pos))
167 return;
168 if (!get_value(expr->left, &left) || !get_value(expr->right, &right))
169 return;
170 sm_warning("odd binop '0x%llx & 0x%llx'", left.uvalue, right.uvalue);
173 void check_or_vs_and(int id)
175 my_id = id;
177 add_hook(&match_logic, LOGIC_HOOK);
178 add_hook(&match_condition, CONDITION_HOOK);
179 if (option_spammy)
180 add_hook(&match_binop, BINOP_HOOK);