[llvm] r290513 - Revert r290512: [ADT] Add a generic concatenating iterator and range.

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 25 01:36:25 PST 2016


Author: chandlerc
Date: Sun Dec 25 03:36:24 2016
New Revision: 290513

URL: http://llvm.org/viewvc/llvm-project?rev=290513&view=rev
Log:
Revert r290512: [ADT] Add a generic concatenating iterator and range.

This code doesn't work on MSVC for reasons that elude me and I've not
yet covinced a workaround to compile cleanly so reverting for now while
I play with it.

Modified:
    llvm/trunk/include/llvm/ADT/STLExtras.h
    llvm/trunk/include/llvm/IR/Module.h
    llvm/trunk/unittests/ADT/STLExtrasTest.cpp

Modified: llvm/trunk/include/llvm/ADT/STLExtras.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/STLExtras.h?rev=290513&r1=290512&r2=290513&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/STLExtras.h (original)
+++ llvm/trunk/include/llvm/ADT/STLExtras.h Sun Dec 25 03:36:24 2016
@@ -31,7 +31,6 @@
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/Compiler.h"
-#include "llvm/Support/ErrorHandling.h"
 
 namespace llvm {
 
@@ -436,151 +435,6 @@ detail::zippy<detail::zip_first, T, U, A
       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
 }
 
