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

Mital Ashok via libcxx-commits libcxx-commits at lists.llvm.org
Tue Sep 17 04:20:33 PDT 2024


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

>From ec8aae9d0128c53b5411efe82902b18ee8b9d7ed Mon Sep 17 00:00:00 2001
From: Mital Ashok <mital at mitalashok.co.uk>
Date: Fri, 30 Aug 2024 15:03:13 +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/__std_clang_module             |    1 +
 libcxx/include/inplace_vector                 | 1091 +++++++++++++++++
 libcxx/include/module.modulemap               |    4 +
 libcxx/include/version                        |    2 +-
 libcxx/modules/CMakeLists.txt                 |    1 +
 libcxx/modules/std.compat.cppm.in             |    3 -
 libcxx/modules/std.cppm.in                    |    4 +-
 libcxx/modules/std/inplace_vector.inc         |   19 +
 .../test/libcxx/transitive_includes/cxx03.csv |   17 +
 .../test/libcxx/transitive_includes/cxx11.csv |   17 +
 .../test/libcxx/transitive_includes/cxx14.csv |   17 +
 .../test/libcxx/transitive_includes/cxx17.csv |   17 +
 .../test/libcxx/transitive_includes/cxx20.csv |   17 +
 .../test/libcxx/transitive_includes/cxx23.csv |   11 +
 .../test/libcxx/transitive_includes/cxx26.csv |   11 +
 .../sequences/inplace.vector/access.pass.cpp  |  148 +++
 .../sequences/inplace.vector/compare.pass.cpp |  131 ++
 .../inplace.vector/compare.three_way.pass.cpp |   38 +
 .../constant_initialization.pass.cpp          |   75 ++
 .../inplace.vector/contiguous.pass.cpp        |   49 +
 .../inplace.vector/empy_type.compile.pass.cpp |   33 +
 .../inplace.vector.capacity/capacity.pass.cpp |   52 +
 .../inplace.vector.capacity/empty.pass.cpp    |   67 +
 .../inplace.vector.capacity/empty.verify.cpp  |   30 +
 .../inplace.vector.capacity/max_size.pass.cpp |   52 +
 .../inplace.vector.capacity/reserve.pass.cpp  |   81 ++
 .../resize_size.pass.cpp                      |   49 +
 .../resize_size_value.pass.cpp                |   73 ++
 .../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                 |  119 ++
 .../assign_move.addressof.compile.pass.cpp    |   33 +
 .../inplace.vector.cons/assign_move.pass.cpp  |   57 +
 .../assign_size_value.pass.cpp                |   47 +
 .../construct_default.pass.cpp                |   73 ++
 .../construct_from_range.pass.cpp             |   43 +
 .../construct_iter_iter.pass.cpp              |  177 +++
 .../construct_size.pass.cpp                   |   82 ++
 .../construct_size_value.pass.cpp             |   60 +
 .../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         |   55 +
 .../move_assign_noexcept.pass.cpp             |   51 +
 .../move_noexcept.pass.cpp                    |   49 +
 .../op_equal_initializer_list.pass.cpp        |   56 +
 .../inplace.vector.data/data.pass.cpp         |   91 ++
 .../inplace.vector.data/data_const.pass.cpp   |   94 ++
 .../inplace.vector.erasure/erase.pass.cpp     |   95 ++
 .../inplace.vector.erasure/erase_if.pass.cpp  |   94 ++
 ...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 |   92 ++
 .../sequences/inplace.vector/types.pass.cpp   |   70 ++
 .../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           |   54 +
 .../destroy_elements.pass.cpp                 |  156 +++
 .../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 |  174 +++
 .../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           |   33 +
 .../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 +-
 .../test/support/test_container_comparisons.h |   39 +
 .../generate_feature_test_macro_components.py |    1 -
 libcxx/utils/libcxx/header_information.py     |    2 +-
 107 files changed, 7554 insertions(+), 23 deletions(-)
 create mode 100644 libcxx/include/inplace_vector
 create mode 100644 libcxx/modules/std/inplace_vector.inc
 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/inplace.vector.erasure/erase.pass.cpp
 create mode 100644 libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase_if.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.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 c909a4300db1a6..9f7427e0835502 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -442,7 +442,7 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_hazard_pointer``                               *unimplemented*
     ---------------------------------------------------------- -----------------
-    ``__cpp_lib_inplace_vector``                               *unimplemented*
+    ``__cpp_lib_inplace_vector``                               ``202406L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_is_virtual_base_of``                           ``202406L``
     ---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 8864b1ebe28891..2d0c67d4967b17 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)","","",""
 "`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)","|Complete|","20.0",""
-"`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)","","",""
 "`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 8c61009167ddce..4c4e19cf420dbe 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -955,6 +955,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 707e10b5ceb53f..c66a2385e95394 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -160,7 +160,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 549d8ff2dbd7db..318616b32b2633 100644
--- a/libcxx/include/__iterator/wrap_iter.h
+++ b/libcxx/include/__iterator/wrap_iter.h
@@ -108,6 +108,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/__std_clang_module b/libcxx/include/__std_clang_module
index a21ed26addfe8e..06b0912c4bef12 100644
--- a/libcxx/include/__std_clang_module
+++ b/libcxx/include/__std_clang_module
@@ -97,6 +97,7 @@
 #include <functional>
 #include <future>
 #include <initializer_list>
