@@ -47,6 +47,7 @@ void verilog_typecheckt::assignment_conversion(
47
47
DATA_INVARIANT (
48
48
rhs.id () == ID_verilog_assignment_pattern,
49
49
" verilog_assignment_pattern expression expected" );
50
+
50
51
if (lhs_type.id () == ID_struct)
51
52
{
52
53
auto &struct_type = to_struct_type (lhs_type);
@@ -139,16 +140,87 @@ void verilog_typecheckt::assignment_conversion(
139
140
}
140
141
}
141
142
142
- // Implements 1800-2017 10.7
143
- // If the RHS is smaller than the LHS:
144
- // * if the RHS is unsigned, it is zero-padded
145
- // * if the RHS is signed, it is sign-extended
146
- // If the RHS is larger than the LHS, it is truncated.
143
+ auto &verilog_dest_type = lhs_type.get (ID_C_verilog_type);
144
+ if (verilog_dest_type == ID_verilog_enum)
145
+ {
146
+ // IEEE 1800-2017 6.19.3: "a variable of type enum cannot be directly
147
+ // assigned a value that lies outside the enumeration set unless an
148
+ // explicit cast is used"
149
+ if (
150
+ rhs.type ().get (ID_C_verilog_type) != ID_verilog_enum ||
151
+ rhs.type ().get (ID_C_identifier) != lhs_type.get (ID_C_identifier))
152
+ {
153
+ throw errort ().with_location (rhs.source_location ())
154
+ << " assignment to enum requires enum of the same type, but got "
155
+ << to_string (rhs.type ());
156
+ }
157
+ }
158
+
159
+ if (lhs_type == rhs.type ())
160
+ return ;
161
+
162
+ // Implements 1800-2017 10.7 and 1800-2017 11.8.3.
163
+
164
+ if (
165
+ lhs_type.id () == ID_verilog_real || lhs_type.id () == ID_verilog_shortreal ||
166
+ lhs_type.id () == ID_verilog_realtime ||
167
+ rhs.type ().id () == ID_verilog_real ||
168
+ rhs.type ().id () == ID_verilog_shortreal)
169
+ {
170
+ // from/to real is just a cast
171
+ rhs = typecast_exprt::conditional_cast (rhs, lhs_type);
172
+ return ;
173
+ }
174
+
175
+ if (rhs.type ().id () == ID_verilog_null)
176
+ {
177
+ if (
178
+ lhs_type.id () == ID_verilog_chandle ||
179
+ lhs_type.id () == ID_verilog_class_type ||
180
+ lhs_type.id () == ID_verilog_event)
181
+ {
182
+ rhs = typecast_exprt{rhs, lhs_type};
183
+ return ;
184
+ }
185
+ }
186
+
187
+ // "The size of the left-hand side of an assignment forms
188
+ // the context for the right-hand expression."
147
189
148
- // This matches our typecast, but differs from the steps taken
149
- // when evaluating binary expressions (11.8.2), where sign
150
- // extension only happens when the propagated type is signed.
151
- implicit_typecast (rhs, lhs_type);
190
+ // Get the width of LHS and RHS
191
+ auto lhs_width = get_width (lhs_type);
192
+ auto rhs_width = get_width (rhs.type ());
193
+
194
+ if (lhs_width > rhs_width)
195
+ {
196
+ // Need to enlarge the RHS.
197
+ //
198
+ // "If needed, extend the size of the right-hand side,
199
+ // performing sign extension if, and only if, the type
200
+ // of the right-hand side is signed.
201
+ if (
202
+ (rhs.type ().id () == ID_signedbv ||
203
+ rhs.type ().id () == ID_verilog_signedbv) &&
204
+ (lhs_type.id () == ID_unsignedbv ||
205
+ lhs_type.id () == ID_verilog_unsignedbv))
206
+ {
207
+ // LHS is unsigned, RHS is signed. Must sign-extend.
208
+ auto new_rhs_type = to_bitvector_type (rhs.type ());
209
+ new_rhs_type.set_width (numeric_cast_v<std::size_t >(lhs_width));
210
+
211
+ downwards_type_propagation (rhs, new_rhs_type);
212
+
213
+ // then cast
214
+ rhs = typecast_exprt::conditional_cast (rhs, lhs_type);
215
+ }
216
+ else
217
+ downwards_type_propagation (rhs, lhs_type);
218
+ }
219
+ else
220
+ {
221
+ // no need to enlarge
222
+ rhs = typecast_exprt::conditional_cast (rhs, lhs_type);
223
+ }
152
224
}
153
225
154
226
/* ******************************************************************\
0 commit comments