[libcxx-commits] [libcxx] [libc++] Implement `std::inplace_vector<T, N>` (PR #105981)

Mital Ashok via libcxx-commits libcxx-commits at lists.llvm.org
Sun Aug 25 04:50:07 PDT 2024


https://github.com/MitalAshok created https://github.com/llvm/llvm-project/pull/105981

P0843R14 <https://wg21.link/P0843R14>: `std::inplace_vector<T, N>`

The ABI of this class is an array of `T[N]` followed by a `__small_size_type` member to hold the size, which is some unsigned integral type depending on `T` and `N` (at least large enough to hold up to `N`). Or if `N == 0`, an empty class as mandated by the standard.

This is not the fastest implementation. It aims to be correct and able to be optimised in the future in an ABI compatible way.

Closes #105433


>From a4127b327df6b05af163d6a58f0f2c8956b1323c Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Sat, 24 Aug 2024 17:57:58 +0100
Subject: [PATCH] [libc++] Implement std::inplace_vector<T, N>

---
 libcxx/docs/FeatureTestMacroTable.rst         |    2 +-
 libcxx/docs/Status/Cxx2cPapers.csv            |    2 +-
 libcxx/include/CMakeLists.txt                 |    1 +
 libcxx/include/__configuration/abi.h          |    3 +-
 libcxx/include/__iterator/wrap_iter.h         |    4 +
 libcxx/include/inplace_vector                 | 1022 +++++++++++++++++
 libcxx/include/module.modulemap               |    4 +
 libcxx/include/version                        |    2 +-
 .../sequences/inplace.vector/access.pass.cpp  |  133 +++
 .../sequences/inplace.vector/compare.pass.cpp |  129 +++
 .../inplace.vector/compare.three_way.pass.cpp |   34 +
 .../constant_initialization.pass.cpp          |   81 ++
 .../inplace.vector/contiguous.pass.cpp        |   49 +
 .../inplace.vector/empy_type.compile.pass.cpp |   33 +
 .../inplace.vector.capacity/capacity.pass.cpp |   51 +
 .../inplace.vector.capacity/empty.pass.cpp    |   68 ++
 .../inplace.vector.capacity/empty.verify.cpp  |   30 +
 .../inplace.vector.capacity/max_size.pass.cpp |   51 +
 .../inplace.vector.capacity/reserve.pass.cpp  |   83 ++
 .../resize_size.pass.cpp                      |   50 +
 .../resize_size_value.pass.cpp                |   74 ++
 .../shrink_to_fit.pass.cpp                    |   41 +
 .../inplace.vector.capacity/size.pass.cpp     |   83 ++
 .../assign_copy.addressof.compile.pass.cpp    |   32 +
 .../inplace.vector.cons/assign_copy.pass.cpp  |   38 +
 .../assign_initializer_list.pass.cpp          |   77 ++
 .../assign_iter_iter.pass.cpp                 |  122 ++
 .../assign_move.addressof.compile.pass.cpp    |   33 +
 .../inplace.vector.cons/assign_move.pass.cpp  |   58 +
 .../assign_size_value.pass.cpp                |   47 +
 .../construct_default.pass.cpp                |   71 ++
 .../construct_from_range.pass.cpp             |   43 +
 .../construct_iter_iter.pass.cpp              |  181 +++
 .../construct_size.pass.cpp                   |   82 ++
 .../construct_size_value.pass.cpp             |   61 +
 .../copy.move_only.verify.cpp                 |   27 +
 .../inplace.vector.cons/copy.pass.cpp         |   51 +
 .../inplace.vector.cons/deduct.pass.cpp       |   57 +
 .../default.recursive.empty.pass.cpp          |   26 +
 .../default.recursive.fail.cpp                |   22 +
 .../default_noexcept.pass.cpp                 |   40 +
 .../dtor_noexcept.pass.cpp                    |   45 +
 .../inplace.vector.cons/exceptions.pass.cpp   |  166 +++
 .../initializer_list.pass.cpp                 |   51 +
 .../move.addressof.compile.pass.cpp           |   31 +
 .../inplace.vector.cons/move.pass.cpp         |   56 +
 .../move_assign_noexcept.pass.cpp             |   51 +
 .../move_noexcept.pass.cpp                    |   49 +
 .../op_equal_initializer_list.pass.cpp        |   56 +
 .../inplace.vector.data/data.pass.cpp         |   93 ++
 .../inplace.vector.data/data_const.pass.cpp   |   96 ++
 ...rator_concept_conformance.compile.pass.cpp |   97 ++
 .../inplace.vector/iterators.pass.cpp         |  198 ++++
 ...range_concept_conformance.compile.pass.cpp |   48 +
 .../inplace.vector/reverse_iterators.pass.cpp |   86 ++
 .../sequences/inplace.vector/types.pass.cpp   |   70 ++
 .../vector.erasure/erase.pass.cpp             |   83 ++
 .../vector.erasure/erase_if.pass.cpp          |   85 ++
 .../vector.modifiers/append_range.pass.cpp    |   66 ++
 .../assert.push_back.invalidation.pass.cpp    |   56 +
 .../vector.modifiers/assign_range.pass.cpp    |   74 ++
 .../vector.modifiers/clear.pass.cpp           |   53 +
 .../destroy_elements.pass.cpp                 |   71 ++
 .../emplace.addressof.compile.pass.cpp        |   25 +
 .../vector.modifiers/emplace.pass.cpp         |  156 +++
 .../vector.modifiers/emplace_back.pass.cpp    |  175 +++
 .../vector.modifiers/emplace_extra.pass.cpp   |   88 ++
 .../erase_iter.addressof.compile.pass.cpp     |   23 +
 .../vector.modifiers/erase_iter.pass.cpp      |  156 +++
 ...erase_iter_iter.addressof.compile.pass.cpp |   23 +
 .../vector.modifiers/erase_iter_iter.pass.cpp |  173 +++
 .../insert_iter_initializer_list.pass.cpp     |  110 ++
 ..._iter_iter_iter.addressof.compile.pass.cpp |   31 +
 .../insert_iter_iter_iter.pass.cpp            |  182 +++
 .../insert_iter_lvalue.pass.cpp               |  137 +++
 ...ert_iter_rvalue.addressof.compile.pass.cpp |   25 +
 .../insert_iter_rvalue.pass.cpp               |   82 ++
 ...iter_size_value.addressof.compile.pass.cpp |   24 +
 .../insert_iter_size_value.pass.cpp           |  117 ++
 ...sert_iter_value.addressof.compile.pass.cpp |   24 +
 .../vector.modifiers/insert_range.pass.cpp    |   67 ++
 .../vector.modifiers/pop_back.pass.cpp        |   59 +
 .../vector.modifiers/push_back.pass.cpp       |  105 ++
 .../push_back_exception_safety.pass.cpp       |   88 ++
 .../push_back_rvalue.pass.cpp                 |  106 ++
 .../resize_not_move_insertable.verify.cpp     |   47 +
 .../swap.addressof.compile.pass.cpp           |   25 +
 .../vector.modifiers/swap.pass.cpp            |   59 +
 .../swap_noexcept.compile.pass.cpp            |   87 ++
 .../vector.special/swap.pass.cpp              |  155 +++
 .../inplace_vector.version.compile.pass.cpp   |   65 ++
 .../version.version.compile.pass.cpp          |   16 +-
 .../generate_feature_test_macro_components.py |    1 -
 93 files changed, 7194 insertions(+), 16 deletions(-)
 create mode 100644 libcxx/include/inplace_vector
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/contiguous.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/empy_type.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.verify.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/shrink_to_fit.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/size.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_initializer_list.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_size_value.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_from_range.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.move_only.verify.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/deduct.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.empty.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.fail.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default_noexcept.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/dtor_noexcept.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/exceptions.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/initializer_list.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_assign_noexcept.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_noexcept.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/op_equal_initializer_list.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/iterator_concept_conformance.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/iterators.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/range_concept_conformance.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/types.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.erasure/erase.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.erasure/erase_if.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/append_range.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assert.push_back.invalidation.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assign_range.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_back.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_extra.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_initializer_list.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_lvalue.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_value.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_range.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/pop_back.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_exception_safety.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_rvalue.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/resize_not_move_insertable.verify.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.addressof.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap_noexcept.compile.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/vector.special/swap.pass.cpp
 create mode 100644 libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp

diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a1506e115fe70f..c257691c256e64 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -440,7 +440,7 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_hazard_pointer``                               *unimplemented*
     ---------------------------------------------------------- -----------------
-    ``__cpp_lib_inplace_vector``                               *unimplemented*
+    ``__cpp_lib_inplace_vector``                               ``202406L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_is_virtual_base_of``                           *unimplemented*
     ---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index dd62bcc2555ffc..7f4cb2c126a22f 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -69,7 +69,7 @@
 "`P3168R2 <https://wg21.link/P3168R2>`__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","","","|ranges|"
 "`P3217R0 <https://wg21.link/P3217R0>`__","Adjoints to 'Enabling list-initialization for algorithms': find_last","2024-06 (St. Louis)","","",""
 "`P2985R0 <https://wg21.link/P2985R0>`__","A type trait for detecting virtual base classes","2024-06 (St. Louis)","","",""
-"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","","",""
+"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","|Complete|","20.0",""
 "`P3235R3 <https://wg21.link/P3235R3>`__","``std::print`` more types faster with less memory","2024-06 (St. Louis)","","","|format| |DR|"
 "`P2968R2 <https://wg21.link/P2968R2>`__","Make ``std::ignore`` a first-class object","2024-06 (St. Louis)","|Complete|","19.0",""
 "`P2075R6 <https://wg21.link/P2075R6>`__","Philox as an extension of the C++ RNG engines","2024-06 (St. Louis)","","",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 32579272858a8e..d1c5aa7aa81540 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -947,6 +947,7 @@ set(files
   functional
   future
   initializer_list
+  inplace_vector
   inttypes.h
   iomanip
   ios
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index 8efbb42d1d8470..ef47f2d3e33341 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -134,7 +134,8 @@
 //
 // Supported containers:
 // - `span`;
-// - `string_view`.
+// - `string_view`;
+// - `inplace_vector`.
 // #define _LIBCPP_ABI_BOUNDED_ITERATORS
 
 // Changes the iterator type of `basic_string` to a bounded iterator that keeps track of whether it's within the bounds
diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h
index 34f8d5f1663b24..e018f516d49b60 100644
--- a/libcxx/include/__iterator/wrap_iter.h
+++ b/libcxx/include/__iterator/wrap_iter.h
@@ -107,6 +107,10 @@ class __wrap_iter {
   friend class _LIBCPP_TEMPLATE_VIS span;
   template <class _Tp, size_t _Size>
   friend struct array;
+#if _LIBCPP_STD_VER >= 26
+  template <class _Tp, size_t _Capacity>
+  friend class inplace_vector;
+#endif
 };
 
 template <class _Iter1>
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
new file mode 100644
index 00000000000000..06673371190997
--- /dev/null
+++ b/libcxx/include/inplace_vector
@@ -0,0 +1,1022 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_INPLACE_VECTOR
+#define _LIBCPP_INPLACE_VECTOR
+
+/*
+   inplace_vector synopsis
+
+// mostly freestanding
+#include <compare>              // see [compare.syn]
+#include <initializer_list>     // see [initializer.list.syn]
+
+namespace std {
+  // [inplace.vector], class template inplace_vector
+  template<class T, size_t N>
+  class inplace_vector {        // partially freestanding
+  public:
+    // types:
+    using value_type             = T;
+    using pointer                = T*;
+    using const_pointer          = const T*;
+    using reference              = value_type&;
+    using const_reference        = const value_type&;
+    using size_type              = size_t;
+    using difference_type        = ptrdiff_t;
+    using iterator               = implementation-defined; // see [container.requirements]
+    using const_iterator         = implementation-defined; // see [container.requirements]
+    using reverse_iterator       = std::reverse_iterator<iterator>;
+    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+    // [inplace.vector.cons], construct/copy/destroy
+    constexpr inplace_vector() noexcept;
+    constexpr explicit inplace_vector(size_type n);                         // freestanding-deleted
+    constexpr inplace_vector(size_type n, const T& value);                  // freestanding-deleted
+    template<class InputIterator>
+      constexpr inplace_vector(InputIterator first, InputIterator last);    // freestanding-deleted
+    template<container-compatible-range<T> R>
+      constexpr inplace_vector(from_range_t, R&& rg);                       // freestanding-deleted
+    constexpr inplace_vector(const inplace_vector&);
+    constexpr inplace_vector(inplace_vector&&)
+      noexcept(N == 0 || is_nothrow_move_constructible_v<T>);
+    constexpr inplace_vector(initializer_list<T> il);                       // freestanding-deleted
+    constexpr ~inplace_vector();
+    constexpr inplace_vector& operator=(const inplace_vector& other);
+    constexpr inplace_vector& operator=(inplace_vector&& other)
+      noexcept(N == 0 || (is_nothrow_move_assignable_v<T> &&
+                          is_nothrow_move_constructible_v<T>));
+    constexpr inplace_vector& operator=(initializer_list<T>);               // freestanding-deleted
+    template<class InputIterator>
+      constexpr void assign(InputIterator first, InputIterator last);       // freestanding-deleted
+    template<container-compatible-range<T> R>
+      constexpr void assign_range(R&& rg);                                  // freestanding-deleted
+    constexpr void assign(size_type n, const T& u);                         // freestanding-deleted
+    constexpr void assign(initializer_list<T> il);                          // freestanding-deleted
+
+    // iterators
+    constexpr iterator               begin()         noexcept;
+    constexpr const_iterator         begin()   const noexcept;
+    constexpr iterator               end()           noexcept;
+    constexpr const_iterator         end()     const noexcept;
+    constexpr reverse_iterator       rbegin()        noexcept;
+    constexpr const_reverse_iterator rbegin()  const noexcept;
+    constexpr reverse_iterator       rend()          noexcept;
+    constexpr const_reverse_iterator rend()    const noexcept;
+
+    constexpr const_iterator         cbegin()  const noexcept;
+    constexpr const_iterator         cend()    const noexcept;
+    constexpr const_reverse_iterator crbegin() const noexcept;
+    constexpr const_reverse_iterator crend()   const noexcept;
+
+    // [inplace.vector.capacity] size/capacity
+    constexpr bool empty() const noexcept;
+    constexpr size_type size() const noexcept;
+    static constexpr size_type max_size() noexcept;
+    static constexpr size_type capacity() noexcept;
+    constexpr void resize(size_type sz);                                    // freestanding-deleted
+    constexpr void resize(size_type sz, const T& c);                        // freestanding-deleted
+    static constexpr void reserve(size_type n);                             // freestanding-deleted
+    static constexpr void shrink_to_fit() noexcept;
+
+    // element access
+    constexpr reference       operator[](size_type n);
+    constexpr const_reference operator[](size_type n) const;
+    constexpr reference       at(size_type n);                              // freestanding-deleted
+    constexpr const_reference at(size_type n) const;                        // freestanding-deleted
+    constexpr reference       front();
+    constexpr const_reference front() const;
+    constexpr reference       back();
+    constexpr const_reference back() const;
+
+    // [inplace.vector.data], data access
+    constexpr       T* data()       noexcept;
+    constexpr const T* data() const noexcept;
+
+    // [inplace.vector.modifiers], modifiers
+    template<class... Args>
+      constexpr reference emplace_back(Args&&... args);                     // freestanding-deleted
+    constexpr reference push_back(const T& x);                              // freestanding-deleted
+    constexpr reference push_back(T&& x);                                   // freestanding-deleted
+    template<container-compatible-range<T> R>
+      constexpr void append_range(R&& rg);                                  // freestanding-deleted
+    constexpr void pop_back();
+
+    template<class... Args>
+      constexpr pointer try_emplace_back(Args&&... args);
+    constexpr pointer try_push_back(const T& x);
+    constexpr pointer try_push_back(T&& x);
+    template<container-compatible-range<T> R>
+      constexpr ranges::borrowed_iterator_t<R> try_append_range(R&& rg);
+
+    template<class... Args>
+      constexpr reference unchecked_emplace_back(Args&&... args);
+    constexpr reference unchecked_push_back(const T& x);
+    constexpr reference unchecked_push_back(T&& x);
+
+    template<class... Args>
+      constexpr iterator emplace(const_iterator position, Args&&... args);  // freestanding-deleted
+    constexpr iterator insert(const_iterator position, const T& x);         // freestanding-deleted
+    constexpr iterator insert(const_iterator position, T&& x);              // freestanding-deleted
+    constexpr iterator insert(const_iterator position, size_type n,         // freestanding-deleted
+                              const T& x);
+    template<class InputIterator>
+      constexpr iterator insert(const_iterator position,                    // freestanding-deleted
+                                InputIterator first, InputIterator last);
+    template<container-compatible-range<T> R>
+      constexpr iterator insert_range(const_iterator position, R&& rg);     // freestanding-deleted
+    constexpr iterator insert(const_iterator position,                      // freestanding-deleted
+                              initializer_list<T> il);
+    constexpr iterator erase(const_iterator position);
+    constexpr iterator erase(const_iterator first, const_iterator last);
+    constexpr void swap(inplace_vector& x)
+      noexcept(N == 0 || (is_nothrow_swappable_v<T> &&
+                          is_nothrow_move_constructible_v<T>));
+    constexpr void clear() noexcept;
+
+    constexpr friend bool operator==(const inplace_vector& x,
+                                     const inplace_vector& y);
+    constexpr friend synth-three-way-result<T>
+      operator<=>(const inplace_vector& x, const inplace_vector& y);
+    constexpr friend void swap(inplace_vector& x, inplace_vector& y)
+      noexcept(N == 0 || (is_nothrow_swappable_v<T> &&
+                          is_nothrow_move_constructible_v<T>))
+      { x.swap(y); }
+  };
+
+  // [inplace.vector.erasure], erasure
+  template<class T, size_t N, class U = T>
+    constexpr typename inplace_vector<T, N>::size_type
+      erase(inplace_vector<T, N>& c, const U& value);
+  template<class T, size_t N, class Predicate>
+    constexpr typename inplace_vector<T, N>::size_type
+      erase_if(inplace_vector<T, N>& c, Predicate pred);
+} // namespace std
+*/
+
+#include <__algorithm/copy.h>
+#include <__algorithm/equal.h>
+#include <__algorithm/lexicographical_compare_three_way.h>
+#include <__algorithm/min.h>
+#include <__algorithm/move.h>
+#include <__algorithm/remove.h>
+#include <__algorithm/remove_if.h>
+#include <__algorithm/rotate.h>
+#include <__compare/synth_three_way.h>
+#include <__config>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/move_iterator.h>
+#include <__iterator/reverse_iterator.h>
+#include <__iterator/wrap_iter.h>
+#include <__memory/construct_at.h>
+#include <__memory/voidify.h>
+#include <__ranges/container_compatible_range.h>
+#include <__ranges/from_range.h>
+#include <__type_traits/is_trivially_assignable.h>
+#include <__type_traits/is_trivially_constructible.h>
+#include <__type_traits/is_trivially_destructible.h>
+#include <__type_traits/is_trivially_relocatable.h>
+#include <__utility/cmp.h>
+#include <__utility/unreachable.h>
+#include <stdexcept>
+
+// standard-mandated includes
+
+// [inplace.vector.syn]
+#include <compare>
+#include <initializer_list>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <class _Tp, size_t _Capacity>
+class _LIBCPP_TEMPLATE_VIS inplace_vector;
+
+template <size_t _RequiredAlign, size_t _Capacity>
+_LIBCPP_HIDE_FROM_ABI auto __inplace_vector_size_type() {
+  if constexpr (_Capacity <= static_cast<unsigned char>(-1) && alignof(unsigned char) >= _RequiredAlign && alignof(unsigned char) < alignof(size_t)) {
+    return static_cast<unsigned char>(0);
+  } else if constexpr (_Capacity <= static_cast<unsigned short>(-1) && alignof(unsigned short) >= _RequiredAlign && alignof(unsigned char) < alignof(size_t)) {
+    return static_cast<unsigned short>(0);
+  } else if constexpr (_Capacity <= static_cast<unsigned int>(-1) && alignof(unsigned int) >= _RequiredAlign && alignof(unsigned int) < alignof(size_t)) {
+    return static_cast<unsigned int>(0);
+  } else {
+    return static_cast<size_t>(0);
+  }
+}
+
+_LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __inplace_vector_throw_out_of_range() {
+  __throw_out_of_range("inplace_vector");
+  __libcpp_unreachable();
+}
+
+template <class _Tp, size_t _Capacity>
+class _LIBCPP_TEMPLATE_VIS __inplace_vector_array {
+  friend inplace_vector<_Tp, _Capacity>;
+  using __small_size_type = decltype(__inplace_vector_size_type<alignof(_Tp), _Capacity>());
+
+  union {
+    _Tp __elems_[_Capacity];
+  };
+  __small_size_type __sz_;
+
+  // When __constexpr is true, do not actually destroy any elements
+  // so that this can be used as a constexpr variable (otherwise it
+  // would be rejected for being uninitialized)
+  static constexpr bool __constexpr = is_trivially_default_constructible_v<_Tp> && is_trivially_destructible_v<_Tp>;
+  static constexpr bool __trivial_copy_construct = is_trivially_copy_constructible_v<_Tp>;
+  static constexpr bool __trivial_move_construct = is_trivially_move_constructible_v<_Tp>;
+  static constexpr bool __trivial_copy_assign = is_trivially_destructible_v<_Tp> && is_trivially_copy_constructible_v<_Tp> && is_trivially_copy_assignable_v<_Tp>;
+  static constexpr bool __trivial_move_assign = is_trivially_destructible_v<_Tp> && is_trivially_move_constructible_v<_Tp> && is_trivially_move_assignable_v<_Tp>;
+
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array() noexcept : __sz_(0) {
+    if consteval {
+      extern _LIBCPP_HIDE_FROM_ABI void __this_inplace_vector_cannot_be_used_in_a_constant_expression_because_the_type_is_not_trivial();
+      __this_inplace_vector_cannot_be_used_in_a_constant_expression_because_the_type_is_not_trivial();
+    }
+    // Start the lifetime of the array without starting the lifetime
+    // of any of its elements
+    // TODO: When start_lifetime_as is implemented on all compilers, remove
+    // this conditional
+#ifdef __cpp_lib_start_lifetime_as
+    std::start_lifetime_as<_Tp[_Capacity]>(__elems_);
+#else
+    ::new (std::__voidify(__elems_)) unsigned char[sizeof(_Tp[_Capacity])];
+#endif
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array() noexcept requires(__constexpr) : __elems_(), __sz_(0) {
+    if !consteval {
+      std::destroy(__elems_, __elems_ + _Capacity);
+    }
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array(const __inplace_vector_array&) noexcept /* strengthened */ requires(__trivial_copy_construct) = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array(__inplace_vector_array&&) noexcept /* strengthened */ requires(__trivial_move_construct) = default;
+
+  constexpr _LIBCPP_HIDE_FROM_ABI ~__inplace_vector_array() {
+    __sz_ = 0;
+    std::destroy(__elems_, __elems_ + __sz_);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI ~__inplace_vector_array() requires(is_trivially_destructible_v<_Tp>) = default;
+
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array& operator=(const __inplace_vector_array&) noexcept requires(__trivial_copy_assign) = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array& operator=(__inplace_vector_array&&) noexcept requires(__trivial_move_assign) = default;
+
+  using __trivially_relocatable = __conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, inplace_vector<_Tp, _Capacity>, void>;
+};
+
+template <class _Tp>
+class _LIBCPP_TEMPLATE_VIS __inplace_vector_array<_Tp, 0> {
+private:
+  friend inplace_vector<_Tp, 0>;
+  using __small_size_type = size_t;
+
+  static constexpr bool __constexpr = true;
+  static constexpr bool __trivial_copy_construct = true;
+  static constexpr bool __trivial_move_construct = true;
+  static constexpr bool __trivial_copy_assign = true;
+  static constexpr bool __trivial_move_assign = true;
+
+  static_assert((static_cast<_Tp(*)[1]>(nullptr) == nullptr), "inplace_vector<T, 0> must still have a valid T");
+  static constexpr _Tp* __elems_ = nullptr;
+  static constexpr __small_size_type __sz_ = 0;
+
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array() noexcept = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array(const __inplace_vector_array&) noexcept /* strengthened */ = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array(__inplace_vector_array&&) noexcept = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI ~__inplace_vector_array() = default;
+
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array& operator=(const __inplace_vector_array&) noexcept = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI __inplace_vector_array& operator=(__inplace_vector_array&&) noexcept = default;
+
+  using __trivially_relocatable = inplace_vector<_Tp, 0>;
+};
+
+
+template <class _Tp, size_t _Capacity>
+class _LIBCPP_TEMPLATE_VIS inplace_vector : private __inplace_vector_array<_Tp, _Capacity> {
+  using __base = __inplace_vector_array<_Tp, _Capacity>;
+  using __base::__elems_, __base::__sz_;
+  using __small_size_type = __base::__small_size_type;
+
+  static constexpr _LIBCPP_HIDE_FROM_ABI bool __do_destroy() noexcept {
+    if consteval {
+      // Do not destroy elements of the array in a constant expression
+      return !__base::__constexpr;
+    }
+    return true;
+  }
+public:
+  // types
+  using value_type = _Tp;
+  using pointer = _Tp*;
+  using const_pointer = const _Tp*;
+  using reference = value_type&;
+  using const_reference = const value_type&;
+  using size_type = size_t;
+  using difference_type = ptrdiff_t;
+#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+  using iterator = __bounded_iter<pointer>;
+  using const_iterator = __bounded_iter<const_pointer>;
+#else
+  using iterator = __wrap_iter<pointer>;
+  using const_iterator = __wrap_iter<const_pointer>;
+#endif
+  using reverse_iterator = std::reverse_iterator<iterator>;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+  using __trivially_relocatable = __base::__trivially_relocatable;
+
+  // [inplace.vector.cons], construct/copy/destroy
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector() noexcept = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI explicit inplace_vector(size_type __n) : inplace_vector() {
+    if (__n > capacity())
+      __throw_bad_alloc();
+    // TODO: investigate optimization for trivially constructible _Tp that,
+    // for small _Capacity, unconditionally value_construct all the elements to turn
+    // "memset(data(), 0, sizeof(_Tp) * __n)" into
+    // "memset(data(), 0, sizeof(_Tp[_Capacity]))" which might optimize better
+    for (size_type __i = 0; __i < __n; ++__i) {
+      unchecked_emplace_back();
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__i == __sz_, "inplace_vector modified before its lifetime began");
+    }
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(size_type __n, const _Tp& __value) : inplace_vector() {
+    if (__n > capacity())
+      __throw_bad_alloc();
+    for (size_type __i = 0; __i < __n; ++__i) {
+      unchecked_emplace_back(__value);
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__i == __sz_, "inplace_vector modified before its lifetime began");
+    }
+  }
+
+  // NOTE: [sequence.reqmts]p(67.1) does not apply to this constructor but apply
+  // it anyways so the (size_type, const T&) constructor can never be ambiguous
+  template<class _InputIterator> requires(__has_input_iterator_category<_InputIterator>::value)
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(_InputIterator __first, _InputIterator __last) : inplace_vector() {
+    if constexpr (__has_forward_iterator_category<_InputIterator>::value) {
+      __append_with_size(__first, __last, std::distance(__first, __last));
+      return;
+    }
+    __append_with_sentinel(__first, __last);
+  }
+  template<_ContainerCompatibleRange<_Tp> _R>
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(from_range_t, _R&& __rg) : inplace_vector() {
+    append_range<true>(__rg);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(const inplace_vector& __other) noexcept(is_nothrow_copy_constructible_v<_Tp>) /* strengthened */ : inplace_vector() {
+    _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(this != std::addressof(__other), "inplace_vector self-assign");
+    __small_size_type __expected_size = __other.__sz_;
+    for (__small_size_type __i = 0; __i < __expected_size; ++__i) {
+      unchecked_push_back(__other.data()[__i]);
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __expected_size, "inplace_vector modified before it's lifetime began");
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__other.__sz_ == __expected_size, "inplace_vector modified while it's being copied from");
+    }
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(const inplace_vector&) noexcept /* strengthened */ requires(__base::__trivial_copy_construct) = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(inplace_vector&& __other) noexcept(is_nothrow_move_constructible_v<_Tp>) /* strengthened */ : inplace_vector() {
+    _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(this != std::addressof(__other), "inplace_vector self-assign");
+    __small_size_type __expected_size = __other.__sz_;
+    for (__small_size_type __i = 0; __i < __expected_size; ++__i) {
+      unchecked_push_back(std::move(__other.data()[__i]));
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __expected_size, "inplace_vector modified before it's lifetime began");
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__other.__sz_ == __expected_size, "inplace_vector modified while it's being copied from");
+    }
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(inplace_vector&&) noexcept /* strengthened */ requires(__base::__trivial_move_construct) = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(initializer_list<_Tp> __il) : inplace_vector(__il.begin(), __il.end()) {}
+
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector& operator=(const inplace_vector& __other) noexcept(is_nothrow_copy_assignable_v<_Tp> && is_nothrow_copy_constructible_v<_Tp>) /* strengthened */ {
+    static_assert(_Capacity != 0, "Should have picked the trivial operator");
+    if (this != std::addressof(__other)) [[likely]] {
+      __small_size_type __assign = std::min(size(), __other.size());
+      std::copy(__other.data(), __other.data() + __assign, data());
+      if (__other.size() > size()) {
+        __append_with_size(__other.data() + __assign, __other.data() + __other.size(), __other.size() - __assign);
+      } else {
+        __resize_down(__other.size());
+      }
+    }
+    return *this;
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector& operator=(const inplace_vector&) noexcept /* strengthened */ requires(__base::__trivial_copy_assign) = default;
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector& operator=(inplace_vector&& __other) noexcept(is_nothrow_move_assignable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>) {
+    static_assert(_Capacity != 0, "Should have picked the trivial operator");
+    if (this != std::addressof(__other)) [[likely]] {
+      __small_size_type __assign = std::min(size(), __other.size());
+      std::move(__other.data(), __other.data() + __assign, data());
+      if (__other.size() > size()) {
+        __append_with_size(std::make_move_iterator(__other.data() + __assign), std::make_move_iterator(__other.data() + __other.size()), __other.size() - __assign);
+      } else {
+        __resize_down(__other.size());
+      }
+    }
+    return *this;
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector& operator=(inplace_vector&&) noexcept /* strengthened */ requires(__base::__trivial_move_assign) = default;
+
+  constexpr _LIBCPP_HIDE_FROM_ABI ~inplace_vector() = default;
+
+private:
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator __make_iter(pointer __p) const noexcept {
+#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+    return std::__make_bounded_iter(__p, __elems_ + 0, __elems_ + __sz_);
+#else
+    return iterator(__p);
+#endif
+  }
+
+  constexpr _LIBCPP_HIDE_FROM_ABI const_iterator __make_iter(const_pointer __p) const noexcept {
+    return __make_iter(const_cast<pointer>(__p));
+  }
+
+  template <class _First, class _Sent>
+  constexpr _LIBCPP_HIDE_FROM_ABI void __assign_with_size(_First&& __first, _Sent&& __sent, size_t __n) {
+    if (__n > capacity()) [[unlikely]]
+      __throw_bad_alloc();
+    if constexpr (is_trivially_copyable_v<_Tp>) {
+      clear();
+      __append_with_size(std::forward<_First>(__first), std::forward<_Sent>(__sent), __n);
+      return;
+    }
+    const size_t __initial_size = size();
+    const size_t __assigned_elems = std::min(__initial_size, __n);
+    const size_t __remaining = __n - __assigned_elems;
+    for (size_t __i = 0; __i < __assigned_elems; ++__i) {
+      data()[__i] = *__first;
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__first != __sent, "Iterators modified during assignment or size was wrong");
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(size() == __initial_size, "Iterator or assignment modified container size during assign");
+      ++__first;
+    }
+    __append_with_size(std::forward<_First>(__first), std::forward<_Sent>(__sent), __remaining);
+  }
+
+  template <class _First, class _Sent>
+  constexpr _LIBCPP_HIDE_FROM_ABI void __assign_with_sentinel(_First&& __first, _Sent&& __sent) {
+    if constexpr (is_trivially_destructible_v<_Tp>) {
+      clear();
+      __append_with_sentinel(std::forward<_First>(__first), std::forward<_Sent>(__sent));
+      return;
+    }
+    size_t __existing = __sz_;
+    for (size_t __i = 0; __i < __existing; ++__i) {
+      if (__first == __sent) return;
+      data()[__i] = *__first;
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__first != __sent, "Iterators modified during assignment");
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__existing + __i == __sz_, "Iterator or assignment modified container size during assign");
+      ++__first;
+    }
+    __append_with_sentinel(std::forward<_First>(__first), std::forward<_Sent>(__sent));
+  }
+public:
+  template <class _InputIterator> requires(__has_input_iterator_category<_InputIterator>::value)
+  constexpr _LIBCPP_HIDE_FROM_ABI void assign(_InputIterator __first, _InputIterator __last) {
+    if constexpr (__has_forward_iterator_category<_InputIterator>::value) {
+      __assign_with_size(__first, __last, std::distance(__first, __last));
+      return;
+    }
+    __assign_with_sentinel(__first, __last);
+  }
+  template <_ContainerCompatibleRange<_Tp> _R>
+  constexpr _LIBCPP_HIDE_FROM_ABI void assign_range(_R&& __rg) {
+    if constexpr (ranges::sized_range<_R&>) {
+      return __assign_with_size(ranges::begin(__rg), ranges::end(__rg), ranges::size(__rg));
+    } else if constexpr (ranges::forward_range<_R&>) {
+      decltype(auto) __first(ranges::begin(__rg));
+      decltype(auto) __last(ranges::end(__rg));
+      return __assign_with_size(__first, __last, ranges::distance(__first, __last));
+    }
+    return __assign_with_sentinel(ranges::begin(__rg), ranges::end(__rg));
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI void assign(size_type __n, const _Tp& __u) {
+    if (__n > capacity()) [[unlikely]]
+      __throw_bad_alloc();
+    if constexpr (is_trivially_copyable_v<_Tp>) {
+      clear();
+    } else {
+      const size_t __initial_size = size();
+      const size_t __assigned_elems = std::min(__initial_size, __n);
+      for (size_t __i = 0; __i < __assigned_elems; ++__i) {
+        data()[__i] = __u;
+        _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+            __sz_ == __initial_size, "inplace_vector element assignment modified container size during assign");
+      }
+    }
+    resize(__n, __u);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI void assign(initializer_list<_Tp> __il) {
+    assign(__il.begin(), __il.end());
+  }
+
+  // iterators
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator               begin()         noexcept { return __make_iter(data()); }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_iterator         begin()   const noexcept { return __make_iter(data()); }
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator               end()           noexcept { return __make_iter(data() + size()); }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_iterator         end()     const noexcept { return __make_iter(data() + size()); }
+  constexpr _LIBCPP_HIDE_FROM_ABI reverse_iterator       rbegin()        noexcept { return reverse_iterator(end()); }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin()  const noexcept { return const_reverse_iterator(end()); }
+  constexpr _LIBCPP_HIDE_FROM_ABI reverse_iterator       rend()          noexcept { return reverse_iterator(begin()); }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend()    const noexcept { return const_reverse_iterator(begin()); }
+
+  constexpr _LIBCPP_HIDE_FROM_ABI const_iterator         cbegin()  const noexcept { return begin(); }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_iterator         cend()    const noexcept { return end(); }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend()   const noexcept { return rend(); }
+
+  // [inplace.vector.capacity] size/capacity
+  _LIBCPP_NODISCARD constexpr _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept {
+    return __sz_ == 0;
+  }
+  _LIBCPP_NODISCARD constexpr _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept {
+    _LIBCPP_ASSERT_INTERNAL(__sz_ <= capacity(), "inplace_vector has impossible size");
+    return __sz_;
+  }
+  _LIBCPP_NODISCARD static _LIBCPP_HIDE_FROM_ABI constexpr size_type max_size() noexcept {
+    return _Capacity;
+  }
+  _LIBCPP_NODISCARD static _LIBCPP_HIDE_FROM_ABI constexpr size_type capacity() noexcept {
+    return _Capacity;
+  }
+
+private:
+  constexpr _LIBCPP_HIDE_FROM_ABI void __resize_down(__small_size_type __n) noexcept {
+    _LIBCPP_ASSERT_INTERNAL(__n <= size(), "Trying to __resize_down to a greater number of elements");
+    const const_pointer __old_last = __elems_ + __sz_;
+    const const_pointer __new_last = __elems_ + __n;
+    if constexpr (_Capacity) {
+      __sz_ = __n;
+    }
+    if (__do_destroy())
+      std::destroy(__new_last, __old_last);
+    _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __n, "inplace_vector modified during element destruction");
+  }
+
+  template <class... _Arg>
+  constexpr _LIBCPP_HIDE_FROM_ABI void __resize(size_type __n, const _Arg&... __arg) {
+    if (__n > capacity()) {
+      __throw_bad_alloc();
+    }
+    if (__n <= __sz_) {
+      __resize_down(__n);
+    } else {
+      [[maybe_unused]] const pointer __current_end = __elems_ + __sz_;
+      size_type __remaining = __n - __sz_;
+      for (size_type __i = 0; __i < __remaining; ++__i) {
+        unchecked_emplace_back(__arg...);
+        _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__current_end + __i == __elems_ + __sz_, "inplace_vector simultaneously modified during resize");
+      }
+    }
+  }
+public:
+  constexpr _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz) {
+    __resize(__sz);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI void resize(size_type __sz, const _Tp& __u) {
+    __resize(__sz, __u);
+  }
+
+  static constexpr _LIBCPP_HIDE_FROM_ABI void reserve(size_type __n) {
+    if (__n > capacity())
+      __throw_bad_alloc();
+  }
+  static constexpr _LIBCPP_HIDE_FROM_ABI void shrink_to_fit() noexcept {}
+
+  // ekenebt access
+  constexpr _LIBCPP_HIDE_FROM_ABI reference operator[](size_type __n) noexcept /* strengthened */ {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "inplace_vector[] index out of bounds");
+    return data()[__n];
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_reference operator[](size_type __n) const noexcept /* strengthened */ {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < size(), "inplace_vector[] index out of bounds");
+    return data()[__n];
+  }
+  constexpr reference at(size_type __n) {
+    if (__n >= size())
+      __inplace_vector_throw_out_of_range();
+    return data()[__n];
+  }
+  constexpr const_reference at(size_type __n) const {
+    if (__n >= size())
+      __inplace_vector_throw_out_of_range();
+    return data()[__n];
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI reference front() noexcept /* strengthened */ {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty inplace_vector");
+    return *data();
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_reference front() const noexcept /* strengthened */ {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "front() called on an empty inplace_vector");
+    return *data();
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI reference back() noexcept /* strengthened */ {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty inplace_vector");
+    return data()[__sz_ - __small_size_type(1)];
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_reference back() const noexcept /* strengthened */ {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "back() called on an empty inplace_vector");
+    return data()[__sz_ - __small_size_type(1)];
+  }
+
+  // [inplace.vector.daa], data access
+  constexpr _LIBCPP_HIDE_FROM_ABI       _Tp* data()       noexcept { return __elems_; }
+  constexpr _LIBCPP_HIDE_FROM_ABI const _Tp* data() const noexcept { return __elems_; }
+
+private:
+  // FIXME: we need __cpp_lib_constexpr_new. See P2747R2
+  // When compiler supports constexpr placement new, use it. Otherwise, construct_at needs to be used
+  // which can introduce a move constructor when *__it is a prvalue.
+  template <class _It>
+  static constexpr _LIBCPP_HIDE_FROM_ABI void __deref_construct_at(pointer __p, _It&& __it) {
+#  if __cpp_constexpr < 202406L
+    if consteval {
+      std::construct_at(__p, *__it);
+    } else {
+#  endif
+      ::new (std::__voidify(*__p)) _Tp(*__it);
+#  if __cpp_constexpr < 202406L
+    }
+#  endif
+  }
+
+  // Does not take into account *__it or incrementing iterators
+  template <class _It>
+  static constexpr _LIBCPP_HIDE_FROM_ABI bool __can_deref_construct_throw() {
+#  if __cpp_constexpr < 202406L
+    if consteval {
+      return !is_nothrow_constructible_v<_Tp, decltype(*declval<_It>())>;
+    }
+#  endif
+    return !noexcept(_Tp(*declval<_It>()));
+  }
+
+  template<class _It, class _Sent>
+  constexpr _LIBCPP_HIDE_FROM_ABI void __append_with_size(_It&& __first, [[maybe_unused]] _Sent&& __last, size_type __n) {
+    [[maybe_unused]] __small_size_type __expected_size = size();
+    while (__n--) {
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+          __first != __last, "Iterators modified during assignment or size was wrong");
+
+      unchecked_emplace_back(*__first);
+      ++__first;
+
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+          __sz_ == ++__expected_size, "Iterator or assignment modified container size during append");
+    }
+  }
+
+  template<bool _ThrowOnMissingCapacity = true, class _It, class _Sent>
+  constexpr _LIBCPP_HIDE_FROM_ABI void __append_with_sentinel(_It&& __it, _Sent&& __last) {
+    const __small_size_type __initial_size = __sz_;
+    [[maybe_unused]] __small_size_type __expected_size = __sz_;
+    pointer __p = __elems_ + __initial_size;
+    while (__p != __elems_ + capacity()) {
+      if (__it == __last)
+        return;
+      __deref_construct_at(__p++, __it);
+      if constexpr (_Capacity) {
+        ++__sz_;
+      }
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+          __sz_ == ++__expected_size, "element assignment modified container size during append");
+      ++__it;
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+          __sz_ == __expected_size, "iterator operation modified container size during append");
+    }
+    if constexpr (_ThrowOnMissingCapacity) {
+      if (__it == __last) return;
+
+      // Exception safety: container must not be changed afterwards
+      __resize_down(__initial_size);
+      __throw_bad_alloc();
+    }
+  }
+
+  template <bool _ThrowOnMissingCapacity, class _R>
+  constexpr _LIBCPP_HIDE_FROM_ABI __conditional_t<_ThrowOnMissingCapacity, void, ranges::borrowed_iterator_t<_R>>
+  __append_range(_R&& __rg) {
+    decltype(auto) __first(ranges::begin(__rg));
+    size_t __remaining = capacity() - size();
+    if (!_ThrowOnMissingCapacity && __remaining != 0) {
+      decltype(auto) __sent(ranges::end(__rg));
+      if constexpr (ranges::sized_range<_R&>) {
+        auto __n = ranges::size(__rg);
+        size_t __copied;
+        if constexpr (_ThrowOnMissingCapacity) {
+          if (std::cmp_greater(__n, capacity()))
+            __throw_bad_alloc();
+          __copied = static_cast<size_t>(__n);
+        } else {
+          if (std::cmp_greater(__n, capacity()))
+            __copied = capacity();
+          else
+            __copied = static_cast<size_t>(__n);
+        }
+        __append_with_size(__first, __sent, __copied);
+      } else {
+        __append_with_sentinel<_ThrowOnMissingCapacity>(__first, __sent);
+      }
+    }
+    if constexpr (!_ThrowOnMissingCapacity)
+      return __first;
+  }
+
+public:
+  // [inplace.vector.modifiers], modifiers
+  template <class... _Args>
+  constexpr _LIBCPP_HIDE_FROM_ABI reference emplace_back(_Args&&... __args) {
+    if (size() == capacity()) [[unlikely]]
+      __throw_bad_alloc();
+    return unchecked_emplace_back(std::forward<_Args>(__args)...);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI reference push_back(const _Tp& __x) { return emplace_back(__x); }
+  constexpr _LIBCPP_HIDE_FROM_ABI reference push_back(_Tp&& __x) { return emplace_back(std::move(__x)); }
+  template <_ContainerCompatibleRange<_Tp> _R>
+  constexpr _LIBCPP_HIDE_FROM_ABI void append_range(_R&& __rg) {
+    __append_range<true>(std::forward<_R>(__rg));
+  }
+
+  constexpr _LIBCPP_HIDE_FROM_ABI void pop_back() noexcept /* strengthened */ {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "pop_back() called on an empty inplace_vector");
+    if constexpr (_Capacity) {
+      [[maybe_unused]] __small_size_type __expected_size = --__sz_;
+      if (__do_destroy())
+        std::destroy_at(__elems_ + __sz_ - 1);
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __expected_size, "inplace_vector modified during element destruction");
+    } else {
+      __libcpp_unreachable();
+    }
+  }
+
+  template<class... _Args>
+  constexpr _LIBCPP_HIDE_FROM_ABI pointer try_emplace_back(_Args&&... __args) noexcept /* strengthened */ {
+    if (size() == capacity())
+      return nullptr;
+    return std::addressof(unchecked_emplace_back(std::forward<_Args>(__args)...));
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI pointer try_push_back(const _Tp& __x) noexcept /* strengthened */ { return try_emplace_back(__x); }
+  constexpr _LIBCPP_HIDE_FROM_ABI pointer try_push_back(_Tp&& __x) noexcept /* strengthened */ { return try_emplace_back(std::move(__x)); }
+  template<_ContainerCompatibleRange<_Tp> _R>
+  constexpr _LIBCPP_HIDE_FROM_ABI ranges::borrowed_iterator_t<_R> try_append_range(_R&& __rg) {
+    return __append_range<false>(std::forward<_R>(__rg));
+  }
+
+  template <class... _Args>
+  constexpr _LIBCPP_HIDE_FROM_ABI reference unchecked_emplace_back(_Args&&... __args) noexcept(std::is_nothrow_constructible_v<_Tp, _Args...>) /* strengthened */ {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(size() < capacity(), "unchecked_emplace_back() called on an at-capacity inplace_vector");
+    if constexpr (_Capacity == 0) {
+      __libcpp_unreachable();
+    }
+    pointer __new = data() + size();
+    [[maybe_unused]] size_t __old_size = __sz_;
+    std::construct_at(__new, std::forward<_Args>(__args)...);
+    _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __old_size, "inplace_vector modified during element construction");
+    if constexpr (_Capacity) {
+      ++__sz_;
+    }
+    return *__new;
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI reference unchecked_push_back(const _Tp& __x) noexcept(std::is_nothrow_copy_constructible_v<_Tp>) /* strengthened */ { return unchecked_emplace_back(__x); }
+  constexpr _LIBCPP_HIDE_FROM_ABI reference unchecked_push_back(_Tp&& __x) noexcept(std::is_nothrow_move_constructible_v<_Tp>) /* strengthened */ { return unchecked_emplace_back(std::move(__x)); }
+
+private:
+  constexpr _LIBCPP_HIDE_FROM_ABI pointer __unwrap_iter(const_iterator __it) noexcept {
+    return const_cast<pointer>(const_cast<const inplace_vector*>(this)->__unwrap_iter(__it));
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI const_pointer __unwrap_iter(const_iterator __it) const noexcept {
+    const_pointer __p = std::to_address(__it);
+    if constexpr (_Capacity == 0) {
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p == nullptr, "Not an iterator into this inplace_vector<T, 0>");
+    } else {
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+          __elems_ <= __p && __p <= __elems_ + capacity(), "Not an iterator into this inplace_vector");
+      _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p <= __elems_ + __sz_, "This inplace_vector iterator is invalid");
+    }
+    return __p;
+  }
+public:
+  template <class... _Args>
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator emplace(const_iterator __position, _Args&&... __args) {
+    const pointer __p = __unwrap_iter(__position);
+    if (size() == capacity())
+      __throw_bad_alloc();
+
+    if (__p == __elems_ + __sz_) {
+      unchecked_emplace_back(std::forward<_Args>(__args)...);
+    } else if (std::is_nothrow_constructible_v<_Tp, _Args&&...>) {
+      unchecked_push_back(std::move(back()));
+      std::move_backward(__p, __elems_ + __sz_ - 1, __elems_ + __sz_);
+      std::destroy_at(__p);
+      std::construct_at(__p, std::forward<_Args>(__args)...);
+    } else {
+      unchecked_emplace_back(std::forward<_Args>(__args)...);
+      std::rotate(__p, __elems_ + __sz_, __elems_ + __sz_ - 1);
+    }
+    // (Update bounds for bounded iter)
+    return __make_iter(__p);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, const _Tp& __x) {
+    return emplace(__position, __x);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, _Tp&& __x) {
+    return emplace(__position, std::move(__x));
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, size_type __n, const _Tp& __x) {
+    const pointer __p = __unwrap_iter(__position);
+    if (__n > capacity() - size())
+      __throw_bad_alloc();
+
+    if (__p == __elems_ + __sz_) {
+      resize(size() + __n, __x);
+    } else {
+      // Move the last __n elements over into newly constructed elements
+      const pointer __old_end = __elems_ + __sz_;
+      for (size_t __i = 0; __i < __n; ++__i) {
+        unchecked_emplace_back(std::move(__elems_[__sz_ - __n]));
+      }
+      // Move over the remaining elements
+      std::move_backward(__p, __old_end - __n, __old_end);
+      // Insert the elements
+      for (size_t __i = 0; __i < __n; ++__i) {
+        __p[__i] = __x;
+      }
+    }
+    return __make_iter(__p);
+  }
+private:
+  template <class _Iterator, class _Sentinel, class _Size>
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator __insert_with_size(const_iterator __position, _Iterator&& __it, _Sentinel&& __sent, _Size __m) {
+    const pointer __p = __unwrap_iter(__position);
+    if (std::cmp_greater(__m, capacity() - size()))
+      __throw_bad_alloc();
+    auto __n = static_cast<__small_size_type>(__m);
+
+    // (It is ok if ++__it throws since the container is still valid)
+    bool __can_avoid_rotate = !__can_deref_construct_throw<_Iterator&>();
+    if (!is_reference_v<decltype(*__it)>)
+      __can_avoid_rotate &= noexcept(*__it);
+
+    if (__p == __elems_ + __sz_) {
+      __append_with_size(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent), __n);
+    } else if (__can_avoid_rotate) {
+      const pointer __old_end = __elems_ + __sz_;
+      for (size_t __i = 0; __i < __n; ++__i) {
+        unchecked_emplace_back(std::move(__elems_[__sz_ - __n]));
+      }
+      std::move_backward(__p, __old_end - __n, __old_end);
+
+      [[maybe_unused]] __small_size_type __expected_size = __sz_;
+      for (size_t __i = 0; __i < __n; ++__i) {
+        if (is_reference_v<decltype(*__it)>) {
+          auto&& __deref = *__it; // (In case *__it is a throwing operation)
+          std::destroy_at(__p + __i);
+          std::construct_at(__p + __i, std::forward<decltype(__deref)>(__deref));
+        } else {
+          std::destroy_at(__p + __i);
+          __deref_construct_at(__p + __i, __it);
+        }
+        _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __expected_size, "inplace_vector modified during element construction/destruction");
+        ++__it;
+        _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == __expected_size, "inplace_vector modified by iterator operation");
+      }
+    } else {
+      __append_with_size(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent), __n);
+      std::rotate(__p, __elems_ + __sz_, __elems_ + __sz_ - __n);
+    }
+    return __make_iter(__p);
+  }
+
+  template <class _Iterator, class _Sentinel>
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator __insert_with_sentinel(const_iterator __position, _Iterator&& __it, _Sentinel&& __sent) {
+    const pointer __p = __unwrap_iter(__position);
+
+    if (__p == __elems_ + __sz_) {
+      __append_with_sentinel(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent));
+    } else {
+      const pointer __original_end = __elems_ + __sz_;
+      __append_with_sentinel(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent));
+      std::rotate(__p, __elems_ + __sz_, __original_end);
+    }
+    return __make_iter(__p);
+  }
+public:
+  template <class _InputIterator> requires(__has_input_iterator_category<_InputIterator>::value)
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, _InputIterator __first, _InputIterator __last) {
+    if constexpr (__has_forward_iterator_category<_InputIterator>::value) {
+      return __insert_with_size(__position, __first, __last, std::distance(__first, __last));
+    }
+    return __insert_with_sentinel(__position, __first, __last);
+  }
+  template <_ContainerCompatibleRange<_Tp> _R>
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator insert_range(const_iterator __position, _R&& __rg) {
+    decltype(auto) __first(ranges::begin(__rg));
+    decltype(auto) __sent(ranges::end(__rg));
+    if constexpr (ranges::sized_range<_R&>) {
+      return __insert_with_sentinel(__first, __sent, ranges::size(__rg));
+    } else {
+      return __insert_with_sentinel(__position, __first, __sent);
+    }
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __position, initializer_list<_Tp> __il) {
+    return insert(__position, __il.begin(), __il.end());
+  }
+
+  constexpr _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __position) {
+    const pointer __p = __unwrap_iter(__position);
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__p != __elems_ + __sz_, "Cannot erase the end iterator");
+    std::move(__p + 1, __elems_ + __sz_, __p);
+    pop_back();
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI void erase(const_iterator __first, const_iterator __last) {
+    const pointer __p = __unwrap_iter(__first);
+    const pointer __q = __unwrap_iter(__last);
+    _LIBCPP_ASSERT_VALID_INPUT_RANGE(__p <= __q, "inplace_vector::erase begin iterator is after end iterator");
+    std::move(__q + 1, __elems_ + __sz_, __p);
+    __resize_down(__q - __elems_);
+  }
+
+  constexpr _LIBCPP_HIDE_FROM_ABI void swap(inplace_vector& __x) noexcept(_Capacity == 0 || (is_nothrow_swappable_v<_Tp> &&
+                                                                                             is_nothrow_move_constructible_v<_Tp>)) {
+    inplace_vector* __smaller = this;
+    inplace_vector* __bigger = std::addressof(__x);
+    __small_size_type __smaller_size = __smaller->__sz_;
+    __small_size_type __bigger_size = __bigger->__sz_;
+    if (__smaller_size > __bigger_size) {
+      std::swap(__smaller, __bigger);
+      std::swap(__smaller_size, __bigger_size);
+    }
+
+    std::swap_ranges(+__smaller->__elems_, __smaller->__elems_ + __smaller_size, +__bigger->__elems_);
+    _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__smaller->__sz_ == __smaller_size && __bigger->__sz_ == __bigger_size, "inplace_vector modified when swapping elements");
+    for (__small_size_type __i = __smaller_size; __i != __bigger_size; ++__i) {
+      unchecked_push_back(std::move(__bigger->data()[__i++]));
+      _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__smaller->__sz_ == __i && __bigger->__sz_ == __bigger_size, "inplace_vector modified when swapping elements");
+    }
+    __bigger->__resize_down(__smaller_size);
+  }
+
+  constexpr _LIBCPP_HIDE_FROM_ABI void clear() {
+    if constexpr (_Capacity != 0) {
+      __sz_ = 0;
+    }
+    if (__do_destroy())
+      std::destroy(__elems_, __elems_ + __sz_);
+    _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__sz_ == 0, "inplace_vector modified by element destructor during clear()");
+  }
+
+  friend constexpr _LIBCPP_HIDE_FROM_ABI bool operator==(const inplace_vector& __x, const inplace_vector& __y) {
+    size_t __sz = __x.size();
+    if (__sz != __y.size())
+      return false;
+    return std::equal(__x.data(), __x.data() + __sz, __y.data());
+  }
+  // Return type is a placeholder type because __synth_three_way_result<_Tp> is a hard error if the constraint isn't met
+  friend constexpr _LIBCPP_HIDE_FROM_ABI auto operator<=>(const inplace_vector& __x, const inplace_vector& __y) requires(requires(const _Tp& __t) { __t < __t; }) {
+    return std::lexicographical_compare_three_way(__x.data(), __x.data() + __x.size(), __y.data(), __y.data() + __y.size(), std::__synth_three_way);
+  }
+
+  constexpr friend _LIBCPP_HIDE_FROM_ABI void swap(inplace_vector& __x, inplace_vector& __y)
+      noexcept(_Capacity == 0 || (is_nothrow_swappable_v<_Tp> &&
+                                  is_nothrow_move_constructible_v<_Tp>))
+  { __x.swap(__y); }
+};
+
+template <class _Tp, size_t _Capacity, class _Up>
+constexpr _LIBCPP_HIDE_FROM_ABI size_t erase(inplace_vector<_Tp, _Capacity>& __c, const _Up& __value) noexcept(
+  std::is_nothrow_move_assignable_v<_Tp> && noexcept(static_cast<bool>(__value == __value)) // strengthened
+) {
+  auto __it = std::remove(__c.begin(), __c.end(), __value);
+  auto __r = __c.end() - __it;
+  __c.erase(__it, __c.end());
+  return __r;
+}
+
+template <class _Tp, size_t _Capacity, class _Predicate>
+constexpr _LIBCPP_HIDE_FROM_ABI size_t erase_if(inplace_vector<_Tp, _Capacity>& __c, _Predicate __pred) noexcept(
+  std::is_nothrow_move_assignable_v<_Tp> && noexcept(remove_cvref_t<_Predicate>(__pred)) && noexcept(static_cast<bool>(!declval<remove_cvref_t<_Predicate>&>()(declval<_Tp&>()))) // strengthened
+) {
+  auto __it = std::remove_if(__c.cbegin(), __c.cend(), __pred);
+  auto __r = __c.end() - __it;
+  __c.erase(__it, __c.end());
+  return __r;
+}
+
+#endif // _LIBCPP_STD_VER >= 26
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_INPLACE_VECTOR
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 13d0dce34d97e3..f2a4537ab9843f 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -103,6 +103,10 @@ module std_initializer_list [system] {
   header "initializer_list"
   export *
 }
