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.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@356818 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/iterator b/include/iterator
index 16c1bcb..5846c1b 100644
--- a/include/iterator
+++ b/include/iterator
@@ -584,6 +584,8 @@
 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 @@
 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;
 }
diff --git a/test/libcxx/iterators/advance.debug1.pass.cpp b/test/libcxx/iterators/advance.debug1.pass.cpp
new file mode 100644
index 0000000..37aa3df
--- /dev/null
+++ b/test/libcxx/iterators/advance.debug1.pass.cpp
@@ -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;
+}
+
diff --git a/test/libcxx/iterators/next.debug1.pass.cpp b/test/libcxx/iterators/next.debug1.pass.cpp
new file mode 100644
index 0000000..72d9fd4
--- /dev/null
+++ b/test/libcxx/iterators/next.debug1.pass.cpp
@@ -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;
+}
+
diff --git a/test/libcxx/iterators/prev.debug1.pass.cpp b/test/libcxx/iterators/prev.debug1.pass.cpp
new file mode 100644
index 0000000..da7c931
--- /dev/null
+++ b/test/libcxx/iterators/prev.debug1.pass.cpp
@@ -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;
+}
diff --git a/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp b/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp
index 87f79fb..26ec32c 100644
--- a/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp
+++ b/test/std/iterators/iterator.primitives/iterator.operations/next.pass.cpp
@@ -55,10 +55,12 @@
 {
     {
     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 @@
 #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)), "" );
diff --git a/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp b/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp
index 2ee0444..8faaf3d 100644
--- a/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp
+++ b/test/std/iterators/iterator.primitives/iterator.operations/prev.pass.cpp
@@ -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 @@
 {
     {
     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 @@
 #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)), "" );