summaryrefslogtreecommitdiffstats
path: root/build/clang-plugin/RecurseGuard.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--build/clang-plugin/RecurseGuard.h56
1 files changed, 56 insertions, 0 deletions
diff --git a/build/clang-plugin/RecurseGuard.h b/build/clang-plugin/RecurseGuard.h
new file mode 100644
index 0000000000..5daf55a9e8
--- /dev/null
+++ b/build/clang-plugin/RecurseGuard.h
@@ -0,0 +1,56 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef RecurseGuard_h__
+#define RecurseGuard_h__
+
+#include "Utils.h"
+
+// This class acts as a tracker for avoiding infinite recursion when traversing
+// chains in CFGs etc.
+//
+// Constructing a RecurseGuard sets up a shared backing store which tracks the
+// currently observed objects. Whenever recursing, use RecurseGuard.recurse(T)
+// to construct another RecurseGuard with the same backing store.
+//
+// The RecurseGuard object will unregister its object when it is destroyed, and
+// has a method `isRepeat()` which will return `true` if the item was already
+// seen.
+template <typename T> class RecurseGuard {
+public:
+ RecurseGuard(T Thing) : Thing(Thing), Set(new DenseSet<T>()), Repeat(false) {
+ Set->insert(Thing);
+ }
+ RecurseGuard(T Thing, std::shared_ptr<DenseSet<T>> &Set)
+ : Thing(Thing), Set(Set), Repeat(false) {
+ Repeat = !Set->insert(Thing).second;
+ }
+ RecurseGuard(const RecurseGuard &) = delete;
+ RecurseGuard(RecurseGuard &&Other)
+ : Thing(Other.Thing), Set(Other.Set), Repeat(Other.Repeat) {
+ Other.Repeat = true;
+ }
+ ~RecurseGuard() {
+ if (!Repeat) {
+ Set->erase(Thing);
+ }
+ }
+
+ bool isRepeat() { return Repeat; }
+
+ T get() { return Thing; }
+
+ operator T() { return Thing; }
+
+ T operator->() { return Thing; }
+
+ RecurseGuard recurse(T NewThing) { return RecurseGuard(NewThing, Set); }
+
+private:
+ T Thing;
+ std::shared_ptr<DenseSet<T>> Set;
+ bool Repeat;
+};
+
+#endif // RecurseGuard_h__