@@ -228,29 +228,32 @@ const exprt &skip_typecast(const exprt &expr)
228228// / "constants"
229229bool is_constantt::is_constant (const exprt &expr) const
230230{
231- if (expr.is_constant ())
232- return true ;
231+ if (
232+ expr.id () == ID_symbol || expr.id () == ID_nondet_symbol ||
233+ expr.id () == ID_side_effect)
234+ {
235+ return false ;
236+ }
233237
234238 if (expr.id () == ID_address_of)
235239 {
236240 return is_constant_address_of (to_address_of_expr (expr).object ());
237241 }
238- else if (
239- expr.id () == ID_typecast || expr.id () == ID_array_of ||
240- expr.id () == ID_plus || expr.id () == ID_mult || expr.id () == ID_array ||
241- expr.id () == ID_with || expr.id () == ID_struct || expr.id () == ID_union ||
242- expr.id () == ID_empty_union || expr.id () == ID_equal ||
243- expr.id () == ID_notequal || expr.id () == ID_lt || expr.id () == ID_le ||
244- expr.id () == ID_gt || expr.id () == ID_ge || expr.id () == ID_if ||
245- expr.id () == ID_not || expr.id () == ID_and || expr.id () == ID_or ||
246- expr.id () == ID_bitnot || expr.id () == ID_bitand || expr.id () == ID_bitor ||
247- expr.id () == ID_bitxor || expr.id () == ID_byte_update_big_endian ||
248- expr.id () == ID_byte_update_little_endian)
242+ else if (auto index = expr_try_dynamic_cast<index_exprt>(expr))
249243 {
250- return std::all_of (
251- expr.operands ().begin (), expr.operands ().end (), [this ](const exprt &e) {
252- return is_constant (e);
253- });
244+ if (!is_constant (index->array ()) || !index->index ().is_constant ())
245+ return false ;
246+
247+ const auto &array_type = to_array_type (index->array ().type ());
248+ if (!array_type.size ().is_constant ())
249+ return false ;
250+
251+ const mp_integer size =
252+ numeric_cast_v<mp_integer>(to_constant_expr (array_type.size ()));
253+ const mp_integer index_int =
254+ numeric_cast_v<mp_integer>(to_constant_expr (index->index ()));
255+
256+ return index_int >= 0 && index_int < size;
254257 }
255258 else if (auto be = expr_try_dynamic_cast<byte_extract_exprt>(expr))
256259 {
@@ -269,7 +272,7 @@ bool is_constantt::is_constant(const exprt &expr) const
269272 numeric_cast_v<mp_integer>(to_constant_expr (be->offset ())) *
270273 be->get_bits_per_byte ();
271274
272- return offset_bits + *extract_bits <= *op_bits;
275+ return offset_bits >= 0 && offset_bits + *extract_bits <= *op_bits;
273276 }
274277 else if (auto eb = expr_try_dynamic_cast<extractbits_exprt>(expr))
275278 {
@@ -292,8 +295,14 @@ bool is_constantt::is_constant(const exprt &expr) const
292295 return lower_bound >= 0 && lower_bound <= upper_bound &&
293296 upper_bound < src_bits;
294297 }
295-
296- return false ;
298+ else
299+ {
300+ // std::all_of returns true when there are no operands
301+ return std::all_of (
302+ expr.operands ().begin (), expr.operands ().end (), [this ](const exprt &e) {
303+ return is_constant (e);
304+ });
305+ }
297306}
298307
299308// / this function determines which reference-typed expressions are constant
0 commit comments