Skip to content

Commit 30b874c

Browse files
Merge pull request #4995 from romainbrenguier/clean-up/string-constraint-generator
Clean up string constraint generator class
2 parents bcaf5f6 + 3cc0c72 commit 30b874c

5 files changed

+46
-43
lines changed

src/solvers/strings/string_constraint_generator.h

+9-12
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ struct string_constraintst final
3737
std::vector<exprt> existential;
3838
std::vector<string_constraintt> universal;
3939
std::vector<string_not_contains_constraintt> not_contains;
40-
41-
/// Clear all constraints
42-
void clear();
4340
};
4441

4542
void merge(string_constraintst &result, string_constraintst other);
@@ -60,23 +57,23 @@ class string_constraint_generatort final
6057

6158
array_poolt array_pool;
6259

63-
string_constraintst constraints;
64-
6560
const namespacet ns;
6661

6762
/// Associate array to pointer, and array to length
6863
/// \return an expression if the given function application is one of
6964
/// associate pointer and associate length
70-
optionalt<exprt>
71-
make_array_pointer_association(const function_application_exprt &expr);
65+
optionalt<exprt> make_array_pointer_association(
66+
const exprt &return_code,
67+
const function_application_exprt &expr);
7268

7369
private:
74-
exprt associate_array_to_pointer(const function_application_exprt &f);
75-
76-
exprt associate_length_to_array(const function_application_exprt &f);
70+
exprt associate_array_to_pointer(
71+
const exprt &return_code,
72+
const function_application_exprt &f);
7773

78-
// MEMBERS
79-
const messaget message;
74+
exprt associate_length_to_array(
75+
const exprt &return_code,
76+
const function_application_exprt &f);
8077
};
8178

8279
// Type used by primitives to signal errors

src/solvers/strings/string_constraint_generator_main.cpp

+12-13
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,12 @@ exprt sum_overflows(const plus_exprt &sum)
5555
/// Insert in `array_pool` a binding from `ptr` to `arr`. If the length of `arr`
5656
/// is infinite, a new integer symbol is created and stored in `array_pool`.
5757
/// This also adds the default axioms for `arr`.
58+
/// \param return_code: expression which is assigned the result of the function
5859
/// \param f: a function application with argument a character array `arr` and
5960
/// a character pointer `ptr`.
61+
/// \return a constraint
6062
exprt string_constraint_generatort::associate_array_to_pointer(
63+
const exprt &return_code,
6164
const function_application_exprt &f)
6265
{
6366
PRECONDITION(f.arguments().size() == 2);
@@ -71,31 +74,26 @@ exprt string_constraint_generatort::associate_array_to_pointer(
7174
const exprt &pointer_expr = f.arguments()[1];
7275
array_pool.insert(simplify_expr(pointer_expr, ns), array_expr);
7376
// created_strings.emplace(to_array_string_expr(array_expr));
74-
return from_integer(0, f.type());
77+
return equal_exprt{return_code, from_integer(0, f.type())};
7578
}
7679

7780
/// Associate an integer length to a char array.
7881
/// This adds an axiom ensuring that `arr.length` and `length` are equal.
82+
/// \param return_code: expression which is assigned the result of the function
7983
/// \param f: a function application with argument a character array `arr` and
8084
/// an integer `length`.
81-
/// \return integer expression equal to 0
85+
/// \return a constraint
8286
exprt string_constraint_generatort::associate_length_to_array(
87+
const exprt &return_code,
8388
const function_application_exprt &f)
8489
{
8590
PRECONDITION(f.arguments().size() == 2);
8691
array_string_exprt array_expr = to_array_string_expr(f.arguments()[0]);
8792
const exprt &new_length = f.arguments()[1];
8893

8994
const auto &length = array_pool.get_or_create_length(array_expr);
90-
constraints.existential.push_back(equal_exprt(length, new_length));
91-
return from_integer(0, f.type());
92-
}
93-
94-
void string_constraintst::clear()
95-
{
96-
existential.clear();
97-
universal.clear();
98-
not_contains.clear();
95+
return and_exprt{equal_exprt{return_code, from_integer(0, f.type())},
96+
equal_exprt(length, new_length)};
9997
}
10098

10199
/// Merge two sets of constraints by appending to the first one
@@ -200,13 +198,14 @@ static irep_idt get_function_name(const function_application_exprt &expr)
200198
}
201199

202200
optionalt<exprt> string_constraint_generatort::make_array_pointer_association(
201+
const exprt &return_code,
203202
const function_application_exprt &expr)
204203
{
205204
const irep_idt &id = get_function_name(expr);
206205
if(id == ID_cprover_associate_array_to_pointer_func)
207-
return associate_array_to_pointer(expr);
206+
return associate_array_to_pointer(return_code, expr);
208207
else if(id == ID_cprover_associate_length_to_array_func)
209-
return associate_length_to_array(expr);
208+
return associate_length_to_array(return_code, expr);
210209
return {};
211210
}
212211