+module std_inplace_vector [system] {
+  header "inplace_vector"
+  export *
+}
 module std_iomanip [system] {
   header "iomanip"
   export *
diff --git a/libcxx/include/version b/libcxx/include/version
index fe64343eafbc9c..9177f97b102762 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -530,7 +530,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 // # define __cpp_lib_function_ref                         202306L
 // # define __cpp_lib_generate_random                      202403L
 // # define __cpp_lib_hazard_pointer                       202306L
-// # define __cpp_lib_inplace_vector                       202406L
+# define __cpp_lib_inplace_vector                       202406L
 // # define __cpp_lib_is_virtual_base_of                   202406L
 // # define __cpp_lib_is_within_lifetime                   202306L
 // # define __cpp_lib_linalg                               202311L
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp
new file mode 100644
index 00000000000000..01900088555f4f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp
@@ -0,0 +1,133 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <vector>
+
+//       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 <vector>
+#include <cassert>
+#include <stdexcept>
+
+#include "min_allocator.h"
+#include "test_macros.h"
+
+template <class C>
+TEST_CONSTEXPR_CXX20 C make(int size, int start) {
+  C c;
+  for (int i = 0; i < size; ++i)
+    c.push_back(start + i);
+  return c;
+}
+
+template <class Vector>
+TEST_CONSTEXPR_CXX20 void test_get_basic(Vector& c, int start_value) {
+  const int n = static_cast<int>(c.size());
+  for (int i = 0; i < n; ++i)
+    assert(c[i] == start_value + i);
+  for (int i = 0; i < n; ++i)
+    assert(c.at(i) == start_value + i);
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  if
+    !consteval {
+      try {
+        TEST_IGNORE_NODISCARD c.at(n);
+        assert(false);
+      } catch (const std::out_of_range&) {
+      }
+    }
+#endif
+
+  assert(c.front() == start_value);
+  assert(c.back() == start_value + n - 1);
+}
+
+template <class Vector>
+TEST_CONSTEXPR_CXX20 void test_get() {
+  int start_value  = 35;
+  Vector c         = make<Vector>(10, start_value);
+  const Vector& cc = c;
+  test_get_basic(c, start_value);
+  test_get_basic(cc, start_value);
+}
+
+template <class Vector>
+TEST_CONSTEXPR_CXX20 void test_set() {
+  int start_value = 35;
+  const int n     = 10;
+  Vector c        = make<Vector>(n, start_value);
+
+  for (int i = 0; i < n; ++i) {
+    assert(c[i] == start_value + i);
+    c[i] = start_value + i + 1;
+    assert(c[i] == start_value + i + 1);
+  }
+  for (int i = 0; i < n; ++i) {
+    assert(c.at(i) == start_value + i + 1);
+    c.at(i) = start_value + i + 2;
+    assert(c.at(i) == start_value + i + 2);
+  }
+
+  assert(c.front() == start_value + 2);
+  c.front() = start_value + 3;
+  assert(c.front() == start_value + 3);
+
+  assert(c.back() == start_value + n + 1);
+  c.back() = start_value + n + 2;
+  assert(c.back() == start_value + n + 2);
+}
+
+template <class Vector>
+TEST_CONSTEXPR_CXX20 void test() {
+  test_get<Vector>();
+  test_set<Vector>();
+
+  Vector c;
+  const Vector& cc = c;
+  ASSERT_SAME_TYPE(typename Vector::reference, decltype(c[0]));
+  ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc[0]));
+
+  ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.at(0)));
+  ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.at(0)));
+
+  ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.front()));
+  ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.front()));
+
+  ASSERT_SAME_TYPE(typename Vector::reference, decltype(c.back()));
+  ASSERT_SAME_TYPE(typename Vector::const_reference, decltype(cc.back()));
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  test<std::vector<int> >();
+#if TEST_STD_VER >= 11
+  test<std::vector<int, min_allocator<int> > >();
+  test<std::vector<int, safe_allocator<int> > >();
+#endif
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp
new file mode 100644
index 00000000000000..413767e52a4d68
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp
@@ -0,0 +1,129 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// bool operator==(const vector& lhs, const vector& rhs);
+// bool operator!=(const vector& lhs, const vector& rhs);
+// bool operator< (const vector& lhs, const vector& rhs);
+// bool operator<=(const vector& lhs, const vector& rhs);
+// bool operator> (const vector& lhs, const vector& rhs);
+// bool operator>=(const vector& lhs, const vector& rhs);
+
+#include <vector>
+#include <cassert>
+
+#include "test_comparisons.h"
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    const std::vector<int> c1, c2;
+    assert(testComparisons(c1, c2, true, false));
+  }
+  {
+    const std::vector<int> c1(1, 1), c2(1, 2);
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    const std::vector<int> c1, c2(1, 2);
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    int items1[3] = {1, 2, 1};
+    int items2[3] = {1, 2, 2};
+    const std::vector<int> c1(items1, items1 + 3);
+    const std::vector<int> c2(items2, items2 + 3);
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    int items1[3] = {3, 2, 3};
+    int items2[3] = {3, 1, 3};
+    const std::vector<int> c1(items1, items1 + 3);
+    const std::vector<int> c2(items2, items2 + 3);
+
+    assert(testComparisons(c1, c2, false, false));
+  }
+  {
+    int items1[2] = {1, 2};
+    int items2[3] = {1, 2, 0};
+    const std::vector<int> c1(items1, items1 + 2);
+    const std::vector<int> c2(items2, items2 + 3);
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    int items1[3] = {1, 2, 0};
+    const std::vector<int> c1(items1, items1 + 3);
+    const std::vector<int> c2(1, 3);
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    const std::vector<LessAndEqComp> c1, c2;
+    assert(testComparisons(c1, c2, true, false));
+  }
+  {
+    const std::vector<LessAndEqComp> c1(1, LessAndEqComp(1));
+    const std::vector<LessAndEqComp> c2(1, LessAndEqComp(1));
+    assert(testComparisons(c1, c2, true, false));
+  }
+  {
+    const std::vector<LessAndEqComp> c1(1, LessAndEqComp(1));
+    const std::vector<LessAndEqComp> c2(1, LessAndEqComp(2));
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    const std::vector<LessAndEqComp> c1;
+    const std::vector<LessAndEqComp> c2(1, LessAndEqComp(2));
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    LessAndEqComp items1[3] = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(2)};
+    LessAndEqComp items2[3] = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)};
+    const std::vector<LessAndEqComp> c1(items1, items1 + 3);
+    const std::vector<LessAndEqComp> c2(items2, items2 + 3);
+    assert(testComparisons(c1, c2, false, false));
+  }
+  {
+    LessAndEqComp items1[3] = {LessAndEqComp(3), LessAndEqComp(3), LessAndEqComp(3)};
+    LessAndEqComp items2[3] = {LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(3)};
+    const std::vector<LessAndEqComp> c1(items1, items1 + 3);
+    const std::vector<LessAndEqComp> c2(items2, items2 + 3);
+    assert(testComparisons(c1, c2, false, false));
+  }
+  {
+    LessAndEqComp items1[2] = {LessAndEqComp(1), LessAndEqComp(2)};
+    LessAndEqComp items2[3] = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(0)};
+    const std::vector<LessAndEqComp> c1(items1, items1 + 2);
+    const std::vector<LessAndEqComp> c2(items2, items2 + 3);
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    LessAndEqComp items1[3] = {LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(0)};
+    const std::vector<LessAndEqComp> c1(items1, items1 + 3);
+    const std::vector<LessAndEqComp> c2(1, LessAndEqComp(3));
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    assert((std::vector<int>() == std::vector<int>()));
+    assert(!(std::vector<int>() != std::vector<int>()));
+    assert(!(std::vector<int>() < std::vector<int>()));
+    assert((std::vector<int>() <= std::vector<int>()));
+    assert(!(std::vector<int>() > std::vector<int>()));
+    assert((std::vector<int>() >= std::vector<int>()));
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER > 17
+  static_assert(test());
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.pass.cpp
new file mode 100644
index 00000000000000..ac03b37dc344c7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.pass.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// class inplace_vector
+
+//   constexpr auto operator<=>(const inplace_vector& x,
+//                              const inplace_vector& y);
+
+// FIXME: check if the auto is valid
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_container_comparisons.h"
+
+template <typename T>
+using inplace_vector_size_10 = std::inplace_vector<T, 10>;
+
+// TODO: test inplace_vector<T, 0> still has a valid definition
+// TODO: modify so that the checks work in constexpr
+
+int main(int, char**) {
+  assert(test_sequence_container_spaceship<inplace_vector_size_10>());
+  // static_assert(test_sequence_container_spaceship<inplace_vector_size_10>());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp
new file mode 100644
index 00000000000000..96383c6203d720
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+#include <inplace_vector>
+#include <type_traits>
+#include <cassert>
+
+struct NonTrivial {
+  bool constant = std::is_constant_evaluated();
+};
+
+constexpr bool tests() {
+  {
+    using V = std::inplace_vector<int, 0>;
+    if
+      !consteval {
+        constinit static V v1;
+        assert(v1.size() == 0);
+      }
+    constexpr static V v2;
+    static_assert(v2.size() == 0);
+  }
+  {
+    using V = std::inplace_vector<int, 10>;
+    if
+      !consteval {
+        constinit static V v1;
+        assert(v1.size() == 0);
+      }
+    constexpr static V v2;
+    static_assert(v2.size() == 0);
+  }
+  {
+    using V = std::inplace_vector<int, 10>;
+    if
+      !consteval {
+        constinit static V v1{1, 2, 3};
+        assert(v1.size() == 3);
+        assert(v1[0] == 1 && v1[1] == 2 && v1[2] == 3);
+      }
+    constexpr static V v2{1, 2, 3};
+    constexpr static V v3 = [] consteval { return V{1, 2, 3}; }
+    ();
+    static_assert(v2.size() == 3);
+    static_assert(v3.size() == 3);
+    static_assert(v2[0] == 1 && v2[1] == 2 && v2[2] == 3);
+    static_assert(v3[0] == 1 && v3[1] == 2 && v3[2] == 3);
+  }
+  {
+    using V = std::inplace_vector<NonTrivial, 0>;
+    if
+      !consteval {
+        constinit static V v1;
+        assert(v1.size() == 0);
+      }
+    constexpr static V v2;
+    static_assert(v2.size() == 0);
+  }
+  if
+    !consteval {
+      using V = std::inplace_vector<NonTrivial, 10>;
+      static V v(3);
+      assert(v.size() == 3);
+      assert(!v[0].constant && !v[1].constant && !v[2].constant);
+    }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/contiguous.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/contiguous.pass.cpp
new file mode 100644
index 00000000000000..9695135155dffb
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/contiguous.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// An inplace_vector is a contiguous container
+
+#include <inplace_vector>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class C>
+constexpr void test_contiguous(const C& c) {
+  for (std::size_t i = 0; i <= c.size(); ++i) {
+    if (i != c.size()) {
+      assert(*(c.begin() + i) == *(std::addressof(*c.begin()) + i));
+      assert(std::addressof(c.begin()[i]) == std::addressof(c.front()) + i);
+    }
+    assert(std::to_address(c.begin() + i) == std::to_address(c.begin()) + i);
+  }
+}
+
+constexpr bool tests() {
+  {
+    using V = std::inplace_vector<int, 10>;
+    test_contiguous(V());
+    test_contiguous(V(3, 5));
+  }
+  {
+    using V = std::inplace_vector<int, 0>;
+    test_contiguous(V());
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/empy_type.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/empy_type.compile.pass.cpp
new file mode 100644
index 00000000000000..6dd0c6109486d9
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/empy_type.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector
+
+#include <inplace_vector>
+#include <type_traits>
+
+struct NonTrivial {
+  int i = 0;
+};
+struct VeryNonTrivial {
+  VeryNonTrivial();
+  VeryNonTrivial(const VeryNonTrivial&);
+  VeryNonTrivial& operator=(const VeryNonTrivial&);
+  ~VeryNonTrivial();
+};
+struct MoreNonTrivial : virtual VeryNonTrivial {
+  virtual void f();
+};
+
+static_assert(std::is_empty_v<std::inplace_vector<int, 0>>);
+static_assert(std::is_empty_v<std::inplace_vector<NonTrivial, 0>>);
+static_assert(std::is_empty_v<std::inplace_vector<VeryNonTrivial, 0>>);
+static_assert(std::is_empty_v<std::inplace_vector<MoreNonTrivial, 0>>);
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp
new file mode 100644
index 00000000000000..dbda41ef850a64
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// static size_type capacity() noexcept;
+
+#include <inplace_vector>
+#include <concepts>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <typename T, std::size_t N>
+constexpr void test() {
+  using V = std::inplace_vector<T, N>;
+  V v;
+  std::same_as<std::size_t> decltype(auto) sz = v.capacity();
+  assert(sz == N);
+  static_assert(v.capacity() == N);
+  static_assert(V::capacity() == N);
+  ASSERT_NOEXCEPT(v.capacity());
+  ASSERT_NOEXCEPT(V::capacity());
+}
+
+constexpr bool tests() {
+  test<int, 10>();
+  test<int, 0>();
+  test<MoveOnly, 0>();
+  if
+    !consteval { test<MoveOnly, 10>(); }
+  {
+    extern std::inplace_vector<MoveOnly, 10> v;
+    assert(v.capacity() == 10);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.pass.cpp
new file mode 100644
index 00000000000000..8919b3720d44ec
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// class inplace_vector
+
+// bool empty() const noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+  {
+    using V = std::inplace_vector<int, 10>;
+    V v;
+    ASSERT_NOEXCEPT(v.empty());
+    assert(v.empty());
+    v.push_back(1);
+    assert(!v.empty());
+    v.clear();
+    assert(v.empty());
+  }
+  {
+    using V = std::inplace_vector<int, 0>;
+    V v;
+    ASSERT_NOEXCEPT(v.empty());
+    assert(v.empty());
+    // Without language extension, since V is an empty type, there is no way for this to *not* be a constant expression
+    static_assert(v.empty());
+  }
+  {
+    using V = std::inplace_vector<MoveOnly, 0>;
+    V v;
+    ASSERT_NOEXCEPT(v.empty());
+    assert(v.empty());
+    // See above
+    static_assert(v.empty());
+  }
+  if
+    !consteval {
+      using V = std::inplace_vector<MoveOnly, 10>;
+      V v;
+      ASSERT_NOEXCEPT(v.empty());
+      assert(v.empty());
+      v.push_back(V::value_type(1));
+      assert(!v.empty());
+      v.clear();
+      assert(v.empty());
+    }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.verify.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.verify.cpp
new file mode 100644
index 00000000000000..6bbb82b40dd72c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.verify.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// class inplace_vector
+
+// bool empty() const noexcept;
+
+// See also: https://wg21.link/P2422R0
+// In practice, this should be marked [[no_discard]]
+
+#include <inplace_vector>
+
+void f() {
+  {
+    std::inplace_vector<int, 10> c;
+    c.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::inplace_vector<int, 0> c;
+    c.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp
new file mode 100644
index 00000000000000..5c6355c1f7f0d4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// static size_type max_size() noexcept;
+
+#include <inplace_vector>
+#include <concepts>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <typename T, std::size_t N>
+constexpr void test() {
+  using V = std::inplace_vector<T, N>;
+  V v;
+  std::same_as<std::size_t> decltype(auto) sz = v.max_size();
+  assert(sz == N);
+  static_assert(v.max_size() == N);
+  static_assert(V::max_size() == N);
+  ASSERT_NOEXCEPT(v.max_size());
+  ASSERT_NOEXCEPT(V::max_size());
+}
+
+constexpr bool tests() {
+  test<int, 10>();
+  test<int, 0>();
+  test<MoveOnly, 0>();
+  if
+    !consteval { test<MoveOnly, 10>(); }
+  {
+    extern std::inplace_vector<MoveOnly, 10> v;
+    assert(v.max_size() == 10);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.pass.cpp
new file mode 100644
index 00000000000000..c6b135503ed773
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.pass.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// static void reserve(size_type n);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+  {
+    using V = std::inplace_vector<int, 10>;
+    V v;
+    for (int i = 0; i <= 10; ++i) {
+      v.reserve(i);
+    }
+    static_assert((v.reserve(0), v.reserve(1), v.reserve(2), v.reserve(8), v.reserve(9), v.reserve(10), true));
+    static_assert((V::reserve(0), V::reserve(1), V::reserve(2), V::reserve(8), V::reserve(9), V::reserve(10), true));
+    if
+      !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+        try {
+          V::reserve(11);
+          assert(false);
+        } catch (const std::bad_alloc&) {
+        } catch (...) {
+          assert(false);
+        }
+        try {
+          V::reserve(-1);
+          assert(false);
+        } catch (const std::bad_alloc&) {
+        } catch (...) {
+          assert(false);
+        }
+#endif
+      }
+  }
+  {
+    using V = std::inplace_vector<int, 0>;
+    V v;
+    v.reserve(0);
+    static_assert((v.reserve(0), true));
+    static_assert((V::reserve(0), true));
+    if
+      !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+        try {
+          V::reserve(1);
+          assert(false);
+        } catch (const std::bad_alloc&) {
+        } catch (...) {
+          assert(false);
+        }
+        try {
+          V::reserve(-1);
+          assert(false);
+        } catch (const std::bad_alloc&) {
+        } catch (...) {
+          assert(false);
+        }
+#endif
+      }
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.pass.cpp
new file mode 100644
index 00000000000000..c0a18c74110eb4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void resize(size_type sz);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+  {
+    std::inplace_vector<int, 400> v(100);
+    v.resize(50);
+    assert(v.size() == 50);
+    for (int i : v) {
+      assert(i == 0);
+    }
+    v.resize(200);
+    assert(v.size() == 200);
+    for (int i : v) {
+      assert(i == 0);
+    }
+  }
+  if
+    !consteval {
+      std::inplace_vector<MoveOnly, 400> v(100);
+      v.resize(50);
+      assert(v.size() == 50);
+      v.resize(200);
+      assert(v.size() == 200);
+    }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp
new file mode 100644
index 00000000000000..bab46ec6ccada3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void resize(size_type sz);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct NonTrivial {
+  int i;
+  NonTrivial() : i(0) {}
+  NonTrivial(int i) : i(i) {}
+  NonTrivial(const NonTrivial& other) : i(other.i) {}
+  NonTrivial& operator=(const NonTrivial& other) {
+    i = other.i;
+    return *this;
+  }
+  ~NonTrivial() {}
+  operator int() const { return i; }
+};
+
+constexpr bool tests() {
+  {
+    std::inplace_vector<int, 400> v(100);
+    v.resize(50, 1);
+    assert(v.size() == 50);
+    for (int i : v) {
+      assert(i == 0);
+    }
+    v.resize(200, 1);
+    assert(v.size() == 200);
+    for (int i = 0; i < 50; ++i) {
+      assert(v[i] == 0);
+    }
+    for (int i = 50; i < 200; ++i) {
+      assert(v[i] == 1);
+    }
+  }
+  if
+    !consteval {
+      std::inplace_vector<NonTrivial, 400> v(100);
+      v.resize(50, 1);
+      assert(v.size() == 50);
+      for (int i : v) {
+        assert(i == 0);
+      }
+      v.resize(200, 1);
+      assert(v.size() == 200);
+      for (int i = 0; i < 50; ++i) {
+        assert(v[i] == 0);
+      }
+      for (int i = 50; i < 200; ++i) {
+        assert(v[i] == 1);
+      }
+    }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/shrink_to_fit.pass.cpp
new file mode 100644
index 00000000000000..bb1c1b3eb65e34
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/shrink_to_fit.pass.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// static void shrink_to_fit() noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <typename T, std::size_t N>
+constexpr void test() {
+  using V = std::inplace_vector<T, N>;
+  static_assert((V::shrink_to_fit(), true));
+  ASSERT_NOEXCEPT(V::shrink_to_fit());
+}
+
+constexpr bool tests() {
+  test<int, 10>();
+  test<int, 0>();
+  test<MoveOnly, 10>();
+  test<MoveOnly, 0>();
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/size.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/size.pass.cpp
new file mode 100644
index 00000000000000..68510865c4f981
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/size.pass.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// class vector
+
+// size_type size() const noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+  {
+    using V = std::inplace_vector<int, 10>;
+    V v;
+    ASSERT_NOEXCEPT(v.size());
+    assert(v.size() == 0);
+    v.push_back(2);
+    assert(v.size() == 1);
+    v.push_back(1);
+    assert(v.size() == 2);
+    v.push_back(3);
+    assert(v.size() == 3);
+    v.erase(v.begin());
+    assert(v.size() == 2);
+    v.erase(v.begin());
+    assert(v.size() == 1);
+    v.erase(v.begin());
+    assert(v.size() == 0);
+  }
+  if
+    !consteval {
+      using V = std::inplace_vector<MoveOnly, 10>;
+      V v;
+      ASSERT_NOEXCEPT(v.size());
+      assert(v.size() == 0);
+      v.push_back(2);
+      assert(v.size() == 1);
+      v.push_back(1);
+      assert(v.size() == 2);
+      v.push_back(3);
+      assert(v.size() == 3);
+      v.erase(v.begin());
+      assert(v.size() == 2);
+      v.erase(v.begin());
+      assert(v.size() == 1);
+      v.erase(v.begin());
+      assert(v.size() == 0);
+    }
+  {
+    using V = std::inplace_vector<int, 0>;
+    V v;
+    ASSERT_NOEXCEPT(v.size());
+    assert(v.size() == 0);
+    // Without language extension, since V is an empty type, there is no way for this to *not* be a constant expression
+    static_assert(v.size() == 0);
+  }
+  {
+    using V = std::inplace_vector<MoveOnly, 0>;
+    V v;
+    ASSERT_NOEXCEPT(v.size());
+    assert(v.size() == 0);
+    // See above
+    static_assert(v.size() == 0);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..be798ea00d231d
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.addressof.compile.pass.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(const inplace_vector& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <inplace_vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  {
+    std::inplace_vector<operator_hijacker, 10> vo;
+    std::inplace_vector<operator_hijacker, 10> v;
+    v = vo;
+  }
+  {
+    std::inplace_vector<operator_hijacker, 0> vo;
+    std::inplace_vector<operator_hijacker, 0> v;
+    v = vo;
+  }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.pass.cpp
new file mode 100644
index 00000000000000..87a7c81c534b99
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_copy.pass.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(const inplace_vector& c);
+
+#include <inplace_vector>
+#include <cassert>
+#include "test_macros.h"
+
+constexpr bool tests() {
+  {
+    std::inplace_vector<int, 100> l(3, 2);
+    std::inplace_vector<int, 100> l2(l);
+    l2 = l;
+    assert(l2 == l);
+  }
+  {
+    std::inplace_vector<int, 10> l(3, 2);
+    std::inplace_vector<int, 10> l2;
+    l2 = l;
+    assert(l2 == l);
+  }
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_initializer_list.pass.cpp
new file mode 100644
index 00000000000000..a8bfc884267f63
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_initializer_list.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void assign(initializer_list<value_type> il);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <typename Vec>
+constexpr void test(Vec& v) {
+  v.assign({3, 4, 5, 6});
+  assert(v.size() == 4);
+  assert(v[0] == 3);
+  assert(v[1] == 4);
+  assert(v[2] == 5);
+  assert(v[3] == 6);
+  v.assign({});
+  assert(v.size() == 0);
+}
+
+constexpr bool tests() {
+  {
+    using V = std::inplace_vector<int, 4>;
+    V d1;
+    V d2{-1, -2};
+    V d3{-1, -2, -3, -4};
+    test(d1);
+    test(d2);
+    test(d3);
+  }
+  {
+    using V = std::inplace_vector<int, 10>;
+    V d1;
+    V d2{-1, -2};
+    V d3{-1, -2, -3, -4};
+    V d4{-1, -2, -3, -4, -6, -7};
+    test(d1);
+    test(d2);
+    test(d3);
+    test(d4);
+  }
+  {
+    using V = std::inplace_vector<int, 100>;
+    V d1;
+    V d2{-1, -2};
+    V d3{-1, -2, -3, -4};
+    V d4{-1, -2, -3, -4, -6, -7};
+    test(d1);
+    test(d2);
+    test(d3);
+    test(d4);
+  }
+  {
+    using V = std::inplace_vector<int, 0>;
+    V d1;
+    d1.assign({});
+    assert(d1.size() == 0);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp
new file mode 100644
index 00000000000000..c4ef0b537bb90c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp
@@ -0,0 +1,122 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template <class InputIter> void assign(InputIter first, InputIter last);
+
+#include <inplace_vector>
+#include <algorithm>
+#include <cassert>
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "emplace_constructible.h"
+#include "container_test_types.h"
+
+constexpr bool test() {
+  int arr1[] = {42};
+  int arr2[] = {1, 101, 42};
+  if
+    !consteval {
+      using T  = EmplaceConstructibleMoveableAndAssignable<int>;
+      using It = forward_iterator<int*>;
+      {
+        std::inplace_vector<T, 10> v;
+        v.assign(It(arr1), It(std::end(arr1)));
+        assert(v[0].value == 42);
+      }
+      {
+        std::inplace_vector<T, 10> v;
+        v.assign(It(arr2), It(std::end(arr2)));
+        assert(v[0].value == 1);
+        assert(v[1].value == 101);
+        assert(v[2].value == 42);
+      }
+    }
+  if
+    !consteval {
+      using T  = EmplaceConstructibleMoveableAndAssignable<int>;
+      using It = cpp17_input_iterator<int*>;
+      {
+        std::inplace_vector<T, 10> v;
+        v.assign(It(arr1), It(std::end(arr1)));
+        assert(v[0].copied == 0);
+        assert(v[0].value == 42);
+      }
+      {
+        std::inplace_vector<T, 10> v;
+        v.assign(It(arr2), It(std::end(arr2)));
+        //assert(v[0].copied == 0);
+        assert(v[0].value == 1);
+        //assert(v[1].copied == 0);
+        assert(v[1].value == 101);
+        assert(v[2].copied == 0);
+        assert(v[2].value == 42);
+      }
+    }
+  {
+    using T  = int;
+    using It = forward_iterator<int*>;
+    {
+      std::inplace_vector<T, 10> v;
+      v.assign(It(arr1), It(std::end(arr1)));
+      assert(v[0] == 42);
+    }
+    {
+      std::inplace_vector<T, 10> v;
+      v.assign(It(arr2), It(std::end(arr2)));
+      assert(v[0] == 1);
+      assert(v[1] == 101);
+      assert(v[2] == 42);
+    }
+  }
+  {
+    using T  = int;
+    using It = cpp17_input_iterator<int*>;
+    {
+      std::inplace_vector<T, 10> v;
+      v.assign(It(arr1), It(std::end(arr1)));
+      assert(v[0] == 42);
+    }
+    {
+      std::inplace_vector<T, 10> v;
+      v.assign(It(arr2), It(std::end(arr2)));
+      assert(v[0] == 1);
+      assert(v[1] == 101);
+      assert(v[2] == 42);
+    }
+  }
+
+  if
+    !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+      try {
+        using It = forward_iterator<int*>;
+
+        std::inplace_vector<int, 10> dst(10);
+        int src[20]{};
+
+        dst.assign(It(src + 0), It(src + 20));
+        assert(false);
+      } catch (const std::bad_alloc& e) {
+        // OK
+      } catch (...) {
+        assert(false);
+      }
+#endif
+    }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..68063fefe4e614
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.addressof.compile.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(vector&& c);
+
+// Validate whether the container can be move-assigned with an ADL-hijacking operator&
+
+#include <inplace_vector>
+#include <utility>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  {
+    std::inplace_vector<operator_hijacker, 10> vo;
+    std::inplace_vector<operator_hijacker, 10> v;
+    v = std::move(vo);
+  }
+  {
+    std::inplace_vector<operator_hijacker, 0> vo;
+    std::inplace_vector<operator_hijacker, 0> v;
+    v = std::move(vo);
+  }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.pass.cpp
new file mode 100644
index 00000000000000..89d9a7426f7b2b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(inplace_vector&& c);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+  if
+    !consteval {
+      std::inplace_vector<MoveOnly, 10> l;
+      std::inplace_vector<MoveOnly, 10> lo;
+      for (int i = 1; i <= 3; ++i) {
+        l.push_back(i);
+        lo.push_back(i);
+      }
+      std::inplace_vector<MoveOnly, 10> l2;
+      l2 = std::move(l);
+      assert(l2.size() == 3);
+      assert(l2[0] == 1);
+      assert(l2[1] == 2);
+      assert(l2[2] == 3);
+      assert(l2 == lo);
+      // assert(l.size() == lo.size()); // l is left unspecified
+    }
+  {
+    std::inplace_vector<int, 10> l;
+    std::inplace_vector<int, 10> lo;
+    for (int i = 1; i <= 3; ++i) {
+      l.push_back(i);
+      lo.push_back(i);
+    }
+    std::inplace_vector<int, 10> l2;
+    l2 = std::move(l);
+    assert(l2 == lo);
+    // assert(l.size() == lo.size()); // l is left unspecified
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_size_value.pass.cpp
new file mode 100644
index 00000000000000..e018e0471c2e3e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_size_value.pass.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// void assign(size_type n, const_reference v);
+
+#include <inplace_vector>
+#include <algorithm>
+#include <cassert>
+
+#include "test_macros.h"
+
+constexpr bool is6(int x) { return x == 6; }
+
+template <typename Vec>
+constexpr void test(Vec& v) {
+  v.assign(5, 6);
+  assert(v.size() == 5);
+  assert(std::all_of(v.begin(), v.end(), is6));
+}
+
+constexpr bool tests() {
+  {
+    using V = std::inplace_vector<int, 10>;
+    V d1;
+    V d2{1, 2, 3, 4, 5, 6, 7, 8};
+    V d3{1, 2, 3};
+    test(d1);
+    test(d2);
+    test(d3);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp
new file mode 100644
index 00000000000000..d57701306e6332
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector();
+
+#include <inplace_vector>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "../../../NotConstructible.h"
+
+template <class C>
+constexpr void test0() {
+  static_assert(noexcept(C{})&& noexcept(C()));
+  static_assert(std::is_trivially_default_constructible_v<C> == (C::capacity() == 0));
+  C c;
+  assert(c.empty());
+  C c1 = {};
+  assert(c1.empty());
+}
+
+struct NonTrivial {
+  NonTrivial();
+};
+
+constexpr bool tests() {
+  {
+    using V = std::inplace_vector<int, 0>;
+    test0<V>();
+    constexpr V _;
+  }
+  {
+    using V = std::inplace_vector<int, 10>;
+    test0<V>();
+    constexpr V _;
+  }
+
+  {
+    using V = std::inplace_vector<NotConstructible, 0>;
+    test0<V>();
+    constexpr V _;
+  }
+  if
+    !consteval { test0<std::inplace_vector<NotConstructible, 10>>(); }
+
+  {
+    using V = std::inplace_vector<NonTrivial, 0>;
+    test0<V>();
+    constexpr V _;
+  }
+  if
+    !consteval { test0<std::inplace_vector<NonTrivial, 10>>(); }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_from_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_from_range.pass.cpp
new file mode 100644
index 00000000000000..fdb8ec9a79ddff
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_from_range.pass.cpp
@@ -0,0 +1,43 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template<container-compatible-range<T> R>
+//   inplace_vector(from_range_t, R&& rg);
+
+#include <inplace_vector>
+
+#include "../../from_range_sequence_containers.h"
+#include "test_macros.h"
+
+// TODO: from_range_sequence_containers.h does not support inplace_vector well because it doesn't have an allocator and has a NTTP
+#if 0
+constexpr bool test() {
+  for_all_iterators_and_allocators<int>([]<class Iter, class Sent, class Alloc>() {
+    test_sequence_container<std::inplace_vector, int, Iter, Sent, Alloc>([](const auto&) {});
+  });
+  test_sequence_container_move_only<std::inplace_vector>();
+
+  return true;
+}
+#endif
+
+int main(int, char**) {
+#if 0
+  static_assert(test_constraints<std::inplace_vector, int, double>());
+  test();
+
+  static_assert(test());
+
+  test_exception_safety_throwing_copy<std::inplace_vector>();
+
+  return 0;
+#endif
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp
new file mode 100644
index 00000000000000..8711b01f9d07d1
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp
@@ -0,0 +1,181 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// template <class InputIter> inplace_vector(InputIter first, InputIter last);
+
+#include <inplace_vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "emplace_constructible.h"
+#include "container_test_types.h"
+
+template <class C, class Iterator>
+constexpr void test(Iterator first, Iterator last) {
+  {
+    C c(first, last);
+    assert(c.size() == static_cast<std::size_t>(std::distance(first, last)));
+    for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i, ++first)
+      assert(*i == *first);
+  }
+  // Test with an empty range
+  {
+    C c(first, first);
+    assert(c.empty());
+  }
+}
+
+constexpr void basic_test_cases() {
+  int a[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0};
+  int* an = a + sizeof(a) / sizeof(a[0]);
+  using V = std::inplace_vector<int, 20>;
+  test<V>(cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(an));
+  test<V>(forward_iterator<const int*>(a), forward_iterator<const int*>(an));
+  test<V>(bidirectional_iterator<const int*>(a), bidirectional_iterator<const int*>(an));
+  test<V>(random_access_iterator<const int*>(a), random_access_iterator<const int*>(an));
+  test<V>(a, an);
+
+  // Regression test for https://github.com/llvm/llvm-project/issues/46841
+  {
+    V v1({}, forward_iterator<const int*>{});
+    V v2(forward_iterator<const int*>{}, {});
+  }
+
+  if
+    !consteval {
+      volatile int src[] = {1, 2, 3};
+      std::inplace_vector<int, 3> v(src, src + 3);
+      assert(v[0] == 1);
+      assert(v[1] == 2);
+      assert(v[2] == 3);
+    }
+}
+
+constexpr void emplaceable_concept_tests() {
+  int arr1[] = {42};
+  int arr2[] = {1, 101, 42};
+  if
+    !consteval {
+      using T  = EmplaceConstructible<int>;
+      using It = forward_iterator<int*>;
+      {
+        std::inplace_vector<T, 10> v(It(arr1), It(std::end(arr1)));
+        assert(v[0].value == 42);
+      }
+      {
+        std::inplace_vector<T, 10> v(It(arr2), It(std::end(arr2)));
+        assert(v[0].value == 1);
+        assert(v[1].value == 101);
+        assert(v[2].value == 42);
+      }
+    }
+
+  if
+    !consteval {
+      using T  = EmplaceConstructibleAndMoveInsertable<int>;
+      using It = cpp17_input_iterator<int*>;
+      {
+        std::inplace_vector<T, 10> v(It(arr1), It(std::end(arr1)));
+        assert(v[0].copied == 0);
+        assert(v[0].value == 42);
+      }
+      {
+        std::inplace_vector<T, 10> v(It(arr2), It(std::end(arr2)));
+        //assert(v[0].copied == 0);
+        assert(v[0].value == 1);
+        //assert(v[1].copied == 0);
+        assert(v[1].value == 101);
+        assert(v[2].copied == 0);
+        assert(v[2].value == 42);
+      }
+    }
+}
+
+constexpr void overcapacity_tests() {
+  if
+    !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+      try {
+        using It = forward_iterator<int*>;
+
+        std::inplace_vector<int, 10> dst(10);
+        int src[20]{};
+
+        dst.assign(It(src + 0), It(src + 20));
+        assert(false);
+      } catch (const std::bad_alloc& e) {
+        // OK
+      } catch (...) {
+        assert(false);
+      }
+#endif
+    }
+}
+
+struct B1 {
+  int x;
+};
+struct B2 {
+  int y;
+};
+struct Der : B1, B2 {
+  int z;
+};
+
+// Initialize a vector with a different value type.
+constexpr void test_ctor_with_different_value_type() {
+  {
+    // Make sure initialization is performed with each element value, not with
+    // a memory blob.
+    float array[3] = {0.0f, 1.0f, 2.0f};
+    TEST_DIAGNOSTIC_PUSH
+    TEST_MSVC_DIAGNOSTIC_IGNORED(4244) // conversion from 'float' to 'int', possible loss of data
+    std::inplace_vector<int, 10> v(array, array + 3);
+    TEST_DIAGNOSTIC_POP
+    assert(v.size() == 3);
+    assert(v[0] == 0);
+    assert(v[1] == 1);
+    assert(v[2] == 2);
+  }
+  {
+    Der z;
+    Der* array[1] = {&z};
+    // Though the types Der* and B2* are very similar, initialization still cannot
+    // be done with `memcpy`.
+    std::inplace_vector<B2*, 10> v(array, array + 1);
+    assert(v.size() == 1);
+    assert(v[0] == &z);
+  }
+  {
+    // Though the types are different, initialization can be done with `memcpy`.
+    std::int32_t array[1] = {-1};
+    std::inplace_vector<std::uint32_t, 10> v(array, array + 1);
+    assert(v.size() == 1);
+    assert(v[0] == 4294967295U);
+  }
+}
+
+constexpr bool tests() {
+  basic_test_cases();
+  emplaceable_concept_tests(); // See PR34898
+  test_ctor_with_different_value_type();
+  overcapacity_tests();
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size.pass.cpp
new file mode 100644
index 00000000000000..cbdcf16d51e91a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// explicit inplace_vector(size_type n);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "DefaultOnly.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+
+template <class C>
+TEST_CONSTEXPR_CXX20 void
+test(typename C::size_type n, typename C::allocator_type const& a = typename C::allocator_type()) {
+  (void)a;
+  // Test without a custom allocator
+  {
+    C c(n);
+    assert(c.size() == n);
+    assert(c.get_allocator() == typename C::allocator_type());
+#if TEST_STD_VER >= 11
+    for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i)
+      assert(*i == typename C::value_type());
+#endif
+  }
+
+  // Test with a custom allocator
+#if TEST_STD_VER >= 14
+  {
+    C c(n, a);
+    assert(c.size() == n);
+    assert(c.get_allocator() == a);
+    for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i)
+      assert(*i == typename C::value_type());
+  }
+#endif
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  test<std::vector<int> >(0);
+  test<std::vector<int> >(50);
+#if TEST_STD_VER >= 11
+  test<std::vector<int, min_allocator<int>>>(0);
+  test<std::vector<int, min_allocator<int>>>(50);
+  test<std::vector<int, safe_allocator<int>>>(0);
+  test<std::vector<int, safe_allocator<int>>>(50);
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  test<std::vector<DefaultOnly> >(0);
+  test<std::vector<DefaultOnly> >(500);
+  assert(DefaultOnly::count == 0);
+
+#if TEST_STD_VER >= 11
+  test<std::vector<DefaultOnly, min_allocator<DefaultOnly>>>(0);
+  test<std::vector<DefaultOnly, min_allocator<DefaultOnly>>>(500);
+  test<std::vector<DefaultOnly, safe_allocator<DefaultOnly>>>(0);
+  test<std::vector<DefaultOnly, safe_allocator<DefaultOnly>>>(500);
+  test<std::vector<DefaultOnly, test_allocator<DefaultOnly>>>(0, test_allocator<DefaultOnly>(23));
+  test<std::vector<DefaultOnly, test_allocator<DefaultOnly>>>(100, test_allocator<DefaultOnly>(23));
+  assert(DefaultOnly::count == 0);
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp
new file mode 100644
index 00000000000000..bfbb145e2bf669
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(size_type n, const value_type& x);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class C>
+constexpr void test(typename C::size_type n, const typename C::value_type& x) {
+  C c(n, x);
+  assert(c.size() == n);
+  for (typename C::const_iterator i = c.cbegin(), e = c.cend(); i != e; ++i)
+    assert(*i == x);
+}
+
+constexpr bool tests() {
+  test<std::inplace_vector<int, 0>>(0, 3);
+  test<std::inplace_vector<int, 10>>(0, 3);
+  test<std::inplace_vector<int, 100>>(50, 3);
+  test<std::inplace_vector<int, 100>>(100, 3);
+  if
+    !consteval {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+      try {
+        std::inplace_vector<int, 10>(50, 3);
+        assert(false);
+      } catch (const std::bad_alloc&) {
+        // OK
+      } catch (...) {
+        assert(false);
+      }
+
+      try {
+        std::inplace_vector<int, 0>(1, 3);
+        assert(false);
+      } catch (const std::bad_alloc&) {
+        // OK
+      } catch (...) {
+        assert(false);
+      }
+#endif
+    }
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.move_only.verify.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.move_only.verify.cpp
new file mode 100644
index 00000000000000..f51899a8ee0e00
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.move_only.verify.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// Make sure that a std::inplace_vector containing move-only types can't be copied.
+
+#include <inplace_vector>
+
+#include "MoveOnly.h"
+
+void f() {
+  {
+    std::inplace_vector<MoveOnly, 10> v;
+    [[maybe_unused]] std::inplace_vector<MoveOnly, 10> copy =
+        v; // expected-error-re@* {{{{(no matching function for call to 'construct_at')|(call to deleted constructor of 'MoveOnly')}}}}
+  }
+  {
+    std::inplace_vector<MoveOnly, 0> v;
+    // FIXME: This might be ill-formed. It also might be well-formed because it's meant to be trivially copyable.
+    [[maybe_unused]] std::inplace_vector<MoveOnly, 0> copy = v;
+  }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.pass.cpp
new file mode 100644
index 00000000000000..325b80d162102e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/copy.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(const inplace_vector& v);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class C>
+constexpr void test(const C& x) {
+  typename C::size_type s = x.size();
+  C c(x);
+  assert(c.size() == s);
+  assert(c == x);
+}
+
+constexpr bool tests() {
+  {
+    int a[]             = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 1, 0};
+    constexpr auto a_sz = sizeof(a) / sizeof(a[0]);
+    int* an             = a + a_sz;
+    test(std::inplace_vector<int, a_sz>(a, an));
+    test(std::inplace_vector<int, a_sz + 1>(a, an));
+    test(std::inplace_vector<int, a_sz * 2>(a, an));
+  }
+  {
+    // Test copy ctor with empty source
+    std::inplace_vector<int, 10 > v;
+    std::inplace_vector<int, 10> v2 = v;
+    assert(v2 == v);
+    assert(v2.empty());
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/deduct.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/deduct.pass.cpp
new file mode 100644
index 00000000000000..b483b2b9f55939
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/deduct.pass.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// No explicit deduction guides. Only implicit copy deduction
+// guide should ever be usable.
+
+// template <class T, size_t N>
+//    inplace_vector(inplace_vector<T, N>) -> inplace_vector<T, N>
+
+#include <inplace_vector>
+#include <utility>
+#include <type_traits>
+#include <span>
+
+#include "test_macros.h"
+#include "test_iterators.h"
+
+TEST_CLANG_DIAGNOSTIC_IGNORED("-Wctad-maybe-unsupported")
+
+template <typename T>
+constexpr bool copy_deduction() {
+  static_assert(std::is_same_v<decltype(std::inplace_vector(std::declval<T>())), T>);
+  static_assert(std::is_same_v<decltype(std::inplace_vector(std::declval<const T>())), T>);
+  static_assert(std::is_same_v<decltype(std::inplace_vector(std::declval<T&>())), T>);
+  static_assert(std::is_same_v<decltype(std::inplace_vector(std::declval<const T&>())), T>);
+  static_assert(std::is_same_v<decltype(std::inplace_vector{std::declval<T>()}), T>);
+  static_assert(std::is_same_v<decltype(std::inplace_vector{std::declval<const T>()}), T>);
+  static_assert(std::is_same_v<decltype(std::inplace_vector{std::declval<T&>()}), T>);
+  static_assert(std::is_same_v<decltype(std::inplace_vector{std::declval<const T&>()}), T>);
+  return true;
+}
+
+static_assert(copy_deduction<std::inplace_vector<int, 10>>());
+static_assert(copy_deduction<std::inplace_vector<int, 0>>());
+
+template <class... Args>
+concept NotDeducible = !(
+    requires(Args... args) { std::inplace_vector(std::forward<Args>(args)...); } ||
+    requires(Args... args) { std::inplace_vector{std::forward<Args>(args)...}; });
+
+static_assert(NotDeducible<>);
+static_assert(NotDeducible<int>);
+static_assert(NotDeducible<std::size_t>);
+static_assert(NotDeducible<int*, int*>);
+static_assert(NotDeducible<std::from_range_t, int (&)[10]>);
+static_assert(NotDeducible<std::from_range_t, std::span<int, 10>>);
+static_assert(NotDeducible<std::initializer_list<int>>);
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.empty.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.empty.pass.cpp
new file mode 100644
index 00000000000000..6e07850d24ff16
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.empty.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// Unlike vector, inplace_vector cannot be used with an incomplete type
+
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+struct X {
+  // FIXME: is this OK?
+  std::inplace_vector<X, 0> q;
+};
+
+int main(int, char**) {
+  [[maybe_unused]] X x;
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.fail.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.fail.cpp
new file mode 100644
index 00000000000000..c2c5fd17e5dc17
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default.recursive.fail.cpp
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// Unlike vector, inplace_vector cannot be used with an incomplete type
+
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+struct Y {
+  std::inplace_vector<Y, 10> q;
+};
+
+int main(int, char**) { return 0; }
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default_noexcept.pass.cpp
new file mode 100644
index 00000000000000..0d66be3148bcc2
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/default_noexcept.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector() noexcept
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <typename C>
+constexpr void test() {
+  static_assert(std::is_nothrow_default_constructible_v<C>);
+  ASSERT_NOEXCEPT(C());
+  ASSERT_NOEXCEPT(C{});
+}
+
+constexpr bool tests() {
+  test<std::inplace_vector<int, 10>>();
+  test<std::inplace_vector<int, 0>>();
+  test<std::inplace_vector<MoveOnly, 10>>();
+  test<std::inplace_vector<MoveOnly, 0>>();
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/dtor_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/dtor_noexcept.pass.cpp
new file mode 100644
index 00000000000000..6b6286415f1724
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/dtor_noexcept.pass.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// ~inplace_vector() // implied noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+  {
+    using C = std::inplace_vector<int, 0>;
+    static_assert(std::is_nothrow_destructible_v<C>);
+  }
+  {
+    using C = std::inplace_vector<int, 10>;
+    static_assert(std::is_nothrow_destructible_v<C>);
+  }
+  {
+    using C = std::inplace_vector<MoveOnly, 0>;
+    static_assert(std::is_nothrow_destructible_v<C>);
+  }
+  {
+    using C = std::inplace_vector<MoveOnly, 10>;
+    static_assert(std::is_nothrow_destructible_v<C>);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/exceptions.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/exceptions.pass.cpp
new file mode 100644
index 00000000000000..d1e539a289ddda
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/exceptions.pass.cpp
@@ -0,0 +1,166 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// UNSUPPORTED: no-exceptions
+
+// <inplace_vector>
+
+// (bug report: https://llvm.org/PR58392)
+// Check that vector constructors don't leak memory when an operation inside the constructor throws an exception
+
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <inplace_vector>
+
+#include "count_new.h"
+#include "test_iterators.h"
+
+struct ThrowingT {
+  int* throw_after_n_ = nullptr;
+  ThrowingT() { throw 0; }
+
+  ThrowingT(int& throw_after_n) : throw_after_n_(&throw_after_n) {
+    if (throw_after_n == 0)
+      throw 0;
+    --throw_after_n;
+  }
+
+  ThrowingT(const ThrowingT&) {
+    if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
+      throw 1;
+    --*throw_after_n_;
+  }
+
+  ThrowingT& operator=(const ThrowingT&) {
+    if (throw_after_n_ == nullptr || *throw_after_n_ == 0)
+      throw 1;
+    --*throw_after_n_;
+    return *this;
+  }
+};
+
+template <class IterCat>
+struct Iterator {
+  using iterator_category = IterCat;
+  using difference_type   = std::ptrdiff_t;
+  using value_type        = int;
+  using reference         = int&;
+  using pointer           = int*;
+
+  int i_;
+  Iterator(int i = 0) : i_(i) {}
+  int& operator*() {
+    if (i_ == 1)
+      throw 1;
+    return i_;
+  }
+
+  friend bool operator==(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ == rhs.i_; }
+
+  friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { return lhs.i_ != rhs.i_; }
+
+  Iterator& operator++() {
+    ++i_;
+    return *this;
+  }
+
+  Iterator operator++(int) {
+    auto tmp = *this;
+    ++i_;
+    return tmp;
+  }
+};
+
+void check_new_delete_called() {
+  assert(globalMemCounter.new_called == globalMemCounter.delete_called);
+  assert(globalMemCounter.new_array_called == globalMemCounter.delete_array_called);
+  assert(globalMemCounter.aligned_new_called == globalMemCounter.aligned_delete_called);
+  assert(globalMemCounter.aligned_new_array_called == globalMemCounter.aligned_delete_array_called);
+}
+
+int main(int, char**) {
+  try { // Throw in inplace_vector(size_type) from type
+    std::inplace_vector<ThrowingT, 1> v(1);
+    assert(false);
+  } catch (int) {
+  } catch (...) {
+    assert(false);
+  }
+  check_new_delete_called();
+
+  try { // Throw in inplace_vector(size_type) from lack of capacity
+    std::inplace_vector<ThrowingT, 1> v(2);
+    assert(false);
+  } catch (const std::bad_alloc&) {
+  } catch (...) {
+    assert(false);
+  }
+  check_new_delete_called();
+
+  try { // Do not throw when none are constructed
+    [[maybe_unused]] std::inplace_vector<ThrowingT, 1> v1(0);
+    [[maybe_unused]] std::inplace_vector<ThrowingT, 0> v2(0);
+  } catch (...) {
+    assert(false);
+  }
+  check_new_delete_called();
+
+  try { // Throw in inplace_vector(size_type, value_type) from type
+    int throw_after = 1;
+    ThrowingT v(throw_after);
+    std::inplace_vector<ThrowingT, 1> vec(1, v);
+    assert(false);
+  } catch (int) {
+  } catch (...) {
+    assert(false);
+  }
+  check_new_delete_called();
+
+  try { // Throw in inplace_vector(InputIterator, InputIterator) from input iterator
+    std::inplace_vector<int, 4> vec((Iterator<std::input_iterator_tag>()), Iterator<std::input_iterator_tag>(2));
+    assert(false);
+  } catch (int) {
+  } catch (...) {
+    assert(false);
+  }
+  check_new_delete_called();
+
+  try { // Throw in inplace_vector(InputIterator, InputIterator) from forward iterator
+    std::inplace_vector<int, 4> vec((Iterator<std::forward_iterator_tag>()), Iterator<std::forward_iterator_tag>(2));
+    assert(false);
+  } catch (int) {
+  } catch (...) {
+    assert(false);
+  }
+  check_new_delete_called();
+
+  try { // Throw in vector(const vector&) from type
+    std::inplace_vector<ThrowingT, 10> vec;
+    int throw_after = 0;
+    vec.emplace_back(throw_after);
+    auto vec2 = vec;
+    assert(false);
+  } catch (int) {
+  } catch (...) {
+    assert(false);
+  }
+  check_new_delete_called();
+
+  try { // Throw in vector(initializer_list<value_type>) from type
+    int throw_after = 1;
+    std::inplace_vector<ThrowingT, 10> vec({ThrowingT(throw_after)});
+    assert(false);
+  } catch (int) {
+  } catch (...) {
+    assert(false);
+  }
+  check_new_delete_called();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/initializer_list.pass.cpp
new file mode 100644
index 00000000000000..922418ba324634
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/initializer_list.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(initializer_list<value_type> il);
+
+#include <inplace_vector>
+#include <cassert>
+#include "test_macros.h"
+
+constexpr bool tests() {
+  {
+    std::inplace_vector<int, 10> d = {3, 4, 5, 6};
+    assert(d.size() == 4);
+    assert(d[0] == 3);
+    assert(d[1] == 4);
+    assert(d[2] == 5);
+    assert(d[3] == 6);
+  }
+  {
+    std::inplace_vector<int, 4> d = {3, 4, 5, 6};
+    assert(d.size() == 4);
+    assert(d[0] == 3);
+    assert(d[1] == 4);
+    assert(d[2] == 5);
+    assert(d[3] == 6);
+  }
+  {
+    std::inplace_vector<int, 10> d = std::initializer_list<int>();
+    assert(d.size() == 0);
+  }
+  {
+    std::inplace_vector<int, 0> d = std::initializer_list<int>();
+    assert(d.size() == 0);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..06e2cd08e82b5b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.addressof.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_(inplace_vector&& c);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <inplace_vector>
+#include <utility>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  {
+    std::inplace_vector<operator_hijacker, 10> vo;
+    [[maybe_unused]] std::inplace_vector<operator_hijacker, 10> v(std::move(vo));
+  }
+  {
+    std::inplace_vector<operator_hijacker, 0> vo;
+    [[maybe_unused]] std::inplace_vector<operator_hijacker, 0> v(std::move(vo));
+  }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp
new file mode 100644
index 00000000000000..9b7c15f0c107ef
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(inplace_vector&&);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+  if
+    !consteval {
+      std::inplace_vector<MoveOnly, 10> l;
+      std::inplace_vector<MoveOnly, 10> lo;
+      for (int i = 1; i <= 3; ++i) {
+        l.push_back(i);
+        lo.push_back(i);
+      }
+      std::inplace_vector<MoveOnly, 10> l2 = std::move(l);
+      assert(l2.size() == 3);
+      assert(l2[0] == 1);
+      assert(l2[1] == 2);
+      assert(l2[2] == 3);
+      assert(l2 == lo);
+      // assert(l.size() == lo.size()); // l is left unspecified
+    }
+  {
+    std::inplace_vector<int, 10> l;
+    std::inplace_vector<int, 10> lo;
+    for (int i = 1; i <= 3; ++i) {
+      l.push_back(i);
+      lo.push_back(i);
+    }
+    std::inplace_vector<int, 10> l2 = std::move(l);
+    assert(l2 == lo);
+    // assert(l.size() == lo.size()); // l is left unspecified
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_assign_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_assign_noexcept.pass.cpp
new file mode 100644
index 00000000000000..45f74f82c46756
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_assign_noexcept.pass.cpp
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(inplace_vector&& c)
+//     noexcept(
+//          N == 0 || (is_nothrow_move_assignable_v<T> &&
+//                     is_nothrow_move_constructible_v<T>));
+
+#include <inplace_vector>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <bool ConstructNoexcept, bool AssignNoexcept>
+struct MoveOnly {
+  MoveOnly(MoveOnly&&) noexcept(ConstructNoexcept);
+  MoveOnly& operator=(MoveOnly&&) noexcept(AssignNoexcept);
+  ~MoveOnly();
+};
+
+struct Immovable {
+  Immovable(Immovable&&)            = delete;
+  Immovable& operator=(Immovable&&) = delete;
+  ~Immovable();
+};
+
+int main(int, char**) {
+  static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<int, 0>>);
+  static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<int, 10>>);
+  static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<true, true>, 0>>);
+  static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<true, true>, 10>>);
+  static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<true, false>, 0>>);
+  static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<true, false>, 10>>);
+  static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<false, true>, 0>>);
+  static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<false, true>, 10>>);
+  static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<false, false>, 0>>);
+  static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<MoveOnly<false, false>, 10>>);
+  static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<Immovable, 0>>);
+  static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<Immovable, 10>>);
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_noexcept.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_noexcept.pass.cpp
new file mode 100644
index 00000000000000..54fd549b4719ad
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move_noexcept.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector(inplace_vector&&)
+//     noexcept(N == 0 || is_nothrow_move_assignable_v<T>);
+
+#include <inplace_vector>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <bool ConstructNoexcept, bool AssignNoexcept>
+struct MoveOnly {
+  MoveOnly(MoveOnly&&) noexcept(ConstructNoexcept);
+  MoveOnly& operator=(MoveOnly&&) noexcept(AssignNoexcept);
+  ~MoveOnly();
+};
+
+struct Immovable {
+  Immovable(Immovable&&)            = delete;
+  Immovable& operator=(Immovable&&) = delete;
+  ~Immovable();
+};
+
+int main(int, char**) {
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<int, 0>>);
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<int, 10>>);
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<true, true>, 0>>);
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<true, true>, 10>>);
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<true, false>, 0>>);
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<true, false>, 10>>);
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<false, true>, 0>>);
+  static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<false, true>, 10>>);
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<false, false>, 0>>);
+  static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<MoveOnly<false, false>, 10>>);
+  static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<Immovable, 0>>);
+  static_assert(!std::is_nothrow_move_constructible_v<std::inplace_vector<Immovable, 10>>);
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/op_equal_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/op_equal_initializer_list.pass.cpp
new file mode 100644
index 00000000000000..e78c4969507137
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/op_equal_initializer_list.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector& operator=(initializer_list<value_type> il);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+constexpr bool tests() {
+  {
+    std::inplace_vector<int, 10> d;
+    d = {3, 4, 5, 6};
+    assert(d.size() == 4);
+    assert(d[0] == 3);
+    assert(d[1] == 4);
+    assert(d[2] == 5);
+    assert(d[3] == 6);
+  }
+  {
+    std::inplace_vector<int, 4> d;
+    d = {3, 4, 5, 6};
+    assert(d.size() == 4);
+    assert(d[0] == 3);
+    assert(d[1] == 4);
+    assert(d[2] == 5);
+    assert(d[3] == 6);
+  }
+  {
+    std::inplace_vector<int, 10> d;
+    d = {};
+    assert(d.size() == 0);
+  }
+  {
+    std::inplace_vector<int, 0> d;
+    d = {};
+    assert(d.size() == 0);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp
new file mode 100644
index 00000000000000..8c3351a82a10cc
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// pointer data() noexcept;
+
+#include <inplace_vector>
+#include <concepts>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Nasty {
+  constexpr Nasty() : i_(0) {}
+  constexpr Nasty(int i) : i_(i) {}
+  constexpr Nasty(const Nasty& other) : i_(other.i_) {}
+  constexpr Nasty& operator=(const Nasty& other) {
+    i_ = other.i_;
+    return *this;
+  }
+  constexpr ~Nasty() {}
+
+  Nasty* operator&() const {
+    assert(false);
+    return nullptr;
+  }
+  int i_;
+};
+
+std::inplace_vector<Nasty, 10> glob{123};
+
+constexpr bool tests() {
+  {
+    std::inplace_vector<int, 0> v;
+    ASSERT_NOEXCEPT(v.data());
+    assert(v.data() == nullptr);
+    static_assert(v.data() == nullptr);
+  }
+  {
+    std::inplace_vector<int, 10> v;
+    ASSERT_NOEXCEPT(v.data());
+    assert(v.data() == std::to_address(v.begin()));
+    std::same_as<int*> decltype(auto) data = v.data();
+    v.push_back(4);
+    assert(data == std::addressof(v.front()));
+    assert(v.data() == data);
+    assert(data[0] == 4);
+    data[0] = 3;
+    assert(v.front() == 3);
+  }
+  {
+    std::inplace_vector<Nasty, 0> v;
+    ASSERT_NOEXCEPT(v.data());
+    assert(v.data() == nullptr);
+    static_assert(v.data() == nullptr);
+  }
+  if
+    !consteval {
+      std::inplace_vector<Nasty, 10> v;
+      ASSERT_NOEXCEPT(v.data());
+      assert(v.data() == std::to_address(v.begin()));
+      std::same_as<Nasty*> decltype(auto) data = v.data();
+      v.push_back(4);
+      assert(data == std::addressof(v.front()));
+      assert(v.data() == data);
+      assert(data[0].i_ == 4);
+      data[0].i_ = 3;
+      assert(v.front().i_ == 3);
+    }
+  if
+    !consteval {
+      static_assert(glob.data() != nullptr);
+      assert(glob.data()[0].i_ == 123);
+      glob.data()[0].i_ = 321;
+      assert(glob.front().i_ == 321);
+    }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp
new file mode 100644
index 00000000000000..672a17f65f73b8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp
@@ -0,0 +1,96 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// const_pointer data() const noexcept;
+
+#include <inplace_vector>
+#include <concepts>
+#include <memory>
+#include <utility>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct Nasty {
+  constexpr Nasty() : i_(0) {}
+  constexpr Nasty(int i) : i_(i) {}
+  constexpr Nasty(const Nasty& other) : i_(other.i_) {}
+  constexpr Nasty& operator=(const Nasty& other) {
+    i_ = other.i_;
+    return *this;
+  }
+  constexpr ~Nasty() {}
+
+  Nasty* operator&() const {
+    assert(false);
+    return nullptr;
+  }
+  int i_;
+};
+
+std::inplace_vector<Nasty, 10> glob{123};
+
+constexpr bool tests() {
+  {
+    std::inplace_vector<int, 0> v;
+    ASSERT_NOEXCEPT(std::as_const(v).data());
+    assert(std::as_const(v).data() == nullptr);
+    static_assert(std::as_const(v).data() == nullptr);
+  }
+  {
+    std::inplace_vector<int, 10> v;
+    ASSERT_NOEXCEPT(std::as_const(v).data());
+    assert(std::as_const(v).data() == v.data());
+    assert(std::as_const(v).data() == std::to_address(std::as_const(v).begin()));
+    std::same_as<const int*> decltype(auto) data = std::as_const(v).data();
+    v.push_back(4);
+    assert(data == std::addressof(v.front()));
+    assert(std::as_const(v).data() == data);
+    assert(data[0] == 4);
+    const_cast<int*>(data)[0] = 3;
+    assert(v.front() == 3);
+  }
+  {
+    std::inplace_vector<Nasty, 0> v;
+    ASSERT_NOEXCEPT(std::as_const(v).data());
+    assert(std::as_const(v).data() == nullptr);
+    static_assert(std::as_const(v).data() == nullptr);
+  }
+  if
+    !consteval {
+      std::inplace_vector<Nasty, 10> v;
+      ASSERT_NOEXCEPT(std::as_const(v).data());
+      assert(std::as_const(v).data() == v.data());
+      assert(std::as_const(v).data() == std::to_address(v.begin()));
+      std::same_as<const Nasty*> decltype(auto) data = std::as_const(v).data();
+      v.push_back(4);
+      assert(data == std::addressof(v.front()));
+      assert(std::as_const(v).data() == data);
+      assert(data[0].i_ == 4);
+      const_cast<Nasty*>(data)[0].i_ = 3;
+      assert(v.front().i_ == 3);
+    }
+  if
+    !consteval {
+      static_assert(std::as_const(glob).data() != nullptr);
+      assert(std::as_const(glob).data()[0].i_ == 123);
+      const_cast<Nasty*>(std::as_const(glob).data())[0].i_ = 321;
+      assert(glob.front().i_ == 321);
+    }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/iterator_concept_conformance.compile.pass.cpp
new file mode 100644
index 00000000000000..f56ca34ce7fe36
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/iterator_concept_conformance.compile.pass.cpp
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// iterator, const_iterator, reverse_iterator, const_reverse_iterator
+
+#include <inplace_vector>
+
+#include <iterator>
+
+template <typename T, std::size_t N>
+void test() {
+  using V                      = std::inplace_vector<T, N>;
+  using iterator               = typename V::iterator;
+  using const_iterator         = typename V::const_iterator;
+  using reverse_iterator       = typename V::reverse_iterator;
+  using const_reverse_iterator = typename V::const_reverse_iterator;
+  using value_type             = T;
+
+  static_assert(std::contiguous_iterator<iterator>);
+  static_assert(std::random_access_iterator<reverse_iterator>);
+  static_assert(!std::contiguous_iterator<reverse_iterator>);
+  static_assert(std::indirectly_writable<iterator, value_type>);
+  static_assert(std::sentinel_for<iterator, iterator>);
+  static_assert(std::sentinel_for<iterator, const_iterator>);
+  static_assert(!std::sentinel_for<iterator, reverse_iterator>);
+  static_assert(!std::sentinel_for<iterator, const_reverse_iterator>);
+  static_assert(std::sized_sentinel_for<iterator, iterator>);
+  static_assert(std::sized_sentinel_for<iterator, const_iterator>);
+  static_assert(!std::sized_sentinel_for<iterator, reverse_iterator>);
+  static_assert(!std::sized_sentinel_for<iterator, const_reverse_iterator>);
+  static_assert(std::indirectly_movable<iterator, iterator>);
+  static_assert(std::indirectly_movable_storable<iterator, iterator>);
+  static_assert(!std::indirectly_movable<iterator, const_iterator>);
+  static_assert(!std::indirectly_movable_storable<iterator, const_iterator>);
+  static_assert(std::indirectly_movable<iterator, reverse_iterator>);
+  static_assert(std::indirectly_movable_storable<iterator, reverse_iterator>);
+  static_assert(!std::indirectly_movable<iterator, const_reverse_iterator>);
+  static_assert(!std::indirectly_movable_storable<iterator, const_reverse_iterator>);
+  static_assert(std::indirectly_copyable<iterator, iterator>);
+  static_assert(std::indirectly_copyable_storable<iterator, iterator>);
+  static_assert(!std::indirectly_copyable<iterator, const_iterator>);
+  static_assert(!std::indirectly_copyable_storable<iterator, const_iterator>);
+  static_assert(std::indirectly_copyable<iterator, reverse_iterator>);
+  static_assert(std::indirectly_copyable_storable<iterator, reverse_iterator>);
+  static_assert(!std::indirectly_copyable<iterator, const_reverse_iterator>);
+  static_assert(!std::indirectly_copyable_storable<iterator, const_reverse_iterator>);
+  static_assert(std::indirectly_swappable<iterator, iterator>);
+
+  static_assert(std::contiguous_iterator<const_iterator>);
+  static_assert(std::random_access_iterator<const_reverse_iterator>);
+  static_assert(!std::contiguous_iterator<const_reverse_iterator>);
+  static_assert(!std::indirectly_writable<const_iterator, value_type>);
+  static_assert(std::sentinel_for<const_iterator, iterator>);
+  static_assert(std::sentinel_for<const_iterator, const_iterator>);
+  static_assert(!std::sentinel_for<const_iterator, reverse_iterator>);
+  static_assert(!std::sentinel_for<const_iterator, const_reverse_iterator>);
+  static_assert(std::sized_sentinel_for<const_iterator, iterator>);
+  static_assert(std::sized_sentinel_for<const_iterator, const_iterator>);
+  static_assert(!std::sized_sentinel_for<const_iterator, reverse_iterator>);
+  static_assert(!std::sized_sentinel_for<const_iterator, const_reverse_iterator>);
+  static_assert(std::indirectly_movable<const_iterator, iterator>);
+  static_assert(std::indirectly_movable_storable<const_iterator, iterator>);
+  static_assert(!std::indirectly_movable<const_iterator, const_iterator>);
+  static_assert(!std::indirectly_movable_storable<const_iterator, const_iterator>);
+  static_assert(std::indirectly_movable<const_iterator, reverse_iterator>);
+  static_assert(std::indirectly_movable_storable<const_iterator, reverse_iterator>);
+  static_assert(!std::indirectly_movable<const_iterator, const_reverse_iterator>);
+  static_assert(!std::indirectly_movable_storable<const_iterator, const_reverse_iterator>);
+  static_assert(std::indirectly_copyable<const_iterator, iterator>);
+  static_assert(std::indirectly_copyable_storable<const_iterator, iterator>);
+  static_assert(!std::indirectly_copyable<const_iterator, const_iterator>);
+  static_assert(!std::indirectly_copyable_storable<const_iterator, const_iterator>);
+  static_assert(std::indirectly_copyable<const_iterator, reverse_iterator>);
+  static_assert(std::indirectly_copyable_storable<const_iterator, reverse_iterator>);
+  static_assert(!std::indirectly_copyable<const_iterator, const_reverse_iterator>);
+  static_assert(!std::indirectly_copyable_storable<const_iterator, const_reverse_iterator>);
+  static_assert(!std::indirectly_swappable<const_iterator, const_iterator>);
+}
+
+struct NonTrivial {
+  int i = 0;
+};
+
+void tests() {
+  test<int, 0>();
+  test<int, 10>();
+  test<NonTrivial, 0>();
+  test<NonTrivial, 10>();
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/iterators.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/iterators.pass.cpp
new file mode 100644
index 00000000000000..22e87d064ac4f2
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/iterators.pass.cpp
@@ -0,0 +1,198 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// iterator       begin()        noexcept;
+// iterator       end()          noexcept;
+// const_iterator begin()  const noexcept;
+// const_iterator end()    const noexcept;
+// const_iterator cbegin() const noexcept;
+// const_iterator cend()   const noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+#include <iterator>
+
+#include "test_macros.h"
+
+struct A {
+  int first;
+  int second;
+};
+
+constexpr bool tests() {
+  {
+    using C = std::inplace_vector<int, 0>;
+    C c;
+    std::same_as<C::iterator> decltype(auto) i = c.begin();
+    C::iterator j                              = c.end();
+    assert(std::distance(i, j) == 0);
+    assert(i == j);
+  }
+  {
+    using C = std::inplace_vector<int, 10>;
+    C c;
+    std::same_as<C::iterator> decltype(auto) i = c.begin();
+    C::iterator j                              = c.end();
+    assert(std::distance(i, j) == 0);
+    assert(i == j);
+  }
+  {
+    using C = std::inplace_vector<int, 0>;
+    const C c;
+    std::same_as<C::const_iterator> decltype(auto) i = c.begin();
+    C::const_iterator j                              = c.end();
+    assert(std::distance(i, j) == 0);
+    assert(i == j);
+  }
+  {
+    using C = std::inplace_vector<int, 10>;
+    const C c;
+    std::same_as<C::const_iterator> decltype(auto) i = c.begin();
+    C::const_iterator j                              = c.end();
+    assert(std::distance(i, j) == 0);
+    assert(i == j);
+  }
+  {
+    using C = std::inplace_vector<int, 10>;
+    C c;
+    std::same_as<C::const_iterator> decltype(auto) i = c.cbegin();
+    C::const_iterator j                              = c.cend();
+    assert(std::distance(i, j) == 0);
+    assert(i == j);
+    assert(i == c.end());
+  }
+  {
+    using C       = std::inplace_vector<int, 10>;
+    const int t[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    C c(std::begin(t), std::end(t));
+    C::iterator i = c.begin();
+    assert(*i == 0);
+    ++i;
+    assert(*i == 1);
+    *i = 10;
+    assert(*i == 10);
+    assert(std::distance(c.begin(), c.end()) == 10);
+  }
+  {
+    using C = std::inplace_vector<int, 10>;
+    [[maybe_unused]] C::iterator i;
+    [[maybe_unused]] C::const_iterator j;
+    C::iterator i2{};
+    C::iterator i3 = i2;
+    C::const_iterator j2{};
+    C::const_iterator j3 = i2;
+    C::const_iterator j4 = j2;
+    assert(i2 == j2);
+    j4 = j3;
+    j2 = i2;
+    i2 = i3;
+  }
+  {
+    using C = std::inplace_vector<int, 10>;
+    C c;
+    C::iterator i = c.begin();
+    C::iterator j = c.end();
+    assert(std::distance(i, j) == 0);
+
+    assert(i == j);
+    assert(!(i != j));
+
+    assert(!(i < j));
+    assert((i <= j));
+
+    assert(!(i > j));
+    assert((i >= j));
+
+    std::same_as<std::strong_ordering> decltype(auto) r1 = i <=> j;
+    assert(r1 == std::strong_ordering::equal);
+  }
+  {
+    using C = std::inplace_vector<int, 10>;
+    const C c;
+    C::const_iterator i = c.begin();
+    C::const_iterator j = c.end();
+    assert(std::distance(i, j) == 0);
+
+    assert(i == j);
+    assert(!(i != j));
+
+    assert(!(i < j));
+    assert((i <= j));
+
+    assert(!(i > j));
+    assert((i >= j));
+
+    std::same_as<std::strong_ordering> decltype(auto) r1 = i <=> j;
+    assert(r1 == std::strong_ordering::equal);
+  }
+  {
+    using C       = std::inplace_vector<int, 10>;
+    const int t[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+    C c(std::begin(t), std::end(t));
+    C::iterator i = c.begin();
+    C::iterator j = i;
+    assert(*i == 0);
+    ++i;
+    assert(*i == 1);
+    *i = 10;
+    assert(*i == 10);
+    assert(j == c.begin());
+    assert(++j == i);
+    assert(std::distance(c.begin(), c.end()) == 10);
+  }
+  {
+    using C             = std::inplace_vector<A, 10>;
+    C c                 = {A{1, 2}};
+    C::iterator i       = c.begin();
+    i->first            = 3;
+    C::const_iterator j = i;
+    assert(j->first == 3);
+  }
+  {
+    using C = std::inplace_vector<int, 10>;
+    C::iterator ii1{}, ii2{};
+    C::iterator ii4 = ii1;
+    C::const_iterator cii{};
+    assert(ii1 == ii2);
+    assert(ii1 == ii4);
+
+    assert(!(ii1 != ii2));
+
+    assert((ii1 == cii));
+    assert((cii == ii1));
+    assert(!(ii1 != cii));
+    assert(!(cii != ii1));
+    assert(!(ii1 < cii));
+    assert(!(cii < ii1));
+    assert((ii1 <= cii));
+    assert((cii <= ii1));
+    assert(!(ii1 > cii));
+    assert(!(cii > ii1));
+    assert((ii1 >= cii));
+    assert((cii >= ii1));
+    assert(cii - ii1 == 0);
+    assert(ii1 - cii == 0);
+
+    std::same_as<std::strong_ordering> decltype(auto) r1 = ii1 <=> ii2;
+    assert(r1 == std::strong_ordering::equal);
+
+    std::same_as<std::strong_ordering> decltype(auto) r2 = cii <=> ii2;
+    assert(r2 == std::strong_ordering::equal);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/range_concept_conformance.compile.pass.cpp
new file mode 100644
index 00000000000000..292affbafc4d59
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/range_concept_conformance.compile.pass.cpp
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// inplace_vector
+
+#include <inplace_vector>
+
+#include <concepts>
+#include <ranges>
+#include "MoveOnly.h"
+
+template <typename T, std::size_t N>
+void test() {
+  using range = std::inplace_vector<T, N>;
+
+  static_assert(std::same_as<std::ranges::iterator_t<range>, typename range::iterator>);
+  static_assert(std::ranges::common_range<range>);
+  static_assert(std::ranges::random_access_range<range>);
+  static_assert(std::ranges::contiguous_range<range>);
+  static_assert(!std::ranges::view<range>);
+  static_assert(std::ranges::sized_range<range>);
+  static_assert(!std::ranges::borrowed_range<range>);
+  static_assert(std::ranges::viewable_range<range>);
+
+  static_assert(std::same_as<std::ranges::iterator_t<range const>, typename range::const_iterator>);
+  static_assert(std::ranges::common_range<range const>);
+  static_assert(std::ranges::random_access_range<range const>);
+  static_assert(std::ranges::contiguous_range<range const>);
+  static_assert(!std::ranges::view<range const>);
+  static_assert(std::ranges::sized_range<range const>);
+  static_assert(!std::ranges::borrowed_range<range const>);
+  static_assert(!std::ranges::viewable_range<range const>);
+}
+
+void tests() {
+  test<int, 0>();
+  test<int, 10>();
+  test<MoveOnly, 0>();
+  test<MoveOnly, 10>();
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp
new file mode 100644
index 00000000000000..5baeac5bf2549a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp
@@ -0,0 +1,86 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// reverse_iterator       rbegin();
+// reverse_iterator       rend();
+// const_reverse_iterator rbegin()  const;
+// const_reverse_iterator rend()    const;
+// const_reverse_iterator crbegin() const;
+// const_reverse_iterator crend()   const;
+
+#include <vector>
+#include <cassert>
+#include <iterator>
+
+#include "min_allocator.h"
+
+template <class Vector>
+TEST_CONSTEXPR_CXX20 void check_vector_reverse_iterators() {
+  {
+    Vector vec;
+    assert(vec.rbegin() == vec.rend());
+    assert(vec.crbegin() == vec.crend());
+  }
+  {
+    const int n = 10;
+    Vector vec;
+    const Vector& cvec = vec;
+    vec.reserve(n);
+    for (int i = 0; i < n; ++i)
+      vec.push_back(i);
+    {
+      int iterations = 0;
+
+      for (typename Vector::const_reverse_iterator it = vec.crbegin(); it != vec.crend(); ++it) {
+        assert(*it == (n - iterations - 1));
+        ++iterations;
+      }
+      assert(iterations == n);
+    }
+    {
+      assert(cvec.rbegin() == vec.crbegin());
+      assert(cvec.rend() == vec.crend());
+    }
+    {
+      int iterations = 0;
+
+      for (typename Vector::reverse_iterator it = vec.rbegin(); it != vec.rend(); ++it) {
+        assert(*it == (n - iterations - 1));
+        *it = 40;
+        assert(*it == 40);
+        ++iterations;
+      }
+      assert(iterations == n);
+    }
+
+    assert(std::distance(vec.rbegin(), vec.rend()) == n);
+    assert(std::distance(cvec.rbegin(), cvec.rend()) == n);
+    assert(std::distance(vec.crbegin(), vec.crend()) == n);
+    assert(std::distance(cvec.crbegin(), cvec.crend()) == n);
+  }
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  check_vector_reverse_iterators<std::vector<int> >();
+#if TEST_STD_VER >= 11
+  check_vector_reverse_iterators<std::vector<int, min_allocator<int> > >();
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER > 17
+  static_assert(test());
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/types.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/types.pass.cpp
new file mode 100644
index 00000000000000..7a6ce7b7cc1dc7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/types.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// Test nested types:
+
+// template <class T, size_t N>
+// class inplace_vector
+// {
+// public:
+//     using value_type             = T;
+//     using pointer                = T*;
+//     using const_pointer          = const T*;
+//     using reference              = value_type&;
+//     using const_reference        = const value_type&;
+//     using size_type              = size_t;
+//     using difference_type        = ptrdiff_t;
+//     using iterator               = implementation-defined;
+//     using const_iterator         = implementation-defined;
+//     using reverse_iterator       = std::reverse_iterator<iterator>;
+//     using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+// };
+
+#include <inplace_vector>
+#include <iterator>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "../../Copyable.h"
+
+template <class T, size_t N>
+void test() {
+  using C = std::inplace_vector<T, N>;
+  static_assert(std::is_same_v<typename C::value_type, T>);
+  static_assert(std::is_same_v<typename C::size_type, std::size_t>);
+  static_assert(std::is_same_v<typename C::difference_type, std::ptrdiff_t>);
+  static_assert(std::is_same_v<typename C::reference, T&>);
+  static_assert(std::is_same_v<typename C::const_reference, const T&>);
+  static_assert(std::is_same_v<typename C::pointer, T*>);
+  static_assert(std::is_same_v<typename C::const_pointer, const T*>);
+  static_assert(std::is_same_v< typename std::iterator_traits<typename C::iterator>::iterator_category,
+                                std::random_access_iterator_tag>);
+  static_assert(std::is_same_v< typename std::iterator_traits<typename C::const_iterator>::iterator_category,
+                                std::random_access_iterator_tag>);
+  static_assert(std::contiguous_iterator<typename C::iterator>);
+  static_assert(std::contiguous_iterator<typename C::const_iterator>);
+  static_assert(std::is_same_v<typename C::reverse_iterator, std::reverse_iterator<typename C::iterator>>);
+  static_assert(std::is_same_v<typename C::const_reverse_iterator, std::reverse_iterator<typename C::const_iterator>>);
+}
+
+template <class T>
+void test() {
+  test<T, 0>();
+  test<T, 1>();
+  test<T, 10>();
+  test<T, 100>();
+}
+
+int main(int, char**) {
+  test<int>();
+  test<int*>();
+  test<Copyable>();
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.erasure/erase.pass.cpp
new file mode 100644
index 00000000000000..175d56c1d09de4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.erasure/erase.pass.cpp
@@ -0,0 +1,83 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <vector>
+
+// template <class T, class Allocator, class U>
+//   typename vector<T, Allocator>::size_type
+//   erase(vector<T, Allocator>& c, const U& value);
+
+#include <vector>
+#include <optional>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class U>
+TEST_CONSTEXPR_CXX20 void test0(S s, U val, S expected, std::size_t expected_erased_count) {
+  ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase(s, val)));
+  assert(expected_erased_count == std::erase(s, val));
+  assert(s == expected);
+}
+
+template <class S>
+TEST_CONSTEXPR_CXX20 void test() {
+  test0(S(), 1, S(), 0);
+
+  test0(S({1}), 1, S(), 1);
+  test0(S({1}), 2, S({1}), 0);
+
+  test0(S({1, 2}), 1, S({2}), 1);
+  test0(S({1, 2}), 2, S({1}), 1);
+  test0(S({1, 2}), 3, S({1, 2}), 0);
+  test0(S({1, 1}), 1, S(), 2);
+  test0(S({1, 1}), 3, S({1, 1}), 0);
+
+  test0(S({1, 2, 3}), 1, S({2, 3}), 1);
+  test0(S({1, 2, 3}), 2, S({1, 3}), 1);
+  test0(S({1, 2, 3}), 3, S({1, 2}), 1);
+  test0(S({1, 2, 3}), 4, S({1, 2, 3}), 0);
+
+  test0(S({1, 1, 1}), 1, S(), 3);
+  test0(S({1, 1, 1}), 2, S({1, 1, 1}), 0);
+  test0(S({1, 1, 2}), 1, S({2}), 2);
+  test0(S({1, 1, 2}), 2, S({1, 1}), 1);
+  test0(S({1, 1, 2}), 3, S({1, 1, 2}), 0);
+  test0(S({1, 2, 2}), 1, S({2, 2}), 1);
+  test0(S({1, 2, 2}), 2, S({1}), 2);
+  test0(S({1, 2, 2}), 3, S({1, 2, 2}), 0);
+
+  //  Test cross-type erasure
+  using opt = std::optional<typename S::value_type>;
+  test0(S({1, 2, 1}), opt(), S({1, 2, 1}), 0);
+  test0(S({1, 2, 1}), opt(1), S({2}), 2);
+  test0(S({1, 2, 1}), opt(2), S({1, 1}), 1);
+  test0(S({1, 2, 1}), opt(3), S({1, 2, 1}), 0);
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  test<std::vector<int>>();
+  test<std::vector<int, min_allocator<int>>>();
+  test<std::vector<int, test_allocator<int>>>();
+  test<std::vector<int, safe_allocator<int>>>();
+
+  test<std::vector<long>>();
+  test<std::vector<double>>();
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.erasure/erase_if.pass.cpp
new file mode 100644
index 00000000000000..189986fe3fd4dc
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.erasure/erase_if.pass.cpp
@@ -0,0 +1,85 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <vector>
+
+// template <class T, class Allocator, class Predicate>
+//   typename vector<T, Allocator>::size_type
+//   erase_if(vector<T, Allocator>& c, Predicate pred);
+
+#include <vector>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <class S, class Pred>
+TEST_CONSTEXPR_CXX20 void test0(S s, Pred p, S expected, std::size_t expected_erased_count) {
+  ASSERT_SAME_TYPE(typename S::size_type, decltype(std::erase_if(s, p)));
+  assert(expected_erased_count == std::erase_if(s, p));
+  assert(s == expected);
+}
+
+template <typename S>
+TEST_CONSTEXPR_CXX20 void test() {
+  auto is1   = [](auto v) { return v == 1; };
+  auto is2   = [](auto v) { return v == 2; };
+  auto is3   = [](auto v) { return v == 3; };
+  auto is4   = [](auto v) { return v == 4; };
+  auto True  = [](auto) { return true; };
+  auto False = [](auto) { return false; };
+
+  test0(S(), is1, S(), 0);
+
+  test0(S({1}), is1, S(), 1);
+  test0(S({1}), is2, S({1}), 0);
+
+  test0(S({1, 2}), is1, S({2}), 1);
+  test0(S({1, 2}), is2, S({1}), 1);
+  test0(S({1, 2}), is3, S({1, 2}), 0);
+  test0(S({1, 1}), is1, S(), 2);
+  test0(S({1, 1}), is3, S({1, 1}), 0);
+
+  test0(S({1, 2, 3}), is1, S({2, 3}), 1);
+  test0(S({1, 2, 3}), is2, S({1, 3}), 1);
+  test0(S({1, 2, 3}), is3, S({1, 2}), 1);
+  test0(S({1, 2, 3}), is4, S({1, 2, 3}), 0);
+
+  test0(S({1, 1, 1}), is1, S(), 3);
+  test0(S({1, 1, 1}), is2, S({1, 1, 1}), 0);
+  test0(S({1, 1, 2}), is1, S({2}), 2);
+  test0(S({1, 1, 2}), is2, S({1, 1}), 1);
+  test0(S({1, 1, 2}), is3, S({1, 1, 2}), 0);
+  test0(S({1, 2, 2}), is1, S({2, 2}), 1);
+  test0(S({1, 2, 2}), is2, S({1}), 2);
+  test0(S({1, 2, 2}), is3, S({1, 2, 2}), 0);
+
+  test0(S({1, 2, 3}), True, S(), 3);
+  test0(S({1, 2, 3}), False, S({1, 2, 3}), 0);
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  test<std::vector<int>>();
+  test<std::vector<int, min_allocator<int>>>();
+  test<std::vector<int, test_allocator<int>>>();
+  test<std::vector<int, safe_allocator<int>>>();
+
+  test<std::vector<long>>();
+  test<std::vector<double>>();
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/append_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/append_range.pass.cpp
new file mode 100644
index 00000000000000..6eb0ddd1c1f3a7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/append_range.pass.cpp
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// template<container-compatible-range<T> R>
+//   constexpr void append_range(R&& rg); // C++23
+
+#include <vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "test_macros.h"
+
+// Tested cases:
+// - different kinds of insertions (appending an {empty/one-element/mid-sized/long range} into an
+//   {empty/one-element/full} container);
+// - appending move-only elements;
+// - an exception is thrown when copying the elements or when allocating new elements.
+constexpr bool test() {
+  static_assert(test_constraints_append_range<std::vector, int, double>());
+
+  for_all_iterators_and_allocators<int, const int*>([]<class Iter, class Sent, class Alloc>() {
+    test_sequence_append_range<std::vector<int, Alloc>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+  });
+  test_sequence_append_range_move_only<std::vector>();
+
+  {   // Vector may or may not need to reallocate because of the insertion -- make sure to test both cases.
+    { // Ensure reallocation happens.
+      int in[]           = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+      std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+      v.shrink_to_fit();
+      assert(v.capacity() < v.size() + std::ranges::size(in));
+
+      v.append_range(in);
+      assert(std::ranges::equal(v, std::array{1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10}));
+    }
+
+    { // Ensure no reallocation happens.
+      int in[]           = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+      std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+      v.reserve(v.size() + std::ranges::size(in));
+      assert(v.capacity() >= v.size() + std::ranges::size(in));
+
+      v.append_range(in);
+      assert(std::ranges::equal(v, std::array{1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10}));
+    }
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  test_append_range_exception_safety_throwing_copy<std::vector>();
+  test_append_range_exception_safety_throwing_allocator<std::vector, int>();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assert.push_back.invalidation.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assert.push_back.invalidation.pass.cpp
new file mode 100644
index 00000000000000..193c00891da7f0
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assert.push_back.invalidation.pass.cpp
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void push_back(const value_type& x);
+//
+// If no reallocation happens, then references, pointers, and iterators before
+// the insertion point remain valid but those at or after the insertion point,
+// including the past-the-end iterator, are invalidated.
+
+// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators-in-vector
+// UNSUPPORTED: c++03
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+  std::vector<int> vec;
+  vec.reserve(4);
+  std::size_t old_capacity = vec.capacity();
+  assert(old_capacity >= 4);
+
+  vec.push_back(0);
+  vec.push_back(1);
+  vec.push_back(2);
+  auto it = vec.begin();
+  vec.push_back(3);
+  assert(vec.capacity() == old_capacity);
+
+  // The capacity did not change, so the iterator remains valid and can reach the new element.
+  assert(*it == 0);
+  assert(*(it + 1) == 1);
+  assert(*(it + 2) == 2);
+  assert(*(it + 3) == 3);
+
+  while (vec.capacity() == old_capacity) {
+    vec.push_back(42);
+  }
+  TEST_LIBCPP_ASSERT_FAILURE(
+      *(it + old_capacity), "__bounded_iter::operator*: Attempt to dereference an iterator at the end");
+  // Unfortunately, the bounded iterator does not detect that it's been invalidated and will still allow attempts to
+  // dereference elements 0 to 3 (even though they refer to memory that's been reallocated).
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assign_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assign_range.pass.cpp
new file mode 100644
index 00000000000000..8fabbbab3d3685
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/assign_range.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// template<container-compatible-range<T> R>
+//   constexpr void assign_range(R&& rg); // C++23
+
+#include <vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "test_macros.h"
+
+// Tested cases:
+// - different kinds of assignments (assigning an {empty/one-element/mid-sized/long range} to an
+//   {empty/one-element/full} container);
+// - assigning move-only elements;
+// - an exception is thrown when copying the elements or when allocating new elements.
+constexpr bool test() {
+  static_assert(test_constraints_assign_range<std::vector, int, double>());
+
+  for_all_iterators_and_allocators<int, const int*>([]<class Iter, class Sent, class Alloc>() {
+    test_sequence_assign_range<std::vector<int, Alloc>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+  });
+  test_sequence_assign_range_move_only<std::vector>();
+
+  {   // Vector may or may not need to reallocate because of the assignment -- make sure to test both cases.
+    { // Ensure reallocation happens.
+      int in[]           = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+      std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+      v.shrink_to_fit();
+      assert(v.capacity() < v.size() + std::ranges::size(in));
+
+      v.assign_range(in);
+      assert(std::ranges::equal(v, in));
+    }
+
+    { // Ensure no reallocation happens -- the input range is shorter than the vector.
+      int in[]           = {-1, -2, -3, -4, -5};
+      std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+
+      v.assign_range(in);
+      assert(std::ranges::equal(v, in));
+    }
+
+    { // Ensure no reallocation happens -- the input range is longer than the vector but within capacity.
+      int in[]           = {-1, -2, -3, -4, -5, -6, -7, -8};
+      std::vector<int> v = {1, 2, 3, 4, 5};
+      v.reserve(std::ranges::size(in));
+      assert(v.capacity() >= std::ranges::size(in));
+
+      v.assign_range(in);
+      assert(std::ranges::equal(v, in));
+    }
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  test_assign_range_exception_safety_throwing_copy<std::vector>();
+  test_assign_range_exception_safety_throwing_allocator<std::vector, int>();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp
new file mode 100644
index 00000000000000..45ecff6962b2bf
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void clear() noexcept;
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    int a[] = {1, 2, 3};
+    std::vector<int> c(a, a + 3);
+    ASSERT_NOEXCEPT(c.clear());
+    c.clear();
+    assert(c.empty());
+  }
+#if TEST_STD_VER >= 11
+  {
+    int a[] = {1, 2, 3};
+    std::vector<int, min_allocator<int>> c(a, a + 3);
+    ASSERT_NOEXCEPT(c.clear());
+    c.clear();
+    assert(c.empty());
+  }
+  {
+    int a[] = {1, 2, 3};
+    std::vector<int, safe_allocator<int>> c(a, a + 3);
+    ASSERT_NOEXCEPT(c.clear());
+    c.clear();
+    assert(c.empty());
+  }
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.pass.cpp
new file mode 100644
index 00000000000000..6cbf1441b46470
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.pass.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Ensure that all the elements in the vector are destroyed, especially when reallocating the internal buffer
+
+// UNSUPPORTED: c++03
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <vector>
+
+#include "test_macros.h"
+
+struct DestroyTracker {
+  TEST_CONSTEXPR_CXX20 DestroyTracker(std::vector<bool>& vec) : vec_(&vec), index_(vec.size()) { vec.push_back(false); }
+
+  TEST_CONSTEXPR_CXX20 DestroyTracker(const DestroyTracker& other) : vec_(other.vec_), index_(vec_->size()) {
+    vec_->push_back(false);
+  }
+
+  TEST_CONSTEXPR_CXX20 DestroyTracker& operator=(const DestroyTracker&) { return *this; }
+  TEST_CONSTEXPR_CXX20 ~DestroyTracker() { (*vec_)[index_] = true; }
+
+  std::vector<bool>* vec_;
+  size_t index_;
+};
+
+template <class Operation>
+TEST_CONSTEXPR_CXX20 void test(Operation operation) {
+  std::vector<bool> all_destroyed;
+
+  {
+    std::vector<DestroyTracker> v;
+    for (size_t i = 0; i != 100; ++i)
+      operation(v, all_destroyed);
+  }
+
+  assert(std::all_of(all_destroyed.begin(), all_destroyed.end(), [](bool b) { return b; }));
+}
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  test([](std::vector<DestroyTracker>& vec, std::vector<bool>& tracker) { vec.emplace_back(tracker); });
+  test([](std::vector<DestroyTracker>& vec, std::vector<bool>& tracker) { vec.push_back(tracker); });
+  test([](std::vector<DestroyTracker>& vec, std::vector<bool>& tracker) { vec.emplace(vec.begin(), tracker); });
+  test([](std::vector<DestroyTracker>& vec, std::vector<bool>& tracker) { vec.insert(vec.begin(), tracker); });
+  test([](std::vector<DestroyTracker>& vec, std::vector<bool>& tracker) { vec.resize(vec.size() + 1, tracker); });
+#if TEST_STD_VER >= 23
+  test([](std::vector<DestroyTracker>& vec, std::vector<bool>& tracker) {
+    vec.insert_range(vec.begin(), std::array<DestroyTracker, 2>{tracker, tracker});
+  });
+
+  test([](std::vector<DestroyTracker>& vec, std::vector<bool>& tracker) {
+    vec.append_range(std::array<DestroyTracker, 2>{tracker, tracker});
+  });
+#endif
+
+  return true;
+}
+
+int main() {
+  test();
+#if TEST_STD_VER >= 20
+  static_assert(test());
+#endif
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..43e553e71e7414
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.addressof.compile.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// template <class... Args> iterator emplace(const_iterator pos, Args&&... args);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::vector<operator_hijacker> v;
+  v.emplace(v.end());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.pass.cpp
new file mode 100644
index 00000000000000..31389181b7f820
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace.pass.cpp
@@ -0,0 +1,156 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// template <class... Args> iterator emplace(const_iterator pos, Args&&... args);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+class A {
+  int i_;
+  double d_;
+
+  A(const A&);
+  A& operator=(const A&);
+
+public:
+  TEST_CONSTEXPR_CXX14 A(int i, double d) : i_(i), d_(d) {}
+
+  TEST_CONSTEXPR_CXX14 A(A&& a) : i_(a.i_), d_(a.d_) {
+    a.i_ = 0;
+    a.d_ = 0;
+  }
+
+  TEST_CONSTEXPR_CXX14 A& operator=(A&& a) {
+    i_   = a.i_;
+    d_   = a.d_;
+    a.i_ = 0;
+    a.d_ = 0;
+    return *this;
+  }
+
+  TEST_CONSTEXPR_CXX14 int geti() const { return i_; }
+  TEST_CONSTEXPR_CXX14 double getd() const { return d_; }
+};
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<A> c;
+    std::vector<A>::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+    assert(i == c.begin());
+    assert(c.size() == 1);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    i = c.emplace(c.cend(), 3, 4.5);
+    assert(i == c.end() - 1);
+    assert(c.size() == 2);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+    i = c.emplace(c.cbegin() + 1, 4, 6.5);
+    assert(i == c.begin() + 1);
+    assert(c.size() == 3);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c[1].geti() == 4);
+    assert(c[1].getd() == 6.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+  }
+  {
+    std::vector<A, limited_allocator<A, 7> > c;
+    std::vector<A, limited_allocator<A, 7> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+    assert(i == c.begin());
+    assert(c.size() == 1);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    i = c.emplace(c.cend(), 3, 4.5);
+    assert(i == c.end() - 1);
+    assert(c.size() == 2);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+    i = c.emplace(c.cbegin() + 1, 4, 6.5);
+    assert(i == c.begin() + 1);
+    assert(c.size() == 3);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c[1].geti() == 4);
+    assert(c[1].getd() == 6.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+  }
+  {
+    std::vector<A, min_allocator<A> > c;
+    std::vector<A, min_allocator<A> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+    assert(i == c.begin());
+    assert(c.size() == 1);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    i = c.emplace(c.cend(), 3, 4.5);
+    assert(i == c.end() - 1);
+    assert(c.size() == 2);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+    i = c.emplace(c.cbegin() + 1, 4, 6.5);
+    assert(i == c.begin() + 1);
+    assert(c.size() == 3);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c[1].geti() == 4);
+    assert(c[1].getd() == 6.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+  }
+  {
+    std::vector<A, safe_allocator<A> > c;
+    std::vector<A, safe_allocator<A> >::iterator i = c.emplace(c.cbegin(), 2, 3.5);
+    assert(i == c.begin());
+    assert(c.size() == 1);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    i = c.emplace(c.cend(), 3, 4.5);
+    assert(i == c.end() - 1);
+    assert(c.size() == 2);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+    i = c.emplace(c.cbegin() + 1, 4, 6.5);
+    assert(i == c.begin() + 1);
+    assert(c.size() == 3);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c[1].geti() == 4);
+    assert(c[1].getd() == 6.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_back.pass.cpp
new file mode 100644
index 00000000000000..f2f4a8d22b9057
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_back.pass.cpp
@@ -0,0 +1,175 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// template <class... Args> reference emplace_back(Args&&... args);
+// return type is 'reference' in C++17; 'void' before
+
+#include <vector>
+#include <cassert>
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+#include "test_allocator.h"
+
+class A {
+  int i_;
+  double d_;
+
+public:
+  A(const A&)            = delete;
+  A& operator=(const A&) = delete;
+
+  TEST_CONSTEXPR_CXX14 A(int i, double d) : i_(i), d_(d) {}
+
+  TEST_CONSTEXPR_CXX14 A(A&& a) : i_(a.i_), d_(a.d_) {
+    a.i_ = 0;
+    a.d_ = 0;
+  }
+
+  TEST_CONSTEXPR_CXX14 A& operator=(A&& a) {
+    i_   = a.i_;
+    d_   = a.d_;
+    a.i_ = 0;
+    a.d_ = 0;
+    return *this;
+  }
+
+  TEST_CONSTEXPR_CXX14 int geti() const { return i_; }
+  TEST_CONSTEXPR_CXX14 double getd() const { return d_; }
+};
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<A> c;
+#if TEST_STD_VER > 14
+    A& r1 = c.emplace_back(2, 3.5);
+    assert(c.size() == 1);
+    assert(&r1 == &c.back());
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    A& r2 = c.emplace_back(3, 4.5);
+    assert(c.size() == 2);
+    assert(&r2 == &c.back());
+#else
+    c.emplace_back(2, 3.5);
+    assert(c.size() == 1);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    c.emplace_back(3, 4.5);
+    assert(c.size() == 2);
+#endif
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+  }
+  {
+    std::vector<A, limited_allocator<A, 4> > c;
+#if TEST_STD_VER > 14
+    A& r1 = c.emplace_back(2, 3.5);
+    assert(c.size() == 1);
+    assert(&r1 == &c.back());
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    A& r2 = c.emplace_back(3, 4.5);
+    assert(c.size() == 2);
+    assert(&r2 == &c.back());
+#else
+    c.emplace_back(2, 3.5);
+    assert(c.size() == 1);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    c.emplace_back(3, 4.5);
+    assert(c.size() == 2);
+#endif
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+  }
+  {
+    std::vector<A, min_allocator<A> > c;
+#if TEST_STD_VER > 14
+    A& r1 = c.emplace_back(2, 3.5);
+    assert(c.size() == 1);
+    assert(&r1 == &c.back());
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    A& r2 = c.emplace_back(3, 4.5);
+    assert(c.size() == 2);
+    assert(&r2 == &c.back());
+#else
+    c.emplace_back(2, 3.5);
+    assert(c.size() == 1);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    c.emplace_back(3, 4.5);
+    assert(c.size() == 2);
+#endif
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+  }
+  {
+    std::vector<A, safe_allocator<A> > c;
+#if TEST_STD_VER > 14
+    A& r1 = c.emplace_back(2, 3.5);
+    assert(c.size() == 1);
+    assert(&r1 == &c.back());
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    A& r2 = c.emplace_back(3, 4.5);
+    assert(c.size() == 2);
+    assert(&r2 == &c.back());
+#else
+    c.emplace_back(2, 3.5);
+    assert(c.size() == 1);
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    c.emplace_back(3, 4.5);
+    assert(c.size() == 2);
+#endif
+    assert(c.front().geti() == 2);
+    assert(c.front().getd() == 3.5);
+    assert(c.back().geti() == 3);
+    assert(c.back().getd() == 4.5);
+  }
+  {
+    std::vector<Tag_X, TaggingAllocator<Tag_X> > c;
+    c.emplace_back();
+    assert(c.size() == 1);
+    c.emplace_back(1, 2, 3);
+    assert(c.size() == 2);
+  }
+
+  { // LWG 2164
+    int arr[] = {0, 1, 2, 3, 4};
+    int sz    = 5;
+    std::vector<int> c(arr, arr + sz);
+    while (c.size() < c.capacity())
+      c.push_back(sz++);
+    c.emplace_back(c.front());
+    assert(c.back() == 0);
+    for (int i = 0; i < sz; ++i)
+      assert(c[i] == i);
+  }
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_extra.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_extra.pass.cpp
new file mode 100644
index 00000000000000..0ec7155cb4e5b4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/emplace_extra.pass.cpp
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <vector>
+
+// template <class... Args> iterator emplace(const_iterator pos, Args&&... args);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<int> v;
+    v.reserve(3);
+    v = {1, 2, 3};
+    v.emplace(v.begin(), v.back());
+    assert(v[0] == 3);
+  }
+  {
+    std::vector<int> v;
+    v.reserve(4);
+    v = {1, 2, 3};
+    v.emplace(v.begin(), v.back());
+    assert(v[0] == 3);
+  }
+  {
+    std::vector<int, min_allocator<int>> v;
+    v.reserve(3);
+    v = {1, 2, 3};
+    v.emplace(v.begin(), v.back());
+    assert(v[0] == 3);
+  }
+  {
+    std::vector<int, min_allocator<int>> v;
+    v.reserve(4);
+    v = {1, 2, 3};
+    v.emplace(v.begin(), v.back());
+    assert(v[0] == 3);
+  }
+  {
+    std::vector<int, safe_allocator<int>> v;
+    v.reserve(3);
+    v = {1, 2, 3};
+    v.emplace(v.begin(), v.back());
+    assert(v[0] == 3);
+  }
+  {
+    std::vector<int, safe_allocator<int>> v;
+    v.reserve(4);
+    v = {1, 2, 3};
+    v.emplace(v.begin(), v.back());
+    assert(v[0] == 3);
+  }
+  {
+    std::vector<int> v;
+    v.reserve(8);
+    std::size_t old_capacity = v.capacity();
+    assert(old_capacity >= 8);
+
+    v.resize(4); // keep the existing capacity
+    assert(v.capacity() == old_capacity);
+
+    v.emplace(v.cend(), 42);
+    assert(v.size() == 5);
+    assert(v.capacity() == old_capacity);
+    assert(v[4] == 42);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..0fce3498fec7e8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.addressof.compile.pass.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator position);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::vector<operator_hijacker> v;
+  v.erase(v.end());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.pass.cpp
new file mode 100644
index 00000000000000..afaecc7ad59cb4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter.pass.cpp
@@ -0,0 +1,156 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator position);
+
+#include <vector>
+#include <iterator>
+#include <cassert>
+
+#include "min_allocator.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct Throws {
+  Throws() : v_(0) {}
+  Throws(int v) : v_(v) {}
+  Throws(const Throws& rhs) : v_(rhs.v_) {
+    if (sThrows)
+      throw 1;
+  }
+  Throws(Throws&& rhs) : v_(rhs.v_) {
+    if (sThrows)
+      throw 1;
+  }
+  Throws& operator=(const Throws& rhs) {
+    v_ = rhs.v_;
+    return *this;
+  }
+  Throws& operator=(Throws&& rhs) {
+    v_ = rhs.v_;
+    return *this;
+  }
+  int v_;
+  static bool sThrows;
+};
+
+bool Throws::sThrows = false;
+#endif
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    int a1[] = {1, 2, 3, 4, 5};
+    std::vector<int> l1(a1, a1 + 5);
+    l1.erase(l1.begin());
+    assert(l1 == std::vector<int>(a1 + 1, a1 + 5));
+  }
+  {
+    int a1[] = {1, 2, 3, 4, 5};
+    int e1[] = {1, 3, 4, 5};
+    std::vector<int> l1(a1, a1 + 5);
+    l1.erase(l1.begin() + 1);
+    assert(l1 == std::vector<int>(e1, e1 + 4));
+  }
+  {
+    int a1[] = {1, 2, 3};
+    std::vector<int> l1(a1, a1 + 3);
+    std::vector<int>::const_iterator i = l1.begin();
+    ++i;
+    std::vector<int>::iterator j = l1.erase(i);
+    assert(l1.size() == 2);
+    assert(std::distance(l1.begin(), l1.end()) == 2);
+    assert(*j == 3);
+    assert(*l1.begin() == 1);
+    assert(*std::next(l1.begin()) == 3);
+    j = l1.erase(j);
+    assert(j == l1.end());
+    assert(l1.size() == 1);
+    assert(std::distance(l1.begin(), l1.end()) == 1);
+    assert(*l1.begin() == 1);
+    j = l1.erase(l1.begin());
+    assert(j == l1.end());
+    assert(l1.size() == 0);
+    assert(std::distance(l1.begin(), l1.end()) == 0);
+  }
+
+  // Make sure vector::erase works with move-only types
+  // When non-trivial
+  {
+    std::vector<MoveOnly> v;
+    v.emplace_back(1);
+    v.emplace_back(2);
+    v.emplace_back(3);
+    v.erase(v.begin());
+    assert(v.size() == 2);
+    assert(v[0] == MoveOnly(2));
+    assert(v[1] == MoveOnly(3));
+  }
+  // When trivial
+  {
+    std::vector<TrivialMoveOnly> v;
+    v.emplace_back(1);
+    v.emplace_back(2);
+    v.emplace_back(3);
+    v.erase(v.begin());
+    assert(v.size() == 2);
+    assert(v[0] == TrivialMoveOnly(2));
+    assert(v[1] == TrivialMoveOnly(3));
+  }
+
+#if TEST_STD_VER >= 11
+  {
+    int a1[] = {1, 2, 3};
+    std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+    std::vector<int, min_allocator<int>>::const_iterator i = l1.begin();
+    ++i;
+    std::vector<int, min_allocator<int>>::iterator j = l1.erase(i);
+    assert(l1.size() == 2);
+    assert(std::distance(l1.begin(), l1.end()) == 2);
+    assert(*j == 3);
+    assert(*l1.begin() == 1);
+    assert(*std::next(l1.begin()) == 3);
+    j = l1.erase(j);
+    assert(j == l1.end());
+    assert(l1.size() == 1);
+    assert(std::distance(l1.begin(), l1.end()) == 1);
+    assert(*l1.begin() == 1);
+    j = l1.erase(l1.begin());
+    assert(j == l1.end());
+    assert(l1.size() == 0);
+    assert(std::distance(l1.begin(), l1.end()) == 0);
+  }
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  // Test for LWG2853:
+  // Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T.
+  {
+    Throws arr[] = {1, 2, 3};
+    std::vector<Throws> v(arr, arr + 3);
+    Throws::sThrows = true;
+    v.erase(v.begin());
+    v.erase(--v.end());
+    v.erase(v.begin());
+    assert(v.size() == 0);
+  }
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..bc90fa783e98f5
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.addressof.compile.pass.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator position);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::vector<operator_hijacker> v;
+  v.erase(v.begin(), v.end());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp
new file mode 100644
index 00000000000000..1e57dd91508a92
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp
@@ -0,0 +1,173 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator erase(const_iterator first, const_iterator last);
+
+#include <vector>
+#include <iterator>
+#include <cassert>
+
+#include "min_allocator.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct Throws {
+  Throws() : v_(0) {}
+  Throws(int v) : v_(v) {}
+  Throws(const Throws& rhs) : v_(rhs.v_) {
+    if (sThrows)
+      throw 1;
+  }
+  Throws(Throws&& rhs) : v_(rhs.v_) {
+    if (sThrows)
+      throw 1;
+  }
+  Throws& operator=(const Throws& rhs) {
+    v_ = rhs.v_;
+    return *this;
+  }
+  Throws& operator=(Throws&& rhs) {
+    v_ = rhs.v_;
+    return *this;
+  }
+  int v_;
+  static bool sThrows;
+};
+
+bool Throws::sThrows = false;
+#endif
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  int a1[] = {1, 2, 3};
+  {
+    std::vector<int> l1(a1, a1 + 3);
+    std::vector<int>::iterator i = l1.erase(l1.cbegin(), l1.cbegin());
+    assert(l1.size() == 3);
+    assert(std::distance(l1.cbegin(), l1.cend()) == 3);
+    assert(i == l1.begin());
+  }
+  {
+    std::vector<int> l1(a1, a1 + 3);
+    std::vector<int>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin()));
+    assert(l1.size() == 2);
+    assert(std::distance(l1.cbegin(), l1.cend()) == 2);
+    assert(i == l1.begin());
+    assert(l1 == std::vector<int>(a1 + 1, a1 + 3));
+  }
+  {
+    std::vector<int> l1(a1, a1 + 3);
+    std::vector<int>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 2));
+    assert(l1.size() == 1);
+    assert(std::distance(l1.cbegin(), l1.cend()) == 1);
+    assert(i == l1.begin());
+    assert(l1 == std::vector<int>(a1 + 2, a1 + 3));
+  }
+  {
+    std::vector<int> l1(a1, a1 + 3);
+    std::vector<int>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 3));
+    assert(l1.size() == 0);
+    assert(std::distance(l1.cbegin(), l1.cend()) == 0);
+    assert(i == l1.begin());
+  }
+  {
+    std::vector<std::vector<int> > outer(2, std::vector<int>(1));
+    outer.erase(outer.begin(), outer.begin());
+    assert(outer.size() == 2);
+    assert(outer[0].size() == 1);
+    assert(outer[1].size() == 1);
+  }
+  // Make sure vector::erase works with move-only types
+  {// When non-trivial
+   {std::vector<MoveOnly> v;
+  v.emplace_back(1);
+  v.emplace_back(2);
+  v.emplace_back(3);
+  v.erase(v.begin(), v.begin() + 2);
+  assert(v.size() == 1);
+  assert(v[0] == MoveOnly(3));
+}
+// When trivial
+{
+  std::vector<TrivialMoveOnly> v;
+  v.emplace_back(1);
+  v.emplace_back(2);
+  v.emplace_back(3);
+  v.erase(v.begin(), v.begin() + 2);
+  assert(v.size() == 1);
+  assert(v[0] == TrivialMoveOnly(3));
+}
+}
+#if TEST_STD_VER >= 11
+{
+  std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+  std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), l1.cbegin());
+  assert(l1.size() == 3);
+  assert(std::distance(l1.cbegin(), l1.cend()) == 3);
+  assert(i == l1.begin());
+}
+{
+  std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+  std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin()));
+  assert(l1.size() == 2);
+  assert(std::distance(l1.cbegin(), l1.cend()) == 2);
+  assert(i == l1.begin());
+  assert((l1 == std::vector<int, min_allocator<int>>(a1 + 1, a1 + 3)));
+}
+{
+  std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+  std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 2));
+  assert(l1.size() == 1);
+  assert(std::distance(l1.cbegin(), l1.cend()) == 1);
+  assert(i == l1.begin());
+  assert((l1 == std::vector<int, min_allocator<int>>(a1 + 2, a1 + 3)));
+}
+{
+  std::vector<int, min_allocator<int>> l1(a1, a1 + 3);
+  std::vector<int, min_allocator<int>>::iterator i = l1.erase(l1.cbegin(), std::next(l1.cbegin(), 3));
+  assert(l1.size() == 0);
+  assert(std::distance(l1.cbegin(), l1.cend()) == 0);
+  assert(i == l1.begin());
+}
+{
+  std::vector<std::vector<int, min_allocator<int>>, min_allocator<std::vector<int, min_allocator<int>>>> outer(
+      2, std::vector<int, min_allocator<int>>(1));
+  outer.erase(outer.begin(), outer.begin());
+  assert(outer.size() == 2);
+  assert(outer[0].size() == 1);
+  assert(outer[1].size() == 1);
+}
+#endif
+
+return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  // Test for LWG2853:
+  // Throws: Nothing unless an exception is thrown by the assignment operator or move assignment operator of T.
+  {
+    Throws arr[] = {1, 2, 3};
+    std::vector<Throws> v(arr, arr + 3);
+    Throws::sThrows = true;
+    v.erase(v.begin(), --v.end());
+    assert(v.size() == 1);
+    v.erase(v.begin(), v.end());
+    assert(v.size() == 0);
+  }
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_initializer_list.pass.cpp
new file mode 100644
index 00000000000000..c6c77debde5a8e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_initializer_list.pass.cpp
@@ -0,0 +1,110 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <vector>
+
+// iterator insert(const_iterator p, initializer_list<value_type> il);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+int throw_if_zero     = 2;
+int constructed_count = 0;
+
+struct ThrowSometimes {
+  ThrowSometimes() { ++constructed_count; }
+  ThrowSometimes(const ThrowSometimes&) {
+    if (--throw_if_zero == 0)
+      throw 1;
+    ++constructed_count;
+  }
+  ThrowSometimes& operator=(const ThrowSometimes&) {
+    if (--throw_if_zero == 0)
+      throw 1;
+    ++constructed_count;
+    return *this;
+  }
+  ~ThrowSometimes() { --constructed_count; }
+};
+
+void test_throwing() {
+  std::vector<ThrowSometimes> v;
+  v.reserve(4);
+  v.emplace_back();
+  v.emplace_back();
+  try {
+    v.insert(v.end(), {ThrowSometimes{}, ThrowSometimes{}});
+    assert(false);
+  } catch (int) {
+    assert(v.size() == 2);
+    assert(constructed_count == 2);
+  }
+}
+#endif // TEST_HAS_NO_EXCEPTIONS
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<int> d(10, 1);
+    std::vector<int>::iterator i = d.insert(d.cbegin() + 2, {3, 4, 5, 6});
+    assert(d.size() == 14);
+    assert(i == d.begin() + 2);
+    assert(d[0] == 1);
+    assert(d[1] == 1);
+    assert(d[2] == 3);
+    assert(d[3] == 4);
+    assert(d[4] == 5);
+    assert(d[5] == 6);
+    assert(d[6] == 1);
+    assert(d[7] == 1);
+    assert(d[8] == 1);
+    assert(d[9] == 1);
+    assert(d[10] == 1);
+    assert(d[11] == 1);
+    assert(d[12] == 1);
+    assert(d[13] == 1);
+  }
+  {
+    std::vector<int, min_allocator<int>> d(10, 1);
+    std::vector<int, min_allocator<int>>::iterator i = d.insert(d.cbegin() + 2, {3, 4, 5, 6});
+    assert(d.size() == 14);
+    assert(i == d.begin() + 2);
+    assert(d[0] == 1);
+    assert(d[1] == 1);
+    assert(d[2] == 3);
+    assert(d[3] == 4);
+    assert(d[4] == 5);
+    assert(d[5] == 6);
+    assert(d[6] == 1);
+    assert(d[7] == 1);
+    assert(d[8] == 1);
+    assert(d[9] == 1);
+    assert(d[10] == 1);
+    assert(d[11] == 1);
+    assert(d[12] == 1);
+    assert(d[13] == 1);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  test_throwing();
+#endif
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..f8311090b37e3c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.addressof.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class Iter>
+//   iterator insert(const_iterator position, Iter first, Iter last);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+#include "test_iterators.h"
+
+void test(cpp17_input_iterator<operator_hijacker*> i) {
+  {
+    std::vector<operator_hijacker> v;
+    v.insert(v.end(), i, i);
+  }
+  {
+    std::vector<operator_hijacker> v;
+    v.insert(v.end(), v.begin(), v.end());
+  }
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
new file mode 100644
index 00000000000000..df41577ac4c75a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_iter_iter.pass.cpp
@@ -0,0 +1,182 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class Iter>
+//   iterator insert(const_iterator position, Iter first, Iter last);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "test_iterators.h"
+#include "min_allocator.h"
+
+namespace adl {
+struct S {};
+void make_move_iterator(S*) {}
+} // namespace adl
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    typedef std::vector<int> V;
+    V v(100);
+    int a[]     = {1, 2, 3, 4, 5};
+    const int N = sizeof(a) / sizeof(a[0]);
+    V::iterator i =
+        v.insert(v.cbegin() + 10, cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(a + N));
+    assert(v.size() == 100 + N);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (std::size_t k = 0; k < N; ++j, ++k)
+      assert(v[j] == a[k]);
+    for (; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+  {
+    typedef std::vector<int> V;
+    V v(100);
+    int a[]       = {1, 2, 3, 4, 5};
+    const int N   = sizeof(a) / sizeof(a[0]);
+    V::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+    assert(v.size() == 100 + N);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (std::size_t k = 0; k < N; ++j, ++k)
+      assert(v[j] == a[k]);
+    for (; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+  {
+    typedef std::vector<int> V;
+    V v(100);
+    while (v.size() < v.capacity())
+      v.push_back(0); // force reallocation
+    std::size_t sz   = v.size();
+    int a[]          = {1, 2, 3, 4, 5};
+    const unsigned N = sizeof(a) / sizeof(a[0]);
+    V::iterator i    = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+    assert(v.size() == sz + N);
+    assert(i == v.begin() + 10);
+    std::size_t j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (std::size_t k = 0; k < N; ++j, ++k)
+      assert(v[j] == a[k]);
+    for (; j < v.size(); ++j)
+      assert(v[j] == 0);
+  }
+  {
+    typedef std::vector<int> V;
+    V v(100);
+    v.reserve(128); // force no reallocation
+    std::size_t sz   = v.size();
+    int a[]          = {1, 2, 3, 4, 5};
+    const unsigned N = sizeof(a) / sizeof(a[0]);
+    V::iterator i    = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+    assert(v.size() == sz + N);
+    assert(i == v.begin() + 10);
+    std::size_t j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (std::size_t k = 0; k < N; ++j, ++k)
+      assert(v[j] == a[k]);
+    for (; j < v.size(); ++j)
+      assert(v[j] == 0);
+  }
+  {
+    typedef std::vector<int, limited_allocator<int, 308> > V;
+    V v(100);
+    int a[]     = {1, 2, 3, 4, 5};
+    const int N = sizeof(a) / sizeof(a[0]);
+    V::iterator i =
+        v.insert(v.cbegin() + 10, cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(a + N));
+    assert(v.size() == 100 + N);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (std::size_t k = 0; k < N; ++j, ++k)
+      assert(v[j] == a[k]);
+    for (; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+  {
+    typedef std::vector<int, limited_allocator<int, 300> > V;
+    V v(100);
+    int a[]       = {1, 2, 3, 4, 5};
+    const int N   = sizeof(a) / sizeof(a[0]);
+    V::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+    assert(v.size() == 100 + N);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (std::size_t k = 0; k < N; ++j, ++k)
+      assert(v[j] == a[k]);
+    for (; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+#if TEST_STD_VER >= 11
+  {
+    typedef std::vector<int, min_allocator<int> > V;
+    V v(100);
+    int a[]     = {1, 2, 3, 4, 5};
+    const int N = sizeof(a) / sizeof(a[0]);
+    V::iterator i =
+        v.insert(v.cbegin() + 10, cpp17_input_iterator<const int*>(a), cpp17_input_iterator<const int*>(a + N));
+    assert(v.size() == 100 + N);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (std::size_t k = 0; k < N; ++j, ++k)
+      assert(v[j] == a[k]);
+    for (; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+  {
+    typedef std::vector<int, min_allocator<int> > V;
+    V v(100);
+    int a[]       = {1, 2, 3, 4, 5};
+    const int N   = sizeof(a) / sizeof(a[0]);
+    V::iterator i = v.insert(v.cbegin() + 10, forward_iterator<const int*>(a), forward_iterator<const int*>(a + N));
+    assert(v.size() == 100 + N);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (std::size_t k = 0; k < N; ++j, ++k)
+      assert(v[j] == a[k]);
+    for (; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+#endif
+
+  {
+    std::vector<adl::S> s;
+    s.insert(s.end(), cpp17_input_iterator<adl::S*>(nullptr), cpp17_input_iterator<adl::S*>(nullptr));
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_lvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_lvalue.pass.cpp
new file mode 100644
index 00000000000000..29c4d1709689a7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_lvalue.pass.cpp
@@ -0,0 +1,137 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, const value_type& x);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool test() {
+  {
+    std::vector<int> v(100);
+    const int lvalue             = 1;
+    std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+    assert(v.size() == 101);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    assert(v[j] == 1);
+    for (++j; j < 101; ++j)
+      assert(v[j] == 0);
+  }
+  {
+    const std::size_t n = 100;
+    std::vector<int> v(n);
+    v.reserve(n + 1);
+    const int lvalue = 1;
+
+    // no reallocation expected
+    std::vector<int>::iterator it = v.insert(v.cbegin() + n, lvalue);
+
+    assert(v.size() == n + 1);
+    assert(it == v.begin() + n);
+    for (std::size_t i = 0; i < n; ++i) {
+      assert(v[i] == 0);
+    }
+    assert(v[n] == lvalue);
+  }
+  {
+    std::vector<int> v(100);
+    while (v.size() < v.capacity())
+      v.push_back(0); // force reallocation
+    std::size_t sz               = v.size();
+    const int lvalue             = 1;
+    std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+    assert(v.size() == sz + 1);
+    assert(i == v.begin() + 10);
+    std::size_t j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    assert(v[j] == 1);
+    for (++j; j < v.size(); ++j)
+      assert(v[j] == 0);
+  }
+  {
+    std::vector<int> v(100);
+    while (v.size() < v.capacity())
+      v.push_back(0);
+    v.pop_back();
+    v.pop_back(); // force no reallocation
+    std::size_t sz               = v.size();
+    const int lvalue             = 1;
+    std::vector<int>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+    assert(v.size() == sz + 1);
+    assert(i == v.begin() + 10);
+    std::size_t j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    assert(v[j] == 1);
+    for (++j; j < v.size(); ++j)
+      assert(v[j] == 0);
+  }
+  {
+    std::vector<int, limited_allocator<int, 300> > v(100);
+    const int lvalue                                           = 1;
+    std::vector<int, limited_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, lvalue);
+    assert(v.size() == 101);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    assert(v[j] == 1);
+    for (++j; j < 101; ++j)
+      assert(v[j] == 0);
+  }
+#if TEST_STD_VER >= 11
+  {
+    std::vector<int, min_allocator<int>> v(100);
+    const int lvalue                                 = 1;
+    std::vector<int, min_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+    assert(v.size() == 101);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    assert(v[j] == 1);
+    for (++j; j < 101; ++j)
+      assert(v[j] == 0);
+  }
+  {
+    std::vector<int, safe_allocator<int>> v(100);
+    const int lvalue                                  = 1;
+    std::vector<int, safe_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, lvalue);
+    assert(v.size() == 101);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    assert(v[j] == 1);
+    for (++j; j < 101; ++j)
+      assert(v[j] == 0);
+  }
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+#if TEST_STD_VER > 17
+  static_assert(test());
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..11f24604eeac4d
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.addressof.compile.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// iterator insert(const_iterator position, value_type&& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::vector<operator_hijacker> v;
+  v.insert(v.end(), operator_hijacker());
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.pass.cpp
new file mode 100644
index 00000000000000..e72bba1ca3551e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_rvalue.pass.cpp
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// iterator insert(const_iterator position, value_type&& x);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "MoveOnly.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<MoveOnly> v(100);
+    std::vector<MoveOnly>::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+    assert(v.size() == 101);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == MoveOnly());
+    assert(v[j] == MoveOnly(3));
+    for (++j; j < 101; ++j)
+      assert(v[j] == MoveOnly());
+  }
+  {
+    std::vector<MoveOnly, limited_allocator<MoveOnly, 300> > v(100);
+    std::vector<MoveOnly, limited_allocator<MoveOnly, 300> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+    assert(v.size() == 101);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == MoveOnly());
+    assert(v[j] == MoveOnly(3));
+    for (++j; j < 101; ++j)
+      assert(v[j] == MoveOnly());
+  }
+  {
+    std::vector<MoveOnly, min_allocator<MoveOnly> > v(100);
+    std::vector<MoveOnly, min_allocator<MoveOnly> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+    assert(v.size() == 101);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == MoveOnly());
+    assert(v[j] == MoveOnly(3));
+    for (++j; j < 101; ++j)
+      assert(v[j] == MoveOnly());
+  }
+  {
+    std::vector<MoveOnly, safe_allocator<MoveOnly> > v(100);
+    std::vector<MoveOnly, safe_allocator<MoveOnly> >::iterator i = v.insert(v.cbegin() + 10, MoveOnly(3));
+    assert(v.size() == 101);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == MoveOnly());
+    assert(v[j] == MoveOnly(3));
+    for (++j; j < 101; ++j)
+      assert(v[j] == MoveOnly());
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..c02b92a4998e85
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, size_type n, const value_type& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::vector<operator_hijacker> v;
+  operator_hijacker val;
+  v.insert(v.end(), 1, val);
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.pass.cpp
new file mode 100644
index 00000000000000..940f4602d128af
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_size_value.pass.cpp
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, size_type n, const value_type& x);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<int> v(100);
+    std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+    assert(v.size() == 105);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (; j < 15; ++j)
+      assert(v[j] == 1);
+    for (++j; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+  {
+    std::vector<int> v(100);
+    while (v.size() < v.capacity())
+      v.push_back(0); // force reallocation
+    std::size_t sz               = v.size();
+    std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+    assert(v.size() == sz + 5);
+    assert(i == v.begin() + 10);
+    std::size_t j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (; j < 15; ++j)
+      assert(v[j] == 1);
+    for (++j; j < v.size(); ++j)
+      assert(v[j] == 0);
+  }
+  {
+    std::vector<int> v(100);
+    v.reserve(128); // force no reallocation
+    std::size_t sz               = v.size();
+    std::vector<int>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+    assert(v.size() == sz + 5);
+    assert(i == v.begin() + 10);
+    std::size_t j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (; j < 15; ++j)
+      assert(v[j] == 1);
+    for (++j; j < v.size(); ++j)
+      assert(v[j] == 0);
+  }
+  {
+    std::vector<int, limited_allocator<int, 300> > v(100);
+    std::vector<int, limited_allocator<int, 300> >::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+    assert(v.size() == 105);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (; j < 15; ++j)
+      assert(v[j] == 1);
+    for (++j; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+#if TEST_STD_VER >= 11
+  {
+    std::vector<int, min_allocator<int>> v(100);
+    std::vector<int, min_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+    assert(v.size() == 105);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (; j < 15; ++j)
+      assert(v[j] == 1);
+    for (++j; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+  {
+    std::vector<int, safe_allocator<int>> v(100);
+    std::vector<int, safe_allocator<int>>::iterator i = v.insert(v.cbegin() + 10, 5, 1);
+    assert(v.size() == 105);
+    assert(i == v.begin() + 10);
+    int j;
+    for (j = 0; j < 10; ++j)
+      assert(v[j] == 0);
+    for (; j < 15; ++j)
+      assert(v[j] == 1);
+    for (++j; j < 105; ++j)
+      assert(v[j] == 0);
+  }
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_value.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_value.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..fbf1a4f50b974f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_iter_value.addressof.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// iterator insert(const_iterator position, const value_type& x);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::vector<operator_hijacker> v;
+  operator_hijacker val;
+  v.insert(v.end(), val);
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_range.pass.cpp
new file mode 100644
index 00000000000000..5353c958973a1e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/insert_range.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// template<container-compatible-range<T> R>
+//   constexpr iterator insert_range(const_iterator position, R&& rg); // C++23
+
+#include <vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "test_macros.h"
+
+// Tested cases:
+// - different kinds of insertions (inserting an {empty/one-element/mid-sized/long range} into an
+//   {empty/one-element/full} container at the {beginning/middle/end});
+// - inserting move-only elements;
+// - an exception is thrown when copying the elements or when allocating new elements.
+
+constexpr bool test() {
+  for_all_iterators_and_allocators<int, const int*>([]<class Iter, class Sent, class Alloc>() {
+    test_sequence_insert_range<std::vector<int, Alloc>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+  });
+  test_sequence_insert_range_move_only<std::vector>();
+
+  {   // Vector may or may not need to reallocate because of the insertion -- make sure to test both cases.
+    { // Ensure reallocation happens.
+      int in[]           = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+      std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+      v.shrink_to_fit();
+      assert(v.capacity() < v.size() + std::ranges::size(in));
+
+      v.insert_range(v.end(), in);
+      assert(std::ranges::equal(v, std::array{1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10}));
+    }
+
+    { // Ensure no reallocation happens.
+      int in[]           = {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10};
+      std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
+      v.reserve(v.size() + std::ranges::size(in));
+      assert(v.capacity() >= v.size() + std::ranges::size(in));
+
+      v.insert_range(v.end(), in);
+      assert(std::ranges::equal(v, std::array{1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10}));
+    }
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  static_assert(test_constraints_insert_range<std::vector, int, double>());
+
+  test_insert_range_exception_safety_throwing_copy<std::vector>();
+  test_insert_range_exception_safety_throwing_allocator<std::vector, int>();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/pop_back.pass.cpp
new file mode 100644
index 00000000000000..9717666079d803
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/pop_back.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void pop_back();
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<int> c;
+    c.push_back(1);
+    assert(c.size() == 1);
+    c.pop_back();
+    assert(c.size() == 0);
+  }
+#if TEST_STD_VER >= 11
+  {
+    std::vector<int, min_allocator<int>> c;
+    c.push_back(1);
+    assert(c.size() == 1);
+    c.pop_back();
+    assert(c.size() == 0);
+  }
+#endif
+
+  { // LWG 526
+    int arr[] = {0, 1, 2, 3, 4};
+    int sz    = 5;
+    std::vector<int> c(arr, arr + sz);
+    while (c.size() < c.capacity())
+      c.push_back(sz++);
+    c.push_back(c.front());
+    assert(c.back() == 0);
+    for (int i = 0; i < sz; ++i)
+      assert(c[i] == i);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back.pass.cpp
new file mode 100644
index 00000000000000..5f23368ffd3bc8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back.pass.cpp
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void push_back(const value_type& x);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<int> c;
+    c.push_back(0);
+    assert(c.size() == 1);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(1);
+    assert(c.size() == 2);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(2);
+    assert(c.size() == 3);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(3);
+    assert(c.size() == 4);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(4);
+    assert(c.size() == 5);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+  }
+  {
+    // libc++ needs 15 because it grows by 2x (1 + 2 + 4 + 8).
+    // Use 17 for implementations that dynamically allocate a container proxy
+    // and grow by 1.5x (1 for proxy + 1 + 2 + 3 + 4 + 6).
+    std::vector<int, limited_allocator<int, 17> > c;
+    c.push_back(0);
+    assert(c.size() == 1);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(1);
+    assert(c.size() == 2);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(2);
+    assert(c.size() == 3);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(3);
+    assert(c.size() == 4);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(4);
+    assert(c.size() == 5);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+  }
+#if TEST_STD_VER >= 11
+  {
+    std::vector<int, min_allocator<int>> c;
+    c.push_back(0);
+    assert(c.size() == 1);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(1);
+    assert(c.size() == 2);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(2);
+    assert(c.size() == 3);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(3);
+    assert(c.size() == 4);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+    c.push_back(4);
+    assert(c.size() == 5);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == j);
+  }
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_exception_safety.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_exception_safety.pass.cpp
new file mode 100644
index 00000000000000..e2cbed783e2c74
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_exception_safety.pass.cpp
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void push_back(const value_type& x);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+// Flag that makes the copy constructor for CMyClass throw an exception
+static bool gCopyConstructorShouldThrow = false;
+
+class CMyClass {
+public:
+  CMyClass(int tag);
+
+public:
+  CMyClass(const CMyClass& iOther);
+
+public:
+  ~CMyClass();
+
+  bool equal(const CMyClass& rhs) const { return fTag == rhs.fTag && fMagicValue == rhs.fMagicValue; }
+
+private:
+  int fMagicValue;
+  int fTag;
+
+private:
+  static int kStartedConstructionMagicValue;
+
+private:
+  static int kFinishedConstructionMagicValue;
+};
+
+// Value for fMagicValue when the constructor has started running, but not yet finished
+int CMyClass::kStartedConstructionMagicValue = 0;
+// Value for fMagicValue when the constructor has finished running
+int CMyClass::kFinishedConstructionMagicValue = 12345;
+
+CMyClass::CMyClass(int tag) : fMagicValue(kStartedConstructionMagicValue), fTag(tag) {
+  // Signal that the constructor has finished running
+  fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::CMyClass(const CMyClass& iOther) : fMagicValue(kStartedConstructionMagicValue), fTag(iOther.fTag) {
+  // If requested, throw an exception _before_ setting fMagicValue to kFinishedConstructionMagicValue
+  if (gCopyConstructorShouldThrow) {
+    TEST_THROW(std::exception());
+  }
+  // Signal that the constructor has finished running
+  fMagicValue = kFinishedConstructionMagicValue;
+}
+
+CMyClass::~CMyClass() {
+  // Only instances for which the constructor has finished running should be destructed
+  assert(fMagicValue == kFinishedConstructionMagicValue);
+}
+
+bool operator==(const CMyClass& lhs, const CMyClass& rhs) { return lhs.equal(rhs); }
+
+int main(int, char**) {
+  CMyClass instance(42);
+  std::vector<CMyClass> vec;
+
+  vec.push_back(instance);
+  std::vector<CMyClass> vec2(vec);
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  gCopyConstructorShouldThrow = true;
+  try {
+    vec.push_back(instance);
+    assert(false);
+  } catch (...) {
+    assert(vec == vec2);
+  }
+#endif
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_rvalue.pass.cpp
new file mode 100644
index 00000000000000..7f3a33c3d865a3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/push_back_rvalue.pass.cpp
@@ -0,0 +1,106 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// void push_back(value_type&& x);
+
+#include <vector>
+#include <cassert>
+#include <cstddef>
+#include "test_macros.h"
+#include "MoveOnly.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<MoveOnly> c;
+    c.push_back(MoveOnly(0));
+    assert(c.size() == 1);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(1));
+    assert(c.size() == 2);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(2));
+    assert(c.size() == 3);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(3));
+    assert(c.size() == 4);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(4));
+    assert(c.size() == 5);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+  }
+  {
+    // libc++ needs 15 because it grows by 2x (1 + 2 + 4 + 8).
+    // Use 17 for implementations that dynamically allocate a container proxy
+    // and grow by 1.5x (1 for proxy + 1 + 2 + 3 + 4 + 6).
+    std::vector<MoveOnly, limited_allocator<MoveOnly, 17> > c;
+    c.push_back(MoveOnly(0));
+    assert(c.size() == 1);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(1));
+    assert(c.size() == 2);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(2));
+    assert(c.size() == 3);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(3));
+    assert(c.size() == 4);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(4));
+    assert(c.size() == 5);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+  }
+  {
+    std::vector<MoveOnly, min_allocator<MoveOnly> > c;
+    c.push_back(MoveOnly(0));
+    assert(c.size() == 1);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(1));
+    assert(c.size() == 2);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(2));
+    assert(c.size() == 3);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(3));
+    assert(c.size() == 4);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+    c.push_back(MoveOnly(4));
+    assert(c.size() == 5);
+    for (int j = 0; static_cast<std::size_t>(j) < c.size(); ++j)
+      assert(c[j] == MoveOnly(j));
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/resize_not_move_insertable.verify.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/resize_not_move_insertable.verify.cpp
new file mode 100644
index 00000000000000..acc0127ac73e2c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/resize_not_move_insertable.verify.cpp
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03 && !stdlib=libc++
+
+// <vector>
+
+// Test that vector produces a decent diagnostic for user types that explicitly
+// delete their move constructor. Such types don't meet the Cpp17CopyInsertable
+// requirements.
+
+#include <vector>
+
+template <int>
+class BadUserNoCookie {
+public:
+  BadUserNoCookie() {}
+
+  BadUserNoCookie(BadUserNoCookie&&)            = delete;
+  BadUserNoCookie& operator=(BadUserNoCookie&&) = delete;
+
+  BadUserNoCookie(const BadUserNoCookie&)            = default;
+  BadUserNoCookie& operator=(const BadUserNoCookie&) = default;
+};
+
+int main(int, char**) {
+  // expected-error@* 2 {{The specified type does not meet the requirements of Cpp17MoveInsertable}}
+
+  // Other diagnostics that might be seen as Clang tries to continue compiling:
+  // expected-error@* 0-2 {{call to deleted constructor}}
+  // expected-error@* 0-2 {{no matching function for call to '__construct_at'}}
+  {
+    std::vector<BadUserNoCookie<1> > x;
+    x.emplace_back();
+  }
+  {
+    std::vector<BadUserNoCookie<2> > x;
+    BadUserNoCookie<2> c;
+    x.push_back(c);
+  }
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.addressof.compile.pass.cpp
new file mode 100644
index 00000000000000..4e908d9ff6eaca
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.addressof.compile.pass.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class T, class Alloc>
+//   void swap(vector<T,Alloc>& x, vector<T,Alloc>& y);
+
+// Validate whether the container can be copy-assigned with an ADL-hijacking operator&
+
+#include <vector>
+
+#include "test_macros.h"
+#include "operator_hijacker.h"
+
+void test() {
+  std::vector<operator_hijacker> vo;
+  std::vector<operator_hijacker> v;
+  v.swap(vo);
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.pass.cpp
new file mode 100644
index 00000000000000..8a45c7c9eb49d7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.pass.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// void swap(vector& x);
+
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    std::vector<int> v1(100);
+    std::vector<int> v2(200);
+    v1.swap(v2);
+    assert(v1.size() == 200);
+    assert(v1.capacity() == 200);
+    assert(v2.size() == 100);
+    assert(v2.capacity() == 100);
+  }
+#if TEST_STD_VER >= 11
+  {
+    std::vector<int, min_allocator<int>> v1(100);
+    std::vector<int, min_allocator<int>> v2(200);
+    v1.swap(v2);
+    assert(v1.size() == 200);
+    assert(v1.capacity() == 200);
+    assert(v2.size() == 100);
+    assert(v2.capacity() == 100);
+  }
+  {
+    std::vector<int, safe_allocator<int>> v1(100);
+    std::vector<int, safe_allocator<int>> v2(200);
+    v1.swap(v2);
+    assert(v1.size() == 200);
+    assert(v1.capacity() == 200);
+    assert(v2.size() == 100);
+    assert(v2.capacity() == 100);
+  }
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap_noexcept.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap_noexcept.compile.pass.cpp
new file mode 100644
index 00000000000000..48e083e42b15ff
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap_noexcept.compile.pass.cpp
@@ -0,0 +1,87 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// <vector>
+
+// void swap(vector& c)
+//     noexcept(!allocator_type::propagate_on_container_swap::value ||
+//              __is_nothrow_swappable<allocator_type>::value);
+//
+//  In C++17, the standard says that swap shall have:
+//     noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
+//              allocator_traits<Allocator>::is_always_equal::value);
+
+// This tests a conforming extension
+
+#include <vector>
+#include <utility>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+#include "test_allocator.h"
+
+template <class T>
+struct some_alloc {
+  typedef T value_type;
+
+  some_alloc() {}
+  some_alloc(const some_alloc&);
+  void allocate(std::size_t);
+  void deallocate(void*, unsigned) {}
+
+  typedef std::true_type propagate_on_container_swap;
+};
+
+template <class T>
+struct some_alloc2 {
+  typedef T value_type;
+
+  some_alloc2() {}
+  some_alloc2(const some_alloc2&);
+  void allocate(std::size_t);
+  void deallocate(void*, unsigned) {}
+
+  typedef std::false_type propagate_on_container_swap;
+  typedef std::true_type is_always_equal;
+};
+
+void test() {
+  {
+    typedef std::vector<MoveOnly> C;
+    static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+  }
+#if defined(_LIBCPP_VERSION)
+  {
+    typedef std::vector<MoveOnly, test_allocator<MoveOnly>> C;
+    static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+  }
+#endif
+  {
+    typedef std::vector<MoveOnly, other_allocator<MoveOnly>> C;
+    static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+  }
+  {
+    typedef std::vector<MoveOnly, some_alloc<MoveOnly>> C;
+#if TEST_STD_VER >= 14
+    //  In C++14, if POCS is set, swapping the allocator is required not to throw
+    static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+#else
+    static_assert(!noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+#endif
+  }
+#if TEST_STD_VER >= 14
+  {
+    typedef std::vector<MoveOnly, some_alloc2<MoveOnly>> C;
+    // If the allocators are always equal, then the swap can be noexcept
+    static_assert(noexcept(swap(std::declval<C&>(), std::declval<C&>())), "");
+  }
+#endif
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/vector.special/swap.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/vector.special/swap.pass.cpp
new file mode 100644
index 00000000000000..51f773ba4f6c5b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.special/swap.pass.cpp
@@ -0,0 +1,155 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <vector>
+
+// template <class T, class Alloc>
+//   void swap(vector<T,Alloc>& x, vector<T,Alloc>& y);
+
+#include <vector>
+#include <iterator>
+#include <cassert>
+#include "test_macros.h"
+#include "test_allocator.h"
+#include "min_allocator.h"
+
+template <typename A>
+TEST_CONSTEXPR_CXX20 void test_with_allocator() {
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]));
+    std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]));
+    swap(c1, c2);
+    assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+    assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int, A> c1(a1, a1);
+    std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]));
+    swap(c1, c2);
+    assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+    assert(c2.empty());
+    assert(std::distance(c2.begin(), c2.end()) == 0);
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]));
+    std::vector<int, A> c2(a2, a2);
+    swap(c1, c2);
+    assert(c1.empty());
+    assert(std::distance(c1.begin(), c1.end()) == 0);
+    assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int, A> c1(a1, a1);
+    std::vector<int, A> c2(a2, a2);
+    swap(c1, c2);
+    assert(c1.empty());
+    assert(std::distance(c1.begin(), c1.end()) == 0);
+    assert(c2.empty());
+    assert(std::distance(c2.begin(), c2.end()) == 0);
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]), A());
+    std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]), A());
+    swap(c1, c2);
+    assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+    assert(c1.get_allocator() == A());
+    assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+    assert(c2.get_allocator() == A());
+  }
+}
+
+TEST_CONSTEXPR_CXX20 bool tests() {
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]));
+    std::vector<int> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]));
+    swap(c1, c2);
+    assert(c1 == std::vector<int>(a2, a2 + sizeof(a2) / sizeof(a2[0])));
+    assert(c2 == std::vector<int>(a1, a1 + sizeof(a1) / sizeof(a1[0])));
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int> c1(a1, a1);
+    std::vector<int> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]));
+    swap(c1, c2);
+    assert(c1 == std::vector<int>(a2, a2 + sizeof(a2) / sizeof(a2[0])));
+    assert(c2.empty());
+    assert(std::distance(c2.begin(), c2.end()) == 0);
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]));
+    std::vector<int> c2(a2, a2);
+    swap(c1, c2);
+    assert(c1.empty());
+    assert(std::distance(c1.begin(), c1.end()) == 0);
+    assert(c2 == std::vector<int>(a1, a1 + sizeof(a1) / sizeof(a1[0])));
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    std::vector<int> c1(a1, a1);
+    std::vector<int> c2(a2, a2);
+    swap(c1, c2);
+    assert(c1.empty());
+    assert(std::distance(c1.begin(), c1.end()) == 0);
+    assert(c2.empty());
+    assert(std::distance(c2.begin(), c2.end()) == 0);
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    typedef test_allocator<int> A;
+    std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]), A(1, 1));
+    std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]), A(1, 2));
+    swap(c1, c2);
+    assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+    assert(c1.get_allocator().get_id() == 1);
+    assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+    assert(c2.get_allocator().get_id() == 2);
+  }
+  {
+    int a1[] = {1, 3, 7, 9, 10};
+    int a2[] = {0, 2, 4, 5, 6, 8, 11};
+    typedef other_allocator<int> A;
+    std::vector<int, A> c1(a1, a1 + sizeof(a1) / sizeof(a1[0]), A(1));
+    std::vector<int, A> c2(a2, a2 + sizeof(a2) / sizeof(a2[0]), A(2));
+    swap(c1, c2);
+    assert((c1 == std::vector<int, A>(a2, a2 + sizeof(a2) / sizeof(a2[0]))));
+    assert(c1.get_allocator() == A(2));
+    assert((c2 == std::vector<int, A>(a1, a1 + sizeof(a1) / sizeof(a1[0]))));
+    assert(c2.get_allocator() == A(1));
+  }
+#if TEST_STD_VER >= 11
+  test_with_allocator<min_allocator<int>>();
+  test_with_allocator<safe_allocator<int>>();
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+#if TEST_STD_VER > 17
+  static_assert(tests());
+#endif
+  return 0;
+}
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp
new file mode 100644
index 00000000000000..ea4409cac91626
--- /dev/null
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp
@@ -0,0 +1,65 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+//
+// clang-format off
+
+// <inplace_vector>
+
+// Test the feature test macros defined by <inplace_vector>
+
+/*  Constant                    Value
+    __cpp_lib_inplace_vector    202406L [C++26]
+*/
+
+#include <inplace_vector>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 14
+
+# ifdef __cpp_lib_inplace_vector
+#   error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_inplace_vector
+#   error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_inplace_vector
+#   error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# ifdef __cpp_lib_inplace_vector
+#   error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER == 23
+
+# ifdef __cpp_lib_inplace_vector
+#   error "__cpp_lib_inplace_vector should not be defined before c++26"
+# endif
+
+#elif TEST_STD_VER > 23
+
+# ifndef __cpp_lib_inplace_vector
+#   error "__cpp_lib_inplace_vector should be defined in c++26"
+# endif
+# if __cpp_lib_inplace_vector != 202406L
+#   error "__cpp_lib_inplace_vector should have the value 202406L in c++26"
+# endif
+
+#endif // TEST_STD_VER > 23
+
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index b8bad696f1bae0..686e80aa9bb21d 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -7021,17 +7021,11 @@
 #   error "__cpp_lib_incomplete_container_elements should have the value 201505L in c++26"
 # endif
 
