Adds negative tests for preconditions on inserting into a full inplace_vector and erasing non-existent elementsi at compile-time. This ensures coverage for the inplace_vector<T, 0> specialization.
Also extends element access tests to cover front() and back() methods, and const and mutable overloads for all accesses. PR libstdc++/119137 libstdc++-v3/ChangeLog: * testsuite/23_containers/inplace_vector/access/elem.cc: Cover front and back methods and const calls. * testsuite/23_containers/inplace_vector/access/elem_neg.cc: Likewise. * testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc: New test. * testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc: New test. --- v3 removes duplicated empty lines. Pushed to trunk. .../inplace_vector/access/elem.cc | 42 ++++++++++------ .../inplace_vector/access/elem_neg.cc | 50 ++++++++++++++++--- .../inplace_vector/modifiers/erase_neg.cc | 43 ++++++++++++++++ .../modifiers/single_insert_neg.cc | 42 ++++++++++++++++ 4 files changed, 155 insertions(+), 22 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc create mode 100644 libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc index a598514bd9b..bc06aa09425 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem.cc @@ -41,22 +41,42 @@ test_out_of_capacity() #endif } -template<typename T> + +template<bool Const, typename T, size_t N> +using InplaceVector = std::conditional_t<Const, + const std::inplace_vector<T, N>, + std::inplace_vector<T, N>>; + +template<bool Const, typename T> constexpr void test_access() { - std::inplace_vector<T, 10> v{1, 2, 3, 4, 5}; + InplaceVector<Const, T, 10> v{1, 2, 3, 4, 5}; + + auto& e0a = v[0]; + auto& e0b = v.at(0); + auto& e0c = v.front(); + VERIFY( &e0a == &e0b ); + VERIFY( &e0a == &e0c ); + VERIFY( &e0a == &v.begin()[0] ); + VERIFY( &e0a == &v.cbegin()[0] ); + VERIFY( &e0a == v.data() ); + VERIFY( e0a == T(1) ); auto& e3a = v[2]; - auto& e3b = std::as_const(v).at(2); + auto& e3b = v.at(2); VERIFY( &e3a == &e3b ); VERIFY( &e3a == &v.begin()[2] ); - VERIFY( &e3a == std::as_const(v).data() + 2 ); + VERIFY( &e3a == &v.cbegin()[2] ); + VERIFY( &e3a == v.data() + 2 ); VERIFY( e3a == T(3) ); - auto& e4a = as_const(v)[4]; + auto& e4a = v[4]; auto& e4b = v.at(4); + auto& e4c = v.back(); VERIFY( &e4a == &e4b ); + VERIFY( &e4a == &e4c ); + VERIFY( &e4a == &v.begin()[4] ); VERIFY( &e4a == &v.cbegin()[4] ); VERIFY( &e4a == v.data() + 4 ); VERIFY( e4a == T(5) ); @@ -77,15 +97,6 @@ test_access() catch (std::out_of_range const&) { } - - try - { - (void)as_const(v).at(7); - VERIFY(false); - } - catch (std::out_of_range const&) - { - } #endif } @@ -94,7 +105,8 @@ int main() auto test_all = [] { test_out_of_capacity<0, int>(); test_out_of_capacity<4, int>(); - test_access<int>(); + test_access<true, int>(); + test_access<false, int>(); return true; }; diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc index e3ba5eb6866..b2bff0d6387 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/access/elem_neg.cc @@ -2,27 +2,63 @@ #include <inplace_vector> -template<size_t N, typename T> +template<bool Const, typename T, size_t N> +using InplaceVector + = std::conditional_t<Const, + const std::inplace_vector<T, N>, + std::inplace_vector<T, N>>; + +template<bool Const, size_t N, typename T> +constexpr bool +test_front_on_empty() +{ + InplaceVector<Const, T, N> v; + (void)v.front(); // { dg-error "in 'constexpr' expansion of" } + return true; +} + +template<bool Const, size_t N, typename T> +constexpr bool +test_back_on_empty() +{ + InplaceVector<Const, T, N> v; + (void)v.back(); // { dg-error "in 'constexpr' expansion of" } + return true; +} + +template<bool Const, size_t N, typename T> constexpr bool test_out_of_capacity() { - std::inplace_vector<T, N> v; + InplaceVector<Const, T, N> v; (void)v[N+2]; // { dg-error "in 'constexpr' expansion of" } return true; } -template<typename T> +template<bool Const, typename T> constexpr bool test_out_of_size() { - std::inplace_vector<T, 10> v{1, 2, 3, 4, 5}; + InplaceVector<Const, T, 10> v{1, 2, 3, 4, 5}; (void)v[7]; // { dg-error "in 'constexpr' expansion of" } return true; } -static_assert(test_out_of_capacity<0, int>()); // { dg-error "in 'constexpr' expansion of" } -static_assert(test_out_of_capacity<4, int>()); // { dg-error "in 'constexpr' expansion of" } -static_assert(test_out_of_size<int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_front_on_empty<false, 0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_front_on_empty<false, 4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_back_on_empty<false, 0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_back_on_empty<false, 4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_out_of_capacity<false, 0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_out_of_capacity<false, 4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_out_of_size<false, int>()); // { dg-error "in 'constexpr' expansion of" } + +static_assert(test_front_on_empty<true, 0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_front_on_empty<true, 4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_back_on_empty<true, 0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_back_on_empty<true, 4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_out_of_capacity<true, 0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_out_of_capacity<true, 4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_out_of_size<true, int>()); // { dg-error "in 'constexpr' expansion of" } // { dg-prune-output "non-constant condition for static assertion" } // { dg-prune-output "is not a constant expression" } diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc new file mode 100644 index 00000000000..a1f43b3b53b --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/erase_neg.cc @@ -0,0 +1,43 @@ +// { dg-do compile { target c++26 } } + +#include <inplace_vector> + +template<size_t N, typename T> +constexpr bool +test_pop_back_on_empty() +{ + std::inplace_vector<T, N> v; + v.pop_back(); // { dg-error "in 'constexpr' expansion of" } + return true; +} + +template<size_t N, typename T> +constexpr bool +test_erase_begin_on_empty() +{ + std::inplace_vector<T, N> v; + v.erase(v.begin()); // { dg-error "in 'constexpr' expansion of" } + return true; +} + +template<size_t N, typename T> +constexpr bool +test_erase_end(size_t size = 0) +{ + std::inplace_vector<T, N> v(size, T()); + v.erase(v.end()); // { dg-error "in 'constexpr' expansion of" } + return true; +} + +static_assert(test_pop_back_on_empty<0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_pop_back_on_empty<4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_erase_begin_on_empty<0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_erase_begin_on_empty<4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_erase_end<0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_erase_end<4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_erase_end<4, int>(2)); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_erase_end<4, int>(4)); // { dg-error "in 'constexpr' expansion of" } + +// { dg-prune-output "non-constant condition for static assertion" } +// { dg-prune-output "is not a constant expression" } +// { dg-prune-output "call to non-'constexpr' function" } diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc new file mode 100644 index 00000000000..0552b8c2b7d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert_neg.cc @@ -0,0 +1,42 @@ +// { dg-do compile { target c++26 } } + +#include <inplace_vector> + +template<size_t N, typename T> +constexpr bool +test_unchecked_emplace_back() +{ + std::inplace_vector<T, N> v(N, T(1)); + v.unchecked_emplace_back(); // { dg-error "in 'constexpr' expansion of" } + return true; +} + +template<size_t N, typename T> +constexpr bool +test_push_back_lvalue() +{ + auto val = T();; + std::inplace_vector<T, N> v(N, T(1)); + v.unchecked_push_back(val); // { dg-error "in 'constexpr' expansion of" } + return true; +} + +template<size_t N, typename T> +constexpr bool +test_push_back_rvalue() +{ + std::inplace_vector<T, N> v(N, T(1)); + v.unchecked_push_back(T()); // { dg-error "in 'constexpr' expansion of" } + return true; +} + +static_assert(test_unchecked_emplace_back<0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_unchecked_emplace_back<4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_push_back_lvalue<0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_push_back_lvalue<4, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_push_back_rvalue<0, int>()); // { dg-error "in 'constexpr' expansion of" } +static_assert(test_push_back_rvalue<4, int>()); // { dg-error "in 'constexpr' expansion of" } + +// { dg-prune-output "non-constant condition for static assertion" } +// { dg-prune-output "is not a constant expression" } +// { dg-prune-output "call to non-'constexpr' function" } -- 2.49.0