src/solvers/strings/string_dependencies.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ void string_dependenciest::output_dot(std::ostream &stream) const
328328
stream << '}' << std::endl;
329329
}
330330

331-
void string_dependenciest::add_constraints(
332-
string_constraint_generatort &generator)
331+
string_constraintst
332+
string_dependenciest::add_constraints(string_constraint_generatort &generator)
333333
{
334334
std::unordered_set<nodet, node_hash> test_dependencies;
335335
for(const auto &builtin : builtin_function_nodes)
@@ -346,16 +346,16 @@ void string_dependenciest::add_constraints(
346346
for_each_successor(n, f);
347347
});
348348

349+
string_constraintst constraints;
349350
for(const auto &node : builtin_function_nodes)
350351
{
351352
if(test_dependencies.count(nodet(node)))
352353
{
353354
const auto &builtin = builtin_function_nodes[node.index];
354-
string_constraintst constraints = builtin.data->constraints(generator);
355-
merge(generator.constraints, std::move(constraints));
355+
merge(constraints, builtin.data->constraints(generator));
356356
}
357357
else
358-
generator.constraints.existential.push_back(
359-
node.data->length_constraint());
358+
constraints.existential.push_back(node.data->length_constraint());
360359
}
360+
return constraints;
361361
}

src/solvers/strings/string_dependencies.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Author: Diffblue Ltd.
1414

1515
#include <memory>
1616

17+
#include <util/nodiscard.h>
18+
1719
#include "string_builtin_function.h"
1820

1921
/// Keep track of dependencies between strings.
@@ -114,7 +116,8 @@ class string_dependenciest
114116
/// For all builtin call on which a test (or an unsupported buitin)
115117
/// result depends, add the corresponding constraints. For the other builtin
116118
/// only add constraints on the length.
117-
void add_constraints(string_constraint_generatort &generatort);
119+
NODISCARD string_constraintst
120+
add_constraints(string_constraint_generatort &generatort);
118121

119122
/// Clear the content of the dependency graph
120123
void clear();

src/solvers/strings/string_refinement.cpp

+15-11
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,13 @@ static void make_char_array_pointer_associations(
251251
const auto fun_app =
252252
expr_try_dynamic_cast<function_application_exprt>(eq.rhs()))
253253
{
254-
if(const auto result = generator.make_array_pointer_association(*fun_app))
255-
eq.rhs() = *result;
254+
const auto new_equation =
255+
generator.make_array_pointer_association(eq.lhs(), *fun_app);
256+
if(new_equation)
257+
{
258+
eq =
259+
equal_exprt{from_integer(true, new_equation->type()), *new_equation};
260+
}
256261
}
257262
}
258263
}
@@ -645,9 +650,8 @@ decision_proceduret::resultt string_refinementt::dec_solve()
645650
}
646651
}
647652

648-
// Generator is also used by get, so we have to use it as a class member
649-
// but we make sure it is cleared at each `dec_solve` call.
650-
generator.constraints.clear();
653+
// Constraints start clear at each `dec_solve` call.
654+
string_constraintst constraints;
651655
make_char_array_pointer_associations(generator, equations);
652656

653657
#ifdef DEBUG
@@ -677,7 +681,7 @@ decision_proceduret::resultt string_refinementt::dec_solve()
677681
#endif
678682

679683
log.debug() << "dec_solve: add constraints" << messaget::eom;
680-
dependencies.add_constraints(generator);
684+
merge(constraints, dependencies.add_constraints(generator));
681685

682686
#ifdef DEBUG
683687
output_equations(log.debug(), equations);
@@ -702,8 +706,8 @@ decision_proceduret::resultt string_refinementt::dec_solve()
702706
}
703707

704708
std::transform(
705-
generator.constraints.universal.begin(),
706-
generator.constraints.universal.end(),
709+
constraints.universal.begin(),
710+
constraints.universal.end(),
707711
std::back_inserter(axioms.universal),
708712
[&](string_constraintt constraint) {
709713
constraint.replace_expr(symbol_resolve);
@@ -715,8 +719,8 @@ decision_proceduret::resultt string_refinementt::dec_solve()
715719
});
716720

717721
std::transform(
718-
generator.constraints.not_contains.begin(),
719-
generator.constraints.not_contains.end(),
722+
constraints.not_contains.begin(),
723+
constraints.not_contains.end(),
720724
std::back_inserter(axioms.not_contains),
721725
[&](string_not_contains_constraintt axiom) {
722726
replace(symbol_resolve, axiom);
@@ -737,7 +741,7 @@ decision_proceduret::resultt string_refinementt::dec_solve()
737741
nc_axiom, generator.fresh_symbol("not_contains_witness", witness_type));
738742
}
739743

740-
for(const exprt &lemma : generator.constraints.existential)
744+
for(const exprt &lemma : constraints.existential)
741745
{
742746
add_lemma(substitute_array_access(lemma, generator.fresh_symbol, true));
743747
}

0 commit comments

Comments
 (0)