[libcxx-commits] [libcxx] r358423 - [libc++] Fix build failure with _LIBCPP_DEBUG=0 when iterators return values instead of references

Thomas Anderson via libcxx-commits libcxx-commits at lists.llvm.org
Mon Apr 15 10:02:15 PDT 2019


Author: thomasanderson
Date: Mon Apr 15 10:02:15 2019
New Revision: 358423

URL: http://llvm.org/viewvc/llvm-project?rev=358423&view=rev
Log:
[libc++] Fix build failure with _LIBCPP_DEBUG=0 when iterators return values instead of references

There are many STL algorithms (such as lexicographical_compare) that compare
values pointed to by iterators like so:
    __comp(*it1, *it2);
	
When building with `_LIBCPP_DEBUG=0`, comparators are wrapped in `__debug_less`
which does some additional validation.  But `__debug_less::operator()` takes
non-const references, so if the type of `*it1` is int, not int&, then the build
will fail.

This change adds a `const&` overload for `operator()` to fix the build.

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

Modified:
    libcxx/trunk/include/algorithm
    libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp

Modified: libcxx/trunk/include/algorithm
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/algorithm?rev=358423&r1=358422&r2=358423&view=diff
==============================================================================
--- libcxx/trunk/include/algorithm (original)
+++ libcxx/trunk/include/algorithm Mon Apr 15 10:02:15 2019
@@ -785,6 +785,15 @@ struct __debug_less
     __debug_less(_Compare& __c) : __comp_(__c) {}
 
     template <class _Tp, class _Up>
+    bool operator()(const _Tp& __x,  const _Up& __y)
+    {
+        bool __r = __comp_(__x, __y);
+        if (__r)
+            __do_compare_assert(0, __y, __x);
+        return __r;
+    }
+
+    template <class _Tp, class _Up>
     _LIBCPP_CONSTEXPR_AFTER_CXX17
     bool operator()(_Tp& __x,  _Up& __y)
     {

Modified: libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp?rev=358423&r1=358422&r2=358423&view=diff
==============================================================================
--- libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp (original)
+++ libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp Mon Apr 15 10:02:15 2019
@@ -235,10 +235,45 @@ void test_non_const_arg_cmp() {
     }
 }
 
+struct ValueIterator {
+    using iterator_category = std::input_iterator_tag;
+    using value_type = size_t;
+    using difference_type = ptrdiff_t;
+    using reference = size_t;
+    using pointer = size_t*;
+
+    ValueIterator() = default;
+
+    reference operator*() { return 0; }
+    ValueIterator& operator++() { return *this; }
+
+    friend bool operator==(ValueIterator, ValueIterator) { return true; }
+    friend bool operator!=(ValueIterator, ValueIterator) { return false; }
+};
+
+void test_value_iterator() {
+    // Ensure no build failures when iterators return values, not references.
+    assert(0 == std::lexicographical_compare(ValueIterator{}, ValueIterator{},
+                                             ValueIterator{}, ValueIterator{}));
+}
+
+void test_value_categories() {
+    std::less<int> l;
+    std::__debug_less<std::less<int>> dl(l);
+    int lvalue = 42;
+    const int const_lvalue = 101;
+
+    assert(dl(lvalue, const_lvalue));
+    assert(dl(/*rvalue*/1, lvalue));
+    assert(dl(static_cast<int&&>(1), static_cast<const int&&>(2)));
+}
+
 int main(int, char**) {
     test_passing();
     test_failing();
     test_upper_and_lower_bound();
     test_non_const_arg_cmp();
+    test_value_iterator();
+    test_value_categories();
     return 0;
 }




More information about the libcxx-commits mailing list