Skip to content

Commit a9de859

Browse files
authored
Merge pull request #1001 from allredj/pr/add-axioms-for-concat-substr
Add add_axioms_for_concat_substr
2 parents f84d96b + cf39c29 commit a9de859

File tree

3 files changed

+87
-46
lines changed

3 files changed

+87
-46
lines changed

regression/strings-smoke-tests/java_replace/test.desc

+2
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,5 @@ test_replace.class
66
^VERIFICATION SUCCESSFUL$
77
--
88
diffblue/test-gen#256
9+
This test is only effective with a model of
10+
java.lang.String.replace(LCharSequence; LCharSequence).

src/solvers/refinement/string_constraint_generator.h

+5
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ class string_constraint_generatort
145145
string_exprt add_axioms_for_copy(const function_application_exprt &f);
146146
string_exprt add_axioms_for_concat(
147147
const string_exprt &s1, const string_exprt &s2);
148+
string_exprt add_axioms_for_concat_substr(
149+
const string_exprt &s1,
150+
const string_exprt &s2,
151+
const exprt &start_index,
152+
const exprt &end_index);
148153
string_exprt add_axioms_for_concat(const function_application_exprt &f);
149154
string_exprt add_axioms_for_concat_int(const function_application_exprt &f);
150155
string_exprt add_axioms_for_concat_long(const function_application_exprt &f);

src/solvers/refinement/string_constraint_generator_concat.cpp

+80-46
Original file line numberDiff line numberDiff line change
@@ -13,60 +13,98 @@ Author: Romain Brenguier, [email protected]
1313

1414
#include <solvers/refinement/string_constraint_generator.h>
1515

16-
/// add axioms to say that the returned string expression is equal to the
17-
/// concatenation of the two string expressions given as input
18-
/// \par parameters: two string expressions
16+
/// Add axioms to say that the returned string expression is equal to the
17+
/// concatenation of s1 with the substring of s2 starting at index start_index
18+
/// and ending at index end_index.
19+
///
20+
/// If start_index >= end_index, the value returned is s1.
21+
/// If end_index > |s2| and/or start_index < 0, the appended string will be of
22+
/// length end_index - start_index and padded with non-deterministic values.
23+
///
24+
/// \param s1: string expression
25+
/// \param s2: string expression
26+
/// \param start_index: expression representing an integer
27+
/// \param end_index: expression representing an integer
1928
/// \return a new string expression
20-
string_exprt string_constraint_generatort::add_axioms_for_concat(
21-
const string_exprt &s1, const string_exprt &s2)
29+
string_exprt string_constraint_generatort::add_axioms_for_concat_substr(
30+
const string_exprt &s1,
31+
const string_exprt &s2,
32+
const exprt &start_index,
33+
const exprt &end_index)
2234
{
2335
const refined_string_typet &ref_type=to_refined_string_type(s1.type());
2436
string_exprt res=fresh_string(ref_type);
2537

2638
// We add axioms:
27-
// a1 : |res|=|s1|+|s2|
28-
// a2 : |s1| <= |res| (to avoid overflow with very long strings)
29-
// a3 : |s2| <= |res| (to avoid overflow with very long strings)
30-
// a4 : forall i<|s1|. res[i]=s1[i]
31-
// a5 : forall i<|s2|. res[i+|s1|]=s2[i]
32-
33-
equal_exprt a1(
34-
res.length(), plus_exprt_with_overflow_check(s1.length(), s2.length()));
39+
// a1 : end_index > start_index => |res|=|s1|+ end_index - start_index
40+
// a2 : end_index <= start_index => res = s1
41+
// a3 : forall i<|s1|. res[i]=s1[i]
42+
// a4 : forall i< end_index - start_index. res[i+|s1|]=s2[start_index+i]
43+
44+
binary_relation_exprt prem(end_index, ID_gt, start_index);
45+
46+
exprt res_length=plus_exprt_with_overflow_check(
47+
s1.length(), minus_exprt(end_index, start_index));
48+
implies_exprt a1(prem, equal_exprt(res.length(), res_length));
3549
axioms.push_back(a1);
36-
axioms.push_back(s1.axiom_for_is_shorter_than(res));
37-
axioms.push_back(s2.axiom_for_is_shorter_than(res));
50+
51+
implies_exprt a2(not_exprt(prem), equal_exprt(res.length(), s1.length()));
52+
axioms.push_back(a2);
3853

3954
symbol_exprt idx=fresh_univ_index("QA_index_concat", res.length().type());
40-
string_constraintt a4(idx, s1.length(), equal_exprt(s1[idx], res[idx]));
41-
axioms.push_back(a4);
55+
string_constraintt a3(idx, s1.length(), equal_exprt(s1[idx], res[idx]));
56+
axioms.push_back(a3);
4257

4358
symbol_exprt idx2=fresh_univ_index("QA_index_concat2", res.length().type());
44-
equal_exprt res_eq(s2[idx2], res[plus_exprt(idx2, s1.length())]);
45-
string_constraintt a5(idx2, s2.length(), res_eq);
46-
axioms.push_back(a5);
59+
equal_exprt res_eq(
60+
res[plus_exprt(idx2, s1.length())], s2[plus_exprt(start_index, idx2)]);
61+
string_constraintt a4(idx2, minus_exprt(end_index, start_index), res_eq);
62+
axioms.push_back(a4);
4763

4864
return res;
4965
}
5066

