[libcxx-commits] [libcxx] r356818 - Fix a minor bug with std::next and prev not and negative numbers. In particular, std::prev cannot require Bidirectional Iterators, because you might 'go back' -1 places, which goes forward. Thanks to Ville and Jonathan for the bug report.
Marshall Clow via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Mar 22 15:32:20 PDT 2019
Author: marshall
Date: Fri Mar 22 15:32:20 2019
New Revision: 356818
URL: http://llvm.org/viewvc/llvm-project?rev=356818&view=rev
Log:
Fix a minor bug with std::next and prev not and negative numbers. In particular, std::prev cannot require Bidirectional Iterators, because you might 'go back' -1 places, which goes forward. Thanks to Ville and Jonathan for the bug report.
Added:
libcxx/trunk/test/libcxx/iterators/advance.debug1.pass.cpp
libcxx/trunk/test/libcxx/iterators/next.debug1.pass.cpp
libcxx/trunk/test/libcxx/iterators/prev.debug1.pass.cpp
Modified:
libcxx/trunk/include/iterator
libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp
libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp
Modified: libcxx/trunk/include/iterator
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/iterator?rev=356818&r1=356817&r2=356818&view=diff
==============================================================================
--- libcxx/trunk/include/iterator (original)
+++ libcxx/trunk/include/iterator Fri Mar 22 15:32:20 2019
@@ -584,6 +584,8 @@ inline _LIBCPP_INLINE_VISIBILITY _LIBCPP
void advance(_InputIter& __i,
typename iterator_traits<_InputIter>::difference_type __n)
{
+ _LIBCPP_ASSERT(__n >= 0 || __is_bidirectional_iterator<_InputIter>::value,
+ "Attempt to advance(it, -n) on a non-bidi iterator");
__advance(__i, __n, typename iterator_traits<_InputIter>::iterator_category());
}
@@ -624,20 +626,25 @@ typename enable_if
next(_InputIter __x,
typename iterator_traits<_InputIter>::difference_type __n = 1)
{
+ _LIBCPP_ASSERT(__n >= 0 || __is_bidirectional_iterator<_InputIter>::value,
+ "Attempt to next(it, -n) on a non-bidi iterator");
+
_VSTD::advance(__x, __n);
return __x;
}
-template <class _BidirectionalIter>
+template <class _InputIter>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
typename enable_if
<
- __is_bidirectional_iterator<_BidirectionalIter>::value,
- _BidirectionalIter
+ __is_input_iterator<_InputIter>::value,
+ _InputIter
>::type
-prev(_BidirectionalIter __x,
- typename iterator_traits<_BidirectionalIter>::difference_type __n = 1)
+prev(_InputIter __x,
+ typename iterator_traits<_InputIter>::difference_type __n = 1)
{
+ _LIBCPP_ASSERT(__n <= 0 || __is_bidirectional_iterator<_InputIter>::value,
+ "Attempt to prev(it, +n) on a non-bidi iterator");
_VSTD::advance(__x, -__n);
return __x;
}
Added: libcxx/trunk/test/libcxx/iterators/advance.debug1.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/iterators/advance.debug1.pass.cpp?rev=356818&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/iterators/advance.debug1.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/iterators/advance.debug1.pass.cpp Fri Mar 22 15:32:20 2019
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Can't test the system lib because this test enables debug mode
+// MODULES_DEFINES: _LIBCPP_DEBUG=1
+// UNSUPPORTED: c++98, c++03
+// UNSUPPORTED: windows
+// UNSUPPORTED: with_system_cxx_lib
+
+// <list>
+
+// Call advance(non-bidi iterator, -1)
+
+#define _LIBCPP_DEBUG 0
+
+#include <iterator>
+#include "debug_mode_helper.h"
+
+#include "test_iterators.h"
+
+int main(int, char**)
+{
+ int a[] = {1, 2, 3};
+
+ bidirectional_iterator<int *> bidi(a+1);
+ std::advance(bidi, 1); // should work fine
+ std::advance(bidi, 0); // should work fine
+ std::advance(bidi, -1); // should work fine
+
+ forward_iterator<int *> it(a+1);
+ std::advance(it, 1); // should work fine
+ std::advance(it, 0); // should work fine
+ EXPECT_DEATH( std::advance(it, -1) ); // can't go backwards on a FwdIter
+
+ return 0;
+}
+
Added: libcxx/trunk/test/libcxx/iterators/next.debug1.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/iterators/next.debug1.pass.cpp?rev=356818&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/iterators/next.debug1.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/iterators/next.debug1.pass.cpp Fri Mar 22 15:32:20 2019
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Can't test the system lib because this test enables debug mode
+// MODULES_DEFINES: _LIBCPP_DEBUG=1
+// UNSUPPORTED: c++98, c++03
+// UNSUPPORTED: windows
+// UNSUPPORTED: with_system_cxx_lib
+
+// <list>
+
+// Call next(non-bidi iterator, -1)
+
+#define _LIBCPP_DEBUG 0
+
+#include <iterator>
+#include "debug_mode_helper.h"
+
+#include "test_iterators.h"
+
+int main(int, char**)
+{
+ int a[] = {1, 2, 3};
+
+
+ forward_iterator<int *> it(a+1);
+ std::next(it, 1); // should work fine
+ std::next(it, 0); // should work fine
+ EXPECT_DEATH( std::next(it, -1) ); // can't go backwards on a FwdIter
+
+ return 0;
+}
+
Added: libcxx/trunk/test/libcxx/iterators/prev.debug1.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/libcxx/iterators/prev.debug1.pass.cpp?rev=356818&view=auto
==============================================================================
--- libcxx/trunk/test/libcxx/iterators/prev.debug1.pass.cpp (added)
+++ libcxx/trunk/test/libcxx/iterators/prev.debug1.pass.cpp Fri Mar 22 15:32:20 2019
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Can't test the system lib because this test enables debug mode
+// MODULES_DEFINES: _LIBCPP_DEBUG=1
+// UNSUPPORTED: with_system_cxx_lib
+// UNSUPPORTED: c++98, c++03
+// UNSUPPORTED: windows
+// UNSUPPORTED: with_system_cxx_lib
+
+// <list>
+
+// Call prev(forward_iterator, -1)
+
+#define _LIBCPP_DEBUG 0
+
+#include <iterator>
+#include "debug_mode_helper.h"
+
+#include "test_iterators.h"
+
+int main(int, char**)
+{
+ int a[] = {1, 2, 3};
+
+ bidirectional_iterator<int *> bidi(a+1);
+ std::prev(bidi, -1); // should work fine
+ std::prev(bidi, 0); // should work fine
+ std::prev(bidi, 1); // should work fine
+
+ forward_iterator<int *> it(a+1);
+ std::prev(it, -1); // should work fine
+ std::prev(it, 0); // should work fine
+ EXPECT_DEATH( std::prev(it, 1) ); // can't go backwards on a FwdIter
+
+ return 0;
+}
Modified: libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp?rev=356818&r1=356817&r2=356818&view=diff
==============================================================================
--- libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp (original)
+++ libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp Fri Mar 22 15:32:20 2019
@@ -55,10 +55,12 @@ int main(int, char**)
{
{
const char* s = "1234567890";
- test(input_iterator<const char*>(s), 10, input_iterator<const char*>(s+10));
- test(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10));
- test(bidirectional_iterator<const char*>(s), 10, bidirectional_iterator<const char*>(s+10));
- test(random_access_iterator<const char*>(s), 10, random_access_iterator<const char*>(s+10));
+ test(input_iterator<const char*>(s), 10, input_iterator<const char*>(s+10));
+ test(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10));
+ test(bidirectional_iterator<const char*>(s), 10, bidirectional_iterator<const char*>(s+10));
+ test(bidirectional_iterator<const char*>(s+10), -10, bidirectional_iterator<const char*>(s));
+ test(random_access_iterator<const char*>(s), 10, random_access_iterator<const char*>(s+10));
+ test(random_access_iterator<const char*>(s+10), -10, random_access_iterator<const char*>(s));
test(s, 10, s+10);
test(input_iterator<const char*>(s), input_iterator<const char*>(s+1));
@@ -70,10 +72,12 @@ int main(int, char**)
#if TEST_STD_VER > 14
{
constexpr const char* s = "1234567890";
- static_assert( constexpr_test(input_iterator<const char*>(s), 10, input_iterator<const char*>(s+10)), "" );
- static_assert( constexpr_test(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10)), "" );
- static_assert( constexpr_test(bidirectional_iterator<const char*>(s), 10, bidirectional_iterator<const char*>(s+10)), "" );
- static_assert( constexpr_test(random_access_iterator<const char*>(s), 10, random_access_iterator<const char*>(s+10)), "" );
+ static_assert( constexpr_test(input_iterator<const char*>(s), 10, input_iterator<const char*>(s+10)), "" );
+ static_assert( constexpr_test(forward_iterator<const char*>(s), 10, forward_iterator<const char*>(s+10)), "" );
+ static_assert( constexpr_test(bidirectional_iterator<const char*>(s), 10, bidirectional_iterator<const char*>(s+10)), "" );
+ static_assert( constexpr_test(bidirectional_iterator<const char*>(s+10), -10, bidirectional_iterator<const char*>(s)), "" );
+ static_assert( constexpr_test(random_access_iterator<const char*>(s), 10, random_access_iterator<const char*>(s+10)), "" );
+ static_assert( constexpr_test(random_access_iterator<const char*>(s+10), -10, random_access_iterator<const char*>(s)), "" );
static_assert( constexpr_test(s, 10, s+10), "" );
static_assert( constexpr_test(input_iterator<const char*>(s), input_iterator<const char*>(s+1)), "" );
Modified: libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp?rev=356818&r1=356817&r2=356818&view=diff
==============================================================================
--- libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp (original)
+++ libcxx/trunk/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp Fri Mar 22 15:32:20 2019
@@ -8,7 +8,7 @@
// <iterator>
-// template <BidirectionalIterator Iter>
+// template <InputIterator Iter>
// Iter prev(Iter x, Iter::difference_type n = 1);
#include <iterator>
@@ -53,8 +53,11 @@ int main(int, char**)
{
{
const char* s = "1234567890";
- test(bidirectional_iterator<const char*>(s+10), 10, bidirectional_iterator<const char*>(s));
- test(random_access_iterator<const char*>(s+10), 10, random_access_iterator<const char*>(s));
+ test(forward_iterator <const char*>(s), -10, forward_iterator <const char*>(s+10));
+ test(bidirectional_iterator<const char*>(s+10), 10, bidirectional_iterator<const char*>(s));
+ test(bidirectional_iterator<const char*>(s), -10, bidirectional_iterator<const char*>(s+10));
+ test(random_access_iterator<const char*>(s+10), 10, random_access_iterator<const char*>(s));
+ test(random_access_iterator<const char*>(s), -10, random_access_iterator<const char*>(s+10));
test(s+10, 10, s);
test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s));
@@ -64,8 +67,11 @@ int main(int, char**)
#if TEST_STD_VER > 14
{
constexpr const char* s = "1234567890";
- static_assert( constexpr_test(bidirectional_iterator<const char*>(s+10), 10, bidirectional_iterator<const char*>(s)), "" );
- static_assert( constexpr_test(random_access_iterator<const char*>(s+10), 10, random_access_iterator<const char*>(s)), "" );
+ static_assert( constexpr_test(forward_iterator <const char*>(s), -10, forward_iterator <const char*>(s+10)), "" );
+ static_assert( constexpr_test(bidirectional_iterator<const char*>(s+10), 10, bidirectional_iterator<const char*>(s)), "" );
+ static_assert( constexpr_test(forward_iterator <const char*>(s), -10, forward_iterator <const char*>(s+10)), "" );
+ static_assert( constexpr_test(random_access_iterator<const char*>(s+10), 10, random_access_iterator<const char*>(s)), "" );
+ static_assert( constexpr_test(forward_iterator <const char*>(s), -10, forward_iterator <const char*>(s+10)), "" );
static_assert( constexpr_test(s+10, 10, s), "" );
static_assert( constexpr_test(bidirectional_iterator<const char*>(s+1), bidirectional_iterator<const char*>(s)), "" );
More information about the libcxx-commits
mailing list