[libcxx-commits] [libcxx] a4c8056 - [libc++] Robust against C++20-hostile iterators

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jun 16 04:27:03 PDT 2022


Author: Nikolas Klauser
Date: 2022-06-16T13:26:53+02:00
New Revision: a4c805600ef28068c224be811b3826cd71369f09

URL: https://github.com/llvm/llvm-project/commit/a4c805600ef28068c224be811b3826cd71369f09
DIFF: https://github.com/llvm/llvm-project/commit/a4c805600ef28068c224be811b3826cd71369f09.diff

LOG: [libc++] Robust against C++20-hostile iterators

Reviewed By: ldionne, #libc, EricWF

Spies: EricWF, libcxx-commits, mgrang

Differential Revision: https://reviews.llvm.org/D127669

Added: 
    libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp

Modified: 
    libcxx/test/std/algorithms/alg.sorting/alg.binary.search/lower.bound/lower_bound.pass.cpp
    libcxx/test/support/test_iterators.h

Removed: 
    


################################################################################
diff  --git a/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp b/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
new file mode 100644
index 0000000000000..fc137e5571d1a
--- /dev/null
+++ b/libcxx/test/libcxx/algorithms/robust_against_cpp20_hostile_iterators.compile.pass.cpp
@@ -0,0 +1,219 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// Check that all STL classic algorithms can be instantiated with a C++20-hostile iterator
+
+// ADDITIONAL_COMPILE_FLAGS: -Wno-ambiguous-reversed-operator
+
+#include <algorithm>
+#include <functional>
+#include <random>
+
+#include "test_macros.h"
+
+template <class Sub, class Iterator>
+struct IteratorAdaptorBase {
+  using OutTraits = std::iterator_traits<Iterator>;
+  using iterator_category = typename OutTraits::iterator_category;
+  using value_type = typename OutTraits::value_type;
+  using pointer = typename OutTraits::pointer;
+  using reference = typename OutTraits::reference;
+  using 
diff erence_type = typename OutTraits::
diff erence_type;
+
+  IteratorAdaptorBase() {}
+  IteratorAdaptorBase(Iterator) {}
+
+  Sub& sub() { return static_cast<Sub&>(*this); }
+  const Sub& sub() const { return static_cast<Sub&>(*this); }
+
+  const Iterator& base() const { return it_; }
+
+  reference get() const { return *it_; }
+  reference operator*() const { return *it_; }
+  pointer operator->() const { return it_; }
+  reference operator[](
diff erence_type) const { return *it_; }
+
+  Sub& operator++() { return static_cast<Sub&>(*this); }
+  Sub& operator--() { return static_cast<Sub&>(*this); }
+  Sub operator++(int) { return static_cast<Sub&>(*this); }
+  Sub operator--(int) { return static_cast<Sub&>(*this); }
+
+  Sub& operator+=(
diff erence_type) { return static_cast<Sub&>(*this); }
+  Sub& operator-=(
diff erence_type) { return static_cast<Sub&>(*this); }
+  bool operator==(Sub) const { return false; }
+  bool operator!=(Sub) const { return false; }
+  bool operator==(Iterator b) const { return *this == Sub(b); }
+  bool operator!=(Iterator b) const { return *this != Sub(b); }
+
+  friend Sub operator+(Sub, 
diff erence_type) { return Sub(); }
+  friend Sub operator+(
diff erence_type, Sub) { return Sub(); }
+  friend Sub operator-(Sub, 
diff erence_type) { return Sub(); }
+  friend 
diff erence_type operator-(Sub, Sub) { return 0; }
+
+  friend bool operator<(Sub, Sub) { return false; }
+  friend bool operator>(Sub, Sub) { return false; }
+  friend bool operator<=(Sub, Sub) { return false; }
+  friend bool operator>=(Sub, Sub) { return false; }
+
+ private:
+  Iterator it_;
+};
+
+template <typename It>
+struct Cpp20HostileIterator
+    : IteratorAdaptorBase<Cpp20HostileIterator<It>, It> {
+  Cpp20HostileIterator() {}
+  Cpp20HostileIterator(It) {}
+};
+
+struct Pred {
+  bool operator()(int, int) { return false; }
+  bool operator()(int) { return false; }
+  int operator()() { return 0; }
+};
+
+void test() {
+  Cpp20HostileIterator<int*> it;
+  Pred pred;
+  std::mt19937_64 rng;
+
+  (void) std::adjacent_find(it, it);
+  (void) std::adjacent_find(it, it, pred);
+  (void) std::all_of(it, it, pred);
+  (void) std::any_of(it, it, pred);
+  (void) std::binary_search(it, it, 0);
+  (void) std::binary_search(it, it, 0, pred);
+  (void) std::copy_if(it, it, it, pred);
+  (void) std::copy_n(it, 0, it);
+  (void) std::copy(it, it, it);
+  (void) std::count_if(it, it, pred);
+  (void) std::count(it, it, 0);
+  (void) std::equal_range(it, it, 0);
+  (void) std::equal_range(it, it, 0, pred);
+  (void) std::equal(it, it, it);
+  (void) std::equal(it, it, it, pred);
+#if TEST_STD_VER > 11
+  (void) std::equal(it, it, it, it);
+  (void) std::equal(it, it, it, it, pred);
+#endif
+  (void) std::fill_n(it, 0, 0);
+  (void) std::fill(it, it, 0);
+  (void) std::find_end(it, it, it, it);
+  (void) std::find_end(it, it, it, it, pred);
+  (void) std::find_first_of(it, it, it, it);
+  (void) std::find_first_of(it, it, it, it, pred);
+  (void) std::find_if_not(it, it, pred);
+  (void) std::find_if(it, it, pred);
+  (void) std::find(it, it, 0);
+#if TEST_STD_VER > 14
+  (void) std::for_each_n(it, 0, pred);
+#endif
+  (void) std::for_each(it, it, pred);
+  (void) std::generate_n(it, 0, pred);
+  (void) std::generate(it, it, pred);
+  (void) std::includes(it, it, it, it);
+  (void) std::includes(it, it, it, it, pred);
+  // (void) std::inplace_merge(it, it, it);
+  // (void) std::inplace_merge(it, it, it, pred);
+  (void) std::is_heap_until(it, it);
+  (void) std::is_heap_until(it, it, pred);
+  (void) std::is_heap(it, it);
+  (void) std::is_heap(it, it, pred);
+  (void) std::is_partitioned(it, it, pred);
+  (void) std::is_permutation(it, it, it);
+  (void) std::is_permutation(it, it, it, pred);
+#if TEST_STD_VER > 11
+  (void) std::is_permutation(it, it, it, it);
+  (void) std::is_permutation(it, it, it, it, pred);
+#endif
+  (void) std::is_sorted_until(it, it);
+  (void) std::is_sorted_until(it, it, pred);
+  (void) std::is_sorted(it, it);
+  (void) std::is_sorted(it, it, pred);
+  (void) std::lexicographical_compare(it, it, it, it);
+  (void) std::lexicographical_compare(it, it, it, it, pred);
+  (void) std::lower_bound(it, it, 0);
+  (void) std::lower_bound(it, it, 0, pred);
+  (void) std::make_heap(it, it);
+  (void) std::make_heap(it, it, pred);
+  (void) std::max_element(it, it);
+  (void) std::max_element(it, it, pred);
+  (void) std::merge(it, it, it, it, it);
+  (void) std::merge(it, it, it, it, it, pred);
+  (void) std::min_element(it, it);
+  (void) std::min_element(it, it, pred);
+  (void) std::minmax_element(it, it);
+  (void) std::minmax_element(it, it, pred);
+  (void) std::mismatch(it, it, it);
+  (void) std::mismatch(it, it, it, pred);
+  (void) std::move_backward(it, it, it);
+  (void) std::move(it, it, it);
+  (void) std::next_permutation(it, it);
+  (void) std::next_permutation(it, it, pred);
+  (void) std::none_of(it, it, pred);
+  (void) std::nth_element(it, it, it);
+  (void) std::nth_element(it, it, it, pred);
+  (void) std::partial_sort_copy(it, it, it, it);
+  (void) std::partial_sort_copy(it, it, it, it, pred);
+  (void) std::partial_sort(it, it, it);
+  (void) std::partial_sort(it, it, it, pred);
+  (void) std::partition_copy(it, it, it, it, pred);
+  (void) std::partition_point(it, it, pred);
+  (void) std::partition(it, it, pred);
+  (void) std::pop_heap(it, it);
+  (void) std::pop_heap(it, it, pred);
+  (void) std::prev_permutation(it, it);
+  (void) std::prev_permutation(it, it, pred);
+  (void) std::push_heap(it, it);
+  (void) std::push_heap(it, it, pred);
+  (void) std::remove_copy_if(it, it, it, pred);
+  (void) std::remove_copy(it, it, it, 0);
+  (void) std::remove_if(it, it, pred);
+  (void) std::remove(it, it, 0);
+  (void) std::replace_copy_if(it, it, it, pred, 0);
+  (void) std::replace_copy(it, it, it, 0, 0);
+  (void) std::replace_if(it, it, pred, 0);
+  (void) std::replace(it, it, 0, 0);
+  (void) std::reverse_copy(it, it, it);
+  (void) std::reverse(it, it);
+  (void) std::rotate_copy(it, it, it, it);
+  (void) std::rotate(it, it, it);
+#if TEST_STD_VER > 14
+  (void) std::sample(it, it, it, 0, rng);
+#endif
+  (void) std::search(it, it, it, it);
+  (void) std::search(it, it, it, it, pred);
+#if TEST_STD_VER > 14
+  (void) std::search(it, it, std::default_searcher<Cpp20HostileIterator<int*>>(it, it));
+#endif
+  (void) std::set_
diff erence(it, it, it, it, it);
+  (void) std::set_
diff erence(it, it, it, it, it, pred);
+  (void) std::set_intersection(it, it, it, it, it);
+  (void) std::set_intersection(it, it, it, it, it, pred);
+  (void) std::set_symmetric_
diff erence(it, it, it, it, it);
+  (void) std::set_symmetric_
diff erence(it, it, it, it, it, pred);
+  (void) std::set_union(it, it, it, it, it);
+  (void) std::set_union(it, it, it, it, it, pred);
+#if TEST_STD_VER > 17
+  (void) std::shift_left(it, it, 0);
+  (void) std::shift_right(it, it, 0);
+#endif
+  (void) std::shuffle(it, it, rng);
+  (void) std::sort_heap(it, it);
+  (void) std::sort_heap(it, it, pred);
+  (void) std::sort(it, it);
+  (void) std::sort(it, it, pred);
+  (void) std::stable_partition(it, it, pred);
+  // (void) std::stable_sort(it, it);
+  (void) std::swap_ranges(it, it, it);
+  (void) std::transform(it, it, it, pred);
+  (void) std::transform(it, it, it, it, pred);
+  (void) std::unique_copy(it, it, it);
+  (void) std::unique(it, it);
+  (void) std::upper_bound(it, it, 0);
+}

diff  --git a/libcxx/test/std/algorithms/alg.sorting/alg.binary.search/lower.bound/lower_bound.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.binary.search/lower.bound/lower_bound.pass.cpp
index 589e748b3e7f6..a2d8ab632303c 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.binary.search/lower.bound/lower_bound.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.binary.search/lower.bound/lower_bound.pass.cpp
@@ -65,11 +65,6 @@ test()
         test(Iter(v.data()), Iter(v.data()+v.size()), x);
 }
 
-void test_instantiation() {
-    auto iter = Cpp20HostileIterator<int*>();
-    std::lower_bound(iter, iter, 0);
-}
-
 int main(int, char**)
 {
     int d[] = {0, 1, 2, 3};

diff  --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index e41852d8e28fc..6d3a8e2699edd 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -794,59 +794,4 @@ class Iterator {
 
 #endif // TEST_STD_VER > 17
 
-template <class Sub, class Iterator>
-struct IteratorAdaptorBase {
-  using OutTraits = std::iterator_traits<Iterator>;
-  using iterator_category = typename OutTraits::iterator_category;
-  using value_type = typename OutTraits::value_type;
-  using pointer = typename OutTraits::pointer;
-  using reference = typename OutTraits::reference;
-  using 
diff erence_type = typename OutTraits::
diff erence_type;
-
-  IteratorAdaptorBase() {}
-  IteratorAdaptorBase(Iterator) {}
-
-  Sub& sub() { return static_cast<Sub&>(*this); }
-  const Sub& sub() const { return static_cast<Sub&>(*this); }
-
-  const Iterator& base() const { return it_; }
-
-  reference get() const { return *it_; }
-  reference operator*() const { return *it_; }
-  pointer operator->() const { return it_; }
-  reference operator[](
diff erence_type) const { return *it_; }
-
-  Sub& operator++() { return static_cast<Sub&>(*this); }
-  Sub& operator--() { return static_cast<Sub&>(*this); }
-  Sub operator++(int) { return static_cast<Sub&>(*this); }
-  Sub operator--(int) { return static_cast<Sub&>(*this); }
-
-  Sub& operator+=(
diff erence_type) { return static_cast<Sub&>(*this); }
-  Sub& operator-=(
diff erence_type) { return static_cast<Sub&>(*this); }
-  bool operator==(Sub) const { return false; }
-  bool operator!=(Sub) const { return false; }
-  bool operator==(Iterator b) const { return *this == Sub(b); }
-  bool operator!=(Iterator b) const { return *this != Sub(b); }
-
-  friend Sub operator+(Sub, 
diff erence_type) { Sub(); }
-  friend Sub operator+(
diff erence_type, Sub) { Sub(); }
-  friend Sub operator-(Sub, 
diff erence_type) { Sub(); }
-  friend 
diff erence_type operator-(Sub, Sub) { return 0; }
-
-  friend bool operator<(Sub, Sub) { return false; }
-  friend bool operator>(Sub, Sub) { return false; }
-  friend bool operator<=(Sub, Sub) { return false; }
-  friend bool operator>=(Sub, Sub) { return false; }
-
- private:
-  Iterator it_;
-};
-
-template <typename It>
-struct Cpp20HostileIterator
-    : IteratorAdaptorBase<Cpp20HostileIterator<It>, It> {
-  Cpp20HostileIterator() {}
-  Cpp20HostileIterator(It it);
-};
-
 #endif // SUPPORT_TEST_ITERATORS_H


        


More information about the libcxx-commits mailing list