[libcxx] Add assertion in deque::pop_back when popping from an empty deque

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.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@348994 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Louis Dionne
2018-12-12 23:58:25 +00:00
parent f0c3a12346
commit f77ee9b3c9
3 changed files with 55 additions and 4 deletions

View File

@@ -987,7 +987,7 @@ public:
#if _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 14
_NOEXCEPT; _NOEXCEPT;
#else #else
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
__is_nothrow_swappable<allocator_type>::value); __is_nothrow_swappable<allocator_type>::value);
#endif #endif
protected: protected:
@@ -1156,7 +1156,7 @@ __deque_base<_Tp, _Allocator>::swap(__deque_base& __c)
#if _LIBCPP_STD_VER >= 14 #if _LIBCPP_STD_VER >= 14
_NOEXCEPT _NOEXCEPT
#else #else
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
__is_nothrow_swappable<allocator_type>::value) __is_nothrow_swappable<allocator_type>::value)
#endif #endif
{ {
@@ -2342,7 +2342,7 @@ deque<_Tp, _Allocator>::__add_front_capacity()
_Dp(__a, __base::__block_size)); _Dp(__a, __base::__block_size));
__buf.push_back(__hold.get()); __buf.push_back(__hold.get());
__hold.release(); __hold.release();
for (typename __base::__map_pointer __i = __base::__map_.begin(); for (typename __base::__map_pointer __i = __base::__map_.begin();
__i != __base::__map_.end(); ++__i) __i != __base::__map_.end(); ++__i)
__buf.push_back(*__i); __buf.push_back(*__i);
@@ -2604,6 +2604,7 @@ template <class _Tp, class _Allocator>
void void
deque<_Tp, _Allocator>::pop_back() deque<_Tp, _Allocator>::pop_back()
{ {
_LIBCPP_ASSERT(!empty(), "deque::pop_back called for empty deque");
allocator_type& __a = __base::__alloc(); allocator_type& __a = __base::__alloc();
size_type __p = __base::size() + __base::__start_ - 1; size_type __p = __base::size() + __base::__start_ - 1;
__alloc_traits::destroy(__a, __to_raw_pointer(*(__base::__map_.begin() + __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 #if _LIBCPP_STD_VER >= 14
_NOEXCEPT _NOEXCEPT
#else #else
_NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value || _NOEXCEPT_(!__alloc_traits::propagate_on_container_swap::value ||
__is_nothrow_swappable<allocator_type>::value) __is_nothrow_swappable<allocator_type>::value)
#endif #endif
{ {

View File

@@ -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();
}

View File

@@ -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();
}