RecurseGuard.h (1658B)
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/. */ 4 5 #ifndef RecurseGuard_h__ 6 #define RecurseGuard_h__ 7 8 #include "Utils.h" 9 10 // This class acts as a tracker for avoiding infinite recursion when traversing 11 // chains in CFGs etc. 12 // 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. 16 // 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 19 // seen. 20 template <typename T> class RecurseGuard { 21 public: 22 RecurseGuard(T Thing) : Thing(Thing), Set(new DenseSet<T>()), Repeat(false) { 23 Set->insert(Thing); 24 } 25 RecurseGuard(T Thing, std::shared_ptr<DenseSet<T>> &Set) 26 : Thing(Thing), Set(Set), Repeat(false) { 27 Repeat = !Set->insert(Thing).second; 28 } 29 RecurseGuard(const RecurseGuard &) = delete; 30 RecurseGuard(RecurseGuard &&Other) 31 : Thing(Other.Thing), Set(Other.Set), Repeat(Other.Repeat) { 32 Other.Repeat = true; 33 } 34 ~RecurseGuard() { 35 if (!Repeat) { 36 Set->erase(Thing); 37 } 38 } 39 40 bool isRepeat() { return Repeat; } 41 42 T get() { return Thing; } 43 44 operator T() { return Thing; } 45 46 T operator->() { return Thing; } 47 48 RecurseGuard recurse(T NewThing) { return RecurseGuard(NewThing, Set); } 49 50 private: 51 T Thing; 52 std::shared_ptr<DenseSet<T>> Set; 53 bool Repeat; 54 }; 55 56 #endif // RecurseGuard_h__