1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #ifndef RecurseGuard_h__
6 #define RecurseGuard_h__
10 // This class acts as a tracker for avoiding infinite recursion when traversing
11 // chains in CFGs etc.
13 // Constructing a RecurseGuard sets up a shared backing store which tracks the
14 // currently observed objects. Whenever recursing, use RecurseGuard.recurse(T)
15 // to construct another RecurseGuard with the same backing store.
17 // The RecurseGuard object will unregister its object when it is destroyed, and
18 // has a method `isRepeat()` which will return `true` if the item was already
20 template <typename T
> class RecurseGuard
{
22 RecurseGuard(T Thing
) : Thing(Thing
), Set(new DenseSet
<T
>()), Repeat(false) {
25 RecurseGuard(T Thing
, std::shared_ptr
<DenseSet
<T
>> &Set
)
26 : Thing(Thing
), Set(Set
), Repeat(false) {
27 Repeat
= !Set
->insert(Thing
).second
;
29 RecurseGuard(const RecurseGuard
&) = delete;
30 RecurseGuard(RecurseGuard
&&Other
)
31 : Thing(Other
.Thing
), Set(Other
.Set
), Repeat(Other
.Repeat
) {
40 bool isRepeat() { return Repeat
; }
42 T
get() { return Thing
; }
44 operator T() { return Thing
; }
46 T
operator->() { return Thing
; }
48 RecurseGuard
recurse(T NewThing
) { return RecurseGuard(NewThing
, Set
); }
52 std::shared_ptr
<DenseSet
<T
>> Set
;
56 #endif // RecurseGuard_h__