Skip to content

Commit 27f2894

Browse files
Make more general interval_constraint function in util.
It is undesirable to have dependencies on the string solver, so char_printable_constraintss has been moved into util and made more general.
1 parent 92ecc4e commit 27f2894

File tree

12 files changed

+149
-84
lines changed

12 files changed

+149
-84
lines changed

jbmc/src/java_bytecode/java_object_factory.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Author: Daniel Kroening, [email protected]
1717

1818
#include <goto-programs/class_identifier.h>
1919
#include <goto-programs/goto_functions.h>
20-
#include <solvers/strings/string_constraint_generator.h>
20+
#include <util/interval_constraint.h>
2121

2222
#include "generic_parameter_specialization_map_keys.h"
2323
#include "java_root_class.h"
@@ -304,10 +304,19 @@ class recursion_set_entryt
304304
}
305305
};
306306

307-
/// A range of the form [low_char]-[high-char] that represents the set of
308-
/// printable characters for the string-printable option. The printable
309-
/// characters are in the range U+0020-U+007E, i.e. ' ' to '~'
310-
const char printable_char_range[] = " -~";
307+
/// Interval that represents the printable character range
308+
/// range U+0020-U+007E, i.e. ' ' to '~'
309+
const integer_intervalt printable_char_range(' ', '~');
310+
311+
/// Converts and \ref integer_intervalt to a a string of the for [lower]-[upper]
312+
static irep_idt integer_interval_to_string(const integer_intervalt &interval)
313+
{
314+
std::string result;
315+
result += numeric_cast_v<char>(interval.lower);
316+
result += "-";
317+
result += numeric_cast_v<char>(interval.upper);
318+
return result;
319+
}
311320