-# if !defined(_LIBCPP_VERSION)
-#   ifndef __cpp_lib_inplace_vector
-#     error "__cpp_lib_inplace_vector should be defined in c++26"
-#   endif
-#   if __cpp_lib_inplace_vector != 202406L
-#     error "__cpp_lib_inplace_vector should have the value 202406L in c++26"
-#   endif
-# else // _LIBCPP_VERSION
-#   ifdef __cpp_lib_inplace_vector
-#     error "__cpp_lib_inplace_vector should not be defined because it is unimplemented in libc++!"
-#   endif
+# ifndef __cpp_lib_inplace_vector
+#   error "__cpp_lib_inplace_vector should be defined in c++26"
+# endif
+# if __cpp_lib_inplace_vector != 202406L
+#   error "__cpp_lib_inplace_vector should have the value 202406L in c++26"
 # endif
 
 # ifndef __cpp_lib_int_pow2
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index b041b08f02aac5..1c66f57e7c048c 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -684,7 +684,6 @@ def add_version_header(tc):
             "name": "__cpp_lib_inplace_vector",
             "values": {"c++26": 202406},  # P0843R14 inplace_vector
             "headers": ["inplace_vector"],
-            "unimplemented": True,
         },
         {
             "name": "__cpp_lib_int_pow2",



More information about the libcxx-commits mailing list