2 * sparse/check_or_vs_and.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
11 #include "smatch_function_hashtable.h"
15 DEFINE_STRING_HASHTABLE_STATIC(unconstant_macros
);
17 static int does_inc_dec(struct expression
*expr
)
19 if (expr
->type
== EXPR_PREOP
|| expr
->type
== EXPR_POSTOP
) {
20 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
22 return does_inc_dec(expr
->unop
);
27 static int expr_equiv(struct expression
*one
, struct expression
*two
)
29 struct symbol
*one_sym
, *two_sym
;
30 char *one_name
= NULL
;
31 char *two_name
= NULL
;
34 if (does_inc_dec(one
) || does_inc_dec(two
))
37 one_name
= get_variable_from_expr_complex(one
, &one_sym
);
38 if (!one_name
|| !one_sym
)
40 two_name
= get_variable_from_expr_complex(two
, &two_sym
);
41 if (!two_name
|| !two_sym
)
43 if (one_sym
!= two_sym
)
45 if (strcmp(one_name
, two_name
) == 0)
48 free_string(one_name
);
49 free_string(two_name
);
53 static int inconsistent_check(struct expression
*left
, struct expression
*right
)
57 if (get_value_sval(left
->left
, &sval
)) {
58 if (get_value_sval(right
->left
, &sval
))
59 return expr_equiv(left
->right
, right
->right
);
60 if (get_value_sval(right
->right
, &sval
))
61 return expr_equiv(left
->right
, right
->left
);
64 if (get_value_sval(left
->right
, &sval
)) {
65 if (get_value_sval(right
->left
, &sval
))
66 return expr_equiv(left
->left
, right
->right
);
67 if (get_value_sval(right
->right
, &sval
))
68 return expr_equiv(left
->left
, right
->left
);
75 static void check_or(struct expression
*expr
)
77 if (expr
->left
->type
!= EXPR_COMPARE
||
78 expr
->left
->op
!= SPECIAL_NOTEQUAL
)
80 if (expr
->right
->type
!= EXPR_COMPARE
||
81 expr
->right
->op
!= SPECIAL_NOTEQUAL
)
83 if (!inconsistent_check(expr
->left
, expr
->right
))
86 sm_msg("warn: was && intended here instead of ||?");
89 static void check_and(struct expression
*expr
)
91 if (expr
->left
->type
!= EXPR_COMPARE
||
92 expr
->left
->op
!= SPECIAL_EQUAL
)
94 if (expr
->right
->type
!= EXPR_COMPARE
||
95 expr
->right
->op
!= SPECIAL_EQUAL
)
97 if (!inconsistent_check(expr
->left
, expr
->right
))
100 sm_msg("warn: was || intended here instead of &&?");
103 static void match_logic(struct expression
*expr
)
105 if (expr
->type
!= EXPR_LOGICAL
)
108 if (expr
->op
== SPECIAL_LOGICAL_OR
)
110 if (expr
->op
== SPECIAL_LOGICAL_AND
)
114 static int is_unconstant_macro(struct expression
*expr
)
118 macro
= get_macro_name(expr
->pos
);
121 if (search_unconstant_macros(unconstant_macros
, macro
))
126 static void match_condition(struct expression
*expr
)
130 if (expr
->type
!= EXPR_BINOP
)
132 if (expr
->op
== '|') {
133 if (get_value_sval(expr
->left
, &sval
) || get_value_sval(expr
->right
, &sval
))
134 sm_msg("warn: suspicious bitop condition");
141 if (get_macro_name(expr
->pos
))
143 if (is_unconstant_macro(expr
->left
) || is_unconstant_macro(expr
->right
))
146 if ((get_value_sval(expr
->left
, &sval
) && sval
.value
== 0) ||
147 (get_value_sval(expr
->right
, &sval
) && sval
.value
== 0))
148 sm_msg("warn: bitwise AND condition is false here");
151 static void match_binop(struct expression
*expr
)
153 sval_t left
, right
, sval
;
157 if (!get_value_sval(expr
, &sval
) || sval
.value
!= 0)
159 if (get_macro_name(expr
->pos
))
161 if (!get_value_sval(expr
->left
, &left
) || !get_value_sval(expr
->right
, &right
))
163 sm_msg("warn: odd binop '0x%llx & 0x%llx'", left
.uvalue
, right
.uvalue
);
166 void check_or_vs_and(int id
)
170 unconstant_macros
= create_function_hashtable(100);
171 load_strings("unconstant_macros", unconstant_macros
);
173 add_hook(&match_logic
, LOGIC_HOOK
);
174 add_hook(&match_condition
, CONDITION_HOOK
);
176 add_hook(&match_binop
, BINOP_HOOK
);