Skip to content

Commit 23290f4

Browse files
authored
Merge pull request #4068 from tautschnig/fix-simplify_function_application
simplify_function_application: do not assume that a symbol always has a value
2 parents 6eaff21 + 79c76a7 commit 23290f4

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed
Binary file not shown.

jbmc/regression/jbmc-strings/StartsWithConstantEvalution/RefineStrings.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ public class RefineStrings {
44
public void constantComparison() {
55
String helloWorld = "Hello world";
66
assert helloWorld.equals(helloWorld());
7+
assert helloWorld.startsWith("Hello");
8+
assert helloWorld.startsWith("ello", 1);
9+
assert !helloWorld.startsWith("ello", -1);
710
}
811

912
public String helloWorld() {

src/util/simplify_expr.cpp

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,15 @@ bool simplify_exprt::simplify_function_application(exprt &expr)
184184
return true;
185185
}
186186

187+
mp_integer offset_int = 0;
188+
if(function_app.arguments().size() == 3)
189+
{
190+
auto &offset = function_app.arguments()[2];
191+
if(offset.id() != ID_constant)
192+
return true;
193+
offset_int = numeric_cast_v<mp_integer>(to_constant_expr(offset));
194+
}
195+
187196
const address_of_exprt &first_address_of =
188197
to_address_of_expr(first_argument.content());
189198
const address_of_exprt &second_address_of =
@@ -214,19 +223,46 @@ bool simplify_exprt::simplify_function_application(exprt &expr)
214223
return true;
215224
}
216225

217-
// If so, it'll be a string array that we can use.
218-
const array_string_exprt &first_string = to_array_string_expr(
219-
ns.lookup(first_string_array.get(ID_identifier)).value);
226+
// get their initial values from the symbol table
227+
const symbolt *symbol_ptr = nullptr;
228+
if(ns.lookup(
229+
to_symbol_expr(first_string_array).get_identifier(), symbol_ptr))
230+
return true;
231+
const exprt &first_value = symbol_ptr->value;
232+
if(ns.lookup(
233+
to_symbol_expr(second_string_array).get_identifier(), symbol_ptr))
234+
return true;
235+
const exprt &second_value = symbol_ptr->value;
220236

221-
const array_string_exprt &second_string = to_array_string_expr(
222-
ns.lookup(second_string_array.get(ID_identifier)).value);
237+
// only compare if both are arrays
238+
if(first_value.id() != ID_array || second_value.id() != ID_array)
239+
return true;
223240

224-
// If the lengths are the same we can do the .equals substitute.
225-
if(first_string.length() == second_string.length())
241+
// test whether second_value is a prefix of first_value
242+
bool is_prefix =
243+
offset_int >= 0 && mp_integer(first_value.operands().size()) >=
244+
offset_int + second_value.operands().size();
245+
if(is_prefix)
226246
{
227-
expr = from_integer(first_string == second_string ? 1 : 0, expr.type());
228-
return false;
247+
exprt::operandst::const_iterator second_it =
248+
second_value.operands().begin();
249+
for(const auto &first_op : first_value.operands())
250+
{
251+
if(offset_int > 0)
252+
--offset_int;
253+
else if(second_it == second_value.operands().end())
254+
break;
255+
else if(first_op != *second_it)
256+
{
257+
is_prefix = false;
258+
break;
259+
}
260+
else
261+
++second_it;
262+
}
229263
}
264+
expr = from_integer(is_prefix ? 1 : 0, expr.type());
265+
return false;
230266
}
231267

232268
return true;

0 commit comments

Comments
 (0)