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 DEFINE_STRING_HASHTABLE_STATIC(unconstant_macros
);
25 static int does_inc_dec(struct expression
*expr
)
27 if (expr
->type
== EXPR_PREOP
|| expr
->type
== EXPR_POSTOP
) {
28 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
30 return does_inc_dec(expr
->unop
);
35 static int expr_equiv(struct expression
*one
, struct expression
*two
)
37 struct symbol
*one_sym
, *two_sym
;
38 char *one_name
= NULL
;
39 char *two_name
= NULL
;
42 if (does_inc_dec(one
) || does_inc_dec(two
))
45 one_name
= expr_to_str_sym(one
, &one_sym
);
46 if (!one_name
|| !one_sym
)
48 two_name
= expr_to_str_sym(two
, &two_sym
);
49 if (!two_name
|| !two_sym
)
51 if (one_sym
!= two_sym
)
53 if (strcmp(one_name
, two_name
) == 0)
56 free_string(one_name
);
57 free_string(two_name
);
61 static int inconsistent_check(struct expression
*left
, struct expression
*right
)
65 if (get_value(left
->left
, &sval
)) {
66 if (get_value(right
->left
, &sval
))
67 return expr_equiv(left
->right
, right
->right
);
68 if (get_value(right
->right
, &sval
))
69 return expr_equiv(left
->right
, right
->left
);
72 if (get_value(left
->right
, &sval
)) {
73 if (get_value(right
->left
, &sval
))
74 return expr_equiv(left
->left
, right
->right
);
75 if (get_value(right
->right
, &sval
))
76 return expr_equiv(left
->left
, right
->left
);
83 static void check_or(struct expression
*expr
)
85 struct expression
*left
, *right
;
87 left
= strip_expr(expr
->left
);
88 right
= strip_expr(expr
->right
);
90 if (left
->type
!= EXPR_COMPARE
||
91 left
->op
!= SPECIAL_NOTEQUAL
)
93 if (right
->type
!= EXPR_COMPARE
||
94 right
->op
!= SPECIAL_NOTEQUAL
)
96 if (!inconsistent_check(left
, right
))
99 sm_msg("warn: was && intended here instead of ||?");
102 static void check_and(struct expression
*expr
)
104 struct expression
*left
, *right
;
106 left
= strip_expr(expr
->left
);
107 right
= strip_expr(expr
->right
);
109 if (left
->type
!= EXPR_COMPARE
||
110 left
->op
!= SPECIAL_EQUAL
)
112 if (right
->type
!= EXPR_COMPARE
||
113 right
->op
!= SPECIAL_EQUAL
)
115 if (!inconsistent_check(left
, right
))
118 sm_msg("warn: was || intended here instead of &&?");
121 static void match_logic(struct expression
*expr
)
123 if (expr
->type
!= EXPR_LOGICAL
)
126 if (expr
->op
== SPECIAL_LOGICAL_OR
)
128 if (expr
->op
== SPECIAL_LOGICAL_AND
)
132 static int is_unconstant_macro(struct expression
*expr
)
136 macro
= get_macro_name(expr
->pos
);
139 if (search_unconstant_macros(unconstant_macros
, macro
))
144 static void match_condition(struct expression
*expr
)
148 if (expr
->type
!= EXPR_BINOP
)
150 if (expr
->op
== '|') {
151 if (get_value(expr
->left
, &sval
) || get_value(expr
->right
, &sval
))
152 sm_msg("warn: suspicious bitop condition");
159 if (get_macro_name(expr
->pos
))
161 if (is_unconstant_macro(expr
->left
) || is_unconstant_macro(expr
->right
))
164 if ((get_value(expr
->left
, &sval
) && sval
.value
== 0) ||
165 (get_value(expr
->right
, &sval
) && sval
.value
== 0))
166 sm_msg("warn: bitwise AND condition is false here");
169 static void match_binop(struct expression
*expr
)
171 sval_t left
, right
, sval
;
175 if (!get_value(expr
, &sval
) || sval
.value
!= 0)
177 if (get_macro_name(expr
->pos
))
179 if (!get_value(expr
->left
, &left
) || !get_value(expr
->right
, &right
))
181 sm_msg("warn: odd binop '0x%llx & 0x%llx'", left
.uvalue
, right
.uvalue
);
184 void check_or_vs_and(int id
)
188 unconstant_macros
= create_function_hashtable(100);
189 load_strings("unconstant_macros", unconstant_macros
);
191 add_hook(&match_logic
, LOGIC_HOOK
);
192 add_hook(&match_condition
, CONDITION_HOOK
);
194 add_hook(&match_binop
, BINOP_HOOK
);