@@ -49,35 +49,20 @@ string_refinementt::string_refinementt(
49
49
50
50
/* ******************************************************************\
51
51
52
- Function: string_refinementt::set_mode
53
-
54
- Purpose: determine which language should be used
55
-
56
- \*******************************************************************/
57
-
58
- void string_refinementt::set_mode ()
59
- {
60
- debug () << " initializing mode" << eom;
61
- symbolt init=ns.lookup (irep_idt (CPROVER_PREFIX" initialize" ));
62
- irep_idt mode=init.mode ;
63
- debug () << " mode detected as " << mode << eom;
64
- generator.set_mode (mode);
65
- }
66
-
67
- /* ******************************************************************\
68
-
69
52
Function: string_refinementt::set_max_string_length
70
53
71
54
Inputs:
72
55
i - maximum length which is allowed for strings.
73
- negative number means no limit
56
+ by default the strings length has no other limit
57
+ than the maximal integer according to the type of their
58
+ length, for instance 2^31-1 for Java.
74
59
75
60
Purpose: Add constraints on the size of strings used in the
76
61
program.
77
62
78
63
\*******************************************************************/
79
64
80
- void string_refinementt::set_max_string_length (int i)
65
+ void string_refinementt::set_max_string_length (size_t i)
81
66
{
82
67
generator.max_string_length =i;
83
68
}
@@ -355,16 +340,18 @@ void string_refinementt::concretize_string(const exprt &expr)
355
340
if (!to_integer (length, found_length))
356
341
{
357
342
assert (found_length.is_long ());
358
- if (found_length < 0 )
343
+ if (found_length< 0 )
359
344
{
345
+ // Lengths should not be negative.
346
+ // TODO: Add constraints no the sign of string lengths.
360
347
debug () << " concretize_results: WARNING found length is negative"
361
348
<< eom;
362
349
}
363
350
else
364
351
{
365
352
size_t concretize_limit=found_length.to_long ();
366
- concretize_limit=concretize_limit>MAX_CONCRETE_STRING_SIZE ?
367
- MAX_CONCRETE_STRING_SIZE :concretize_limit;
353
+ concretize_limit=concretize_limit>generator. max_string_length ?
354
+ generator. max_string_length :concretize_limit;
368
355
exprt content_expr=str.content ();
369
356
for (size_t i=0 ; i<concretize_limit; ++i)
370
357
{
@@ -391,9 +378,9 @@ Function: string_refinementt::concretize_results
391
378
392
379
void string_refinementt::concretize_results ()
393
380
{
394
- for (const auto & it : symbol_resolve)
381
+ for (const auto & it : symbol_resolve)
395
382
concretize_string (it.second );
396
- for (const auto & it : generator.created_strings )
383
+ for (const auto & it : generator.created_strings )
397
384
concretize_string (it);
398
385
add_instantiations ();
399
386
}
@@ -409,7 +396,7 @@ Function: string_refinementt::concretize_lengths
409
396
410
397
void string_refinementt::concretize_lengths ()
411
398
{
412
- for (const auto & it : symbol_resolve)
399
+ for (const auto & it : symbol_resolve)
413
400
{
414
401
if (refined_string_typet::is_refined_string_type (it.second .type ()))
415
402
{
@@ -420,7 +407,7 @@ void string_refinementt::concretize_lengths()
420
407
found_length[content]=length;
421
408
}
422
409
}
423
- for (const auto & it : generator.created_strings )
410
+ for (const auto & it : generator.created_strings )
424
411
{
425
412
if (refined_string_typet::is_refined_string_type (it.type ()))
426
413
{
@@ -448,12 +435,6 @@ void string_refinementt::set_to(const exprt &expr, bool value)
448
435
{
449
436
assert (equality_propagation);
450
437
451
- // TODO: remove the mode field of generator since we should be language
452
- // independent.
453
- // We only set the mode once.
454
- if (generator.get_mode ()==ID_unknown)
455
- set_mode ();
456
-
457
438
if (expr.id ()==ID_equal)
458
439
{
459
440
equal_exprt eq_expr=to_equal_expr (expr);
@@ -743,7 +724,7 @@ exprt string_refinementt::get_array(const exprt &arr, const exprt &size) const
743
724
array_typet ret_type (char_type, from_integer (n, index_type));
744
725
array_exprt ret (ret_type);
745
726
746
- if (n>MAX_CONCRETE_STRING_SIZE )
727
+ if (n>generator. max_string_length )
747
728
{
748
729
#if 0
749
730
debug() << "(sr::get_array) long string (size=" << n << ")" << eom;
@@ -947,6 +928,125 @@ void string_refinementt::fill_model()
947
928
}
948
929
949
930
931
+ /* ******************************************************************\
932
+
933
+ Function: string_refinementt::substitute_array_with_expr()
934
+
935
+ Inputs:
936
+ expr - A (possibly nested) 'with' expression on an `array_of`
937
+ expression
938
+ index - An index with which to build the equality condition
939
+
940
+ Outputs: An expression containing no 'with' expression
941
+
942
+ Purpose: Create a new expression where 'with' expressions on arrays
943
+ are replaced by 'if' expressions.
944
+ e.g. for an array access arr[x], where:
945
+ `arr := array_of(12) with {0:=24} with {2:=42}`
946
+ the constructed expression will be:
947
+ `index==0 ? 24 : index==2 ? 42 : 12`
948
+
949
+ \*******************************************************************/
950
+
951
+ exprt string_refinementt::substitute_array_with_expr (
952
+ const exprt &expr, const exprt &index) const
953
+ {
954
+ if (expr.id ()==ID_with)
955
+ {
956
+ const with_exprt &with_expr=to_with_expr (expr);
957
+ const exprt &then_expr=with_expr.new_value ();
958
+ exprt else_expr=substitute_array_with_expr (with_expr.old (), index );
959
+ const typet &type=then_expr.type ();
960
+ assert (else_expr.type ()==type);
961
+ return if_exprt (
962
+ equal_exprt (index , with_expr.where ()), then_expr, else_expr, type);
963
+ }
964
+ else
965
+ {
966
+ // Only handle 'with' expressions on 'array_of' expressions.
967
+ assert (expr.id ()==ID_array_of);
968
+ return to_array_of_expr (expr).what ();
969
+ }
970
+ }
971
+
972
+ /* ******************************************************************\
973
+
974
+ Function: string_refinementt::substitute_array_access()
975
+
976
+ Inputs:
977
+ expr - an expression containing array accesses
978
+
979
+ Outputs: an expression containing no array access
980
+
981
+ Purpose: create an equivalent expression where array accesses and
982
+ 'with' expressions are replaced by 'if' expressions.
983
+ e.g. for an array access arr[x], where:
984
+ `arr := {12, 24, 48}`
985
+ the constructed expression will be:
986
+ `index==0 ? 12 : index==1 ? 24 : 48`
987
+
988
+ \*******************************************************************/
989
+
990
+ void string_refinementt::substitute_array_access (exprt &expr) const
991
+ {
992
+ for (auto &op : expr.operands ())
993
+ substitute_array_access (op);
994
+
995
+ if (expr.id ()==ID_index)
996
+ {
997
+ index_exprt &index_expr=to_index_expr (expr);
998
+
999
+ if (index_expr.array ().id ()==ID_symbol)
1000
+ {
1001
+ expr=index_expr;
1002
+ return ;
1003
+ }
1004
+
1005
+ if (index_expr.array ().id ()==ID_with)
1006
+ {
1007
+ expr=substitute_array_with_expr (
1008
+ index_expr.array (), index_expr.index ());
1009
+ return ;
1010
+ }
1011
+
1012
+ if (index_expr.array ().id ()==ID_array_of)
1013
+ {
1014
+ expr=to_array_of_expr (index_expr.array ()).op ();
1015
+ return ;
1016
+ }
1017
+
1018
+ assert (index_expr.array ().id ()==ID_array);
1019
+ array_exprt &array_expr=to_array_expr (index_expr.array ());
1020
+
1021
+ assert (!array_expr.operands ().empty ());
1022
+ size_t last_index=array_expr.operands ().size ()-1 ;
1023
+
1024
+ const typet &char_type=index_expr.array ().type ().subtype ();
1025
+ exprt ite=array_expr.operands ().back ();
1026
+
1027
+ if (ite.type ()!=char_type)
1028
+ {
1029
+ // We have to manualy set the type for unknown values
1030
+ assert (ite.id ()==ID_unknown);
1031
+ ite.type ()=char_type;
1032
+ }
1033
+
1034
+ auto op_it=++array_expr.operands ().rbegin ();
1035
+ for (size_t i=last_index-1 ;
1036
+ op_it!=array_expr.operands ().rend (); ++op_it, --i)
1037
+ {
1038
+ equal_exprt equals (index_expr.index (), from_integer (i, java_int_type ()));
1039
+ ite=if_exprt (equals, *op_it, ite);
1040
+ if (ite.type ()!=char_type)
1041
+ {
1042
+ assert (ite.id ()==ID_unknown);
1043
+ ite.type ()=char_type;
1044
+ }
1045
+ }
1046
+ expr=ite;
1047
+ }
1048
+ }
1049
+
950
1050
/* ******************************************************************\
951
1051
952
1052
Function: string_refinementt::add_negation_of_constraint_to_solver
@@ -991,6 +1091,7 @@ void string_refinementt::add_negation_of_constraint_to_solver(
991
1091
and_exprt negaxiom (premise, not_exprt (axiom.body ()));
992
1092
993
1093
debug () << " (sr::check_axioms) negated axiom: " << from_expr (negaxiom) << eom;
1094
+ substitute_array_access (negaxiom);
994
1095
solver << negaxiom;
995
1096
}
996
1097
@@ -1031,6 +1132,7 @@ bool string_refinementt::check_axioms()
1031
1132
1032
1133
satcheck_no_simplifiert sat_check;
1033
1134
supert solver (ns, sat_check);
1135
+ solver.set_ui (ui);
1034
1136
add_negation_of_constraint_to_solver (axiom_in_model, solver);
1035
1137
1036
1138
switch (solver ())
@@ -1085,6 +1187,7 @@ bool string_refinementt::check_axioms()
1085
1187
exprt premise (axiom.premise ());
1086
1188
exprt body (axiom.body ());
1087
1189
implies_exprt instance (premise, body);
1190
+ replace_expr (symbol_resolve, instance);
1088
1191
replace_expr (axiom.univ_var (), val, instance);
1089
1192
debug () << " adding counter example " << from_expr (instance) << eom;
1090
1193
add_lemma (instance);
0 commit comments