-/// Iterator wrapper that concatenates sequences together.
-///
-/// This can concatenate different iterators, even with different types, into
-/// a single iterator provided the value types of all the concatenated
-/// iterators expose `reference` and `pointer` types that can be converted to
-/// `ValueT &` and `ValueT *` respectively. It doesn't support more
-/// interesting/customized pointer or reference types.
-///
-/// Currently this only supports forward or higher iterator categories as
-/// inputs and always exposes a forward iterator interface.
-template <typename ValueT, typename... IterTs>
-class concat_iterator
-    : public iterator_facade_base<concat_iterator<ValueT, IterTs...>,
-                                  std::forward_iterator_tag, ValueT> {
-  typedef typename concat_iterator::iterator_facade_base BaseT;
-
-  /// We store both the current and end iterators for each concatenated
-  /// sequence in a tuple of pairs.
-  ///
-  /// Note that something like iterator_range seems nice at first here, but the
-  /// range properties are of little benefit and end up getting in the way
-  /// because we need to do mutation on the current iterators.
-  std::tuple<std::pair<IterTs, IterTs>...> IterPairs;
-
-  /// Attempts to increment a specific iterator.
-  ///
-  /// Returns true if it was able to increment the iterator. Returns false if
-  /// the iterator is already at the end iterator.
-  template <size_t Index> bool incrementHelper() {
-    auto &IterPair = std::get<Index>(IterPairs);
-    if (IterPair.first == IterPair.second)
-      return false;
-
-    ++IterPair.first;
-    return true;
-  }
-
-  /// Increments the first non-end iterator.
-  ///
-  /// It is an error to call this with all iterators at the end.
-  template <size_t... Ns> void increment(index_sequence<Ns...>) {
-    // Build a sequence of functions to increment each iterator if possible.
-    decltype(&concat_iterator::incrementHelper<0>) IncrementHelperFns[] = {
-        &concat_iterator::incrementHelper<Ns>...};
-
-    // Loop over them, and stop as soon as we succeed at incrementing one.
-    for (auto &IncrementHelperFn : IncrementHelperFns)
-      if ((this->*IncrementHelperFn)())
-        return;
-
-    llvm_unreachable("Attempted to increment an end concat iterator!");
-  }
-
-  /// Returns null if the specified iterator is at the end. Otherwise,
-  /// dereferences the iterator and returns the address of the resulting
-  /// reference.
-  template <size_t Index> ValueT *getHelper() const {
-    auto &IterPair = std::get<Index>(IterPairs);
-    if (IterPair.first == IterPair.second)
-      return nullptr;
-
-    return &*IterPair.first;
-  }
-
-  /// Finds the first non-end iterator, dereferences, and returns the resulting
-  /// reference.
-  ///
-  /// It is an error to call this with all iterators at the end.
-  template <size_t... Ns> ValueT &get(index_sequence<Ns...>) const {
-    // Build a sequence of functions to get from iterator if possible.
-    decltype(&concat_iterator::getHelper<0>) GetHelperFns[] = {
-        &concat_iterator::getHelper<Ns>...};
-
-    // Loop over them, and return the first result we find.
-    for (auto &GetHelperFn : GetHelperFns)
-      if (ValueT *P = (this->*GetHelperFn)())
-        return *P;
-
-    llvm_unreachable("Attempted to get a pointer from an end concat iterator!");
-  }
-
-public:
-  /// Constructs an iterator from a squence of ranges.
-  ///
-  /// We need the full range to know how to switch between each of the
-  /// iterators.
-  template <typename... RangeTs>
-  explicit concat_iterator(RangeTs &&... Ranges)
-      : IterPairs({std::begin(Ranges), std::end(Ranges)}...) {}
-
-  using BaseT::operator++;
-  concat_iterator &operator++() {
-    increment(index_sequence_for<IterTs...>());
-    return *this;
-  }
-
-  ValueT &operator*() const { return get(index_sequence_for<IterTs...>()); }
-
-  bool operator==(const concat_iterator &RHS) const {
-    return IterPairs == RHS.IterPairs;
-  }
-};
-
-namespace detail {
-/// Helper to store a sequence of ranges being concatenated and access them.
-///
-/// This is designed to facilitate providing actual storage when temporaries
-/// are passed into the constructor such that we can use it as part of range
-/// based for loops.
-template <typename ValueT, typename... RangeTs> class concat_range {
-public:
-  typedef concat_iterator<ValueT,
-                          decltype(std::begin(std::declval<RangeTs &>()))...>
-      iterator;
-
-private:
-  std::tuple<RangeTs...> Ranges;
-
-  template <size_t... Ns> iterator begin_impl(index_sequence<Ns...>) {
-    return iterator(std::get<Ns>(Ranges)...);
-  }
-  template <size_t... Ns> iterator end_impl(index_sequence<Ns...>) {
-    return iterator(make_range(std::end(std::get<Ns>(Ranges)),
-                               std::end(std::get<Ns>(Ranges)))...);
-  }
-
-public:
-  iterator begin() { return begin_impl(index_sequence_for<RangeTs...>{}); }
-  iterator end() { return end_impl(index_sequence_for<RangeTs...>{}); }
-  concat_range(RangeTs &&... Ranges)
-      : Ranges(std::forward<RangeTs>(Ranges)...) {}
-};
-}
-
-/// Concatenated range across two or more ranges.
-///
-/// The desired value type must be explicitly specified.
-template <typename ValueT, typename... RangeTs>
-detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
-  static_assert(sizeof...(RangeTs) > 1,
-                "Need more than one range to concatenate!");
-  return detail::concat_range<ValueT, RangeTs...>(
-      std::forward<RangeTs>(Ranges)...);
-}
-
 //===----------------------------------------------------------------------===//
 //     Extra additions to <utility>
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/include/llvm/IR/Module.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Module.h?rev=290513&r1=290512&r2=290513&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Module.h (original)
+++ llvm/trunk/include/llvm/IR/Module.h Sun Dec 25 03:36:24 2016
@@ -590,29 +590,69 @@ public:
 /// @name Convenience iterators
 /// @{
 
