summaryrefslogtreecommitdiffstats
path: root/build/clang-plugin/RecurseGuard.h
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /build/clang-plugin/RecurseGuard.h
parentInitial commit. (diff)
downloadfirefox-e51783d008170d9ab27d25da98ca3a38b0a41b67.tar.xz
firefox-e51783d008170d9ab27d25da98ca3a38b0a41b67.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'build/clang-plugin/RecurseGuard.h')
-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__