Skip to content

Commit a817543

Browse files
committed
Expr-depth-iterator: use indices not iterators
The iterators are appealing, but are invalidated when an expression is replaced via mutate(), preventing iteration from continuing over the newly altered node.
1 parent 3f06c82 commit a817543

File tree

1 file changed

+16
-24
lines changed

1 file changed

+16
-24
lines changed

src/util/expr_iterator.h

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,18 @@ class const_unique_depth_iteratort;
4242
struct depth_iterator_expr_statet final
4343
{
4444
typedef exprt::operandst::const_iterator operands_iteratort;
45-
inline depth_iterator_expr_statet(
46-
const exprt &expr,
47-
operands_iteratort it,
48-
operands_iteratort end):
49-
expr(expr), it(it), end(end) { }
45+
explicit depth_iterator_expr_statet(const exprt &expr) : expr(expr), op_idx(0)
46+
{
47+
}
5048
std::reference_wrapper<const exprt> expr;
51-
operands_iteratort it;
52-
operands_iteratort end;
49+
std::size_t op_idx;
5350
};
5451

5552
inline bool operator==(
5653
const depth_iterator_expr_statet &left,
5754
const depth_iterator_expr_statet &right)
5855
{
59-
return distance(left.it, left.end) == distance(right.it, right.end) &&
60-
left.expr.get() == right.expr.get();
56+
return left.op_idx == right.op_idx && left.expr.get() == right.expr.get();
6157
}
6258

6359
/// Depth first search iterator base - iterates over supplied expression
@@ -100,16 +96,19 @@ class depth_iterator_baset
10096
PRECONDITION(!m_stack.empty());
10197
while(true)
10298
{
103-
if(m_stack.back().it==m_stack.back().end)
99+
if(m_stack.back().op_idx == m_stack.back().expr.get().operands().size())
104100
{
105101
m_stack.pop_back();
106102
if(m_stack.empty())
107103
break;
108104
}
109105
// Check eg. if we haven't seen this node before
110-
else if(this->downcast().push_expr(*m_stack.back().it))
106+
else if(this->downcast().push_expr(
107+
m_stack.back().expr.get().operands()[m_stack.back().op_idx]))
108+
{
111109
break;
112-
m_stack.back().it++;
110+
}
111+
++m_stack.back().op_idx;
113112
}
114113
return this->downcast();
115114
}
@@ -120,7 +119,7 @@ class depth_iterator_baset
120119
m_stack.pop_back();
121120
if(!m_stack.empty())
122121
{
123-
++m_stack.back().it;
122+
++m_stack.back().op_idx;
124123
return ++(*this);
125124
}
126125
return this->downcast();
@@ -185,18 +184,11 @@ class depth_iterator_baset
185184
for(auto &state : m_stack)
186185
{
187186
// This deliberately breaks sharing as expr is now non-const
188-
auto &operands = expr->operands();
189-
// Get iterators into the operands of the new expr corresponding to the
190-
// ones into the operands of the old expr
191-
const auto it = operands.end() - (state.end - state.it);
187+
(void)expr->write();
192188
state.expr = *expr;
193-
state.it=it;
194-
state.end=operands.end();
195189
// Get the expr for the next level down to use in the next iteration
196-
if(!(state==m_stack.back()))
197-
{
198-
expr = &*it;
199-
}
190+
if(!(state == m_stack.back()))
191+
expr = &expr->operands()[state.op_idx];
200192
}
201193
return *expr;
202194
}
@@ -208,7 +200,7 @@ class depth_iterator_baset
208200
/// false otherwise. If returning false, child will not be iterated over.
209201
bool push_expr(const exprt &expr)
210202
{
211-
m_stack.emplace_back(expr, expr.operands().begin(), expr.operands().end());
203+
m_stack.emplace_back(expr);
212204
return true;
213205
}
214206

0 commit comments

Comments
 (0)