@@ -9,6 +9,7 @@ Author: Daniel Kroening, kroening@kroening.com
99
1010#include " expr_util.h"
1111
12+ #include < unordered_set>
1213#include " expr.h"
1314#include " expr_iterator.h"
1415#include " fixedbv.h"
@@ -140,28 +141,36 @@ bool has_subtype(
140141 const std::function<bool (const typet &)> &pred,
141142 const namespacet &ns)
142143{
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;
152146
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 ())
161154 {
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+ }
165174 }
166175
167176 return false ;
0 commit comments