|
16 | 16 | #include <util/arith_tools.h>
|
17 | 17 | #include <util/c_types.h>
|
18 | 18 | #include <util/config.h>
|
| 19 | +#include <util/expr_util.h> |
19 | 20 | #include <util/std_types.h>
|
20 | 21 | #include <util/prefix.h>
|
21 | 22 | #include <util/cprover_prefix.h>
|
22 | 23 | #include <util/simplify_expr.h>
|
23 | 24 | #include <util/base_type.h>
|
| 25 | +#include <util/file_util.h> |
24 | 26 | #include <util/std_expr.h>
|
25 | 27 | #include <util/pointer_offset_size.h>
|
26 | 28 | #include <util/pointer_predicates.h>
|
@@ -2813,6 +2815,36 @@ void c_typecheck_baset::typecheck_expr_binary_arithmetic(exprt &expr)
|
2813 | 2815 |
|
2814 | 2816 | // promote!
|
2815 | 2817 |
|
| 2818 | + // warn about an implicit 0-extension of bitand operands |
| 2819 | + // expect an explicit cast to avoid this warning |
| 2820 | + if((expr.id()==ID_bitand) && |
| 2821 | + (op0.type().id()==ID_signedbv || op0.type().id()==ID_unsignedbv) && |
| 2822 | + (op1.type().id()==ID_signedbv || op1.type().id()==ID_unsignedbv)) |
| 2823 | + { |
| 2824 | + bool unintentional=false; |
| 2825 | + // do not apply, if we are working with constants and the & operator |
| 2826 | + if(op0.id()!=ID_constant && op1.id()!=ID_constant) |
| 2827 | + { |
| 2828 | + // mismatch occurs only, if we have "&" with two different width, |
| 2829 | + // where the side with the smaller width has to use the "~" operator |
| 2830 | + const size_t width0=to_bitvector_type(op0.type()).get_width(); |
| 2831 | + const size_t width1=to_bitvector_type(op1.type()).get_width(); |
| 2832 | + unintentional=(width0<width1 && has_subexpr(op0, ID_bitnot)) || |
| 2833 | + (width0>width1 && has_subexpr(op1, ID_bitnot)); |
| 2834 | + } |
| 2835 | + |
| 2836 | + // is all conditions are met for an unintended combination |
| 2837 | + // of the operators ~ and &, print a warning |
| 2838 | + if(unintentional) |
| 2839 | + { |
| 2840 | + warning().source_location=expr.find_source_location(); |
| 2841 | + warning() << "Implicit zero extension of bitwise operand" |
| 2842 | + << " in combination with bitwise negation may" |
| 2843 | + << " cause unexpected results" |
| 2844 | + << eom; |
| 2845 | + } |
| 2846 | + } |
| 2847 | + |
2816 | 2848 | implicit_typecast_arithmetic(op0, op1);
|
2817 | 2849 |
|
2818 | 2850 | const typet &type0=follow(op0.type());
|
@@ -3205,6 +3237,22 @@ void c_typecheck_baset::typecheck_side_effect_assignment(
|
3205 | 3237 | o_type0.id()==ID_signedbv ||
|
3206 | 3238 | o_type0.id()==ID_c_bit_field)
|
3207 | 3239 | {
|
| 3240 | + // check whether an implicit cast might be dangerous, |
| 3241 | + // i.e. it involves the & and ~ operator |
| 3242 | + if((o_type0.id()==ID_unsignedbv || o_type0.id()==ID_signedbv) && |
| 3243 | + (o_type1.id()==ID_unsignedbv || o_type1.id()==ID_signedbv) && |
| 3244 | + op1.id()!=ID_constant && |
| 3245 | + (to_bitvector_type(o_type0).get_width()> |
| 3246 | + to_bitvector_type(o_type1).get_width()) && |
| 3247 | + has_subexpr(op1, ID_bitnot)) |
| 3248 | + { |
| 3249 | + warning().source_location=expr.find_source_location(); |
| 3250 | + warning() << "Implicit zero extension of bitwise operand" |
| 3251 | + << " in combination with bitwise negation may" |
| 3252 | + << " cause unexpected results" |
| 3253 | + << eom; |
| 3254 | + } |
| 3255 | + // perform the cast |
3208 | 3256 | implicit_typecast(op1, o_type0);
|
3209 | 3257 | return;
|
3210 | 3258 | }
|
|
0 commit comments