kernel.return_fixes: add mipi_dsi_device_transfer(), timer_delete() and get_device()
[smatch.git] / check_logical_instead_of_bitwise.c
blob64a194c54323c502110a4a1e615a3d9f96badea2
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_extra.h"
21 static int my_id;
23 static int is_bitshift(struct expression *expr)
25 expr = strip_expr(expr);
27 if (expr->type != EXPR_BINOP)
28 return 0;
29 if (expr->op == SPECIAL_LEFTSHIFT)
30 return 1;
31 return 0;
34 static int warn_if_both_known_values(struct expression *expr)
36 sval_t left, right;
38 if (get_macro_name(expr->pos))
39 return 0;
41 if (!get_value(expr->right, &left) ||
42 !get_value(expr->left, &right))
43 return 0;
45 if ((left.value == 0 || left.value == 1) &&
46 (right.value == 0 || right.value == 1))
47 return 0;
49 sm_warning("should this be a bitwise op?");
50 return 1;
53 static int check_is_mask(struct expression *expr)
55 expr = strip_expr(expr);
57 if (expr->type != EXPR_BINOP)
58 return 0;
59 if (expr->op != SPECIAL_LEFTSHIFT &&
60 expr->op != SPECIAL_RIGHTSHIFT &&
61 expr->op != '|')
62 return 0;
63 if (implied_not_equal(expr, 0))
64 return 1;
65 return 0;
68 static void match_logic(struct expression *expr)
70 struct range_list *rl;
72 if (expr->type != EXPR_LOGICAL)
73 return;
75 if (warn_if_both_known_values(expr))
76 return;
78 if (!check_is_mask(expr->right))
79 return;
81 /* check for logic, by looking for bool */
82 get_absolute_rl(expr->left, &rl);
83 if (rl_min(rl).value >= 0 && rl_max(rl).value <= 1)
84 return;
86 sm_warning("should this be a bitwise op?");
89 static void match_assign(struct expression *expr)
91 struct expression *right;
93 right = strip_expr(expr->right);
94 if (right->type != EXPR_LOGICAL)
95 return;
96 if (is_bitshift(right->left) || is_bitshift(right->right))
97 sm_warning("should this be a bitwise op?");
100 static int is_bool(struct expression *expr)
102 struct range_list *rl;
104 get_absolute_rl(expr, &rl);
106 if (rl_min(rl).value != 0 && rl_min(rl).value != 1)
107 return 0;
108 if (rl_max(rl).value != 0 && rl_max(rl).value != 1)
109 return 0;
111 return 1;
114 static void match_assign_mask(struct expression *expr)
116 struct expression *right;
118 if (!option_spammy)
119 return;
121 if (expr->op != SPECIAL_AND_ASSIGN &&
122 expr->op != SPECIAL_OR_ASSIGN)
123 return;
125 if (is_bool(expr->left))
126 return;
128 right = strip_expr(expr->right);
129 if (right->type != EXPR_PREOP || right->op != '!')
130 return;
131 if (is_bool(right->unop))
132 return;
133 sm_warning("should this be a bitwise negate mask?");
136 static void match_logical_negate(struct expression *expr)
138 sval_t sval;
140 if (expr->op != '!')
141 return;
142 expr = strip_expr(expr->unop);
143 if (expr->type != EXPR_BINOP || expr->op != SPECIAL_LEFTSHIFT)
144 return;
145 if (!get_value(expr->left, &sval) || sval.value != 1)
146 return;
147 sm_warning("potential ! vs ~ typo");
150 void check_logical_instead_of_bitwise(int id)
152 my_id = id;
154 add_hook(&match_logic, LOGIC_HOOK);
155 add_hook(&match_logical_negate, OP_HOOK);
156 add_hook(&match_assign, ASSIGNMENT_HOOK);
157 add_hook(&match_assign_mask, ASSIGNMENT_HOOK);