[libcxx] Add assertion in deque::pop_back when popping from an empty deque
authorLouis Dionne <ldionne@apple.com>
Wed, 12 Dec 2018 23:58:25 +0000 (23:58 +0000)
committerLouis Dionne <ldionne@apple.com>
Wed, 12 Dec 2018 23:58:25 +0000 (23:58 +0000)
Also, add tests making sure that vector and deque both catch the problem
when assertions are enabled. Otherwise, deque would segfault and vector
would never terminate.

llvm-svn: 348994

libcxx/include/deque
libcxx/test/libcxx/containers/sequences/deque/pop_back_empty.pass.cpp [new file with mode: 0644]
libcxx/test/libcxx/containers/sequences/vector/pop_back_empty.pass.cpp [new file with mode: 0644]

index 414c7a8..c232e53 100644 (file)
@@ -987,7 +987,7 @@ public:
 #if _LIBCPP_STD_VER >= 14
         _NOEXCEPT;
 #else
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
                     __is_nothrow_swappable<allocator_type>::value);
 #endif
 protected:
@@ -1156,7 +1156,7 @@ __deque_base<_Tp, _Allocator>::swap(__deque_base& __c)
 #if _LIBCPP_STD_VER >= 14
         _NOEXCEPT
 #else
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
                     __is_nothrow_swappable<allocator_type>::value)
 #endif
 {
@@ -2342,7 +2342,7 @@ deque<_Tp, _Allocator>::__add_front_capacity()
                 _Dp(__a, __base::__block_size));
         __buf.push_back(__hold.get());
         __hold.release();
-    
+
         for (typename __base::__map_pointer __i = __base::__map_.begin();
                 __i != __base::__map_.end(); ++__i)
             __buf.push_back(*__i);
@@ -2604,6 +2604,7 @@ template <class _Tp, class _Allocator>
 void
 deque<_Tp, _Allocator>::pop_back()
 {
+    _LIBCPP_ASSERT(!empty(), "deque::pop_back called for empty deque");
     allocator_type& __a = __base::__alloc();
     size_type __p = __base::size() + __base::__start_ - 1;
     __alloc_traits::destroy(__a, __to_raw_pointer(*(__base::__map_.begin() +
@@ -2854,7 +2855,7 @@ deque<_Tp, _Allocator>::swap(deque& __c)
 #if _LIBCPP_STD_VER >= 14
         _NOEXCEPT
 #else
-        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || 
+        _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
                     __is_nothrow_swappable<allocator_type>::value)
 #endif
 {
diff --git a/libcxx/test/libcxx/containers/sequences/deque/pop_back_empty.pass.cpp b/libcxx/test/libcxx/containers/sequences/deque/pop_back_empty.pass.cpp
new file mode 100644 (file)
index 0000000..1435f95
--- /dev/null
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <deque>
+
+// pop_back() more than the number of elements in a deque
+
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+
+#include <cstdlib>
+#include <deque>
+
+
+int main() {
+    std::deque<int> q;
+    q.push_back(0);
+    q.pop_back();
+    q.pop_back();
+}
diff --git a/libcxx/test/libcxx/containers/sequences/vector/pop_back_empty.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector/pop_back_empty.pass.cpp
new file mode 100644 (file)
index 0000000..4714912
--- /dev/null
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// pop_back() more than the number of elements in a vector
+
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+
+#include <cstdlib>
+#include <vector>
+
+
+int main() {
+    std::vector<int> v;
+    v.push_back(0);
+    v.pop_back();
+    v.pop_back();
+}