@@ -80,6 +80,7 @@ exprt string_constraint_generatort::add_axioms_for_index_of(
80
80
// / `haystack` of the first occurrence of `needle` starting the search at
81
81
// / `from_index`, or `-1` if needle does not occur at or after position
82
82
// / `from_index`.
83
+ // / If needle is an empty string then the result is `from_index`.
83
84
// /
84
85
// / These axioms are:
85
86
// / 1. \f$ contains \Rightarrow {\tt from\_index} \le \tt{index}
@@ -93,6 +94,7 @@ exprt string_constraint_generatort::add_axioms_for_index_of(
93
94
// / 5. \f$ \forall n \in [{\tt from\_index},|{\tt haystack}|-|{\tt needle}|]
94
95
// / .\ \lnot contains \Rightarrow (\exists m \in [0,|{\tt needle}|)
95
96
// / .\ {\tt haystack}[m+n] \ne {\tt needle}[m]) \f$
97
+ // / 6. \f$ |{\tt needle}| = 0 \Rightarrow \tt{index} = from_index \f$
96
98
// / \param haystack: an array of character expression
97
99
// / \param needle: an array of character expression
98
100
// / \param from_index: an integer expression
@@ -152,13 +154,19 @@ exprt string_constraint_generatort::add_axioms_for_index_of_string(
152
154
needle);
153
155
axioms.push_back (a5);
154
156
157
+ const implies_exprt a6 (
158
+ equal_exprt (needle.length (), from_integer (0 , index_type)),
159
+ equal_exprt (offset, from_index));
160
+ axioms.push_back (a6);
161
+
155
162
return offset;
156
163
}
157
164
158
165
// / Add axioms stating that the returned value is the index within haystack of
159
166
// / the last occurrence of needle starting the search backward at from_index (ie
160
167
// / the index is smaller or equal to from_index), or -1 if needle does not occur
161
168
// / before from_index.
169
+ // / If `needle` is the empty string, the result is `from_index`.
162
170
// /
163
171
// / These axioms are:
164
172
// / 1. \f$ contains \Rightarrow -1 \le {\tt index}
@@ -178,6 +186,7 @@ exprt string_constraint_generatort::add_axioms_for_index_of_string(
178
186
// / .\ \lnot contains \Rightarrow
179
187
// / (\exists m \in [0,|{\tt needle}|)
180
188
// / .\ {\tt haystack}[m+n] \ne {\tt needle}[m]) \f$
189
+ // / 6. \f$ |{\tt needle}| = 0 \Rightarrow index = from_index \f$
181
190
// / \param haystack: an array of characters expression
182
191
// / \param needle: an array of characters expression
183
192
// / \param from_index: integer expression
@@ -238,6 +247,11 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of_string(
238
247
needle);
239
248
axioms.push_back (a5);
240
249
250
+ const implies_exprt a6 (
251
+ equal_exprt (needle.length (), from_integer (0 , index_type)),
252
+ equal_exprt (offset, from_index));
253
+ axioms.push_back (a6);
254
+
241
255
return offset;
242
256
}
243
257
@@ -295,13 +309,16 @@ exprt string_constraint_generatort::add_axioms_for_index_of(
295
309
// / \todo Change argument names to match add_axioms_for_last_index_of_string
296
310
// /
297
311
// / These axioms are :
298
- // / 1. \f$ -1 \le {\tt index} \le {\tt from\_index} \f$
312
+ // / 1. \f$ -1 \le {\tt index} \le {\tt from\_index}
313
+ // / \land {\tt index} < |{\tt haystack}| \f$
299
314
// / 2. \f$ {\tt index} = -1 \Leftrightarrow \lnot contains\f$
300
- // / 3. \f$ contains \Rightarrow ({\tt index} \le {\tt from\_index} \land
301
- // / {\tt haystack}[i] = {\tt needle} )\f$
302
- // / 4. \f$ \forall n \in [{\tt index} +1, {\tt from\_index}+1)
315
+ // / 3. \f$ contains \Rightarrow
316
+ // / {\tt haystack}[{\tt index}] = {\tt needle} )\f$
317
+ // / 4. \f$ \forall n \in [{\tt index} +1,
318
+ // / min({\tt from\_index}+1, |{\tt haystack}|))
303
319
// / .\ contains \Rightarrow {\tt haystack}[n] \ne {\tt needle} \f$
304
- // / 5. \f$ \forall m \in [0, {\tt from\_index}+1)
320
+ // / 5. \f$ \forall m \in [0,
321
+ // / min({\tt from\_index}+1, |{\tt haystack}|))
305
322
// / .\ \lnot contains \Rightarrow {\tt haystack}[m] \ne {\tt needle}\f$
306
323
// / \param str: an array of characters expression
307
324
// / \param c: a character expression
@@ -314,42 +331,41 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of(
314
331
const exprt &from_index)
315
332
{
316
333
const typet &index_type = str.length ().type ();
317
- symbol_exprt index= fresh_exist_index (" last_index_of" , index_type);
318
- symbol_exprt contains= fresh_boolean (" contains_in_last_index_of" );
334
+ const symbol_exprt index = fresh_exist_index (" last_index_of" , index_type);
335
+ const symbol_exprt contains = fresh_boolean (" contains_in_last_index_of" );
319
336
320
- exprt index1=from_integer (1 , index_type);
321
- exprt minus1=from_integer (-1 , index_type);
322
- exprt from_index_plus_one=plus_exprt_with_overflow_check (from_index, index1);
323
- and_exprt a1 (
337
+ const exprt minus1 = from_integer (-1 , index_type);
338
+ const and_exprt a1 (
324
339
binary_relation_exprt (index, ID_ge, minus1),
325
- binary_relation_exprt (index, ID_lt, from_index_plus_one));
340
+ binary_relation_exprt (index, ID_le, from_index),
341
+ binary_relation_exprt (index, ID_lt, str.length ()));
326
342
axioms.push_back (a1);
327
343
328
- equal_exprt a2 (not_exprt ( contains) , equal_exprt (index, minus1));
344
+ const notequal_exprt a2 (contains, equal_exprt (index, minus1));
329
345
axioms.push_back (a2);
330
346
331
- implies_exprt a3 (
332
- contains,
333
- and_exprt (
334
- binary_relation_exprt (from_index, ID_ge, index),
335
- equal_exprt (str[index], c)));
347
+ const implies_exprt a3 (contains, equal_exprt (str[index], c));
336
348
axioms.push_back (a3);
337
349
338
- symbol_exprt n=fresh_univ_index (" QA_last_index_of1" , index_type);
339
- string_constraintt a4 (
350
+ const exprt index1 = from_integer (1 , index_type);
351
+ const plus_exprt from_index_plus_one (from_index, index1);
352
+ const if_exprt end_index (
353
+ binary_relation_exprt (from_index_plus_one, ID_le, str.length ()),
354
+ from_index_plus_one,
355
+ str.length ());
356
+
357
+ const symbol_exprt n = fresh_univ_index (" QA_last_index_of1" , index_type);
358
+ const string_constraintt a4 (
340
359
n,
341
360
plus_exprt (index, index1),
342
- from_index_plus_one ,
361
+ end_index ,
343
362
contains,
344
- not_exprt ( equal_exprt ( str[n], c) ));
363
+ notequal_exprt ( str[n], c));
345
364
axioms.push_back (a4);
346
365
347
- symbol_exprt m=fresh_univ_index (" QA_last_index_of2" , index_type);
348
- string_constraintt a5 (
349
- m,
350
- from_index_plus_one,
351
- not_exprt (contains),
352
- not_exprt (equal_exprt (str[m], c)));
366
+ const symbol_exprt m = fresh_univ_index (" QA_last_index_of2" , index_type);
367
+ const string_constraintt a5 (
368
+ m, end_index, not_exprt (contains), notequal_exprt (str[m], c));
353
369
axioms.push_back (a5);
354
370
355
371
return index;
@@ -384,9 +400,7 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of(
384
400
const typet &char_type = str.content ().type ().subtype ();
385
401
PRECONDITION (f.type () == index_type);
386
402
387
- const exprt from_index =
388
- args.size () == 2 ? minus_exprt (str.length (), from_integer (1 , index_type))
389
- : args[2 ];
403
+ const exprt from_index = args.size () == 2 ? str.length () : args[2 ];
390
404
391
405
if (c.type ().id ()==ID_unsignedbv || c.type ().id ()==ID_signedbv)
392
406
{
0 commit comments