@@ -41,16 +41,43 @@ void verilog_typecheckt::assignment_conversion(
41
41
exprt &rhs,
42
42
const typet &lhs_type)
43
43
{
44
- // Implements 1800-2017 10.7
45
- // If the RHS is smaller than the LHS:
46
- // * if the RHS is unsigned, it is zero-padded
47
- // * if the RHS is signed, it is sign-extended
48
- // If the RHS is larger than the LHS, it is truncated.
49
-
50
- // This matches our typecast, but differs from the steps taken
51
- // when evaluating binary expressions (11.8.2), where sign
52
- // extension only happens when the propagated type is signed.
53
- implicit_typecast (rhs, lhs_type);
44
+ // Implements 1800-2017 10.7 and 1800-2017 11.8.3.
45
+ //
46
+ // "The size of the left-hand side of an assignment forms
47
+ // the context for the right-hand expression."
48
+
49
+ // Get the width of LHS and RHS
50
+ auto lhs_width = get_width (lhs_type);
51
+ auto rhs_width = get_width (rhs.type ());
52
+
53
+ if (lhs_width > rhs_width)
54
+ {
55
+ // Need to enlarge the RHS.
56
+ //
57
+ // "If needed, extend the size of the right-hand side,
58
+ // performing sign extension if, and only if, the type
59
+ // of the right-hand side is signed.
60
+ if ((rhs.type ().id () == ID_signedbv || rhs.type ().id () == ID_verilog_signedbv) &&
61
+ (lhs_type.id () == ID_unsignedbv || lhs_type.id () == ID_verilog_unsignedbv))
62
+ {
63
+ // LHS is unsigned, RHS is signed. Must sign-extend.
64
+ auto new_rhs_type = to_bitvector_type (rhs.type ());
65
+ new_rhs_type.set_width (numeric_cast_v<std::size_t >(lhs_width));
66
+
67
+ downwards_type_propagation (rhs, new_rhs_type);
68
+
69
+ // then cast
70
+ rhs = typecast_exprt::conditional_cast (rhs, lhs_type);
71
+ }
72
+ else
73
+ downwards_type_propagation (rhs, lhs_type);
74
+ }
75
+ else
76
+ {
77
+ // no need to enlarge
78
+ rhs = typecast_exprt::conditional_cast (rhs, lhs_type);
79
+ }
80
+
54
81
}
55
82
56
83
/* ******************************************************************\
0 commit comments