@@ -49,35 +49,20 @@ string_refinementt::string_refinementt(
4949
5050/* ******************************************************************\
5151
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-
6952Function: string_refinementt::set_max_string_length
7053
7154 Inputs:
7255 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.
7459
7560 Purpose: Add constraints on the size of strings used in the
7661 program.
7762
7863\*******************************************************************/
7964
80- void string_refinementt::set_max_string_length (int i)
65+ void string_refinementt::set_max_string_length (size_t i)
8166{
8267 generator.max_string_length =i;
8368}
@@ -355,16 +340,18 @@ void string_refinementt::concretize_string(const exprt &expr)
355340 if (!to_integer (length, found_length))
356341 {
357342 assert (found_length.is_long ());
358- if (found_length < 0 )
343+ if (found_length< 0 )
359344 {
345+ // Lengths should not be negative.
346+ // TODO: Add constraints no the sign of string lengths.
360347 debug () << " concretize_results: WARNING found length is negative"
361348 << eom;
362349 }
363350 else
364351 {
365352 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;
368355 exprt content_expr=str.content ();
369356 for (size_t i=0 ; i<concretize_limit; ++i)
370357 {
@@ -391,9 +378,9 @@ Function: string_refinementt::concretize_results
391378
392379void string_refinementt::concretize_results ()
393380{
394- for (const auto & it : symbol_resolve)
381+ for (const auto & it : symbol_resolve)
395382 concretize_string (it.second );
396- for (const auto & it : generator.created_strings )
383+ for (const auto & it : generator.created_strings )
397384 concretize_string (it);
398385 add_instantiations ();
399386}
@@ -409,7 +396,7 @@ Function: string_refinementt::concretize_lengths
409396
410397void string_refinementt::concretize_lengths ()
411398{
412- for (const auto & it : symbol_resolve)
399+ for (const auto & it : symbol_resolve)
413400 {
414401 if (refined_string_typet::is_refined_string_type (it.second .type ()))
415402 {
@@ -420,7 +407,7 @@ void string_refinementt::concretize_lengths()
420407 found_length[content]=length;
421408 }
422409 }
423- for (const auto & it : generator.created_strings )
410+ for (const auto & it : generator.created_strings )
424411 {
425412 if (refined_string_typet::is_refined_string_type (it.type ()))
426413 {
@@ -448,12 +435,6 @@ void string_refinementt::set_to(const exprt &expr, bool value)
448435{
449436 assert (equality_propagation);
450437
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-
457438 if (expr.id ()==ID_equal)
458439 {
459440 equal_exprt eq_expr=to_equal_expr (expr);
@@ -743,7 +724,7 @@ exprt string_refinementt::get_array(const exprt &arr, const exprt &size) const
743724 array_typet ret_type (char_type, from_integer (n, index_type));
744725 array_exprt ret (ret_type);
745726
746- if (n>MAX_CONCRETE_STRING_SIZE )
727+ if (n>generator. max_string_length )
747728 {
748729#if 0
749730 debug() << "(sr::get_array) long string (size=" << n << ")" << eom;
@@ -947,6 +928,125 @@ void string_refinementt::fill_model()
947928}
948929
949930
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+
9501050/* ******************************************************************\
9511051
9521052Function: string_refinementt::add_negation_of_constraint_to_solver
@@ -991,6 +1091,7 @@ void string_refinementt::add_negation_of_constraint_to_solver(
9911091 and_exprt negaxiom (premise, not_exprt (axiom.body ()));
9921092
9931093 debug () << " (sr::check_axioms) negated axiom: " << from_expr (negaxiom) << eom;
1094+ substitute_array_access (negaxiom);
9941095 solver << negaxiom;
9951096}
9961097
@@ -1031,6 +1132,7 @@ bool string_refinementt::check_axioms()
10311132
10321133 satcheck_no_simplifiert sat_check;
10331134 supert solver (ns, sat_check);
1135+ solver.set_ui (ui);
10341136 add_negation_of_constraint_to_solver (axiom_in_model, solver);
10351137
10361138 switch (solver ())
@@ -1085,6 +1187,7 @@ bool string_refinementt::check_axioms()
10851187 exprt premise (axiom.premise ());
10861188 exprt body (axiom.body ());
10871189 implies_exprt instance (premise, body);
1190+ replace_expr (symbol_resolve, instance);
10881191 replace_expr (axiom.univ_var (), val, instance);
10891192 debug () << " adding counter example " << from_expr (instance) << eom;
10901193 add_lemma (instance);
0 commit comments