@@ -31,7 +31,6 @@ string_constraint_generatort::string_constraint_generatort(
31
31
const string_constraint_generatort::infot &info,
32
32
const namespacet &ns)
33
33
: max_string_length(info.string_max_length),
34
- force_printable_characters(info.string_printable),
35
34
ns(ns)
36
35
{
37
36
}
@@ -319,21 +318,71 @@ void string_constraint_generatort::add_default_axioms(
319
318
if (!created_strings.insert (s).second )
320
319
return ;
321
320
322
- axioms.push_back (
323
- s.axiom_for_length_ge (from_integer (0 , s.length ().type ())));
321
+ const exprt index_zero = from_integer (0 , s.length ().type ());
322
+ axioms.push_back (s.axiom_for_length_ge (index_zero));
323
+
324
324
if (max_string_length!=std::numeric_limits<size_t >::max ())
325
325
axioms.push_back (s.axiom_for_length_le (max_string_length));
326
+ }
326
327
327
- if (force_printable_characters)
328
- {
329
- symbol_exprt qvar=fresh_univ_index (" printable" , s.length ().type ());
330
- exprt chr=s[qvar];
331
- and_exprt printable (
332
- binary_relation_exprt (chr, ID_ge, from_integer (' ' , chr.type ())),
333
- binary_relation_exprt (chr, ID_le, from_integer (' ~' , chr.type ())));
334
- string_constraintt sc (qvar, s.length (), printable);
335
- axioms.push_back (sc);
336
- }
328
+ // / Add constraint on characters of a string.
329
+ // /
330
+ // / This constraint is
331
+ // / \f$ \forall i \in [start, end), low\_char \le s[i] \le high\_char \f$
332
+ // / \param s: a string expression
333
+ // / \param start: index of the first character to constrain
334
+ // / \param end: index at which we stop adding constraints
335
+ // / \param char_set: a string of the form "<low_char>-<high_char>" where
336
+ // / `<low_char>` and `<high_char>` are two characters, which represents
337
+ // / the set of characters that are between `low_char` and `high_char`.
338
+ // / \return a string expression that is linked to the argument through axioms
339
+ // / that are added to the list
340
+ void string_constraint_generatort::add_constraint_on_characters (
341
+ const array_string_exprt &s,
342
+ const exprt &start,
343
+ const exprt &end,
344
+ const std::string &char_set)
345
+ {
346
+ // Parse char_set
347
+ PRECONDITION (char_set.length () == 3 );
348
+ PRECONDITION (char_set[1 ] == ' -' );
349
+ const char &low_char = char_set[0 ];
350
+ const char &high_char = char_set[2 ];
351
+
352
+ // Add constraint
353
+ const symbol_exprt qvar = fresh_univ_index (" char_constr" , s.length ().type ());
354
+ const exprt chr = s[qvar];
355
+ const and_exprt char_in_set (
356
+ binary_relation_exprt (chr, ID_ge, from_integer (low_char, chr.type ())),
357
+ binary_relation_exprt (chr, ID_le, from_integer (high_char, chr.type ())));
358
+ const string_constraintt sc (qvar, start, end, true_exprt (), char_in_set);
359
+ axioms.push_back (sc);
360
+ }
361
+
362
+ // / Add axioms to ensure all characters of a string belong to a given set.
363
+ // /
364
+ // / The axiom is: \f$\forall i \in [start, end).\ s[i] \in char_set \f$, where
365
+ // / `char_set` is given by the string `char_set_string` composed of three
366
+ // / characters `low_char`, `-` and `high_char`. Character `c` belongs to
367
+ // / `char_set` if \f$low_char \le c \le high_char\f$.
368
+ // / \param f: a function application with arguments: integer `|s|`, character
369
+ // / pointer `&s[0]`, string `char_set_string`,
370
+ // / optional integers `start` and `end`
371
+ // / \return integer expression whose value is zero
372
+ exprt string_constraint_generatort::add_axioms_for_constrain_characters (
373
+ const function_application_exprt &f)
374
+ {
375
+ const auto &args = f.arguments ();
376
+ PRECONDITION (3 <= args.size () && args.size () <= 5 );
377
+ PRECONDITION (args[2 ].type ().id () == ID_string);
378
+ PRECONDITION (args[2 ].id () == ID_constant);
379
+ const array_string_exprt s = char_array_of_pointer (args[1 ], args[0 ]);
380
+ const irep_idt &char_set_string = to_constant_expr (args[2 ]).get_value ();
381
+ const exprt &start =
382
+ args.size () >= 4 ? args[3 ] : from_integer (0 , s.length ().type ());
383
+ const exprt &end = args.size () >= 5 ? args[4 ] : s.length ();
384
+ add_constraint_on_characters (s, start, end, char_set_string.c_str ());
385
+ return from_integer (0 , get_return_code_type ());
337
386
}
338
387
339
388
// / Adds creates a new array if it does not already exists
@@ -472,6 +521,8 @@ exprt string_constraint_generatort::add_axioms_for_function_application(
472
521
res = associate_array_to_pointer (expr);
473
522
else if (id == ID_cprover_associate_length_to_array_func)
474
523
res = associate_length_to_array (expr);
524
+ else if (id == ID_cprover_string_constrain_characters_func)
525
+ res = add_axioms_for_constrain_characters (expr);
475
526
else
476
527
{
477
528
std::string msg (
0 commit comments