-  typedef concat_iterator<GlobalObject, iterator, global_iterator>
-      global_object_iterator;
-  typedef concat_iterator<const GlobalObject, const_iterator,
-                          const_global_iterator>
-      const_global_object_iterator;
+  template <bool IsConst> class global_object_iterator_t {
+    friend Module;
 
-  iterator_range<global_object_iterator> global_objects() {
-    return concat<GlobalObject>(functions(), globals());
-  }
-  iterator_range<const_global_object_iterator> global_objects() const {
-    return concat<const GlobalObject>(functions(), globals());
-  }
+    typename std::conditional<IsConst, const_iterator, iterator>::type
+        function_i,
+        function_e;
+    typename std::conditional<IsConst, const_global_iterator,
+                              global_iterator>::type global_i;
+
+    typedef
+        typename std::conditional<IsConst, const Module, Module>::type ModuleTy;
+
+    global_object_iterator_t(ModuleTy &M)
+        : function_i(M.begin()), function_e(M.end()),
+          global_i(M.global_begin()) {}
+    global_object_iterator_t(ModuleTy &M, int)
+        : function_i(M.end()), function_e(M.end()), global_i(M.global_end()) {}
+
+  public:
+    global_object_iterator_t &operator++() {
+      if (function_i != function_e)
+        ++function_i;
+      else
+        ++global_i;
+      return *this;
+    }
+
+    typename std::conditional<IsConst, const GlobalObject, GlobalObject>::type &
+    operator*() const {
+      if (function_i != function_e)
+        return *function_i;
+      else
+        return *global_i;
+    }
+
+    bool operator!=(const global_object_iterator_t &other) const {
+      return function_i != other.function_i || global_i != other.global_i;
+    }
+  };
+
+  typedef global_object_iterator_t</*IsConst=*/false> global_object_iterator;
+  typedef global_object_iterator_t</*IsConst=*/true>
+      const_global_object_iterator;
 
   global_object_iterator global_object_begin() {
-    return global_objects().begin();
+    return global_object_iterator(*this);
+  }
+  global_object_iterator global_object_end() {
+    return global_object_iterator(*this, 0);
   }
-  global_object_iterator global_object_end() { return global_objects().end(); }
 
   const_global_object_iterator global_object_begin() const {
-    return global_objects().begin();
+    return const_global_object_iterator(*this);
   }
   const_global_object_iterator global_object_end() const {
-    return global_objects().end();
+    return const_global_object_iterator(*this, 0);
+  }
+
+  iterator_range<global_object_iterator> global_objects() {
+    return make_range(global_object_begin(), global_object_end());
+  }
+  iterator_range<const_global_object_iterator> global_objects() const {
+    return make_range(global_object_begin(), global_object_end());
   }
 
   /// @}

Modified: llvm/trunk/unittests/ADT/STLExtrasTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/STLExtrasTest.cpp?rev=290513&r1=290512&r2=290513&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/STLExtrasTest.cpp (original)
+++ llvm/trunk/unittests/ADT/STLExtrasTest.cpp Sun Dec 25 03:36:24 2016
@@ -10,7 +10,6 @@
 #include "llvm/ADT/STLExtras.h"
 #include "gtest/gtest.h"
 
-#include <list>
 #include <vector>
 
 using namespace llvm;
@@ -254,26 +253,4 @@ TEST(STLExtrasTest, CountAdaptor) {
   EXPECT_EQ(1, count(v, 3));
   EXPECT_EQ(1, count(v, 4));
 }
-
-TEST(STLExtrasTest, ConcatRange) {
-  std::vector<int> Expected = {1, 2, 3, 4, 5, 6, 7, 8};
-  std::vector<int> Test;
-
-  std::vector<int> V1234 = {1, 2, 3, 4};
-  std::list<int> L56 = {5, 6};
-  SmallVector<int, 2> SV78 = {7, 8};
-
-  // Use concat across different sized ranges of different types with different
-  // iterators.
-  for (int &i : concat<int>(V1234, L56, SV78))
-    Test.push_back(i);
-  EXPECT_EQ(Expected, Test);
-
-  // Use concat between a temporary, an L-value, and an R-value to make sure
-  // complex lifetimes work well.
-  Test.clear();
-  for (int &i : concat<int>(std::vector<int>(V1234), L56, std::move(SV78)))
-    Test.push_back(i);
-  EXPECT_EQ(Expected, Test);
-}
 }




More information about the llvm-commits mailing list