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
19 #include "smatch_function_hashtable.h"
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
)
28 return does_inc_dec(expr
->unop
);
33 static int expr_equiv_no_inc_dec(struct expression
*one
, struct expression
*two
)
37 if (does_inc_dec(one
) || does_inc_dec(two
))
39 if (get_value(one
, &dummy
) &&
40 get_value(two
, &dummy
))
43 return expr_equiv(one
, two
);
46 static int inconsistent_check(struct expression
*left
, struct expression
*right
)
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
);
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
);
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
)
77 if (right
->type
!= EXPR_COMPARE
|| right
->op
!= SPECIAL_NOTEQUAL
)
79 if (!inconsistent_check(left
, right
))
82 sm_warning("was && intended here instead of ||?");
85 static int is_kernel_min_macro(struct expression
*expr
)
89 if (option_project
!= PROJ_KERNEL
)
91 macro
= get_macro_name(expr
->pos
);
94 if (strcmp(macro
, "min") == 0 ||
95 strcmp(macro
, "min_t") == 0 ||
96 strcmp(macro
, "max") == 0 ||
97 strcmp(macro
, "max_t") == 0)
102 static void check_and(struct expression
*expr
)
104 struct expression
*left
, *right
;
106 if (is_kernel_min_macro(expr
))
109 left
= strip_expr(expr
->left
);
110 right
= strip_expr(expr
->right
);
112 if (left
->type
!= EXPR_COMPARE
|| left
->op
!= SPECIAL_EQUAL
)
114 if (right
->type
!= EXPR_COMPARE
|| right
->op
!= SPECIAL_EQUAL
)
116 if (!inconsistent_check(left
, right
))
119 sm_warning("was || intended here instead of &&?");
122 static void match_logic(struct expression
*expr
)
124 if (expr
->type
!= EXPR_LOGICAL
)
127 if (expr
->op
== SPECIAL_LOGICAL_OR
)
129 if (expr
->op
== SPECIAL_LOGICAL_AND
)
133 static void match_condition(struct expression
*expr
)
137 if (expr
->type
!= EXPR_BINOP
)
139 if (expr
->op
== '|') {
140 if (get_value(expr
->left
, &sval
) || get_value(expr
->right
, &sval
))
141 sm_warning("suspicious bitop condition");
148 if (get_macro_name(expr
->pos
))
150 if (is_unconstant_macro(expr
->left
) || is_unconstant_macro(expr
->right
))
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
;
164 if (!get_value(expr
, &sval
) || sval
.value
!= 0)
166 if (get_macro_name(expr
->pos
))
168 if (!get_value(expr
->left
, &left
) || !get_value(expr
->right
, &right
))
170 sm_warning("odd binop '0x%llx & 0x%llx'", left
.uvalue
, right
.uvalue
);
173 void check_or_vs_and(int id
)
177 add_hook(&match_logic
, LOGIC_HOOK
);
178 add_hook(&match_condition
, CONDITION_HOOK
);
180 add_hook(&match_binop
, BINOP_HOOK
);