51-
/// add axioms to say that the returned string expression is equal to the
52-
/// concatenation of the two string arguments of the function application
53-
/// \par parameters: function application with two arguments which are strings
67+
/// Add axioms to say that the returned string expression is equal to the
68+
/// concatenation of the two string expressions given as input.
69+
///
70+
/// \param s1: the string expression to append to
71+
/// \param s2: the string expression to append to the first one
72+
/// \return a new string expression
73+
string_exprt string_constraint_generatort::add_axioms_for_concat(
74+
const string_exprt &s1, const string_exprt &s2)
75+
{
76+
exprt index_zero=from_integer(0, s2.length().type());
77+
return add_axioms_for_concat_substr(s1, s2, index_zero, s2.length());
78+
}
79+
80+
/// Add axioms to say that the returned string expression is equal to the
81+
/// concatenation of the two string arguments of the function application.
82+
///
83+
/// In case 4 arguments instead of 2 are given the last two arguments are
84+
/// intepreted as a start index and last index from which we extract a substring
85+
/// of the second argument: this is similar to the Java
86+
/// StringBuilder.append(CharSequence s, int start, int end) method.
87+
///
88+
/// \param f: function application with two arguments which are strings
5489
/// \return a new string expression
5590
string_exprt string_constraint_generatort::add_axioms_for_concat(
5691
const function_application_exprt &f)
5792
{
5893
const function_application_exprt::argumentst &args=f.arguments();
59-
assert(args.size()==2);
60-
94+
PRECONDITION(args.size()>=2);
6195
string_exprt s1=get_string_expr(args[0]);
6296
string_exprt s2=get_string_expr(args[1]);
63-
97+
if(args.size()!=2)
98+
{
99+
PRECONDITION(args.size()==4);
100+
return add_axioms_for_concat_substr(s1, s2, args[2], args[3]);
101+
}
64102
return add_axioms_for_concat(s1, s2);
65103
}
66104

67-
/// add axioms corresponding to the StringBuilder.append(I) java function
68-
/// \par parameters: function application with two arguments: a string and an
69-
/// integer
105+
/// Add axioms corresponding to the StringBuilder.append(I) java function
106+
/// \param f: function application with two arguments: a string and an
107+
/// integer
70108
/// \return a new string expression
71109
string_exprt string_constraint_generatort::add_axioms_for_concat_int(
72110
const function_application_exprt &f)
@@ -79,8 +117,8 @@ string_exprt string_constraint_generatort::add_axioms_for_concat_int(
79117
}
80118

