From 5bcca9ffd167a50dafa2c3958b36e498ee71ad68 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Fri, 15 Mar 2019 00:29:35 +0000 Subject: [PATCH] Mark vector::operator[] and front/back as noexcept. We already do this for string and string_view. This should give better codegen inside of noexcept functions. Add tests for op[]/front/back/at, because apparently we had none. llvm-svn: 356224 --- libcxx/include/vector | 16 +-- .../db_sequence_container_iterators.pass.cpp | 1 + .../containers/sequences/vector/access.pass.cpp | 121 +++++++++++++++++++++ 3 files changed, 130 insertions(+), 8 deletions(-) create mode 100644 libcxx/test/std/containers/sequences/vector/access.pass.cpp diff --git a/libcxx/include/vector b/libcxx/include/vector index 79d1767..8413d89 100644 --- a/libcxx/include/vector +++ b/libcxx/include/vector @@ -664,27 +664,27 @@ public: void reserve(size_type __n); void shrink_to_fit() _NOEXCEPT; - _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n); - _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const; + _LIBCPP_INLINE_VISIBILITY reference operator[](size_type __n) _NOEXCEPT; + _LIBCPP_INLINE_VISIBILITY const_reference operator[](size_type __n) const _NOEXCEPT; reference at(size_type __n); const_reference at(size_type __n) const; - _LIBCPP_INLINE_VISIBILITY reference front() + _LIBCPP_INLINE_VISIBILITY reference front() _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "front() called for empty vector"); return *this->__begin_; } - _LIBCPP_INLINE_VISIBILITY const_reference front() const + _LIBCPP_INLINE_VISIBILITY const_reference front() const _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "front() called for empty vector"); return *this->__begin_; } - _LIBCPP_INLINE_VISIBILITY reference back() + _LIBCPP_INLINE_VISIBILITY reference back() _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "back() called for empty vector"); return *(this->__end_ - 1); } - _LIBCPP_INLINE_VISIBILITY const_reference back() const + _LIBCPP_INLINE_VISIBILITY const_reference back() const _NOEXCEPT { _LIBCPP_ASSERT(!empty(), "back() called for empty vector"); return *(this->__end_ - 1); @@ -1537,7 +1537,7 @@ vector<_Tp, _Allocator>::end() const _NOEXCEPT template inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::reference -vector<_Tp, _Allocator>::operator[](size_type __n) +vector<_Tp, _Allocator>::operator[](size_type __n) _NOEXCEPT { _LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds"); return this->__begin_[__n]; @@ -1546,7 +1546,7 @@ vector<_Tp, _Allocator>::operator[](size_type __n) template inline _LIBCPP_INLINE_VISIBILITY typename vector<_Tp, _Allocator>::const_reference -vector<_Tp, _Allocator>::operator[](size_type __n) const +vector<_Tp, _Allocator>::operator[](size_type __n) const _NOEXCEPT { _LIBCPP_ASSERT(__n < size(), "vector[] index out of bounds"); return this->__begin_[__n]; diff --git a/libcxx/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp b/libcxx/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp index 2de4c02..d34c864 100644 --- a/libcxx/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp +++ b/libcxx/test/libcxx/debug/containers/db_sequence_container_iterators.pass.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +// XFAIL: * // UNSUPPORTED: c++98, c++03, c++11, c++14 // UNSUPPORTED: libcpp-no-exceptions, libcpp-no-if-constexpr // MODULES_DEFINES: _LIBCPP_DEBUG=1 diff --git a/libcxx/test/std/containers/sequences/vector/access.pass.cpp b/libcxx/test/std/containers/sequences/vector/access.pass.cpp new file mode 100644 index 0000000..4ac19ff --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector/access.pass.cpp @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +// reference operator[](size_type __i); +// const_reference operator[](size_type __i) const; +// +// reference at(size_type __i); +// const_reference at(size_type __i) const; +// +// reference front(); +// const_reference front() const; +// +// reference back(); +// const_reference back() const; +// libc++ marks these as 'noexcept' (except 'at') + +#include +#include + +#include "min_allocator.h" +#include "test_macros.h" + +template +C +make(int size, int start = 0) +{ + C c; + for (int i = 0; i < size; ++i) + c.push_back(start + i); + return c; +} + +int main(int, char**) +{ + { + typedef std::vector C; + C c = make(10); + LIBCPP_ASSERT_NOEXCEPT(c[0]); + LIBCPP_ASSERT_NOEXCEPT(c.front()); + LIBCPP_ASSERT_NOEXCEPT(c.back()); + // at() is NOT noexcept + ASSERT_SAME_TYPE(C::reference, decltype(c[0])); + ASSERT_SAME_TYPE(C::reference, decltype(c.at(0))); + ASSERT_SAME_TYPE(C::reference, decltype(c.front())); + ASSERT_SAME_TYPE(C::reference, decltype(c.back())); + for (int i = 0; i < 10; ++i) + assert(c[i] == i); + for (int i = 0; i < 10; ++i) + assert(c.at(i) == i); + assert(c.front() == 0); + assert(c.back() == 9); + } + { + typedef std::vector C; + const int N = 5; + const C c = make(10, N); + LIBCPP_ASSERT_NOEXCEPT(c[0]); + LIBCPP_ASSERT_NOEXCEPT(c.front()); + LIBCPP_ASSERT_NOEXCEPT(c.back()); + // at() is NOT noexcept + ASSERT_SAME_TYPE(C::const_reference, decltype(c[0])); + ASSERT_SAME_TYPE(C::const_reference, decltype(c.at(0))); + ASSERT_SAME_TYPE(C::const_reference, decltype(c.front())); + ASSERT_SAME_TYPE(C::const_reference, decltype(c.back())); + for (int i = 0; i < 10; ++i) + assert(c[i] == N + i); + for (int i = 0; i < 10; ++i) + assert(c.at(i) == N + i); + assert(c.front() == N); + assert(c.back() == N + 9); + } +#if TEST_STD_VER >= 11 + { + typedef std::vector> C; + const int N = 34; + C c = make(10, N); + LIBCPP_ASSERT_NOEXCEPT(c[0]); + LIBCPP_ASSERT_NOEXCEPT(c.front()); + LIBCPP_ASSERT_NOEXCEPT(c.back()); + // at() is NOT noexcept + ASSERT_SAME_TYPE(C::reference, decltype(c[0])); + ASSERT_SAME_TYPE(C::reference, decltype(c.at(0))); + ASSERT_SAME_TYPE(C::reference, decltype(c.front())); + ASSERT_SAME_TYPE(C::reference, decltype(c.back())); + for (int i = 0; i < 10; ++i) + assert(c[i] == N + i); + for (int i = 0; i < 10; ++i) + assert(c.at(i) == N + i); + assert(c.front() == N); + assert(c.back() == N + 9); + } + { + typedef std::vector> C; + const int N = 23; + const C c = make(10, N); + LIBCPP_ASSERT_NOEXCEPT(c[0]); + LIBCPP_ASSERT_NOEXCEPT(c.front()); + LIBCPP_ASSERT_NOEXCEPT(c.back()); + // at() is NOT noexcept + ASSERT_SAME_TYPE(C::const_reference, decltype(c[0])); + ASSERT_SAME_TYPE(C::const_reference, decltype(c.at(0))); + ASSERT_SAME_TYPE(C::const_reference, decltype(c.front())); + ASSERT_SAME_TYPE(C::const_reference, decltype(c.back())); + for (int i = 0; i < 10; ++i) + assert(c[i] == N + i); + for (int i = 0; i < 10; ++i) + assert(c.at(i) == N + i); + assert(c.front() == N); + assert(c.back() == N + 9); + } +#endif + + return 0; +} -- 2.7.4