Skip to content

Commit 5bf57ef

Browse files
committed
find_symbols: support restriction to non-bound symbols
Adds a new symbol kind to distinguish bound from unbound ones. Add documentation to all non-deprecated functions and clarify whether or not bound symbols are included.
1 parent de7aa25 commit 5bf57ef

File tree

5 files changed

+118
-31
lines changed

5 files changed

+118
-31
lines changed

src/ansi-c/goto_check_c.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ void goto_check_ct::invalidate(const exprt &lhs)
466466
for(auto it = assertions.begin(); it != assertions.end();)
467467
{
468468
if(
469-
has_symbol_expr(it->second, lhs_id) ||
469+
has_symbol_expr(it->second, lhs_id, false) ||
470470
has_subexpr(it->second, ID_dereference))
471471
{
472472
it = assertions.erase(it);

src/goto-symex/postcondition.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ bool postconditiont::is_used(
167167
for(const exprt &e :
168168
value_set.get_value_set(to_dereference_expr(expr).pointer(), ns))
169169
{
170-
if(has_symbol_expr(get_original_name(e), identifier))
170+
if(has_symbol_expr(get_original_name(e), identifier, false))
171171
return true;
172172
}
173173

src/goto-symex/precondition.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ void preconditiont::compute_rec(exprt &dest)
117117
for(const exprt &e : value_sets.get_values(
118118
SSA_step.source.function_id, target, deref_expr.pointer()))
119119
{
120-
if(has_symbol_expr(e, lhs_identifier))
120+
if(has_symbol_expr(e, lhs_identifier, false))
121121
{
122122
may_alias = true;
123123
break;

src/util/find_symbols.cpp

Lines changed: 91 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ enum class symbol_kindt
2323
F_TYPE_NON_PTR,
2424
/// Symbol expressions.
2525
F_EXPR,
26-
/// Symbol expressions, but excluding bindings.
27-
F_EXPR_NOT_BOUND,
26+
/// Symbol expressions, but excluding bound variables.
27+
F_EXPR_FREE,
2828
/// All of the above.
2929
F_ALL
3030
};
@@ -46,33 +46,77 @@ bool has_symbol(const exprt &src, const find_symbols_sett &symbols)
4646
static bool find_symbols(
4747
symbol_kindt,
4848
const typet &,
49-
std::function<bool(const symbol_exprt &)>);
49+
std::function<bool(const symbol_exprt &)>,
50+
std::unordered_set<irep_idt> &bindings);
5051

5152
static bool find_symbols(
5253
symbol_kindt kind,
5354
const exprt &src,
54-
std::function<bool(const symbol_exprt &)> op)
55+
std::function<bool(const symbol_exprt &)> op,
56+
std::unordered_set<irep_idt> &bindings)
5557
{
58+
if(kind == symbol_kindt::F_EXPR_FREE)
59+
{
60+
if(src.id() == ID_forall || src.id() == ID_exists || src.id() == ID_lambda)
61+
{
62+
const auto &binding_expr = to_binding_expr(src);
63+
std::unordered_set<irep_idt> new_bindings{bindings};
64+
for(const auto &v : binding_expr.variables())
65+
new_bindings.insert(v.get_identifier());
66+
67+
if(!find_symbols(kind, binding_expr.where(), op, new_bindings))
68+
return false;
69+
70+
return find_symbols(kind, binding_expr.type(), op, bindings);
71+
}
72+
else if(src.id() == ID_let)
73+
{
74+
const auto &let_expr = to_let_expr(src);
75+
std::unordered_set<irep_idt> new_bindings{bindings};
76+
for(const auto &v : let_expr.variables())
77+
new_bindings.insert(v.get_identifier());
78+
79+
if(!find_symbols(kind, let_expr.where(), op, new_bindings))
80+
return false;
81+
82+
if(!find_symbols(kind, let_expr.op1(), op, new_bindings))
83+
return false;
84+
85+
return find_symbols(kind, let_expr.type(), op, bindings);
86+
}
87+
}
88+
5689
forall_operands(it, src)
5790
{
58-
if(!find_symbols(kind, *it, op))
91+
if(!find_symbols(kind, *it, op, bindings))
5992
return false;
6093
}
6194

62-
if(!find_symbols(kind, src.type(), op))
95+
if(!find_symbols(kind, src.type(), op, bindings))
6396
return false;
6497

65-
if(kind == symbol_kindt::F_ALL || kind == symbol_kindt::F_EXPR)
98+
if(src.id() == ID_symbol)
6699
{
67-
if(src.id() == ID_symbol && !op(to_symbol_expr(src)))
68-
return false;
100+
const symbol_exprt &s = to_symbol_expr(src);
101+
102+
if(kind == symbol_kindt::F_ALL || kind == symbol_kindt::F_EXPR)
103+
{
104+
if(!op(s))
105+
return false;
106+
}
107+
else if(kind == symbol_kindt::F_EXPR_FREE)
108+
{
109+
if(bindings.find(s.get_identifier()) == bindings.end() && !op(s))
110+
return false;
111+
}
69112
}
70113

71114
const irept &c_sizeof_type=src.find(ID_C_c_sizeof_type);
72115

73116
if(
74117
c_sizeof_type.is_not_nil() &&
75-
!find_symbols(kind, static_cast<const typet &>(c_sizeof_type), op))
118+
!find_symbols(
119+
kind, static_cast<const typet &>(c_sizeof_type), op, bindings))
76120
{
77121
return false;
78122
}
@@ -81,7 +125,7 @@ static bool find_symbols(
81125

82126
if(
83127
va_arg_type.is_not_nil() &&
84-
!find_symbols(kind, static_cast<const typet &>(va_arg_type), op))
128+
!find_symbols(kind, static_cast<const typet &>(va_arg_type), op, bindings))
85129
{
86130
return false;
87131
}
@@ -92,20 +136,21 @@ static bool find_symbols(
92136
static bool find_symbols(
93137
symbol_kindt kind,
94138
const typet &src,
95-
std::function<bool(const symbol_exprt &)> op)
139+
std::function<bool(const symbol_exprt &)> op,
140+
std::unordered_set<irep_idt> &bindings)
96141
{
97142
if(kind != symbol_kindt::F_TYPE_NON_PTR || src.id() != ID_pointer)
98143
{
99144
if(
100145
src.has_subtype() &&
101-
!find_symbols(kind, to_type_with_subtype(src).subtype(), op))
146+
!find_symbols(kind, to_type_with_subtype(src).subtype(), op, bindings))
102147
{
103148
return false;
104149
}
105150

106151
for(const typet &subtype : to_type_with_subtypes(src).subtypes())
107152
{
108-
if(!find_symbols(kind, subtype, op))
153+
if(!find_symbols(kind, subtype, op, bindings))
109154
return false;
110155
}
111156

@@ -126,26 +171,26 @@ static bool find_symbols(
126171

127172
for(const auto &c : struct_union_type.components())
128173
{
129-
if(!find_symbols(kind, c, op))
174+
if(!find_symbols(kind, c, op, bindings))
130175
return false;
131176
}
132177
}
133178
else if(src.id()==ID_code)
134179
{
135180
const code_typet &code_type=to_code_type(src);
136-
if(!find_symbols(kind, code_type.return_type(), op))
181+
if(!find_symbols(kind, code_type.return_type(), op, bindings))
137182
return false;
138183

139184
for(const auto &p : code_type.parameters())
140185
{
141-
if(!find_symbols(kind, p, op))
186+
if(!find_symbols(kind, p, op, bindings))
142187
return false;
143188
}
144189
}
145190
else if(src.id()==ID_array)
146191
{
147192
// do the size -- the subtype is already done
148-
if(!find_symbols(kind, to_array_type(src).size(), op))
193+
if(!find_symbols(kind, to_array_type(src).size(), op, bindings))
149194
return false;
150195
}
151196
else if(
@@ -172,6 +217,24 @@ static bool find_symbols(
172217
return true;
173218
}
174219

220+
static bool find_symbols(
221+
symbol_kindt kind,
222+
const typet &type,
223+
std::function<bool(const symbol_exprt &)> op)
224+
{
225+
std::unordered_set<irep_idt> bindings;
226+
return find_symbols(kind, type, op, bindings);
227+
}
228+
229+
static bool find_symbols(
230+
symbol_kindt kind,
231+
const exprt &src,
232+
std::function<bool(const symbol_exprt &)> op)
233+
{
234+
std::unordered_set<irep_idt> bindings;
235+
return find_symbols(kind, src, op, bindings);
236+
}
237+
175238
void find_symbols(const exprt &src, std::set<symbol_exprt> &dest)
176239
{
177240
find_symbols(symbol_kindt::F_EXPR, src, [&dest](const symbol_exprt &e) {
@@ -180,11 +243,17 @@ void find_symbols(const exprt &src, std::set<symbol_exprt> &dest)
180243
});
181244
}
182245

183-
bool has_symbol_expr(const exprt &src, const irep_idt &identifier)
246+
bool has_symbol_expr(
247+
const exprt &src,
248+
const irep_idt &identifier,
249+
bool include_bound_symbols)
184250
{
185-
return !find_symbols(symbol_kindt::F_EXPR, src, [&identifier](const symbol_exprt &e) {
186-
return e.get_identifier() != identifier;
187-
});
251+
return !find_symbols(
252+
include_bound_symbols ? symbol_kindt::F_EXPR : symbol_kindt::F_EXPR_FREE,
253+
src,
254+
[&identifier](const symbol_exprt &e) {
255+
return e.get_identifier() != identifier;
256+
});
188257
}
189258

190259
void find_type_symbols(const exprt &src, find_symbols_sett &dest)

src/util/find_symbols.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,20 @@ class typet;
2424
typedef std::unordered_set<irep_idt> find_symbols_sett;
2525

2626
/// Returns true if one of the symbol expressions in \p src has identifier
27-
/// \p identifier.
28-
bool has_symbol_expr(const exprt &src, const irep_idt &identifier);
27+
/// \p identifier; if
28+
/// \p include_bound_symbols is true, then bindings are included in the search.
29+
bool has_symbol_expr(
30+
const exprt &src,
31+
const irep_idt &identifier,
32+
bool include_bound_symbols);
2933

3034
DEPRECATED(SINCE(2022, 3, 14, "use find_symbols"))
3135
/// Add to the set \p dest the sub-expressions of \p src with id ID_symbol or
3236
/// ID_next_symbol
3337
void find_symbols_or_nexts(const exprt &src, find_symbols_sett &dest);
3438

35-
/// Add to the set \p dest the sub-expressions of \p src with id ID_symbol.
39+
/// Add to the set \p dest the sub-expressions of \p src with id ID_symbol, for
40+
/// both free and bound variables.
3641
void find_symbols(const exprt &src, find_symbols_sett &dest);
3742

3843
/// \return set of sub-expressions of the expressions contained in the range
@@ -49,20 +54,23 @@ find_symbols_sett find_symbols_or_nexts(iteratort begin, iteratort end)
4954
return result;
5055
}
5156

52-
/// Find sub expressions with id ID_symbol
57+
/// Find sub expressions with id ID_symbol, considering both free and bound
58+
/// variables.
5359
void find_symbols(
5460
const exprt &src,
5561
std::set<symbol_exprt> &dest);
5662

57-
/// Find sub expressions with id ID_symbol
63+
/// Find sub expressions with id ID_symbol, considering both free and bound
64+
/// variables.
5865
inline std::set<symbol_exprt> find_symbols(const exprt &src)
5966
{
6067
std::set<symbol_exprt> syms;
6168
find_symbols(src, syms);
6269
return syms;
6370
}
6471

65-
/// Find identifiers of the sub expressions with id ID_symbol
72+
/// Find identifiers of the sub expressions with id ID_symbol, considering both
73+
/// free and bound variables.
6674
inline find_symbols_sett find_symbol_identifiers(const exprt &src)
6775
{
6876
find_symbols_sett identifiers;
@@ -76,26 +84,36 @@ bool has_symbol(
7684
const exprt &src,
7785
const find_symbols_sett &symbols);
7886

87+
/// Collect all type tags contained in \p src and add them to \p dest.
7988
void find_type_symbols(
8089
const typet &src,
8190
find_symbols_sett &dest);
8291

92+
/// Collect all type tags contained in \p src and add them to \p dest.
8393
void find_type_symbols(
8494
const exprt &src,
8595
find_symbols_sett &dest);
8696

97+
/// Collect type tags contained in \p src when the expression of such a type is
98+
/// not a pointer, and add them to \p dest.
8799
void find_non_pointer_type_symbols(
88100
const typet &src,
89101
find_symbols_sett &dest);
90102

103+
/// Collect type tags contained in \p src when the expression of such a type is
104+
/// not a pointer, and add them to \p dest.
91105
void find_non_pointer_type_symbols(
92106
const exprt &src,
93107
find_symbols_sett &dest);
94108

109+
/// Find identifiers of the sub expressions with id ID_symbol, considering both
110+
/// free and bound variables, as well as any type tags.
95111
void find_type_and_expr_symbols(
96112
const typet &src,
97113
find_symbols_sett &dest);
98114

115+
/// Find identifiers of the sub expressions with id ID_symbol, considering both
116+
/// free and bound variables, as well as any type tags.
99117
void find_type_and_expr_symbols(
100118
const exprt &src,
101119
find_symbols_sett &dest);

0 commit comments

Comments
 (0)