@@ -54,30 +54,22 @@ string_refinementt::string_refinementt(
54
54
non_empty_string(false )
55
55
{ }
56
56
57
- // / determine which language should be used
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
57
/* ******************************************************************\
68
58
69
59
Function: string_refinementt::set_max_string_length
70
60
71
61
Inputs:
72
62
i - maximum length which is allowed for strings.
73
- negative number means no limit
63
+ by default the strings length has no other limit
64
+ than the maximal integer according to the type of their
65
+ length, for instance 2^31-1 for Java.
74
66
75
67
Purpose: Add constraints on the size of strings used in the
76
68
program.
77
69
78
70
\*******************************************************************/
79
71
80
- void string_refinementt::set_max_string_length (int i)
72
+ void string_refinementt::set_max_string_length (size_t i)
81
73
{
82
74
generator.max_string_length =i;
83
75
}
@@ -325,16 +317,18 @@ void string_refinementt::concretize_string(const exprt &expr)
325
317
if (!to_integer (length, found_length))
326
318
{
327
319
assert (found_length.is_long ());
328
- if (found_length < 0 )
320
+ if (found_length< 0 )
329
321
{
322
+ // Lengths should not be negative.
323
+ // TODO: Add constraints no the sign of string lengths.
330
324
debug () << " concretize_results: WARNING found length is negative"
331
325
<< eom;
332
326
}
333
327
else
334
328
{
335
329
size_t concretize_limit=found_length.to_long ();
336
- concretize_limit=concretize_limit>MAX_CONCRETE_STRING_SIZE ?
337
- MAX_CONCRETE_STRING_SIZE :concretize_limit;
330
+ concretize_limit=concretize_limit>generator. max_string_length ?
331
+ generator. max_string_length :concretize_limit;
338
332
exprt content_expr=str.content ();
339
333
for (size_t i=0 ; i<concretize_limit; ++i)
340
334
{
@@ -361,9 +355,9 @@ Function: string_refinementt::concretize_results
361
355
362
356
void string_refinementt::concretize_results ()
363
357
{
364
- for (const auto & it : symbol_resolve)
358
+ for (const auto & it : symbol_resolve)
365
359
concretize_string (it.second );
366
- for (const auto & it : generator.created_strings )
360
+ for (const auto & it : generator.created_strings )
367
361
concretize_string (it);
368
362
add_instantiations ();
369
363
}
@@ -379,7 +373,7 @@ Function: string_refinementt::concretize_lengths
379
373
380
374
void string_refinementt::concretize_lengths ()
381
375
{
382
- for (const auto & it : symbol_resolve)
376
+ for (const auto & it : symbol_resolve)
383
377
{
384
378
if (refined_string_typet::is_refined_string_type (it.second .type ()))
385
379
{
@@ -390,7 +384,7 @@ void string_refinementt::concretize_lengths()
390
384
found_length[content]=length;
391
385
}
392
386
}
393
- for (const auto & it : generator.created_strings )
387
+ for (const auto & it : generator.created_strings )
394
388
{
395
389
if (refined_string_typet::is_refined_string_type (it.type ()))
396
390
{
@@ -418,12 +412,6 @@ void string_refinementt::set_to(const exprt &expr, bool value)
418
412
{
419
413
assert (equality_propagation);
420
414
421
- // TODO: remove the mode field of generator since we should be language
422
- // independent.
423
- // We only set the mode once.
424
- if (generator.get_mode ()==ID_unknown)
425
- set_mode ();
426
-
427
415
if (expr.id ()==ID_equal)
428
416
{
429
417
equal_exprt eq_expr=to_equal_expr (expr);
@@ -695,7 +683,7 @@ exprt string_refinementt::get_array(const exprt &arr, const exprt &size) const
695
683
array_typet ret_type (char_type, from_integer (n, index_type));
696
684
array_exprt ret (ret_type);
697
685
698
- if (n>MAX_CONCRETE_STRING_SIZE )
686
+ if (n>generator. max_string_length )
699
687
{
700
688
#if 0
701
689
debug() << "(sr::get_array) long string (size=" << n << ")" << eom;
@@ -898,6 +886,125 @@ void string_refinementt::fill_model()
898
886
}
899
887
900
888
889
+ /* ******************************************************************\
890
+
891
+ Function: string_refinementt::substitute_array_with_expr()
892
+
893
+ Inputs:
894
+ expr - A (possibly nested) 'with' expression on an `array_of`
895
+ expression
896
+ index - An index with which to build the equality condition
897
+
898
+ Outputs: An expression containing no 'with' expression
899
+
900
+ Purpose: Create a new expression where 'with' expressions on arrays
901
+ are replaced by 'if' expressions.
902
+ e.g. for an array access arr[x], where:
903
+ `arr := array_of(12) with {0:=24} with {2:=42}`
904
+ the constructed expression will be:
905
+ `index==0 ? 24 : index==2 ? 42 : 12`
906
+
907
+ \*******************************************************************/
908
+
909
+ exprt string_refinementt::substitute_array_with_expr (
910
+ const exprt &expr, const exprt &index) const
911
+ {
912
+ if (expr.id ()==ID_with)
913
+ {
914
+ const with_exprt &with_expr=to_with_expr (expr);
915
+ const exprt &then_expr=with_expr.new_value ();
916
+ exprt else_expr=substitute_array_with_expr (with_expr.old (), index );
917
+ const typet &type=then_expr.type ();
918
+ assert (else_expr.type ()==type);
919
+ return if_exprt (
920
+ equal_exprt (index , with_expr.where ()), then_expr, else_expr, type);
921
+ }
922
+ else
923
+ {
924
+ // Only handle 'with' expressions on 'array_of' expressions.
925
+ assert (expr.id ()==ID_array_of);
926
+ return to_array_of_expr (expr).what ();
927
+ }
928
+ }
929
+
930
+ /* ******************************************************************\
931
+
932
+ Function: string_refinementt::substitute_array_access()
933
+
934
+ Inputs:
935
+ expr - an expression containing array accesses
936
+
937
+ Outputs: an expression containing no array access
938
+
939
+ Purpose: create an equivalent expression where array accesses and
940
+ 'with' expressions are replaced by 'if' expressions.
941
+ e.g. for an array access arr[x], where:
942
+ `arr := {12, 24, 48}`
943
+ the constructed expression will be:
944
+ `index==0 ? 12 : index==1 ? 24 : 48`
945
+
946
+ \*******************************************************************/
947
+
948
+ void string_refinementt::substitute_array_access (exprt &expr) const
949
+ {
950
+ for (auto &op : expr.operands ())
951
+ substitute_array_access (op);
952
+
953
+ if (expr.id ()==ID_index)
954
+ {
955
+ index_exprt &index_expr=to_index_expr (expr);
956
+
957
+ if (index_expr.array ().id ()==ID_symbol)
958
+ {
959
+ expr=index_expr;
960
+ return ;
961
+ }
962
+
963
+ if (index_expr.array ().id ()==ID_with)
964
+ {
965
+ expr=substitute_array_with_expr (
966
+ index_expr.array (), index_expr.index ());
967
+ return ;
968
+ }
969
+
970
+ if (index_expr.array ().id ()==ID_array_of)
971
+ {
972
+ expr=to_array_of_expr (index_expr.array ()).op ();
973
+ return ;
974
+ }
975
+
976
+ assert (index_expr.array ().id ()==ID_array);
977
+ array_exprt &array_expr=to_array_expr (index_expr.array ());
978
+
979
+ assert (!array_expr.operands ().empty ());
980
+ size_t last_index=array_expr.operands ().size ()-1 ;
981
+
982
+ const typet &char_type=index_expr.array ().type ().subtype ();
983
+ exprt ite=array_expr.operands ().back ();
984
+
985
+ if (ite.type ()!=char_type)
986
+ {
987
+ // We have to manualy set the type for unknown values
988
+ assert (ite.id ()==ID_unknown);
989
+ ite.type ()=char_type;
990
+ }
991
+
992
+ auto op_it=++array_expr.operands ().rbegin ();
993
+ for (size_t i=last_index-1 ;
994
+ op_it!=array_expr.operands ().rend (); ++op_it, --i)
995
+ {
996
+ equal_exprt equals (index_expr.index (), from_integer (i, java_int_type ()));
997
+ ite=if_exprt (equals, *op_it, ite);
998
+ if (ite.type ()!=char_type)
999
+ {
1000
+ assert (ite.id ()==ID_unknown);
1001
+ ite.type ()=char_type;
1002
+ }
1003
+ }
1004
+ expr=ite;
1005
+ }
1006
+ }
1007
+
901
1008
/* ******************************************************************\
902
1009
903
1010
Function: string_refinementt::add_negation_of_constraint_to_solver
@@ -942,6 +1049,7 @@ void string_refinementt::add_negation_of_constraint_to_solver(
942
1049
and_exprt negaxiom (premise, not_exprt (axiom.body ()));
943
1050
944
1051
debug () << " (sr::check_axioms) negated axiom: " << from_expr (negaxiom) << eom;
1052
+ substitute_array_access (negaxiom);
945
1053
solver << negaxiom;
946
1054
}
947
1055
@@ -982,6 +1090,7 @@ bool string_refinementt::check_axioms()
982
1090
983
1091
satcheck_no_simplifiert sat_check;
984
1092
supert solver (ns, sat_check);
1093
+ solver.set_ui (ui);
985
1094
add_negation_of_constraint_to_solver (axiom_in_model, solver);
986
1095
987
1096
switch (solver ())
@@ -1036,6 +1145,7 @@ bool string_refinementt::check_axioms()
1036
1145
exprt premise (axiom.premise ());
1037
1146
exprt body (axiom.body ());
1038
1147
implies_exprt instance (premise, body);
1148
+ replace_expr (symbol_resolve, instance);
1039
1149
replace_expr (axiom.univ_var (), val, instance);
1040
1150
debug () << " adding counter example " << from_expr (instance) << eom;
1041
1151
add_lemma (instance);
0 commit comments