Index: include/llvm/ADT/BitVector.h =================================================================== --- include/llvm/ADT/BitVector.h +++ include/llvm/ADT/BitVector.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_BITVECTOR_H #define LLVM_ADT_BITVECTOR_H +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/MathExtras.h" #include #include @@ -25,6 +26,50 @@ namespace llvm { +/// ForwardIterator for the bits that are set. +/// Iterators get invalidated when resize / reserve is called. +template class const_bits_set_iterator_impl { + const BitVectorT &Parent; + int Current = 0; + + void advance() { + assert(Current != -1 && "Trying to advance past end."); + Current = Parent.find_next(Current); + } + +public: + const_bits_set_iterator_impl(const BitVectorT &Parent, int Current) + : Parent(Parent), Current(Current) {} + explicit const_bits_set_iterator_impl(const BitVectorT &Parent) + : const_bits_set_iterator_impl(Parent, Parent.find_first()) {} + const_bits_set_iterator_impl(const const_bits_set_iterator_impl &) = default; + + const_bits_set_iterator_impl operator++(int) { + auto Prev = *this; + advance(); + return Prev; + } + + const_bits_set_iterator_impl &operator++() { + advance(); + return *this; + } + + unsigned operator*() const { return Current; } + + bool operator==(const const_bits_set_iterator_impl &Other) const { + assert(&Parent == &Other.Parent && + "Comparing iterators from different BitVectors"); + return Current == Other.Current; + } + + bool operator!=(const const_bits_set_iterator_impl &Other) const { + assert(&Parent == &Other.Parent && + "Comparing iterators from different BitVectors"); + return Current != Other.Current; + } +}; + class BitVector { typedef unsigned long BitWord; @@ -73,6 +118,18 @@ } }; + typedef const_bits_set_iterator_impl const_bits_set_iterator; + typedef const_bits_set_iterator set_iterator; + + const_bits_set_iterator bit_set_begin() const { + return const_bits_set_iterator(*this); + } + const_bits_set_iterator bit_set_end() const { + return const_bits_set_iterator(*this, -1); + } + iterator_range bit_set() const { + return make_range(bit_set_begin(), bit_set_end()); + } /// BitVector default ctor - Creates an empty bitvector. BitVector() : Size(0), Capacity(0) { Index: include/llvm/ADT/SmallBitVector.h =================================================================== --- include/llvm/ADT/SmallBitVector.h +++ include/llvm/ADT/SmallBitVector.h @@ -136,6 +136,19 @@ } public: + typedef const_bits_set_iterator_impl const_bits_set_iterator; + typedef const_bits_set_iterator set_iterator; + + const_bits_set_iterator bit_set_begin() const { + return const_bits_set_iterator(*this); + } + const_bits_set_iterator bit_set_end() const { + return const_bits_set_iterator(*this, -1); + } + iterator_range bit_set() const { + return make_range(bit_set_begin(), bit_set_end()); + } + /// Creates an empty bitvector. SmallBitVector() : X(1) {} Index: unittests/ADT/BitVectorTest.cpp =================================================================== --- unittests/ADT/BitVectorTest.cpp +++ unittests/ADT/BitVectorTest.cpp @@ -501,5 +501,34 @@ testEmpty(E); } +TYPED_TEST(BitVectorTest, Iterators) { + TypeParam Filled(10, true); + EXPECT_NE(Filled.bit_set_begin(), Filled.bit_set_end()); + int Counter = 0; + for (int Bit : Filled.bit_set()) + EXPECT_EQ(Bit, Counter++); + + TypeParam Empty; + EXPECT_EQ(Empty.bit_set_begin(), Empty.bit_set_end()); + for (int Bit : Empty.bit_set()) { + (void)Bit; + EXPECT_TRUE(false); + } + + TypeParam ToFill(100, false); + ToFill.set(0); + EXPECT_NE(ToFill.bit_set_begin(), ToFill.bit_set_end()); + EXPECT_EQ(++ToFill.bit_set_begin(), ToFill.bit_set_end()); + EXPECT_EQ(*ToFill.bit_set_begin(), 0U); + ToFill.reset(0); + EXPECT_EQ(ToFill.bit_set_begin(), ToFill.bit_set_end()); + + const int List[] = {1, 10, 25, 99}; + for (int Num : List) + ToFill.set(Num); + int i = 0; + for (int Bit : ToFill.bit_set()) + EXPECT_EQ(List[i++], Bit); +} } #endif