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

Reply via email to