@@ -9,6 +9,7 @@ Author: Daniel Kroening, kroening@kroening.com
9
9
10
10
#include " expr_util.h"
11
11
12
+ #include < unordered_set>
12
13
#include " expr.h"
13
14
#include " expr_iterator.h"
14
15
#include " fixedbv.h"
@@ -140,28 +141,36 @@ bool has_subtype(
140
141
const std::function<bool (const typet &)> &pred,
141
142
const namespacet &ns)
142
143
{
143
- if (pred (type))
144
- return true ;
145
- else if (type.id () == ID_symbol)
146
- return has_subtype (ns.follow (type), pred, ns);
147
- else if (type.id () == ID_c_enum_tag)
148
- return has_subtype (ns.follow_tag (to_c_enum_tag_type (type)), pred, ns);
149
- else if (type.id () == ID_struct || type.id () == ID_union)
150
- {
151
- const struct_union_typet &struct_union_type = to_struct_union_type (type);
144
+ std::vector<std::reference_wrapper<const typet>> stack;
145
+ std::unordered_set<typet, irep_hash> visited;
152
146
153
- for (const auto &comp : struct_union_type.components ())
154
- if (has_subtype (comp.type (), pred, ns))
155
- return true ;
156
- }
157
- // do not look into pointer subtypes as this could cause unbounded recursion
158
- else if (type.id () == ID_array || type.id () == ID_vector)
159
- return has_subtype (type.subtype (), pred, ns);
160
- else if (type.has_subtypes ())
147
+ const auto push_if_not_visited = [&](const typet &t) {
148
+ if (visited.insert (t).second )
149
+ stack.emplace_back (t);
150
+ };
151
+
152
+ push_if_not_visited (type);
153
+ while (!stack.empty ())
161
154
{
162
- for (const auto &subtype : type.subtypes ())
163
- if (has_subtype (subtype, pred, ns))
164
- return true ;
155
+ const typet &top = stack.back ().get ();
156
+ stack.pop_back ();
157
+
158
+ if (pred (top))
159
+ return true ;
160
+ else if (top.id () == ID_symbol)
161
+ push_if_not_visited (ns.follow (top));
162
+ else if (top.id () == ID_c_enum_tag)
163
+ push_if_not_visited (ns.follow_tag (to_c_enum_tag_type (top)));
164
+ else if (top.id () == ID_struct || top.id () == ID_union)
165
+ {
166
+ for (const auto &comp : to_struct_union_type (top).components ())
167
+ push_if_not_visited (comp.type ());
168
+ }
169
+ else
170
+ {
171
+ for (const auto &subtype : top.subtypes ())
172
+ push_if_not_visited (subtype);
173
+ }
165
174
}
166
175
167
176
return false ;
0 commit comments