Skip to content

Commit d66d542

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 d66d542

File tree

5 files changed

+67
-59
lines changed

5 files changed

+67
-59
lines changed

src/solvers/refinement/string_refinement.cpp

+4-3
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>
@@ -341,7 +342,7 @@ static union_find_replacet generate_symbol_resolution_from_equations(
341342
// in the convert_function_application step of dec_solve
342343
}
343344
else if(lhs.type().id() != ID_pointer &&
344-
has_char_pointer_subtype(lhs.type()))
345+
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
{
@@ -485,7 +486,7 @@ union_find_replacet string_identifiers_resolution_from_equations(
485486
equation_map.add(i, expr);
486487
}
487488
else if(eq.lhs().type().id() != ID_pointer &&
488-
has_string_subtype(eq.lhs().type()))
489+
has_subtype(eq.lhs().type(), ID_string, ns))
489490
{
490491
std::vector<exprt> lhs_strings = extract_strings_from_lhs(eq.lhs());
491492

src/solvers/refinement/string_refinement_util.cpp

+3-33
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

+2-23
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

+38
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

+20
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,26 @@ exprt boolean_negate(const exprt &);
4444
/// returns true if the expression has a subexpression with given ID
4545
bool has_subexpr(const exprt &, const irep_idt &);
4646

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

0 commit comments

Comments
 (0)