@@ -184,6 +184,15 @@ bool simplify_exprt::simplify_function_application(exprt &expr)
184
184
return true ;
185
185
}
186
186
187
+ mp_integer offset_int = 0 ;
188
+ if (function_app.arguments ().size () == 3 )
189
+ {
190
+ auto &offset = function_app.arguments ()[2 ];
191
+ if (offset.id () != ID_constant)
192
+ return true ;
193
+ offset_int = numeric_cast_v<mp_integer>(to_constant_expr (offset));
194
+ }
195
+
187
196
const address_of_exprt &first_address_of =
188
197
to_address_of_expr (first_argument.content ());
189
198
const address_of_exprt &second_address_of =
@@ -214,19 +223,46 @@ bool simplify_exprt::simplify_function_application(exprt &expr)
214
223
return true ;
215
224
}
216
225
217
- // If so, it'll be a string array that we can use.
218
- const array_string_exprt &first_string = to_array_string_expr (
219
- ns.lookup (first_string_array.get (ID_identifier)).value );
226
+ // get their initial values from the symbol table
227
+ const symbolt *symbol_ptr = nullptr ;
228
+ if (ns.lookup (
229
+ to_symbol_expr (first_string_array).get_identifier (), symbol_ptr))
230
+ return true ;
231
+ const exprt &first_value = symbol_ptr->value ;
232
+ if (ns.lookup (
233
+ to_symbol_expr (second_string_array).get_identifier (), symbol_ptr))
234
+ return true ;
235
+ const exprt &second_value = symbol_ptr->value ;
220
236
221
- const array_string_exprt &second_string = to_array_string_expr (
222
- ns.lookup (second_string_array.get (ID_identifier)).value );
237
+ // only compare if both are arrays
238
+ if (first_value.id () != ID_array || second_value.id () != ID_array)
239
+ return true ;
223
240
224
- // If the lengths are the same we can do the .equals substitute.
225
- if (first_string.length () == second_string.length ())
241
+ // test whether second_value is a prefix of first_value
242
+ bool is_prefix =
243
+ offset_int >= 0 && mp_integer (first_value.operands ().size ()) >=
244
+ offset_int + second_value.operands ().size ();
245
+ if (is_prefix)
226
246
{
227
- expr = from_integer (first_string == second_string ? 1 : 0 , expr.type ());
228
- return false ;
247
+ exprt::operandst::const_iterator second_it =
248
+ second_value.operands ().begin ();
249
+ for (const auto &first_op : first_value.operands ())
250
+ {
251
+ if (offset_int > 0 )
252
+ --offset_int;
253
+ else if (second_it == second_value.operands ().end ())
254
+ break ;
255
+ else if (first_op != *second_it)
256
+ {
257
+ is_prefix = false ;
258
+ break ;
259
+ }
260
+ else
261
+ ++second_it;
262
+ }
229
263
}
264
+ expr = from_integer (is_prefix ? 1 : 0 , expr.type ());
265
+ return false ;
230
266
}
231
267
232
268
return true ;
0 commit comments