Author: ericwf Date: Tue Jul 19 18:27:18 2016 New Revision: 276059 URL: http://llvm.org/viewvc/llvm-project?rev=276059&view=rev Log: Add heterogeneous comparator support for __debug_less. Fixes PR17147.
Added: libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp Modified: libcxx/trunk/include/algorithm Modified: libcxx/trunk/include/algorithm URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/algorithm?rev=276059&r1=276058&r2=276059&view=diff ============================================================================== --- libcxx/trunk/include/algorithm (original) +++ libcxx/trunk/include/algorithm Tue Jul 19 18:27:18 2016 @@ -749,14 +749,28 @@ struct __debug_less { _Compare __comp_; __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) - _LIBCPP_ASSERT(!__comp_(__y, __x), "Comparator does not induce a strict weak ordering"); + __do_compare_assert(0, __y, __x); return __r; } + + template <class _LHS, class _RHS> + inline _LIBCPP_INLINE_VISIBILITY + decltype((void)_VSTD::declval<_Compare&>()( + _VSTD::declval<_LHS const&>(), _VSTD::declval<_RHS const&>())) + __do_compare_assert(int, _LHS const& __l, _RHS const& __r) { + _LIBCPP_ASSERT(!__comp_(__l, __r), + "Comparator does not induce a strict weak ordering"); + } + + template <class _LHS, class _RHS> + inline _LIBCPP_INLINE_VISIBILITY + void __do_compare_assert(long, _LHS const&, _RHS const&) {} }; #endif // _LIBCPP_DEBUG Added: 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=276059&view=auto ============================================================================== --- libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp (added) +++ libcxx/trunk/test/libcxx/algorithms/debug_less.pass.cpp Tue Jul 19 18:27:18 2016 @@ -0,0 +1,167 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: libcpp-no-exceptions + +// <algorithm> + +// template <class _Compare> struct __debug_less + +// __debug_less checks that a comparator actually provides a strict-weak ordering. + +struct DebugException {}; + +#define _LIBCPP_DEBUG 0 +#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : throw ::DebugException()) + +#include <algorithm> +#include <cassert> + +template <int ID> +struct MyType { + int value; + explicit MyType(int xvalue = 0) : value(xvalue) {} +}; + +template <int ID1, int ID2> +bool operator<(MyType<ID1> const& LHS, MyType<ID2> const& RHS) { + return LHS.value < RHS.value; +} + +struct CompareBase { + static int called; + static void reset() { + called = 0; + } +}; + +int CompareBase::called = 0; + +template <class ValueType> +struct GoodComparator : public CompareBase { + bool operator()(ValueType const& lhs, ValueType const& rhs) const { + ++CompareBase::called; + return lhs < rhs; + } +}; + +template <class ValueType> +struct BadComparator : public CompareBase { + bool operator()(ValueType const&, ValueType const&) const { + ++CompareBase::called; + return true; + } +}; + +template <class T1, class T2> +struct TwoWayHomoComparator : public CompareBase { + bool operator()(T1 const& lhs, T2 const& rhs) const { + ++CompareBase::called; + return lhs < rhs; + } + + bool operator()(T2 const& lhs, T1 const& rhs) const { + ++CompareBase::called; + return lhs < rhs; + } +}; + +template <class T1, class T2> +struct OneWayHomoComparator : public CompareBase { + bool operator()(T1 const& lhs, T2 const& rhs) const { + ++CompareBase::called; + return lhs < rhs; + } +}; + +using std::__debug_less; + +typedef MyType<0> MT0; +typedef MyType<1> MT1; + +void test_passing() { + int& called = CompareBase::called; + called = 0; + MT0 one(1); + MT0 two(2); + MT1 three(3); + MT1 four(4); + + { + typedef GoodComparator<MT0> C; + typedef __debug_less<C> D; + + C c; + D d(c); + + assert(d(one, two) == true); + assert(called == 2); + called = 0; + + assert(d(one, one) == false); + assert(called == 1); + called = 0; + + assert(d(two, one) == false); + assert(called == 1); + called = 0; + } + { + typedef TwoWayHomoComparator<MT0, MT1> C; + typedef __debug_less<C> D; + C c; + D d(c); + + assert(d(one, three) == true); + assert(called == 2); + called = 0; + + assert(d(three, one) == false); + assert(called == 1); + called = 0; + } + { + typedef OneWayHomoComparator<MT0, MT1> C; + typedef __debug_less<C> D; + C c; + D d(c); + + assert(d(one, three) == true); + assert(called == 1); + called = 0; + } +} + +void test_failing() { + int& called = CompareBase::called; + called = 0; + MT0 one(1); + MT0 two(2); + + { + typedef BadComparator<MT0> C; + typedef __debug_less<C> D; + C c; + D d(c); + + try { + d(one, two); + assert(false); + } catch (DebugException const&) { + } + + assert(called == 2); + called = 0; + } +} + +int main() { + test_passing(); + test_failing(); +} \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits