Skip to content

Commit e9ebd59

Browse files
committed
has_subtype(type, pred, ns) to search for contained type matching pred
This is the counterpart to has_subexpr; the previous local implementation in string_refinement_util is promoted to expr_util and extended to work with types that require a namespace lookup.
1 parent da63652 commit e9ebd59

File tree

7 files changed

+88
-72
lines changed

7 files changed

+88
-72
lines changed

src/solvers/refinement/string_refinement.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Author: Alberto Griggio, [email protected]
2323
#include <numeric>
2424
#include <stack>
2525
#include <util/expr_iterator.h>
26+
#include <util/expr_util.h>
2627
#include <util/simplify_expr.h>
2728
#include <solvers/sat/satcheck.h>
2829
#include <solvers/refinement/string_constraint_instantiation.h>
@@ -340,8 +341,8 @@ static union_find_replacet generate_symbol_resolution_from_equations(
340341
// function applications can be ignored because they will be replaced
341342
// in the convert_function_application step of dec_solve
342343
}
343-
else if(lhs.type().id() != ID_pointer &&
344-
has_char_pointer_subtype(lhs.type()))
344+
else if(
345+
lhs.type().id() != ID_pointer && has_char_pointer_subtype(lhs.type(), ns))
345346
{
346347
if(rhs.type().id() == ID_struct)
347348
{
@@ -432,7 +433,7 @@ static void add_string_equation_to_symbol_resolution(
432433
{
433434
symbol_resolve.make_union(eq.lhs(), eq.rhs());
434435
}
435-
else if(has_string_subtype(eq.lhs().type()))
436+
else if(has_subtype(eq.lhs().type(), ID_string, ns))
436437
{
437438
if(eq.rhs().type().id() == ID_struct)
438439
{
@@ -484,8 +485,9 @@ union_find_replacet string_identifiers_resolution_from_equations(
484485
for(const auto &expr : rhs_strings)
485486
equation_map.add(i, expr);
486487
}
487-
else if(eq.lhs().type().id() != ID_pointer &&
488-
has_string_subtype(eq.lhs().type()))
488+
else if(
489+
eq.lhs().type().id() != ID_pointer &&
490+
has_subtype(eq.lhs().type(), ID_string, ns))
489491
{
490492
std::vector<exprt> lhs_strings = extract_strings_from_lhs(eq.lhs());
491493

src/solvers/refinement/string_refinement_util.cpp

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <functional>
1212
#include <iostream>
1313
#include <util/arith_tools.h>
14+
#include <util/expr_util.h>
1415
#include <util/ssa_expr.h>
1516
#include <util/std_expr.h>
1617
#include <util/expr_iterator.h>
@@ -45,40 +46,9 @@ bool is_char_pointer_type(const typet &type)
4546
return type.id() == ID_pointer && is_char_type(type.subtype());
4647
}
4748

48-
bool has_subtype(
49-
const typet &type,
50-
const std::function<bool(const typet &)> &pred)
49+
bool has_char_pointer_subtype(const typet &type, const namespacet &ns)
5150
{
52-
if(pred(type))
53-
return true;
54-
55-
if(type.id() == ID_struct || type.id() == ID_union)
56-
{
57-
const struct_union_typet &struct_type = to_struct_union_type(type);
58-
return std::any_of(
59-
struct_type.components().begin(),
60-
struct_type.components().end(), // NOLINTNEXTLINE
61-
[&](const struct_union_typet::componentt &comp) {
62-
return has_subtype(comp.type(), pred);
63-
});
64-
}
65-
66-
return std::any_of( // NOLINTNEXTLINE
67-
type.subtypes().begin(), type.subtypes().end(), [&](const typet &t) {
68-
return has_subtype(t, pred);
69-
});
70-
}
71-
72-
bool has_char_pointer_subtype(const typet &type)
73-
{
74-
return has_subtype(type, is_char_pointer_type);
75-
}
76-
77-
bool has_string_subtype(const typet &type)
78-
{
79-
// NOLINTNEXTLINE
80-
return has_subtype(
81-
type, [](const typet &subtype) { return subtype == string_typet(); });
51+
return has_subtype(type, is_char_pointer_type, ns);
8252
}
8353

8454
bool has_char_array_subexpr(const exprt &expr, const namespacet &ns)

src/solvers/refinement/string_refinement_util.h

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,13 @@ bool is_char_array_type(const typet &type, const namespacet &ns);
3535
bool is_char_pointer_type(const typet &type);
3636

3737
/// \param type: a type
38-
/// \param pred: a predicate
39-
/// \return true if one of the subtype of `type` satisfies predicate `pred`.
40-
/// The meaning of "subtype" is in the algebraic datatype sense:
41-
/// for example, the subtypes of a struct are the types of its
42-
/// components, the subtype of a pointer is the type it points to,
43-
/// etc...
44-
/// For instance in the type `t` defined by
45-
/// `{ int a; char[] b; double * c; { bool d} e}`, `int`, `char`,
46-
/// `double` and `bool` are subtypes of `t`.
47-
bool has_subtype(
48-
const typet &type,
49-
const std::function<bool(const typet &)> &pred);
50-
51-
/// \param type: a type
38+
/// \param ns: namespace
5239
/// \return true if a subtype of `type` is an pointer of characters.
5340
/// The meaning of "subtype" is in the algebraic datatype sense:
5441
/// for example, the subtypes of a struct are the types of its
5542
/// components, the subtype of a pointer is the type it points to,
5643
/// etc...
57-
bool has_char_pointer_subtype(const typet &type);
58-
59-
/// \param type: a type
60-
/// \return true if a subtype of `type` is string_typet.
61-
/// The meaning of "subtype" is in the algebraic datatype sense:
62-
/// for example, the subtypes of a struct are the types of its
63-
/// components, the subtype of a pointer is the type it points to,
64-
/// etc...
65-
bool has_string_subtype(const typet &type);
44+
bool has_char_pointer_subtype(const typet &type, const namespacet &ns);
6645

6746
/// \param expr: an expression
6847
/// \param ns: namespace

src/util/expr_util.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,44 @@ bool has_subexpr(const exprt &src, const irep_idt &id)
132132
return false;
133133
}
134134

135+
bool has_subtype(
136+
const typet &type,
137+
const std::function<bool(const typet &)> &pred,
138+
const namespacet &ns)
139+
{
140+
if(pred(type))
141+
return true;
142+
else if(type.id() == ID_symbol)
143+
return has_subtype(ns.follow(type), pred, ns);
144+
else if(type.id() == ID_c_enum_tag)
145+
return has_subtype(ns.follow_tag(to_c_enum_tag_type(type)), pred, ns);
146+
else if(type.id() == ID_struct || type.id() == ID_union)
147+
{
148+
const struct_union_typet &struct_union_type = to_struct_union_type(type);
149+
150+
for(const auto &comp : struct_union_type.components())
151+
if(has_subtype(comp.type(), pred, ns))
152+
return true;
153+
}
154+
// do not look into pointer subtypes as this could cause unbounded recursion
155+
else if(type.id() == ID_array || type.id() == ID_vector)
156+
return has_subtype(type.subtype(), pred, ns);
157+
else if(type.has_subtypes())
158+
{
159+
for(const auto &subtype : type.subtypes())
160+
if(has_subtype(subtype, pred, ns))
161+
return true;
162+
}
163+
164+
return false;
165+
}
166+
167+
bool has_subtype(const typet &type, const irep_idt &id, const namespacet &ns)
168+
{
169+
return has_subtype(
170+
type, [&](const typet &subtype) { return subtype.id() == id; }, ns);
171+
}
172+
135173
if_exprt lift_if(const exprt &src, std::size_t operand_number)
136174
{
137175
PRECONDITION(operand_number<src.operands().size());

src/util/expr_util.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Author: Daniel Kroening, [email protected]
1919

2020
#include "irep.h"
2121

22+
#include <functional>
23+
2224
class exprt;
2325
class symbol_exprt;
2426
class update_exprt;
@@ -44,6 +46,26 @@ exprt boolean_negate(const exprt &);
4446
/// returns true if the expression has a subexpression with given ID
4547
bool has_subexpr(const exprt &, const irep_idt &);
4648

49+
/// returns true if any of the contained types satisfies pred
50+
/// \param type: a type
51+
/// \param pred: a predicate
52+
/// \param ns: namespace for symbol type lookups
53+
/// \return true if one of the subtype of `type` satisfies predicate `pred`.
54+
/// The meaning of "subtype" is in the algebraic datatype sense:
55+
/// for example, the subtypes of a struct are the types of its
56+
/// components, the subtype of a pointer is the type it points to,
57+
/// etc...
58+
/// For instance in the type `t` defined by
59+
/// `{ int a; char[] b; double * c; { bool d} e}`, `int`, `char`,
60+
/// `double` and `bool` are subtypes of `t`.
61+
bool has_subtype(
62+
const typet &type,
63+
const std::function<bool(const typet &)> &pred,
64+
const namespacet &ns);
65+
66+
/// returns true if any of the contained types is id
67+
bool has_subtype(const typet &, const irep_idt &id, const namespacet &);
68+
4769
/// lift up an if_exprt one level
4870
if_exprt lift_if(const exprt &, std::size_t operand_number);
4971

unit/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ SRC += unit_tests.cpp \
3838
solvers/refinement/string_constraint_instantiation/instantiate_not_contains.cpp \
3939
solvers/refinement/string_refinement/concretize_array.cpp \
4040
solvers/refinement/string_refinement/dependency_graph.cpp \
41-
solvers/refinement/string_refinement/has_subtype.cpp \
4241
solvers/refinement/string_refinement/substitute_array_list.cpp \
4342
solvers/refinement/string_refinement/string_symbol_resolution.cpp \
4443
solvers/refinement/string_refinement/sparse_array.cpp \
4544
solvers/refinement/string_refinement/union_find_replace.cpp \
4645
util/expr_cast/expr_cast.cpp \
4746
util/expr_iterator.cpp \
47+
util/has_subtype.cpp \
4848
util/irep.cpp \
4949
util/irep_sharing.cpp \
5050
util/message.cpp \
Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
/*******************************************************************\
22
3-
Module: Unit tests for has_subtype in
4-
solvers/refinement/string_refinement.cpp
3+
Module: Unit tests for has_subtype in expr_util.cpp
54
65
Author: Diffblue Ltd.
76
@@ -10,7 +9,10 @@
109
#include <testing-utils/catch.hpp>
1110

1211
#include <util/c_types.h>
13-
#include <solvers/refinement/string_refinement.h>
12+
#include <util/expr_util.h>
13+
#include <util/namespace.h>
14+
#include <util/symbol_table.h>
15+
1416
#include <java_bytecode/java_types.h>
1517

1618
// Curryfied version of type comparison.
@@ -23,12 +25,15 @@ static std::function<bool(const typet &)> is_type(const typet &t1)
2325

2426
SCENARIO("has_subtype", "[core][solvers][refinement][string_refinement]")
2527
{
28+
const symbol_tablet symbol_table;
29+
const namespacet ns(symbol_table);
30+
2631
const typet char_type = java_char_type();
2732
const typet int_type = java_int_type();
2833
const typet bool_type = java_boolean_type();
2934

30-
REQUIRE(has_subtype(char_type, is_type(char_type)));
31-
REQUIRE_FALSE(has_subtype(char_type, is_type(int_type)));
35+
REQUIRE(has_subtype(char_type, is_type(char_type), ns));
36+
REQUIRE_FALSE(has_subtype(char_type, is_type(int_type), ns));
3237

3338
GIVEN("a struct with char and int fields")
3439
{
@@ -37,12 +42,12 @@ SCENARIO("has_subtype", "[core][solvers][refinement][string_refinement]")
3742
struct_type.components().emplace_back("int_field", int_type);
3843
THEN("char and int are subtypes")
3944
{
40-
REQUIRE(has_subtype(struct_type, is_type(char_type)));
41-
REQUIRE(has_subtype(struct_type, is_type(int_type)));
45+
REQUIRE(has_subtype(struct_type, is_type(char_type), ns));
46+
REQUIRE(has_subtype(struct_type, is_type(int_type), ns));
4247
}
4348
THEN("bool is not a subtype")
4449
{
45-
REQUIRE_FALSE(has_subtype(struct_type, is_type(bool_type)));
50+
REQUIRE_FALSE(has_subtype(struct_type, is_type(bool_type), ns));
4651
}
4752
}
4853

@@ -51,11 +56,11 @@ SCENARIO("has_subtype", "[core][solvers][refinement][string_refinement]")
5156
pointer_typet ptr_type = pointer_type(char_type);
5257
THEN("char is a subtype")
5358
{
54-
REQUIRE(has_subtype(ptr_type, is_type(char_type)));
59+
REQUIRE(has_subtype(ptr_type, is_type(char_type), ns));
5560
}
5661
THEN("int is not a subtype")
5762
{
58-
REQUIRE_FALSE(has_subtype(ptr_type, is_type(int_type)));
63+
REQUIRE_FALSE(has_subtype(ptr_type, is_type(int_type), ns));
5964
}
6065
}
6166
}

0 commit comments

Comments
 (0)