+#include <inplace_vector>
 #include <inttypes.h>
 #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
 #  include <iomanip>
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
new file mode 100644
index 00000000000000..2e5fe846e8ee95
--- /dev/null
+++ b/libcxx/include/inplace_vector
@@ -0,0 +1,1091 @@
+// -*- 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/move_backward.h>
+#include <__algorithm/remove.h>
+#include <__algorithm/remove_if.h>
+#include <__algorithm/rotate.h>
+#include <__algorithm/swap_ranges.h>
+#include <__compare/synth_three_way.h>
+#include <__config>
+#include <__cstddef/size_t.h>
+#include <__iterator/distance.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/move_iterator.h>
+#include <__iterator/reverse_iterator.h>
+#include <__iterator/size.h>
+#include <__iterator/wrap_iter.h>
+#include <__memory/addressof.h>
+#include <__memory/construct_at.h>
+#include <__memory/pointer_traits.h>
+#include <__memory/voidify.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/container_compatible_range.h>
+#include <__ranges/dangling.h>
+#include <__ranges/from_range.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/is_nothrow_assignable.h>
+#include <__type_traits/is_nothrow_constructible.h>
+#include <__type_traits/is_swappable.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/forward.h>
+#include <__utility/unreachable.h>
+#include <new>
+#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 _MaximumPadding, size_t _Capacity>
+_LIBCPP_HIDE_FROM_ABI auto __inplace_vector_size_type() {
+  if constexpr (_MaximumPadding >= sizeof(size_t)) {
+    // Unconditionally use size_t in this case. Using a smaller size
+    // will not change the size of the inplace_vector because it will
+    // only introduce more padding bits
+    return static_cast<size_t>(0);
+  } else if constexpr (_Capacity <= static_cast<unsigned char>(-1) && (sizeof(unsigned char) < sizeof(size_t))) {
+    return static_cast<unsigned char>(0);
+  } else if constexpr (_Capacity <= static_cast<unsigned short>(-1) && (sizeof(unsigned short) < sizeof(size_t))) {
+    return static_cast<unsigned short>(0);
+  } else if constexpr (_Capacity <= static_cast<unsigned int>(-1) && (sizeof(unsigned int) < sizeof(size_t))) {
+    return static_cast<unsigned int>(0);
+  } else if constexpr (_Capacity <= static_cast<unsigned long>(-1) && (sizeof(unsigned long) < sizeof(size_t))) {
+    return static_cast<unsigned long>(0);
+  } else {
+    return static_cast<size_t>(0);
+  }
+}
+
+[[__noreturn__]] _LIBCPP_HIDE_FROM_ABI inline void __inplace_vector_throw_out_of_range() {
+  __throw_out_of_range("inplace_vector");
+  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() {
+    __small_size_type __size = __sz_;
+    __sz_                    = 0;
+    std::destroy(__elems_, __elems_ + __size);
+  }
+  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<__wrap_iter<pointer>>;
+  using const_iterator = __bounded_iter<__wrap_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 + 1zu == __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 + 1zu == __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> _Range>
+  constexpr _LIBCPP_HIDE_FROM_ABI inplace_vector(from_range_t, _Range&& __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(__i + 1zu == __sz_, "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(__i + 1zu == __sz_, "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, __wrap_iter<pointer>(__elems_ + 0), __wrap_iter<pointer>(__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> _Range>
+  constexpr _LIBCPP_HIDE_FROM_ABI void assign_range(_Range&& __rg) {
+    if constexpr (ranges::sized_range<_Range&>) {
+      return __assign_with_size(ranges::begin(__rg), ranges::end(__rg), ranges::size(__rg));
+    } else if constexpr (ranges::forward_range<_Range&>) {
+      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
+  [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __sz_ == 0; }
+  [[nodiscard]] constexpr _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept {
+    _LIBCPP_ASSERT_UNCATEGORIZED(__sz_ <= capacity(), "inplace_vector has impossible size");
+    // Let the optimizer know about this inequality
+    if (__sz_ > capacity())
+      unreachable();
+    return __sz_;
+  }
+  [[nodiscard]] static _LIBCPP_HIDE_FROM_ABI constexpr size_type max_size() noexcept { return _Capacity; }
+  [[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);
+      return;
+    }
+
+    size_type __remaining = __n - __sz_;
+    for (size_type __i = 0; __i < __remaining; ++__i) {
+      unchecked_emplace_back(__arg...);
+    }
+  }
+
+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 _LIBCPP_HIDE_FROM_ABI reference at(size_type __n) {
+    if (__n >= size())
+      __inplace_vector_throw_out_of_range();
+    return data()[__n];
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI 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:
+  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;
+      unchecked_emplace_back(*__it);
+      ++__expected_size;
+      ++__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 remain unchanged
+      __resize_down(__initial_size);
+      __throw_bad_alloc();
+    }
+  }
+
+  template <bool _ThrowOnMissingCapacity, class _Range>
+  constexpr _LIBCPP_HIDE_FROM_ABI __conditional_t<_ThrowOnMissingCapacity, void, ranges::borrowed_iterator_t<_Range>>
+  __append_range(_Range&& __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<_Range&>) {
+        auto __n = ranges::size(__rg);
+        size_t __copied;
+        if constexpr (_ThrowOnMissingCapacity) {
+          if (std::cmp_greater(__n, __remaining))
+            __throw_bad_alloc();
+          __copied = static_cast<size_t>(__n);
+        } else {
+          if (std::cmp_greater(__n, __remaining))
+            __copied = __remaining;
+          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> _Range>
+  constexpr _LIBCPP_HIDE_FROM_ABI void append_range(_Range&& __rg) {
+    __append_range<true>(std::forward<_Range>(__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 {
+      unreachable();
+    }
+  }
+
+  template <class... _Args>
+  constexpr _LIBCPP_HIDE_FROM_ABI pointer
+  try_emplace_back(_Args&&... __args) noexcept(is_nothrow_constructible_v<_Tp, _Args...> // 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(is_nothrow_copy_constructible_v<_Tp>) // strengthened
+  {
+    return try_emplace_back(__x);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI pointer
+  try_push_back(_Tp&& __x) noexcept(is_nothrow_move_constructible_v<_Tp> // strengthened
+  ) {
+    return try_emplace_back(std::move(__x));
+  }
+  template <_ContainerCompatibleRange<_Tp> _Range>
+  constexpr _LIBCPP_HIDE_FROM_ABI ranges::borrowed_iterator_t<_Range> try_append_range(_Range&& __rg) {
+    return __append_range<false>(std::forward<_Range>(__rg));
+  }
+
+  template <class... _Args>
+  constexpr _LIBCPP_HIDE_FROM_ABI reference
+  unchecked_emplace_back(_Args&&... __args) noexcept(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) {
+      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(is_nothrow_copy_constructible_v<_Tp>) /* strengthened */ {
+    return unchecked_emplace_back(__x);
+  }
+  constexpr _LIBCPP_HIDE_FROM_ABI reference
+  unchecked_push_back(_Tp&& __x) noexcept(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) {
+    pointer const __p = __unwrap_iter(__position);
+    if (size() == capacity())
+      __throw_bad_alloc();
+
+    if (__p == __elems_ + __sz_) {
+      unchecked_emplace_back(std::forward<_Args>(__args)...);
+    } else if (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_ - 1, __elems_ + __sz_);
+    }
+    // (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) {
+    pointer const __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
+      pointer const __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) {
+    pointer const __p = __unwrap_iter(__position);
+    if (std::cmp_greater(__m, capacity() - size()))
+      __throw_bad_alloc();
+    auto __n = static_cast<__small_size_type>(__m);
+
+    // Exception guarantee: Cannot modify the initial elements if copy/move construct/assign of _Tp throws or if
+    // iterator operations throw, so elements must be rotated in if they can throw. Otherwise, optimise by moving
+    // existing elements "out of the way" first then construct in-place to avoid swapping.
+    bool __can_avoid_rotate = is_nothrow_copy_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp> &&
+                              noexcept(++__it) && noexcept(*__it) && is_nothrow_constructible_v<_Tp, decltype(*__it)>;
+
+    if (__p == __elems_ + __sz_) {
+      __append_with_size(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent), __n);
+    } else if (__can_avoid_rotate) {
+      pointer const __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) {
+        std::destroy_at(__p + __i);
+        // This has already been checked to not throw so the container will never contain a destructed element
+        std::construct_at(__p + __i, *__it);
+        ++__it;
+        _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
+            __sz_ == __expected_size, "inplace_vector modified by iterator operation during insert");
+      }
+    } else {
+      __append_with_size(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent), __n);
+      std::rotate(__p, __elems_ + __sz_ - __n, __elems_ + __sz_);
+    }
+    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) {
+    pointer const __p = __unwrap_iter(__position);
+
+    if (__p == __elems_ + __sz_) {
+      __append_with_sentinel(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent));
+    } else {
+      pointer const __original_end = __elems_ + __sz_;
+      __append_with_sentinel(std::forward<_Iterator>(__it), std::forward<_Sentinel>(__sent));
+      std::rotate(__p, __original_end, __elems_ + __sz_);
+    }
+    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> _Range>
+  constexpr _LIBCPP_HIDE_FROM_ABI iterator insert_range(const_iterator __position, _Range&& __rg) {
+    decltype(auto) __first(ranges::begin(__rg));
+    decltype(auto) __sent(ranges::end(__rg));
+    if constexpr (ranges::sized_range<_Range&>) {
+      return __insert_with_size(__position, __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) noexcept /* strengthened */ {
+    pointer const __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) noexcept
+  /* strengthened */ {
+    pointer const __p = __unwrap_iter(__first);
+    pointer const __q = __unwrap_iter(__last);
+    _LIBCPP_ASSERT_VALID_INPUT_RANGE(__p <= __q, "inplace_vector::erase begin iterator is after end iterator");
+    const __small_size_type __erased = __q - __p;
+    std::move(__q, __elems_ + __sz_, __p);
+    __resize_down(__sz_ - __erased);
+  }
+
+  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() noexcept {
+    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());
+  }
+  // LWG4122
+  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(
+    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(
+    is_nothrow_move_assignable_v<_Tp> && noexcept(remove_cvref_t<_Predicate>(__pred)) &&
+    noexcept(static_cast<bool>(!std::declval<remove_cvref_t<_Predicate>&>()(std::declval<_Tp&>()))) // strengthened
+) {
+  auto __it = std::remove_if(__c.begin(), __c.end(), __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 c1181a3622513f..b5bdc58ab8d606 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -140,6 +140,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 5d679caac0b3b7..0e3cdd4c9070be 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -535,7 +535,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
 # if __has_builtin(__builtin_is_virtual_base_of)
 #   define __cpp_lib_is_virtual_base_of                 202406L
 # endif
diff --git a/libcxx/modules/CMakeLists.txt b/libcxx/modules/CMakeLists.txt
index d47d19a4755317..6859a497432215 100644
--- a/libcxx/modules/CMakeLists.txt
+++ b/libcxx/modules/CMakeLists.txt
@@ -52,6 +52,7 @@ set(LIBCXX_MODULE_STD_SOURCES
   std/generator.inc
   std/hazard_pointer.inc
   std/initializer_list.inc
+  std/inplace_vector.inc
   std/iomanip.inc
   std/ios.inc
   std/iosfwd.inc
diff --git a/libcxx/modules/std.compat.cppm.in b/libcxx/modules/std.compat.cppm.in
index 797b413f68e272..8d5cf5400034c6 100644
--- a/libcxx/modules/std.compat.cppm.in
+++ b/libcxx/modules/std.compat.cppm.in
@@ -65,9 +65,6 @@ module;
 #  if __has_include(<hazard_pointer>)
 #    error "please update the header information for <hazard_pointer> in headers_not_available in utils/libcxx/header_information.py"
 #  endif // __has_include(<hazard_pointer>)
-#  if __has_include(<inplace_vector>)
-#    error "please update the header information for <inplace_vector> in headers_not_available in utils/libcxx/header_information.py"
-#  endif // __has_include(<inplace_vector>)
 #  if __has_include(<linalg>)
 #    error "please update the header information for <linalg> in headers_not_available in utils/libcxx/header_information.py"
 #  endif // __has_include(<linalg>)
diff --git a/libcxx/modules/std.cppm.in b/libcxx/modules/std.cppm.in
index 0575774f6f42fd..8cf8a150e5ea0c 100644
--- a/libcxx/modules/std.cppm.in
+++ b/libcxx/modules/std.cppm.in
@@ -72,6 +72,7 @@ module;
 #include <functional>
 #include <future>
 #include <initializer_list>
+#include <inplace_vector>
 #if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
 #  include <iomanip>
 #endif
@@ -173,9 +174,6 @@ module;
 #  if __has_include(<hazard_pointer>)
 #    error "please update the header information for <hazard_pointer> in headers_not_available in utils/libcxx/header_information.py"
 #  endif // __has_include(<hazard_pointer>)
-#  if __has_include(<inplace_vector>)
-#    error "please update the header information for <inplace_vector> in headers_not_available in utils/libcxx/header_information.py"
-#  endif // __has_include(<inplace_vector>)
 #  if __has_include(<linalg>)
 #    error "please update the header information for <linalg> in headers_not_available in utils/libcxx/header_information.py"
 #  endif // __has_include(<linalg>)
diff --git a/libcxx/modules/std/inplace_vector.inc b/libcxx/modules/std/inplace_vector.inc
new file mode 100644
index 00000000000000..1d54d2615b0aa7
--- /dev/null
+++ b/libcxx/modules/std/inplace_vector.inc
@@ -0,0 +1,19 @@
+// -*- 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
+//
+//===----------------------------------------------------------------------===//
+
+export namespace std {
+
+  // [inplace.vector], class template inplace_vector
+  using std::inplace_vector;
+
+  // [inplace.vector.erasure], erasure
+  using std::erase;
+  using std::erase_if;
+
+} // namespace std
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index 506b5cd02c4495..2d0be2fa661f36 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -938,6 +938,23 @@ future vector
 future version
 initializer_list cstddef
 initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
 iomanip algorithm
 iomanip array
 iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 506b5cd02c4495..2d0be2fa661f36 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -938,6 +938,23 @@ future vector
 future version
 initializer_list cstddef
 initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
 iomanip algorithm
 iomanip array
 iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 828e1d62c6ec3e..920048db06d454 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -961,6 +961,23 @@ future vector
 future version
 initializer_list cstddef
 initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
 iomanip algorithm
 iomanip array
 iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 0bee6e9beb7af1..053326b6526e10 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -962,6 +962,23 @@ future vector
 future version
 initializer_list cstddef
 initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
 iomanip algorithm
 iomanip array
 iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 026c26f3bd9819..488c56973e2a01 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -948,6 +948,23 @@ future vector
 future version
 initializer_list cstddef
 initializer_list version
+inplace_vector cctype
+inplace_vector cmath
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cstdlib
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector exception
+inplace_vector initializer_list
+inplace_vector iosfwd
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector type_traits
+inplace_vector typeinfo
+inplace_vector version
 iomanip algorithm
 iomanip array
 iomanip atomic
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index 861fd2bb9ba98f..012ace6f4804cb 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -517,6 +517,17 @@ future typeinfo
 future version
 initializer_list cstddef
 initializer_list version
+inplace_vector cctype
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector initializer_list
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector version
 iomanip bitset
 iomanip cctype
 iomanip cerrno
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index a31139f1ee8565..668a4dbe11c7e6 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -516,6 +516,17 @@ future typeinfo
 future version
 initializer_list cstddef
 initializer_list version
+inplace_vector cctype
+inplace_vector compare
+inplace_vector cstddef
+inplace_vector cstdint
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector initializer_list
+inplace_vector limits
+inplace_vector new
+inplace_vector stdexcept
+inplace_vector version
 iomanip bitset
 iomanip cctype
 iomanip cerrno
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..9232715d4676a0
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/access.pass.cpp
@@ -0,0 +1,148 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+//       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 <inplace_vector>
+#include <cassert>
+#include <stdexcept>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+template <class C>
+constexpr 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>
+constexpr 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&) {
+    } catch (...) {
+      assert(false);
+    }
+  }
+#endif
+
+  assert(c.front() == start_value);
+  assert(c.back() == start_value + n - 1);
+}
+
+template <class Vector, bool IsConstexpr>
+constexpr void test_get() {
+  bool can_run = Vector::capacity() >= 10;
+  if consteval {
+    can_run &= IsConstexpr;
+  }
+  if (can_run) {
+    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, bool IsConstexpr>
+constexpr void test_set() {
+  const int n  = 10;
+  bool can_run = Vector::capacity() >= n;
+  if consteval {
+    can_run &= IsConstexpr;
+  }
+  if (can_run) {
+    int start_value = 35;
+    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, bool IsConstexpr>
+constexpr void test() {
+  test_get<Vector, IsConstexpr>();
+  test_set<Vector, IsConstexpr>();
+
+  union {
+    int _ = 0;
+    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()));
+}
+
+constexpr bool tests() {
+  test<std::inplace_vector<int, 0>, true>();
+  test<std::inplace_vector<int, 10>, true>();
+  test<std::inplace_vector<int, 100>, true>();
+  test<std::inplace_vector<MoveOnly, 0>, true>();
+  test<std::inplace_vector<MoveOnly, 10>, false>();
+  test<std::inplace_vector<MoveOnly, 100>, false>();
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  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..446349ab2dfe24
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/compare.pass.cpp
@@ -0,0 +1,131 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// friend bool operator==(const inplace_vector& lhs, const inplace_vector& rhs);
+// synthesized operator!=
+// constexpr auto operator<=>(const inplace_vector& x,
+//                            const inplace_vector& y);  // synth-three-way-result
+// synthesized operator<, operator>, operator<=, operator>=
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_comparisons.h"
+
+constexpr bool test() {
+  {
+    const std::inplace_vector<int, 0> c1, c2;
+    assert(testComparisons(c1, c2, true, false));
+  }
+  {
+    const std::inplace_vector<int, 10> c1, c2;
+    assert(testComparisons(c1, c2, true, false));
+  }
+  {
+    const std::inplace_vector<int, 10> c1(1, 1), c2(1, 2);
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    const std::inplace_vector<int, 10> c1, c2(1, 2);
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    const std::inplace_vector<int, 10> c1{1, 2, 1};
+    const std::inplace_vector<int, 10> c2{1, 2, 2};
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    const std::inplace_vector<int, 10> c1{3, 2, 3};
+    const std::inplace_vector<int, 10> c2{3, 1, 3};
+
+    assert(testComparisons(c1, c2, false, false));
+  }
+  {
+    const std::inplace_vector<int, 10> c1{1, 2};
+    const std::inplace_vector<int, 10> c2{1, 2, 0};
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    const std::inplace_vector<int, 10> c1{1, 2, 0};
+    const std::inplace_vector<int, 10> c2{3};
+    assert(testComparisons(c1, c2, false, true));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 0> c1, c2;
+    assert(testComparisons(c1, c2, true, false));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 10> c1, c2;
+    assert(testComparisons(c1, c2, true, false));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1)};
+    const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(1)};
+    assert(testComparisons(c1, c2, true, false));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1)};
+    const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(2)};
+    assert(testComparisons(c1, c2, false, true));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 10> c1;
+    const std::inplace_vector<LessAndEqComp, 10> c2(1, LessAndEqComp(2));
+    assert(testComparisons(c1, c2, false, true));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(2)};
+    const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)};
+    assert(testComparisons(c1, c2, false, false));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(3), LessAndEqComp(3), LessAndEqComp(3)};
+    const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(3), LessAndEqComp(2), LessAndEqComp(3)};
+    assert(testComparisons(c1, c2, false, false));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1), LessAndEqComp(2)};
+    const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(0)};
+    assert(testComparisons(c1, c2, false, true));
+  }
+  if !consteval {
+    const std::inplace_vector<LessAndEqComp, 10> c1{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(0)};
+    const std::inplace_vector<LessAndEqComp, 10> c2{LessAndEqComp(3)};
+    assert(testComparisons(c1, c2, false, true));
+  }
+  {
+    using V = std::inplace_vector<int, 0>;
+    assert((V() == V()));
+    assert(!(V() != V()));
+    assert(!(V() < V()));
+    assert((V() <= V()));
+    assert(!(V() > V()));
+    assert((V() >= V()));
+  }
+  {
+    using V = std::inplace_vector<int, 10>;
+    assert((V() == V()));
+    assert(!(V() != V()));
+    assert(!(V() < V()));
+    assert((V() <= V()));
+    assert(!(V() > V()));
+    assert((V() >= V()));
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  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..ce8555dd653ebb
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/compare.three_way.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>
+
+// 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>;
+template <typename T>
+using inplace_vector_size_0 = std::inplace_vector<T, 0>;
+
+// 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>());
+  assert(test_sequence_container_spaceship<inplace_vector_size_0>());
+  static_assert(test_sequence_container_spaceship<inplace_vector_size_0>());
+  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..5dc7020fa70d85
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/constant_initialization.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..5f00dd1faecff7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/capacity.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..641519c62c0b9a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/empty.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, 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..b71210a22580a7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/max_size.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..31081d4c6f2f15
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/reserve.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>
+
+// 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..d67fe2986240de
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size.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>
+
+// 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..4cc65dd73ca48a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.capacity/resize_size_value.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..b0024d3ca42887
--- /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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// class inplace_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..8319fccff40a21
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_iter_iter.pass.cpp
@@ -0,0 +1,119 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..e0f7640359122c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/assign_move.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>
+
+// 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..3573542f888f8b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_default.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..fd027183169097
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_iter_iter.pass.cpp
@@ -0,0 +1,177 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..60e4d9c880cd3a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/construct_size_value.pass.cpp
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..4d6fddacc654d3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.cons/move.pass.cpp
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..97e17f4df34713
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data.pass.cpp
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..cf1df0b3b3e210
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.data/data_const.pass.cpp
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/inplace.vector.erasure/erase.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase.pass.cpp
new file mode 100644
index 00000000000000..fa89dd944ae98f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase.pass.cpp
@@ -0,0 +1,95 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 T, size_t N, class U>
+//   typename inplace_vector<T, N>::size_type
+//   erase(inplace_vector<T, N>& c, const U& value);
+
+#include <inplace_vector>
+#include <optional>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class S, class U>
+constexpr 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 T, std::size_t N>
+constexpr void test1() {
+  using S = std::inplace_vector<T, N>;
+
+  test0(S(), 1, S(), 0);
+
+  if constexpr (S::capacity() >= 1) {
+    test0(S({1}), 1, S(), 1);
+    test0(S({1}), 2, S({1}), 0);
+  }
+
+  if constexpr (S::capacity() >= 2) {
+    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);
+  }
+
+  if constexpr (S::capacity() >= 3) {
+    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(), opt(), S(), 0);
+  if constexpr (S::capacity() >= 3) {
+    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);
+  }
+}
+
+template <class T>
+constexpr void test2() {
+  test1<T, 0>();
+  test1<T, 3>();
+  test1<T, 10>();
+  test1<T, 100>();
+}
+
+constexpr bool tests() {
+  test2<int>();
+  test2<long>();
+  test2<double>();
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase_if.pass.cpp b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase_if.pass.cpp
new file mode 100644
index 00000000000000..3642bc71dce468
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/inplace.vector.erasure/erase_if.pass.cpp
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 T, size_t N, class Predicate>
+//   typename inplace_vector<T, N>::size_type
+//   erase_if(inplace_vector<T, N>& c, Predicate pred);
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <class S, class Pred>
+constexpr 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 <class T, std::size_t N>
+constexpr void test1() {
+  using S = std::inplace_vector<T, N>;
+
+  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);
+
+  if constexpr (S::capacity() >= 1) {
+    test0(S({1}), is1, S(), 1);
+    test0(S({1}), is2, S({1}), 0);
+  }
+
+  if constexpr (S::capacity() >= 2) {
+    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);
+  }
+
+  if constexpr (S::capacity() >= 3) {
+    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);
+  }
+}
+
+template <class T>
+constexpr void test2() {
+  test1<T, 0>();
+  test1<T, 3>();
+  test1<T, 10>();
+  test1<T, 100>();
+}
+
+constexpr bool tests() {
+  test2<int>();
+  test2<long>();
+  test2<double>();
+
+  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..37e83391c3019a
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/reverse_iterators.pass.cpp
@@ -0,0 +1,92 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// 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 <inplace_vector>
+#include <cassert>
+#include <iterator>
+
+#include "MoveOnly.h"
+
+template <class Vector, bool IsConstexpr>
+constexpr void check_vector_reverse_iterators() {
+  bool ConstexprTests = true;
+  if consteval {
+    ConstexprTests = IsConstexpr;
+  }
+
+  if (ConstexprTests) {
+    Vector vec;
+    assert(vec.rbegin() == vec.rend());
+    assert(vec.crbegin() == vec.crend());
+  }
+  if (ConstexprTests && Vector::capacity() >= 10) {
+    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);
+  }
+}
+
+constexpr bool test() {
+  check_vector_reverse_iterators<std::inplace_vector<int, 0>, true>();
+  check_vector_reverse_iterators<std::inplace_vector<int, 10>, true>();
+  check_vector_reverse_iterators<std::inplace_vector<int, 100>, true>();
+  check_vector_reverse_iterators<std::inplace_vector<MoveOnly, 0>, true>();
+  check_vector_reverse_iterators<std::inplace_vector<MoveOnly, 10>, false>();
+  check_vector_reverse_iterators<std::inplace_vector<MoveOnly, 100>, false>();
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  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.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..90056fff8d9b56
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/clear.pass.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 clear() noexcept;
+
+#include <inplace_vector>
+#include <cassert>
+
+#include "test_macros.h"
+#include "MoveOnly.h"
+
+constexpr bool tests() {
+  {
+    std::inplace_vector<int, 10> c{1, 2, 3};
+    ASSERT_NOEXCEPT(c.clear());
+    c.clear();
+    assert(c.empty());
+  }
+  {
+    std::inplace_vector<int, 0> c;
+    ASSERT_NOEXCEPT(c.clear());
+    c.clear();
+    assert(c.empty());
+  }
+  {
+    std::inplace_vector<MoveOnly, 0> c;
+    ASSERT_NOEXCEPT(c.clear());
+    c.clear();
+    assert(c.empty());
+  }
+  if !consteval {
+    std::inplace_vector<MoveOnly, 10> c;
+    c.push_back(0);
+    ASSERT_NOEXCEPT(c.clear());
+    c.clear();
+    assert(c.empty());
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  tests();
+  static_assert(tests());
+  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..7ef83fb3754c3f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/destroy_elements.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, c++11, c++14, c++17, c++20, c++23
+
+// <inplace_vector>
+
+// Ensure that all the elements in the inplace_vector are destroyed
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <vector>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+struct DestroyTracker {
+  constexpr DestroyTracker(std::vector<bool>& vec) : vec_(&vec), index_(vec.size()) { vec.push_back(false); }
+
+  constexpr DestroyTracker(const DestroyTracker& other) : vec_(other.vec_), index_(vec_->size()) {
+    vec_->push_back(false);
+  }
+
+  constexpr DestroyTracker& operator=(const DestroyTracker&) { return *this; }
+  constexpr ~DestroyTracker() { (*vec_)[index_] = true; }
+
+  std::vector<bool>* vec_;
+  size_t index_;
+};
+
+template <std::size_t N, class Operation>
+constexpr void test(Operation operation) {
+  std::vector<bool> all_destroyed;
+
+  {
+    std::inplace_vector<DestroyTracker, N> 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; }));
+}
+
+template <typename V>
+constexpr void checked_op(V& vec, std::vector<bool>& tracker, int operation_number) {
+  bool needed       = (operation_number < 0) ? 2 : 1;
+  bool has_capacity = vec.capacity() - vec.size() >= needed;
+  if consteval {
+    if (!has_capacity)
+      return; // No exceptions in constant expression
+  }
+#ifdef TEST_HAS_NO_EXCEPTIONS
+  if (!has_capacity)
+    return;
+#else
+  try {
+#endif
+  switch (operation_number) {
+  case 0:
+    vec.emplace_back(tracker);
+    break;
+  case 1:
+    vec.push_back(DestroyTracker(tracker));
+    break;
+  case 2:
+    vec.push_back(static_cast<const DestroyTracker&>(DestroyTracker(tracker)));
+    break;
+  case 3:
+    vec.emplace(vec.begin(), tracker);
+    break;
+  case 4:
+    vec.insert(vec.begin(), DestroyTracker(tracker));
+    break;
+  case 5:
+    vec.insert(vec.begin(), static_cast<const DestroyTracker&>(DestroyTracker(tracker)));
+    break;
+  case -1:
+    vec.insert_range(vec.begin(), std::array<DestroyTracker, 2>{tracker, tracker});
+    break;
+  case -2:
+    vec.append_range(std::array<DestroyTracker, 2>{tracker, tracker});
+    break;
+  }
+  assert(has_capacity);
+#ifndef TEST_HAS_NO_EXCEPTIONS
+}
+catch (const std::bad_alloc&) {
+  assert(!has_capacity);
+}
+catch (...) {
+  assert(false);
+}
+#endif
+}
+
+template <typename V>
+constexpr void single_try_op(V& vec, std::vector<bool>& tracker, int operation_number) {
+  bool needed       = (operation_number < 0) ? 2 : 1;
+  bool has_capacity = vec.capacity() - vec.size() > needed;
+
+  switch (operation_number) {
+  case 0:
+    vec.try_emplace_back(tracker);
+    break;
+  case 1:
+    vec.try_push_back(DestroyTracker(tracker));
+    break;
+  case 2:
+    vec.try_push_back(static_cast<const DestroyTracker&>(DestroyTracker(tracker)));
+    break;
+  case 3:
+    vec.try_emplace(vec.begin(), tracker);
+    break;
+  case 4:
+    vec.try_insert(vec.begin(), DestroyTracker(tracker));
+    break;
+  case 5:
+    vec.try_insert(vec.begin(), static_cast<const DestroyTracker&>(DestroyTracker(tracker)));
+    break;
+  case -1:
+    vec.insert_range(vec.begin(), std::array<DestroyTracker, 2>{tracker, tracker});
+    break;
+  case -2:
+    vec.append_range(std::array<DestroyTracker, 2>{tracker, tracker});
+    break;
+  }
+  assert(has_capacity);
+}
+
+template <std::size_t N>
+constexpr bool test() {
+  using V = std::inplace_vector<DestroyTracker, N>;
+  for (int i = -2; i <= 5; ++i) {
+    test<N>([i](V& vec, std::vector<bool>& tracker) { checked_op(vec, tracker, i); });
+  }
+
+  return true;
+}
+
+constexpr bool tests() {
+  test<0>();
+  test<10>();
+  test<100>();
+  return true;
+}
+
+int main() {
+  tests();
+  // inplace_vector does not support constexpr evaluation when type is not trivially destructible
+  // static_assert(tests());
+}
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..80ed572e195624
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/erase_iter_iter.pass.cpp
@@ -0,0 +1,174 @@
+//===----------------------------------------------------------------------===//
+//
+// 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..87330978ef22c9
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace.vector/vector.modifiers/swap.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>
+
+// template <class T, size_t N>
+//   friend void swap(inplace_vector<T, N>& x, inplace_vector<T, N>& y);
+
+// 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, 0> vo;
+    std::inplace_vector<operator_hijacker, 0> v;
+    v.swap(vo);
+  }
+  {
+    std::inplace_vector<operator_hijacker, 10> vo;
+    std::inplace_vector<operator_hijacker, 10> 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 985ffeffab96db..de4df21e745097 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
@@ -7022,17 +7022,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/test/support/test_container_comparisons.h b/libcxx/test/support/test_container_comparisons.h
index 543c5899922d02..e72efc39a8ad92 100644
--- a/libcxx/test/support/test_container_comparisons.h
+++ b/libcxx/test/support/test_container_comparisons.h
@@ -12,18 +12,53 @@
 
 #include <functional>
 #include <set>
+#include <cstddef>
+#include <type_traits>
 
+#include "test_macros.h"
 #include "test_comparisons.h"
 
+#if TEST_STD_VER >= 26
+#  include <inplace_vector>
+
+template <typename C>
+concept is_inplace_vector = std::is_same_v<C, std::inplace_vector<typename C::value_type, C::capacity()>>;
+#else
+template <typename C>
+concept is_inplace_vector = false;
+#endif
+
+template <typename C>
+constexpr bool can_run() {
+  if constexpr (is_inplace_vector<C>) {
+    if consteval {
+      return std::is_trivial_v<typename C::value_type>;
+    }
+  }
+  return true;
+}
+
+template <typename C>
+constexpr std::size_t get_max_size() {
+  if constexpr (is_inplace_vector<C>) {
+    return C::max_size();
+  }
+  return static_cast<std::size_t>(-1);
+}
+
 // Implementation detail of `test_sequence_container_spaceship`
 template <template <typename...> typename Container, typename Elem, typename Order>
 constexpr void test_sequence_container_spaceship_with_type() {
+  if (!can_run<Container<Elem>>())
+    return;
   // Empty containers
   {
     Container<Elem> l1;
     Container<Elem> l2;
     assert(testOrder(l1, l2, Order::equivalent));
   }
+  if (get_max_size<Container<Elem>>() < 2)
+    return;
   // Identical contents
   {
     Container<Elem> l1{1, 1};
@@ -91,6 +126,8 @@ template <template <typename...> typename ContainerAdaptor,
           typename Elem,
           typename Order>
 constexpr void test_sequence_container_adaptor_spaceship_with_type() {
+  if (!can_run<Container<Elem>>())
+    return;
   // Empty containers
   {
     Container<Elem> l1;
@@ -99,6 +136,8 @@ constexpr void test_sequence_container_adaptor_spaceship_with_type() {
     ContainerAdaptor<Elem, Container<Elem>> ca2{l2};
     assert(testOrder(ca1, ca2, Order::equivalent));
   }
+  if (get_max_size<Container<Elem>>() < 2)
+    return;
   // Identical contents
   {
     Container<Elem> l1{1, 1};
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index cb5ff770b1196e..b6e70f7c284b3b 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -685,7 +685,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",
diff --git a/libcxx/utils/libcxx/header_information.py b/libcxx/utils/libcxx/header_information.py
index fd48b35a88b558..8d1eb481c57a71 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -86,6 +86,7 @@
     "deque": ["compare", "initializer_list"],
     "filesystem": ["compare"],
     "forward_list": ["compare", "initializer_list"],
+    "inplace_vector": ["compare", "initializer_list"],
     "ios": ["iosfwd"],
     "iostream": ["ios", "istream", "ostream", "streambuf"],
     "iterator": ["compare", "concepts"],
@@ -127,7 +128,6 @@
     "flat_set",
     "generator",
     "hazard_pointer",
-    "inplace_vector",
     "linalg",
     "rcu",
     "spanstream",



More information about the libcxx-commits mailing list