@@ -249,25 +249,59 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of_string(
249
249
binary_relation_exprt (from_index, ID_le, length_diff),
250
250
from_index,
251
251
length_diff);
252
- string_not_contains_constraintt a4 (
253
- plus_exprt (offset, from_integer (1 , index_type)),
254
- from_index,
255
- end_index,
256
- from_integer (0 , index_type),
257
- substring.length (),
258
- str,
259
- substring);
260
- axioms.push_back (a4);
261
252
262
- string_not_contains_constraintt a5 (
263
- from_integer (0 , index_type),
264
- end_index,
265
- not_exprt (contains),
266
- from_integer (0 , index_type),
267
- substring.length (),
268
- str,
269
- substring);
270
- axioms.push_back (a5);
253
+ if (!is_constant_string (substring))
254
+ {
255
+ string_not_contains_constraintt a4 (
256
+ plus_exprt (offset, from_integer (1 , index_type)),
257
+ from_index,
258
+ plus_exprt (end_index, from_integer (1 , index_type)),
259
+ from_integer (0 , index_type),
260
+ substring.length (),
261
+ str,
262
+ substring);
263
+ axioms.push_back (a4);
264
+
265
+ string_not_contains_constraintt a5 (
266
+ from_integer (0 , index_type),
267
+ plus_exprt (end_index, from_integer (1 , index_type)),
268
+ not_exprt (contains),
269
+ from_integer (0 , index_type),
270
+ substring.length (),
271
+ str,
272
+ substring);
273
+ axioms.push_back (a5);
274
+ }
275
+ else
276
+ {
277
+ // Unfold the existential quantifier as a disjunction in case of a constant
278
+ // a4 && a5 <=> a6:
279
+ // forall n:[0, min(from_index,|str|-|substring|)].
280
+ // !contains || n > offset =>
281
+ // str[n]!=substring[0] || ... ||
282
+ // str[n+|substring|-1]!=substring[|substring|-1]
283
+ symbol_exprt qvar2=fresh_univ_index (" QA_index_of_string_2" , index_type);
284
+ mp_integer sub_length;
285
+ assert (!to_integer (substring.length (), sub_length));
286
+ exprt::operandst disjuncts;
287
+ for (mp_integer offset=0 ; offset<sub_length; ++offset)
288
+ {
289
+ exprt expr_offset=from_integer (offset, index_type);
290
+ plus_exprt shifted (expr_offset, qvar2);
291
+ disjuncts.push_back (
292
+ not_exprt (equal_exprt (str[shifted], substring[expr_offset])));
293
+ }
294
+
295
+ or_exprt premise (
296
+ not_exprt (contains), binary_relation_exprt (qvar, ID_gt, offset));
297
+ string_constraintt a6 (
298
+ qvar2,
299
+ from_index,
300
+ plus_exprt (from_integer (1 , index_type), end_index),
301
+ premise,
302
+ disjunction (disjuncts));
303
+ axioms.push_back (a6);
304
+ }
271
305
272
306
return offset;
273
307
}
0 commit comments