312321
/// Initialise length and data fields for a nondeterministic String structure.
313322
///
@@ -425,7 +434,7 @@ void initialize_nondet_string_fields(
425434
add_character_set_constraint(
426435
array_pointer,
427436
length_expr,
428-
printable_char_range,
437+
integer_interval_to_string(printable_char_range),
429438
symbol_table,
430439
loc,
431440
function_id,
@@ -1054,7 +1063,7 @@ void java_object_factoryt::gen_nondet_init(
10541063
if(type == java_char_type() && object_factory_parameters.string_printable)
10551064
{
10561065
assignments.add(
1057-
code_assumet(char_range_constraints(expr, printable_char_range)));
1066+
code_assumet(interval_constraint(expr, printable_char_range)));
10581067
}
10591068
// add assumes to obey numerical restrictions
10601069
if(type != java_boolean_type() && type != java_char_type())

jbmc/src/java_bytecode/java_string_library_preprocess.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ void add_array_to_length_association(
669669
/// belong to the character set.
670670
/// \param pointer: a character pointer expression
671671
/// \param length: length of the character sequence pointed by `pointer`
672-
/// \param char_set: character set given by a range expression consisting of
672+
/// \param char_range: character set given by a range expression consisting of
673673
/// two characters separated by an hyphen. For instance "a-z" denotes all
674674
/// lower case ascii letters.
675675
/// \param symbol_table: the symbol table
@@ -679,7 +679,7 @@ void add_array_to_length_association(
679679
void add_character_set_constraint(
680680
const exprt &pointer,
681681
const exprt &length,
682-
const irep_idt &char_set,
682+
const irep_idt &char_range,
683683
symbol_table_baset &symbol_table,
684684
const source_locationt &loc,
685685
const irep_idt &function_id,
@@ -690,7 +690,7 @@ void add_character_set_constraint(
690690
java_int_type(), "cnstr_added", loc, function_id, symbol_table);
691691
const auto return_expr = return_sym.symbol_expr();
692692
code.add(code_declt(return_expr), loc);
693-
const constant_exprt char_set_expr(char_set, string_typet());
693+
const constant_exprt char_set_expr(char_range, string_typet());
694694
code.add(
695695
code_assign_function_application(
696696
return_expr,

jbmc/src/java_bytecode/java_string_library_preprocess.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ void add_array_to_length_association(
334334
void add_character_set_constraint(
335335
const exprt &pointer,
336336
const exprt &length,
337-
const irep_idt &char_set,
337+
const irep_idt &char_range,
338338
symbol_table_baset &symbol_table,
339339
const source_locationt &loc,
340340
const irep_idt &function_id,

src/solvers/strings/string_constraint_generator.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,6 @@ std::pair<exprt, string_constraintst> add_axioms_for_string_of_int_with_radix(
111111
const namespacet &ns,
112112
array_poolt &array_pool);
113113

114-
/// Given an exprt and a string representing a character range of the form
115-
/// [low_char]-[high_char], return an and_exprt that represents restricting
116-
/// the selection of the character to the range.
117-
exprt char_range_constraints(const exprt &expr, const std::string &char_range);
118-
119114
string_constraintst add_constraint_on_characters(
120115
symbol_generatort &fresh_symbol,
121116
const array_string_exprt &s,

src/solvers/strings/string_constraint_generator_main.cpp

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Author: Romain Brenguier, [email protected]
2929
#include <util/simplify_expr.h>
3030
#include <util/ssa_expr.h>
3131
#include <util/string_constant.h>
32+
#include <util/interval_constraint.h>
3233

3334
string_constraint_generatort::string_constraint_generatort(const namespacet &ns)
3435
: array_pool(fresh_symbol), ns(ns)
@@ -114,23 +115,6 @@ void merge(string_constraintst &result, string_constraintst other)
114115
std::back_inserter(result.not_contains));
115116
}
116117

117-
exprt char_range_constraints(const exprt &expr, const std::string &char_range)
118-
{
119-
// Parse char_set
120-
PRECONDITION(char_range.length() == 3);
121-
PRECONDITION(char_range[1] == '-');
122-
const char &low_char = char_range[0];
123-
const char &high_char = char_range[2];
124-
INVARIANT(
125-
low_char <= high_char,
126-
"The lower character must be smaller or equal to the high character.");
127-
128-
// expr >= low_char && expr <= high_char
129-
return and_exprt(
130-
binary_relation_exprt(expr, ID_ge, from_integer(low_char, expr.type())),
131-
binary_relation_exprt(expr, ID_le, from_integer(high_char, expr.type())));
132-
}
133-
134118
/// Add constraint on characters of a string.
135119
///
136120
/// This constraint is
@@ -153,14 +137,19 @@ string_constraintst add_constraint_on_characters(
153137
const std::string &char_set,
154138
array_poolt &array_pool)
155139
{
140+
// Parse char_set
141+
PRECONDITION(char_set.length() == 3);
142+
PRECONDITION(char_set[1] == '-');
143+
const integer_intervalt char_range(char_set[0], char_set[2]);
144+
156145
// Add constraint
157146
const symbol_exprt qvar = fresh_symbol("char_constr", s.length_type());
158147
const exprt chr = s[qvar];
159148
const string_constraintt sc(
160149
qvar,
161150
zero_if_negative(start),
162151
zero_if_negative(end),
163-
char_range_constraints(chr, char_set));
152+
interval_constraint(chr, char_range));
164153
return {{}, {sc}, {}};
165154
}
166155

src/util/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ SRC = allocate_objects.cpp \
3434
irep_hash_container.cpp \
3535
irep_ids.cpp \
3636
irep_serialization.cpp \
37+
interval_constraint.cpp \
3738
invariant_utils.cpp \
3839
json.cpp \
3940
json_irep.cpp \

src/util/interval_constraint.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*******************************************************************\
2+
3+
Module: Interval constraint
4+
5+
Author: Jeannie Moulton
6+
7+
\*******************************************************************/
8+
9+
#include "interval_constraint.h"
10+
#include "arith_tools.h"
11+
12+
exprt interval_constraint(const exprt &expr, const integer_intervalt &interval)
13+
{
14+
// expr >= lower_bound && expr <= upper_bound
15+
return and_exprt(
16+
binary_relation_exprt(
17+
expr, ID_ge, from_integer(interval.lower, expr.type())),
18+
binary_relation_exprt(
19+
expr, ID_le, from_integer(interval.upper, expr.type())));
20+
}

src/util/interval_constraint.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*******************************************************************\
2+
3+
Module: Interval constraint
4+
5+
Author: Jeannie Moulton
6+
7+
\*******************************************************************/
8+
9+
#ifndef CPROVER_UTIL_INTERVAL_CONSTRAINT_H
10+
#define CPROVER_UTIL_INTERVAL_CONSTRAINT_H
11+
12+
#include "integer_interval.h"
13+
14+
class exprt;
15+
16+
/// Given an exprt and an integer interval return an exprt that represents
17+
/// restricting the expression to the range in the interval (inclusive).
18+
exprt interval_constraint(const exprt &expr, const integer_intervalt &interval);
19+
20+
#endif // CPROVER_UTIL_INTERVAL_CONSTRAINT_H

unit/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ SRC += analyses/ai/ai.cpp \
5050
solvers/prop/bdd_expr.cpp \
5151
solvers/sat/satcheck_minisat2.cpp \
5252
solvers/strings/array_pool/array_pool.cpp \
53-
solvers/strings/string_constraint_generator_main/char_range_constraints.cpp \
5453
solvers/strings/string_constraint_generator_valueof/calculate_max_string_length.cpp \
5554
solvers/strings/string_constraint_generator_valueof/get_numeric_value_from_character.cpp \
5655
solvers/strings/string_constraint_generator_valueof/is_digit_with_radix.cpp \
@@ -69,6 +68,7 @@ SRC += analyses/ai/ai.cpp \
6968
util/format_number_range.cpp \
7069
util/get_base_name.cpp \
7170
util/graph.cpp \
71+
util/interval_constraint.cpp \
7272
util/irep.cpp \
7373
util/irep_sharing.cpp \
7474
util/json_array.cpp \

unit/solvers/strings/string_constraint_generator_main/char_range_constraints.cpp

Lines changed: 0 additions & 46 deletions
This file was deleted.

unit/solvers/strings/string_constraint_generator_main/module_dependencies.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

unit/util/interval_constraint.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for interval_constraint in
4+
util/interval_constraint.cpp
5+
6+
Author: Diffblue Ltd.
7+
8+
\*******************************************************************/
9+
10+
#include <testing-utils/use_catch.h>
11+
12+
#include <util/interval_constraint.h>
13+
#include <util/std_expr.h>
14+
#include <util/std_types.h>
15+
16+
SCENARIO(
17+
"interval_constraint with characters",
18+
"[core][util][interval_constraint]")
19+
{
20+
GIVEN("A string representing a character range and an character expression")
21+
{
22+
const integer_intervalt char_range('a', 'z');
23+
const exprt expr{"dummy", unsignedbv_typet(16)};
24+
25+
WHEN("interval_constraint is called")
26+
{
27+
const auto result = interval_constraint(expr, char_range);
28+
29+
THEN(
30+
"expect that the result is an and_exprt with two inequality "
31+
"expressions representing a <= expr && expr <= z")
32+
{
33+
REQUIRE(can_cast_expr<and_exprt>(result));
34+
35+
REQUIRE(result.op0().id() == ID_ge);
36+
REQUIRE(result.op0().op0().type() == unsignedbv_typet(16));
37+
REQUIRE(can_cast_expr<constant_exprt>(result.op0().op1()));
38+
REQUIRE(to_constant_expr(result.op0().op1()).get_value() == "61"); // a
39+
40+
REQUIRE(result.op1().id() == ID_le);
41+
REQUIRE(result.op1().op0().type() == unsignedbv_typet(16));
42+
REQUIRE(can_cast_expr<constant_exprt>(result.op1().op1()));
43+
REQUIRE(to_constant_expr(result.op1().op1()).get_value() == "7A"); // b
44+
}
45+
}
46+
}
47+
}
48+
49+
SCENARIO(
50+
"interval_constraint with integers",
51+
"[core][util][interval_constraint]")
52+
{
53+
GIVEN("A string representing a int range and an int expression")
54+
{
55+
const integer_intervalt int_range(6, 9);
56+
const exprt expr{"dummy", unsignedbv_typet(32)};
57+
58+
WHEN("interval_constraint is called")
59+
{
60+
const auto result = interval_constraint(expr, int_range);
61+
62+
THEN(
63+
"expect that the result is an and_exprt with two inequality "
64+
"expressions representing 6 <= expr && expr <= 9")
65+
{
66+
REQUIRE(can_cast_expr<and_exprt>(result));
67+
68+
REQUIRE(result.op0().id() == ID_ge);
69+
REQUIRE(result.op0().op0().type() == unsignedbv_typet(32));
70+
REQUIRE(can_cast_expr<constant_exprt>(result.op0().op1()));
71+
REQUIRE(to_constant_expr(result.op0().op1()).get_value() == "6");
72+
73+
REQUIRE(result.op1().id() == ID_le);
74+
REQUIRE(result.op1().op0().type() == unsignedbv_typet(32));
75+
REQUIRE(can_cast_expr<constant_exprt>(result.op1().op1()));
76+
REQUIRE(to_constant_expr(result.op1().op1()).get_value() == "9");
77+
}
78+
}
79+
}
80+
}

0 commit comments

Comments
 (0)