2 * Copyright 2023 Linaro Ltd.
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_extra.h"
23 static const char *okay_macros
[] = {
27 static const char *kernel_macros
[] = {
28 "DP_FFE_PRESET_MAX_LEVEL",
33 "LOGICVC_DIMENSIONS_MAX",
38 "TSL2591_ALS_MAX_VALUE",
39 "UBIFS_COMPR_TYPES_CNT",
40 "XFS_MAX_CRC_AG_BLOCKS",
44 static const char **allowed_macros
;
46 static bool is_lt_zero(int op
, sval_t known
)
48 if (op
!= '<' && op
!= SPECIAL_UNSIGNED_LT
)
55 static bool check_is_ulong_max_recursive(struct expression
*expr
)
59 expr
= strip_expr(expr
);
61 if (!get_value(expr
, &sval
))
64 if (expr
->type
== EXPR_BINOP
) {
65 if (check_is_ulong_max_recursive(expr
->left
))
70 if (sval_cmp(sval
, sval_type_max(&ulong_ctype
)) == 0)
75 static bool is_u64_vs_ulongmax(struct expression
*expr
)
77 struct symbol
*left
, *right
;
79 if (expr
->op
!= '>' && expr
->op
!= SPECIAL_UNSIGNED_GT
)
81 if (!check_is_ulong_max_recursive(expr
->right
))
84 left
= get_type(expr
->left
);
85 right
= get_type(expr
->right
);
89 if (type_positive_bits(left
) < type_positive_bits(right
))
92 if (type_bits(left
) != 64)
94 if (right
!= &ulong_ctype
&& right
!= &uint_ctype
)
100 static bool is_long_vs_UINTMAX(struct range_list
*rl
, int op
, sval_t known
)
102 if (op
!= '>' && op
!= SPECIAL_UNSIGNED_GT
)
104 if (rl_type(rl
) != &long_ctype
&& rl_type(rl
) != &ulong_ctype
)
106 if (known
.value
== UINT_MAX
)
111 static bool is_allowed_impossible_limit(struct expression
*expr
)
119 macro
= get_macro_name(expr
->pos
);
121 macro
= pos_ident(expr
->pos
);
126 while (allowed_macros
[++i
]) {
127 if (strcmp(macro
, allowed_macros
[i
]) == 0)
133 static void match_condition(struct expression
*expr
)
137 struct range_list
*var_rl
, *known_rl
, *rl_right
, *rl_left
;
141 if (expr
->type
!= EXPR_COMPARE
)
144 type
= get_type(expr
);
148 if (get_macro_name(expr
->pos
))
152 if (get_value(expr
->right
, &known
)) {
153 /* check that one and only one side is known */
154 if (get_value(expr
->left
, &dummy
))
157 var_rl
= alloc_whole_rl(get_type(expr
->left
));
158 } else if (get_value(expr
->left
, &known
)) {
159 op
= flip_comparison(op
);
160 var_rl
= alloc_whole_rl(get_type(expr
->right
));
164 known
= sval_cast(type
, known
);
165 known_rl
= alloc_rl(known
, known
);
166 var_rl
= cast_rl(type
, var_rl
);
168 /* handled by check_unsigned_lt_zero.c */
169 if (is_lt_zero(op
, known
))
172 if (possibly_true_rl(var_rl
, op
, known_rl
))
174 if (is_u64_vs_ulongmax(expr
))
176 if (is_long_vs_UINTMAX(var_rl
, op
, known
))
178 if (is_allowed_impossible_limit(expr
->right
))
181 name
= expr_to_str(expr
);
182 get_absolute_rl(expr
->left
, &rl_left
);
183 get_absolute_rl(expr
->right
, &rl_right
);
184 sm_warning("impossible condition '(%s) => (%s %s %s)'", name
,
185 show_rl(rl_left
), show_special(expr
->op
), show_rl(rl_right
));
189 void check_impossible_compare(int id
)
193 allowed_macros
= okay_macros
;
194 if (option_project
== PROJ_KERNEL
)
195 allowed_macros
= kernel_macros
;
197 add_hook(&match_condition
, CONDITION_HOOK
);