[clang] 40457f3 - [llvm][ADT] Make ImmutableList conform the fwd iterator concept (#202580)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 10 02:32:13 PDT 2026
Author: Balázs Benics
Date: 2026-06-10T10:32:07+01:00
New Revision: 40457f351f1dd9edda9679a6c63b48c7c73dcb4c
URL: https://github.com/llvm/llvm-project/commit/40457f351f1dd9edda9679a6c63b48c7c73dcb4c
DIFF: https://github.com/llvm/llvm-project/commit/40457f351f1dd9edda9679a6c63b48c7c73dcb4c.diff
LOG: [llvm][ADT] Make ImmutableList conform the fwd iterator concept (#202580)
We missed post increment and a couple of typedefs. This would enable
llvm algorithms like filter_range, etc.
Added:
Modified:
clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
llvm/include/llvm/ADT/ImmutableList.h
llvm/unittests/ADT/ImmutableListTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
index 354d4c99b2fbe..03c576270797b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -282,19 +282,6 @@ class BlockInCriticalSectionChecker : public Checker<check::PostCall> {
REGISTER_LIST_WITH_PROGRAMSTATE(ActiveCritSections, CritSectionMarker)
-// Iterator traits for ImmutableList data structure
-// that enable the use of STL algorithms.
-// TODO: Move these to llvm::ImmutableList when overhauling immutable data
-// structures for proper iterator concept support.
-template <>
-struct std::iterator_traits<llvm::ImmutableList<CritSectionMarker>::iterator> {
- using iterator_category = std::forward_iterator_tag;
- using value_type = CritSectionMarker;
- using
diff erence_type = std::ptr
diff _t;
- using reference = CritSectionMarker &;
- using pointer = CritSectionMarker *;
-};
-
std::optional<MutexDescriptor>
BlockInCriticalSectionChecker::checkDescriptorMatch(const CallEvent &Call,
CheckerContext &C,
diff --git a/llvm/include/llvm/ADT/ImmutableList.h b/llvm/include/llvm/ADT/ImmutableList.h
index bbf0a96464e58..24a4b732cd090 100644
--- a/llvm/include/llvm/ADT/ImmutableList.h
+++ b/llvm/include/llvm/ADT/ImmutableList.h
@@ -17,7 +17,9 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Allocator.h"
#include <cassert>
+#include <cstddef>
#include <cstdint>
+#include <iterator>
#include <new>
namespace llvm {
@@ -86,10 +88,21 @@ class ImmutableList {
const ImmutableListImpl<T>* L = nullptr;
public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = std::remove_reference_t<T>;
+ using
diff erence_type = std::ptr
diff _t;
+ using pointer = const value_type *;
+ using reference = const value_type &;
+
iterator() = default;
iterator(ImmutableList l) : L(l.getInternalPointer()) {}
iterator& operator++() { L = L->getTail(); return *this; }
+ iterator operator++(int) {
+ iterator Tmp = *this;
+ ++*this;
+ return Tmp;
+ }
bool operator==(const iterator& I) const { return L == I.L; }
bool operator!=(const iterator& I) const { return L != I.L; }
const value_type& operator*() const { return L->getHead(); }
diff --git a/llvm/unittests/ADT/ImmutableListTest.cpp b/llvm/unittests/ADT/ImmutableListTest.cpp
index 2da0ca65d1a4f..3046c5da54651 100644
--- a/llvm/unittests/ADT/ImmutableListTest.cpp
+++ b/llvm/unittests/ADT/ImmutableListTest.cpp
@@ -7,7 +7,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/STLExtras.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include <algorithm>
+#include <vector>
using namespace llvm;
@@ -269,4 +273,66 @@ TEST_F(ImmutableListTest, LongListOrderingTest) {
static_assert(std::is_trivially_copyable_v<ImmutableList<Wrapper<long>>>,
"trivially copyable");
+// Verify ImmutableList<T>::iterator satisfies the std::iterator_traits
+// contract:
+using IntListIter = ImmutableList<Wrapper<int>>::iterator;
+static_assert(
+ std::is_same_v<std::iterator_traits<IntListIter>::iterator_category,
+ std::forward_iterator_tag>);
+static_assert(std::is_same_v<std::iterator_traits<IntListIter>::value_type,
+ Wrapper<int>>);
+static_assert(std::is_same_v<std::iterator_traits<IntListIter>::
diff erence_type,
+ std::ptr
diff _t>);
+static_assert(std::is_same_v<std::iterator_traits<IntListIter>::pointer,
+ const Wrapper<int> *>);
+static_assert(std::is_same_v<std::iterator_traits<IntListIter>::reference,
+ const Wrapper<int> &>);
+
+using RefListIter = ImmutableList<const Unmodifiable &>::iterator;
+static_assert(
+ std::is_same_v<std::iterator_traits<RefListIter>::iterator_category,
+ std::forward_iterator_tag>);
+static_assert(std::is_same_v<std::iterator_traits<RefListIter>::value_type,
+ const Unmodifiable>);
+static_assert(std::is_same_v<std::iterator_traits<RefListIter>::pointer,
+ const Unmodifiable *>);
+static_assert(std::is_same_v<std::iterator_traits<RefListIter>::reference,
+ const Unmodifiable &>);
+
+TEST_F(ImmutableListTest, IteratorPostIncrementTest) {
+ ImmutableList<Wrapper<int>>::Factory f;
+ ImmutableList<Wrapper<int>> L =
+ f.add(5, f.add(4, f.add(3, f.getEmptyList())));
+
+ auto It = L.begin();
+ EXPECT_EQ(5, *It);
+
+ auto Old = It++;
+ EXPECT_EQ(5, *Old);
+ EXPECT_EQ(4, *It);
+ EXPECT_TRUE(Old != It);
+}
+
+TEST_F(ImmutableListTest, IteratorPostIncrementInLoopTest) {
+ ImmutableList<Wrapper<int>>::Factory f;
+ ImmutableList<Wrapper<int>> L =
+ f.add(5, f.add(4, f.add(3, f.getEmptyList())));
+
+ std::vector<int> Values;
+ for (auto I = L.begin(), E = L.end(); I != E; I++)
+ Values.push_back(*I);
+
+ EXPECT_THAT(Values, testing::ElementsAre(5, 4, 3));
+}
+
+TEST_F(ImmutableListTest, FilterRangeCompat) {
+ ImmutableList<Wrapper<int>>::Factory f;
+ ImmutableList<Wrapper<int>> L =
+ f.add(5, f.add(4, f.add(3, f.getEmptyList())));
+
+ auto IsOdd = [](int Val) { return Val % 2; };
+ auto OddElements = llvm::make_filter_range(L, IsOdd);
+ EXPECT_THAT(OddElements, testing::ElementsAre(5, 3));
+}
+
} // namespace
More information about the cfe-commits
mailing list