summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/ADT/Sequence.h76
-rw-r--r--llvm/include/llvm/ADT/iterator.h20
-rw-r--r--llvm/unittests/ADT/CMakeLists.txt1
-rw-r--r--llvm/unittests/ADT/SequenceTest.cpp39
4 files changed, 134 insertions, 2 deletions
diff --git a/llvm/include/llvm/ADT/Sequence.h b/llvm/include/llvm/ADT/Sequence.h
new file mode 100644
index 00000000000..8323b053cca
--- /dev/null
+++ b/llvm/include/llvm/ADT/Sequence.h
@@ -0,0 +1,76 @@
+//===- Sequence.h - Utility for producing sequences of values ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This routine provides some synthesis utilities to produce sequences of
+/// values. The names are intentionally kept very short as they tend to occur
+/// in common and widely used contexts.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ADT_SEQ_H
+#define LLVM_ADT_SEQ_H
+
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+
+namespace llvm {
+
+namespace detail {
+template <typename ValueT>
+class value_sequence_iterator
+ : public iterator_facade_base<value_sequence_iterator<ValueT>,
+ std::random_access_iterator_tag,
+ const ValueT> {
+ typedef typename value_sequence_iterator::iterator_facade_base BaseT;
+
+ ValueT Value;
+
+public:
+ typedef typename BaseT::difference_type difference_type;
+ typedef typename BaseT::reference reference;
+
+ value_sequence_iterator() = default;
+
+ template <typename U>
+ value_sequence_iterator(U &&Value) : Value(std::forward<U>(Value)) {}
+
+ value_sequence_iterator &operator+=(difference_type N) {
+ Value += N;
+ return *this;
+ }
+ value_sequence_iterator &operator-=(difference_type N) {
+ Value -= N;
+ return *this;
+ }
+ using BaseT::operator-;
+ difference_type operator-(const value_sequence_iterator &RHS) const {
+ return Value - RHS.Value;
+ }
+
+ bool operator==(const value_sequence_iterator &RHS) const {
+ return Value == RHS.Value;
+ }
+ bool operator<(const value_sequence_iterator &RHS) const {
+ return Value < RHS.Value;
+ }
+
+ reference operator*() const { return Value; }
+};
+} // End detail namespace.
+
+template <typename ValueT>
+iterator_range<detail::value_sequence_iterator<ValueT>> seq(ValueT Begin,
+ ValueT End) {
+ return make_range(detail::value_sequence_iterator<ValueT>(Begin),
+ detail::value_sequence_iterator<ValueT>(End));
+}
+
+}
+
+#endif
diff --git a/llvm/include/llvm/ADT/iterator.h b/llvm/include/llvm/ADT/iterator.h
index c3079289270..2898a677db3 100644
--- a/llvm/include/llvm/ADT/iterator.h
+++ b/llvm/include/llvm/ADT/iterator.h
@@ -46,6 +46,22 @@ protected:
std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value,
};
+ /// A proxy object for computing a reference via indirecting a copy of an
+ /// iterator. This is used in APIs which need to produce a reference via
+ /// indirection but for which the iterator object might be a temporary. The
+ /// proxy preserves the iterator internally and exposes the indirected
+ /// reference via a conversion operator.
+ class ReferenceProxy {
+ friend iterator_facade_base;
+
+ DerivedT I;
+
+ ReferenceProxy(DerivedT I) : I(std::move(I)) {}
+
+ public:
+ operator ReferenceT() const { return *I; }
+ };
+
public:
DerivedT operator+(DifferenceTypeT n) const {
static_assert(
@@ -120,10 +136,10 @@ public:
PointerT operator->() const {
return &static_cast<const DerivedT *>(this)->operator*();
}
- ReferenceT operator[](DifferenceTypeT n) const {
+ ReferenceProxy operator[](DifferenceTypeT n) const {
static_assert(IsRandomAccess,
"Subscripting is only defined for random access iterators.");
- return *static_cast<const DerivedT *>(this)->operator+(n);
+ return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n));
}
};
diff --git a/llvm/unittests/ADT/CMakeLists.txt b/llvm/unittests/ADT/CMakeLists.txt
index 49ea73c7757..bbd87701497 100644
--- a/llvm/unittests/ADT/CMakeLists.txt
+++ b/llvm/unittests/ADT/CMakeLists.txt
@@ -32,6 +32,7 @@ set(ADTSources
PostOrderIteratorTest.cpp
RangeAdapterTest.cpp
SCCIteratorTest.cpp
+ SequenceTest.cpp
SetVectorTest.cpp
SmallPtrSetTest.cpp
SmallStringTest.cpp
diff --git a/llvm/unittests/ADT/SequenceTest.cpp b/llvm/unittests/ADT/SequenceTest.cpp
new file mode 100644
index 00000000000..d82c3c2d4ef
--- /dev/null
+++ b/llvm/unittests/ADT/SequenceTest.cpp
@@ -0,0 +1,39 @@
+//===- SequenceTest.cpp - Unit tests for a sequence abstraciton -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Sequence.h"
+#include "gtest/gtest.h"
+
+#include <list>
+
+using namespace llvm;
+
+namespace {
+
+TEST(SequenceTest, Basic) {
+ int x = 0;
+ for (int i : seq(0, 10))
+ EXPECT_EQ(x++, i);
+ EXPECT_EQ(10, x);
+
+ auto my_seq = seq(0, 4);
+ EXPECT_EQ(4, my_seq.end() - my_seq.begin());
+ for (int i : {0, 1, 2, 3})
+ EXPECT_EQ(i, (int)my_seq.begin()[i]);
+
+ EXPECT_TRUE(my_seq.begin() < my_seq.end());
+
+ auto adjusted_begin = my_seq.begin() + 2;
+ auto adjusted_end = my_seq.end() - 2;
+ EXPECT_TRUE(adjusted_begin == adjusted_end);
+ EXPECT_EQ(2, *adjusted_begin);
+ EXPECT_EQ(2, *adjusted_end);
+}
+
+} // anonymous namespace
OpenPOWER on IntegriCloud