81119
/// Add axioms corresponding to the StringBuilder.append(J) java function
82-
/// \par parameters: function application with two arguments: a string and a
83-
/// integer of type long
120+
/// \param f: function application with two arguments: a string and an
121+
/// integer of type long
84122
/// \return a new string expression
85123
string_exprt string_constraint_generatort::add_axioms_for_concat_long(
86124
const function_application_exprt &f)
@@ -91,8 +129,8 @@ string_exprt string_constraint_generatort::add_axioms_for_concat_long(
91129
return add_axioms_for_concat(s1, s2);
92130
}
93131

94-
/// add axioms corresponding to the StringBuilder.append(Z) java function
95-
/// \par parameters: function application two arguments: a string and a bool
132+
/// Add axioms corresponding to the StringBuilder.append(Z) java function
133+
/// \param f: function application two arguments: a string and a bool
96134
/// \return a new string expression
97135
string_exprt string_constraint_generatort::add_axioms_for_concat_bool(
98136
const function_application_exprt &f)
@@ -103,9 +141,8 @@ string_exprt string_constraint_generatort::add_axioms_for_concat_bool(
103141
return add_axioms_for_concat(s1, s2);
104142
}
105143

106-
/// add axioms corresponding to the StringBuilder.append(C) java function
107-
/// \par parameters: function application with two arguments: a string and a
108-
/// char
144+
/// Add axioms corresponding to the StringBuilder.append(C) java function
145+
/// \param f: function application with two arguments: a string and a char
109146
/// \return a new string expression
110147
string_exprt string_constraint_generatort::add_axioms_for_concat_char(
111148
const function_application_exprt &f)
@@ -116,37 +153,34 @@ string_exprt string_constraint_generatort::add_axioms_for_concat_char(
116153
return add_axioms_for_concat(s1, s2);
117154
}
118155

119-
/// add axioms corresponding to the StringBuilder.append(D) java function
120-
/// \par parameters: function application with two arguments: a string and a
121-
/// double
156+
/// Add axioms corresponding to the StringBuilder.append(D) java function
157+
/// \param f: function application with two arguments: a string and a double
122158
/// \return a new string expression
123159
string_exprt string_constraint_generatort::add_axioms_for_concat_double(
124160
const function_application_exprt &f)
125161
{
126162
string_exprt s1=get_string_expr(args(f, 2)[0]);
127-
assert(refined_string_typet::is_refined_string_type(f.type()));
163+
PRECONDITION(refined_string_typet::is_refined_string_type(f.type()));
128164
refined_string_typet ref_type=to_refined_string_type(f.type());
129165
string_exprt s2=add_axioms_from_float(args(f, 2)[1], ref_type, true);
130166
return add_axioms_for_concat(s1, s2);
131167
}
132168

133-
/// add axioms corresponding to the StringBuilder.append(F) java function
134-
/// \par parameters: function application with two arguments: a string and a
135-
/// float
169+
/// Add axioms corresponding to the StringBuilder.append(F) java function
170+
/// \param f: function application with two arguments: a string and a float
136171
/// \return a new string expression
137172
string_exprt string_constraint_generatort::add_axioms_for_concat_float(
138173
const function_application_exprt &f)
139174
{
140175
string_exprt s1=get_string_expr(args(f, 2)[0]);
141-
assert(refined_string_typet::is_refined_string_type(f.type()));
176+
PRECONDITION(refined_string_typet::is_refined_string_type(f.type()));
142177
refined_string_typet ref_type=to_refined_string_type(f.type());
143178
string_exprt s2=add_axioms_from_float(args(f, 2)[1], ref_type, false);
144179
return add_axioms_for_concat(s1, s2);
145180
}
146181

147182
/// Add axioms corresponding to the StringBuilder.appendCodePoint(I) function
148-
/// \par parameters: function application with two arguments: a string and a
149-
/// code point
183+
/// \param f: function application with two arguments: a string and a code point
150184
/// \return a new string expression
151185
string_exprt string_constraint_generatort::add_axioms_for_concat_code_point(
152186
const function_application_exprt &f)

0 commit comments

Comments
 (0)