[libcxx-commits] [libcxx] [libc++] Implement P0843R14: `inplace_vector` (PR #204008)
William Tran-Viet via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Jun 17 22:55:40 PDT 2026
https://github.com/smallp-o-p updated https://github.com/llvm/llvm-project/pull/204008
>From 2b57d1e56ab1c58386c78e9c983e0a9d53639e14 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 11 May 2026 20:55:42 -0400
Subject: [PATCH 01/11] Update documentation, transitive includes, module map
for inplace_vector
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +-
libcxx/docs/Hardening.rst | 7 +++
libcxx/docs/ReleaseNotes/23.rst | 1 +
libcxx/docs/Status/Cxx2cPapers.csv | 6 +-
libcxx/include/module.modulemap.in | 5 ++
libcxx/modules/std.compat.cppm.in | 3 -
libcxx/modules/std.cppm.in | 4 +-
libcxx/modules/std/inplace_vector.inc | 15 +++++
.../test/libcxx/transitive_includes/cxx03.csv | 5 ++
.../test/libcxx/transitive_includes/cxx11.csv | 5 ++
.../test/libcxx/transitive_includes/cxx14.csv | 5 ++
.../test/libcxx/transitive_includes/cxx17.csv | 5 ++
.../test/libcxx/transitive_includes/cxx26.csv | 11 ++++
.../inplace_vector.version.compile.pass.cpp | 62 +++++++++++++++++++
.../version.version.compile.pass.cpp | 16 ++---
.../generate_feature_test_macro_components.py | 3 +-
libcxx/utils/libcxx/header_information.py | 1 -
17 files changed, 132 insertions(+), 24 deletions(-)
create mode 100644 libcxx/modules/std/inplace_vector.inc
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 1b748e37293df..9ac0f558900f7 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -484,7 +484,7 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_hazard_pointer`` *unimplemented*
---------------------------------------------------------- -----------------
- ``__cpp_lib_inplace_vector`` *unimplemented*
+ ``__cpp_lib_inplace_vector`` ``202603L``
---------------------------------------------------------- -----------------
``__cpp_lib_integer_sequence`` ``202511L``
---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/Hardening.rst b/libcxx/docs/Hardening.rst
index 1360518379aef..f32f24ad9fdb6 100644
--- a/libcxx/docs/Hardening.rst
+++ b/libcxx/docs/Hardening.rst
@@ -440,6 +440,13 @@ CMake configuration time. The available options are:
ABI impact: changes the iterator type of ``std::array``, its size and its layout.
+- ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_INPLACE_VECTOR`` -- changes the iterator type of
+ ``inplace_vector`` to a bounded iterator that keeps track of whether it's within the
+ bounds of the original container and asserts it on every dereference and when
+ performing iterator arithmetics.
+
+ ABI impact: changes the iterator type of ``inplace_vector``.
+
ABI tags
--------
diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index c8f7cf5455d92..aa2ecd5510e19 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -51,6 +51,7 @@ Implemented Papers
- P2542R8: ``views::concat`` (`Github <https://llvm.org/PR105419>`__)
- P3383R3: ``mdspan.at()`` (`Github <https://llvm.org/PR175213>`__)
- P3508R0: Wording for "constexpr for specialized memory algorithms" (`Github <https://llvm.org/PR118379>`__)
+- P0843R14: ``inplace_vector`` (`Github <https://llvm.org/PR105433>`__)
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 2132e80251657..337a28eae5889 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)","|Complete|","22","`#105430 <https://github.com/llvm/llvm-project/issues/105430>`__",""
"`P3217R0 <https://wg21.link/P3217R0>`__","Adjoints to 'Enabling list-initialization for algorithms': find_last","2024-06 (St. Louis)","","","`#105431 <https://github.com/llvm/llvm-project/issues/105431>`__",""
"`P2985R0 <https://wg21.link/P2985R0>`__","A type trait for detecting virtual base classes","2024-06 (St. Louis)","|Complete|","20","`#105432 <https://github.com/llvm/llvm-project/issues/105432>`__",""
-"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","","","`#105433 <https://github.com/llvm/llvm-project/issues/105433>`__",""
+"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","|Partial|","23","`#105433 <https://github.com/llvm/llvm-project/issues/105433>`__","inplace_vector<T,N> where T is not a trivial type cannot be used in a constant expression."
"`P3235R3 <https://wg21.link/P3235R3>`__","``std::print`` more types faster with less memory","2024-06 (St. Louis)","","","`#105435 <https://github.com/llvm/llvm-project/issues/105435>`__",""
"`P2968R2 <https://wg21.link/P2968R2>`__","Make ``std::ignore`` a first-class object","2024-06 (St. Louis)","|Complete|","19","`#105436 <https://github.com/llvm/llvm-project/issues/105436>`__",""
"`P2075R6 <https://wg21.link/P2075R6>`__","Philox as an extension of the C++ RNG engines","2024-06 (St. Louis)","","","`#105437 <https://github.com/llvm/llvm-project/issues/105437>`__",""
@@ -195,8 +195,8 @@
"`P3948R1 <https://wg21.link/P3948R1>`__","``constant_wrapper`` is the only tool needed for passing constant expressions via function arguments","2026-03 (Croydon)","","","`#189604 <https://github.com/llvm/llvm-project/issues/189604>`__",""
"`P3978R3 <https://wg21.link/P3978R3>`__","``constant_wrapper`` should unwrap on call and subscript","2026-03 (Croydon)","|Complete|","23","`#189605 <https://github.com/llvm/llvm-project/issues/189605>`__",""
"`P3961R1 <https://wg21.link/P3961R1>`__","Less double indirection in ``function_ref`` (RU-220)","2026-03 (Croydon)","","","`#189606 <https://github.com/llvm/llvm-project/issues/189606>`__",""
-"`P3981R2 <https://wg21.link/P3981R2>`__","Better return types in ``std::inplace_vector`` and ``std::exception_ptr_cast``","2026-03 (Croydon)","","","`#189607 <https://github.com/llvm/llvm-project/issues/189607>`__",""
-"`P4022R0 <https://wg21.link/P4022R0>`__","Remove ``try_append_range`` from ``inplace_vector`` for now","2026-03 (Croydon)","","","`#189608 <https://github.com/llvm/llvm-project/issues/189608>`__",""
+"`P3981R2 <https://wg21.link/P3981R2>`__","Better return types in ``std::inplace_vector`` and ``std::exception_ptr_cast``","2026-03 (Croydon)","|Partial|","23","`#189607 <https://github.com/llvm/llvm-project/issues/189607>`__","inplace_vector portion is completed."
+"`P4022R0 <https://wg21.link/P4022R0>`__","Remove ``try_append_range`` from ``inplace_vector`` for now","2026-03 (Croydon)","|Complete|","23","`#189608 <https://github.com/llvm/llvm-project/issues/189608>`__",""
"`P4037R1 <https://wg21.link/P4037R1>`__","Supporting ``signed char`` and ``unsigned char`` in random number generation","2026-03 (Croydon)","","","`#189609 <https://github.com/llvm/llvm-project/issues/189609>`__",""
"`P3450R1 <https://wg21.link/P3450R1>`__","Extend ``std::is_within_lifetime``","2026-03 (Croydon)","","","`#189610 <https://github.com/llvm/llvm-project/issues/189610>`__",""
"`P3982R2 <https://wg21.link/P3982R2>`__","Split ``strided_slice`` into ``extent_slice`` and ``range_slice`` for C++26","2026-03 (Croydon)","","","`#189611 <https://github.com/llvm/llvm-project/issues/189611>`__",""
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index b11055940a82c..1301b80da9ce8 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1504,6 +1504,11 @@ module std [system] {
export std.ios // base class
}
+ module inplace_vector {
+ header "inplace_vector"
+ export *
+ }
+
module iterator {
module access { header "__iterator/access.h" }
module advance { header "__iterator/advance.h" }
diff --git a/libcxx/modules/std.compat.cppm.in b/libcxx/modules/std.compat.cppm.in
index dd7385bf33a42..09ceace63cc83 100644
--- a/libcxx/modules/std.compat.cppm.in
+++ b/libcxx/modules/std.compat.cppm.in
@@ -57,9 +57,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 6de6369c3387f..bbdcad23cf8d5 100644
--- a/libcxx/modules/std.cppm.in
+++ b/libcxx/modules/std.cppm.in
@@ -66,6 +66,7 @@ module;
#include <functional>
#include <future>
#include <initializer_list>
+#include <inplace_vector>
#include <iomanip>
#include <ios>
#include <iosfwd>
@@ -139,9 +140,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 0000000000000..458ca4488fb46
--- /dev/null
+++ b/libcxx/modules/std/inplace_vector.inc
@@ -0,0 +1,15 @@
+// -*- 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 {
+#if _LIBCPP_STD_VER >= 26
+ using std::inplace_vector;
+#endif
+
+}
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index c0031543e47bc..920a6145a02b8 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -122,15 +122,19 @@ atomic ratio
atomic type_traits
atomic version
barrier atomic
+barrier cctype
barrier climits
barrier cmath
barrier compare
barrier concepts
barrier cstddef
barrier cstdint
+barrier cstdio
barrier cstdlib
barrier cstring
barrier ctime
+barrier cwchar
+barrier cwctype
barrier exception
barrier initializer_list
barrier iosfwd
@@ -2032,6 +2036,7 @@ stdexcept new
stdexcept type_traits
stdexcept typeinfo
stdexcept version
+stop_token cstddef
stop_token iosfwd
stop_token version
streambuf algorithm
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index c0031543e47bc..920a6145a02b8 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -122,15 +122,19 @@ atomic ratio
atomic type_traits
atomic version
barrier atomic
+barrier cctype
barrier climits
barrier cmath
barrier compare
barrier concepts
barrier cstddef
barrier cstdint
+barrier cstdio
barrier cstdlib
barrier cstring
barrier ctime
+barrier cwchar
+barrier cwctype
barrier exception
barrier initializer_list
barrier iosfwd
@@ -2032,6 +2036,7 @@ stdexcept new
stdexcept type_traits
stdexcept typeinfo
stdexcept version
+stop_token cstddef
stop_token iosfwd
stop_token version
streambuf algorithm
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index c2eb5b44e8d7a..cfcf7bc7c4c19 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -125,15 +125,19 @@ atomic ratio
atomic type_traits
atomic version
barrier atomic
+barrier cctype
barrier climits
barrier cmath
barrier compare
barrier concepts
barrier cstddef
barrier cstdint
+barrier cstdio
barrier cstdlib
barrier cstring
barrier ctime
+barrier cwchar
+barrier cwctype
barrier exception
barrier initializer_list
barrier iosfwd
@@ -2072,6 +2076,7 @@ stdexcept new
stdexcept type_traits
stdexcept typeinfo
stdexcept version
+stop_token cstddef
stop_token iosfwd
stop_token version
streambuf algorithm
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 332cb62f35b5f..534776e6f0526 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -122,15 +122,19 @@ atomic ratio
atomic type_traits
atomic version
barrier atomic
+barrier cctype
barrier climits
barrier cmath
barrier compare
barrier concepts
barrier cstddef
barrier cstdint
+barrier cstdio
barrier cstdlib
barrier cstring
barrier ctime
+barrier cwchar
+barrier cwctype
barrier exception
barrier initializer_list
barrier iosfwd
@@ -2085,6 +2089,7 @@ stdexcept new
stdexcept type_traits
stdexcept typeinfo
stdexcept version
+stop_token cstddef
stop_token iosfwd
stop_token version
streambuf algorithm
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index 1450a13e125ef..7aa17cdb19acc 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -443,6 +443,17 @@ future tuple
future typeinfo
future version
initializer_list version
+inplace_vector cctype
+inplace_vector compare
+inplace_vector cstdint
+inplace_vector cstring
+inplace_vector cwchar
+inplace_vector cwctype
+inplace_vector initializer_list
+inplace_vector limits
+inplace_vector optional
+inplace_vector stdexcept
+inplace_vector version
iomanip cctype
iomanip cerrno
iomanip climits
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 0000000000000..849c754f015f3
--- /dev/null
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/inplace_vector.version.compile.pass.cpp
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+
+// <inplace_vector>
+
+// Test the feature test macros defined by <inplace_vector>
+
+// clang-format off
+
+#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 != 202603L
+# error "__cpp_lib_inplace_vector should have the value 202603L in c++26"
+# endif
+
+#endif // TEST_STD_VER > 23
+
+// clang-format on
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 20c16700ef76a..0a51929660a55 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
@@ -7199,17 +7199,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
-# 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 != 202603L
+# error "__cpp_lib_inplace_vector should have the value 202603L in c++26"
# endif
# ifndef __cpp_lib_int_pow2
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index d8fb575b97b2f..f57e64ee12a39 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -759,9 +759,8 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_inplace_vector",
- "values": {"c++26": 202406}, # P0843R14 inplace_vector
+ "values": {"c++26": 202603}, # 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 384ff9f759460..5e6e4565383e8 100644
--- a/libcxx/utils/libcxx/header_information.py
+++ b/libcxx/utils/libcxx/header_information.py
@@ -166,7 +166,6 @@ def __hash__(self) -> int:
"debugging",
"generator",
"hazard_pointer",
- "inplace_vector",
"linalg",
"rcu",
"spanstream",
>From 70bdc288f0c7d69001e5f9517926716b3c72aa07 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 11 May 2026 20:55:57 -0400
Subject: [PATCH 02/11] Implement std::inplace_vector<T,N>
---
...-hardening-mode-fast-with-abi-breaks.cmake | 1 +
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/inplace_vector | 1130 +++++++++++++++++
libcxx/include/version | 4 +-
.../inplace_vector/assert.back.empty.pass.cpp | 29 +
.../assert.front.empty.pass.cpp | 27 +
.../inplace_vector/assert.index.oob.pass.cpp | 32 +
.../inplace_vector/assert.iterator.pass.cpp | 116 ++
.../assert.pop_back.empty.pass.cpp | 26 +
...sert.unchecked_push_back.capacity.pass.cpp | 35 +
.../assert.zero_capacity.pass.cpp | 31 +
.../inplace_vector/nodiscard.verify.cpp | 90 ++
.../sequences/inplace_vector/access.pass.cpp | 121 ++
.../inplace_vector/addressof.compile.pass.cpp | 52 +
.../sequences/inplace_vector/common.h | 161 +++
.../sequences/inplace_vector/compare.pass.cpp | 104 ++
.../inplace_vector/compare.three_way.pass.cpp | 108 ++
.../constant_initialization.pass.cpp | 26 +
.../inplace_vector/contiguous.pass.cpp | 39 +
.../inplace.vector.capacity/capacity.pass.cpp | 44 +
.../inplace.vector.capacity/empty.pass.cpp | 37 +
.../inplace.vector.capacity/max_size.pass.cpp | 44 +
.../inplace.vector.capacity/reserve.pass.cpp | 49 +
.../resize_size.pass.cpp | 44 +
.../resize_size_exceptions.pass.cpp | 42 +
.../resize_size_value.pass.cpp | 44 +
.../resize_size_value_exceptions.pass.cpp | 44 +
.../shrink_to_fit.pass.cpp | 38 +
.../inplace.vector.capacity/size.pass.cpp | 43 +
.../inplace.vector.capacity/swap.pass.cpp | 76 ++
.../inplace.vector.cons/assign_copy.pass.cpp | 65 +
.../assign_initializer_list.pass.cpp | 44 +
.../assign_iter_iter.pass.cpp | 58 +
.../inplace.vector.cons/assign_move.pass.cpp | 95 ++
.../assign_size_value.pass.cpp | 44 +
.../construct_default.pass.cpp | 67 +
.../construct_from_range.pass.cpp | 52 +
.../construct_iter_iter.pass.cpp | 54 +
.../construct_size.pass.cpp | 47 +
.../construct_size_value.pass.cpp | 47 +
.../copy.move_only.verify.cpp | 25 +
.../inplace.vector.cons/copy.pass.cpp | 42 +
.../inplace.vector.cons/exceptions.pass.cpp | 128 ++
.../initializer_list.pass.cpp | 40 +
.../inplace.vector.cons/move.pass.cpp | 67 +
.../op_equal_initializer_list.pass.cpp | 45 +
.../inplace.vector.data/data.pass.cpp | 50 +
.../inplace.vector.data/data_const.pass.cpp | 63 +
.../inplace.vector.erasure/erase.pass.cpp | 42 +
.../inplace.vector.erasure/erase_if.pass.cpp | 42 +
.../append_range.pass.cpp | 68 +
.../assign_range.pass.cpp | 64 +
.../inplace.vector.modifiers/clear.pass.cpp | 38 +
.../destroy_elements.pass.cpp | 72 ++
.../inplace.vector.modifiers/emplace.pass.cpp | 62 +
.../emplace_back.pass.cpp | 59 +
.../erase_iter.pass.cpp | 50 +
.../erase_iter_iter.pass.cpp | 50 +
.../insert_iter_initializer_list.pass.cpp | 46 +
.../insert_iter_iter_iter.pass.cpp | 82 ++
.../insert_iter_lvalue.pass.cpp | 49 +
.../insert_iter_rvalue.pass.cpp | 55 +
.../insert_iter_size_value.pass.cpp | 46 +
.../insert_range.pass.cpp | 84 ++
.../pop_back.pass.cpp | 38 +
.../push_back.pass.cpp | 48 +
.../push_back_exception_safety.pass.cpp | 72 ++
.../push_back_rvalue.pass.cpp | 54 +
.../try_push_back.pass.cpp | 116 ++
.../unchecked_push_back.pass.cpp | 68 +
.../inplace.vector.special/swap.pass.cpp | 63 +
...rator_concept_conformance.compile.pass.cpp | 32 +
.../inplace_vector/iterators.pass.cpp | 128 ++
...range_concept_conformance.compile.pass.cpp | 30 +
.../inplace_vector/reverse_iterators.pass.cpp | 68 +
.../triviality.compile.pass.cpp | 141 ++
.../inplace_vector/types.compile.pass.cpp | 53 +
.../zero_capacity.exceptions.pass.cpp | 124 ++
.../libcxx/test/features/libcxx_macros.py | 1 +
79 files changed, 5614 insertions(+), 2 deletions(-)
create mode 100644 libcxx/include/inplace_vector
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/assert.back.empty.pass.cpp
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/assert.front.empty.pass.cpp
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/assert.index.oob.pass.cpp
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/assert.iterator.pass.cpp
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/assert.pop_back.empty.pass.cpp
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/assert.unchecked_push_back.capacity.pass.cpp
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/nodiscard.verify.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/access.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/addressof.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/common.h
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/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/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_exceptions.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/resize_size_value_exceptions.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.capacity/swap.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.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/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.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/inplace.vector.modifiers/append_range.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/assign_range.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/clear.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/destroy_elements.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/emplace.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/emplace_back.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/erase_iter.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/erase_iter_iter.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_initializer_list.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_iter_iter.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_lvalue.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_rvalue.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_size_value.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_range.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/pop_back.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_exception_safety.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_rvalue.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/try_push_back.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/unchecked_push_back.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.special/swap.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/triviality.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/types.compile.pass.cpp
create mode 100644 libcxx/test/std/containers/sequences/inplace_vector/zero_capacity.exceptions.pass.cpp
diff --git a/libcxx/cmake/caches/Generic-hardening-mode-fast-with-abi-breaks.cmake b/libcxx/cmake/caches/Generic-hardening-mode-fast-with-abi-breaks.cmake
index 2d617737e9635..185b6fa2abfcd 100644
--- a/libcxx/cmake/caches/Generic-hardening-mode-fast-with-abi-breaks.cmake
+++ b/libcxx/cmake/caches/Generic-hardening-mode-fast-with-abi-breaks.cmake
@@ -6,6 +6,7 @@ set(_defines
_LIBCPP_ABI_BOUNDED_UNIQUE_PTR
_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY
_LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+ _LIBCPP_ABI_BOUNDED_ITERATORS_IN_INPLACE_VECTOR
)
set(LIBCXX_ABI_DEFINES "${_defines}" CACHE STRING "")
set(LIBCXX_TEST_PARAMS "enable_modules=clang" CACHE STRING "")
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index cb7ae820bc012..b2add223b1dd0 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -1042,6 +1042,7 @@ set(files
functional
future
initializer_list
+ inplace_vector
iomanip
ios
iosfwd
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
new file mode 100644
index 0000000000000..0d0f0418274dd
--- /dev/null
+++ b/libcxx/include/inplace_vector
@@ -0,0 +1,1130 @@
+// -*- 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
+
+namespace std {
+ template<class T, size_t N>
+ class inplace_vector {
+ 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], 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 optional<reference> try_emplace_back(Args&&... args);
+ constexpr optional<reference> try_push_back(const T& x);
+ constexpr optional<reference> try_push_back(T&& x);
+
+ 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;
+
+ friend constexpr bool operator==(const inplace_vector& x,
+ const inplace_vector& y);
+ friend constexpr auto
+ operator<=>(const inplace_vector& x, const inplace_vector& y)
+ requires requires (const T t) { synth-three-way(t, t); }
+ {
+ return lexicographical_compare_three_way(x.begin(), x.end(), y.begin(), y.end(),
+ synth-three-way);
+ }
+ friend constexpr 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); }
+ };
+}
+*/
+
+#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+# include <__cxx03/__config>
+#else
+# include <__config>
+
+# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+# endif
+
+_LIBCPP_PUSH_MACROS
+# include <__undef_macros>
+
+# if _LIBCPP_STD_VER >= 26
+# include <__algorithm/fill_n.h>
+# include <__algorithm/lexicographical_compare_three_way.h>
+# include <__algorithm/min.h>
+# include <__algorithm/move.h>
+# include <__algorithm/move_backward.h>
+# include <__algorithm/ranges_copy.h>
+# include <__algorithm/ranges_copy_n.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 <__compare/three_way_comparable.h>
+# include <__concepts/assignable.h>
+# include <__cstddef/ptrdiff_t.h>
+# include <__cstddef/size_t.h>
+# include <__iterator/bounded_iter.h>
+# include <__iterator/capacity_aware_iterator.h>
+# include <__iterator/concepts.h>
+# include <__iterator/distance.h>
+# include <__iterator/iterator_traits.h>
+# include <__iterator/move_iterator.h>
+# include <__iterator/reverse_iterator.h>
+# include <__memory/construct_at.h>
+# include <__memory/destroy.h>
+# include <__memory/ranges_destroy.h>
+# include <__memory/ranges_uninitialized_algorithms.h>
+# include <__memory/uninitialized_algorithms.h>
+# include <__new/exceptions.h>
+# include <__ranges/access.h>
+# include <__ranges/concepts.h>
+# include <__ranges/container_compatible_range.h>
+# include <__ranges/from_range.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_copyable.h>
+# include <__type_traits/is_trivially_destructible.h>
+# include <__utility/exception_guard.h>
+# include <__utility/move.h>
+# include <__utility/unreachable.h>
+# include <__verbose_trap>
+# include <initializer_list>
+# include <limits>
+# include <optional>
+# include <stdexcept>
+# include <version>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp, size_t _Cap>
+class inplace_vector {
+private:
+ static constexpr decltype(auto) __get_size_type() {
+ if constexpr (_Cap <= std::numeric_limits<unsigned char>::max() && sizeof(unsigned char) < sizeof(std::size_t))
+ return static_cast<unsigned char>(0);
+ else if constexpr (_Cap <= std::numeric_limits<unsigned short>::max() &&
+ sizeof(unsigned short) < sizeof(std::size_t))
+ return static_cast<unsigned short>(0);
+ else if constexpr (_Cap <= std::numeric_limits<unsigned int>::max() && sizeof(unsigned int) < sizeof(std::size_t))
+ return static_cast<unsigned int>(0);
+ else if constexpr (_Cap <= std::numeric_limits<unsigned long>::max() && sizeof(unsigned long) < sizeof(std::size_t))
+ return static_cast<unsigned long>(0);
+ else
+ return static_cast<std::size_t>(0);
+ }
+
+ using __size_type = decltype(__get_size_type());
+
+ union {
+ _Tp __elems_[_Cap];
+ };
+ __size_type __size_{0};
+
+ constexpr void __init() {
+ if consteval {
+ if constexpr (is_trivially_copyable_v<_Tp> && is_trivially_default_constructible_v<_Tp> &&
+ is_trivially_assignable_v<_Tp&, _Tp>) {
+ for (size_t __i{0}; __i < _Cap; ++__i) {
+ __elems_[__i] = _Tp();
+ }
+ } else {
+# if !defined(__cpp_trivial_union)
+ _LIBCPP_VERBOSE_ABORT("std::inplace_vector<T,N> currently cannot be used in constant expressions for "
+ "non-trivial T on compilers where P3074 is not implemented.");
+# endif
+ }
+ }
+ // std::start_lifetime_as_array?
+ }
+
+public:
+ 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_IN_INPLACE_VECTOR
+ using iterator = __bounded_iter<pointer>;
+ using const_iterator = __bounded_iter<const_pointer>;
+# else
+ using iterator = __capacity_aware_iterator<pointer, inplace_vector<_Tp, _Cap>, _Cap>;
+ using const_iterator = __capacity_aware_iterator<const_pointer, inplace_vector<_Tp, _Cap>, _Cap>;
+# endif
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+private:
+ struct _ConstructTransaction {
+ constexpr explicit _ConstructTransaction(inplace_vector& __v, size_type __n)
+ : __v_(__v), __pos_(__v.data() + __v.__size_), __new_end_(__v.data() + __v.__size_ + __n) {}
+
+ constexpr ~_ConstructTransaction() { __v_.__size_ = __pos_ - __v_.data(); }
+
+ inplace_vector& __v_;
+ pointer __pos_;
+ const_pointer const __new_end_;
+
+ _ConstructTransaction(_ConstructTransaction const&) = delete;
+ _ConstructTransaction& operator=(_ConstructTransaction const&) = delete;
+ };
+
+ constexpr void __move_range(pointer __from_s, pointer __from_e, pointer __to) {
+ pointer __old_last = data() + __size_;
+ difference_type __n = __old_last - __to;
+ {
+ pointer __i = __from_s + __n;
+ _ConstructTransaction __tx(*this, __from_e - __i);
+ for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, ++__pos, __tx.__pos_ = __pos) {
+ std::construct_at(__pos, std::move(*__i));
+ }
+ }
+ std::move_backward(__from_s, __from_s + __n, __old_last);
+ }
+
+ template <class _It, class _Sentinel>
+ constexpr void __assign(_It __first, _Sentinel __last) {
+ if constexpr (std::sized_sentinel_for<_Sentinel, _It>) {
+ auto __d = std::ranges::distance(__first, __last);
+ reserve(__d);
+
+ if (size() > static_cast<size_type>(__d)) {
+ auto [__it_in, __it_out] = std::ranges::copy(std::move(__first), __last, begin());
+ std::ranges::destroy(__it_out, end());
+ } else {
+ auto [__it_in, __it_out] = std::ranges::copy_n(std::move(__first), __size_, data());
+ std::ranges::uninitialized_copy(__it_in, __last, __it_out, data() + _Cap);
+ }
+ __size_ = __d;
+ } else {
+ size_t __d = 0;
+ for (; __first != __last && __d < __size_; (void)++__first, ++__d) {
+ data()[__d] = *__first;
+ }
+
+ if (__first == __last) { // __d <= size()
+ std::destroy(data() + __d, data() + __size_);
+ __size_ = __d;
+ } else { // __d > size()
+ while (__first != __last) {
+ emplace_back(*__first);
+ __first++;
+ }
+ }
+ }
+ }
+
+ template <class _It, class _Sentinel>
+ constexpr iterator __insert(const_iterator __position, _It __first, _Sentinel __last) {
+ pointer __pos = data() + (__position - cbegin());
+ size_type __old_size = __size_;
+ if constexpr (std::sized_sentinel_for<_Sentinel, _It>) {
+ const auto __d = std::ranges::distance(__first, __last);
+ if (__d > static_cast<difference_type>(_Cap - __size_)) {
+ std::__throw_bad_alloc();
+ }
+ std::ranges::uninitialized_copy(std::move(__first), __last, data() + __size_, data() + _Cap);
+ __size_ += __d;
+ } else {
+ auto __guard = std::__make_exception_guard([this, __old_size]() {
+ std::ranges::destroy(this->data() + __old_size, this->data() + __size_);
+ this->__size_ = __old_size;
+ });
+
+ while (__first != __last) {
+ emplace_back(*__first);
+ __first++;
+ }
+
+ __guard.__complete();
+ }
+
+ iterator __iter = __make_iter(__pos);
+ if (__size_ > 0) {
+ std::rotate(__iter, begin() + __old_size, end());
+ }
+
+ return __iter;
+ }
+
+ constexpr iterator __make_iter(pointer __p) {
+# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_INPLACE_VECTOR
+ return std::__make_bounded_iter(__p, data(), data() + __size_);
+# else
+ return std::__make_capacity_aware_iterator<pointer, inplace_vector<_Tp, _Cap>, _Cap>(__p);
+# endif
+ }
+
+ constexpr const_iterator __make_iter(const_pointer __p) const {
+# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_INPLACE_VECTOR
+ return std::__make_bounded_iter(__p, data(), data() + __size_);
+# else
+ return std::__make_capacity_aware_iterator<const_pointer, inplace_vector<_Tp, _Cap>, _Cap>(__p);
+# endif
+ }
+
+public:
+ // [inplace.vector.cons], construct/copy/destroy
+ constexpr inplace_vector() noexcept { __init(); }
+
+ constexpr explicit inplace_vector(size_type __n) {
+ __init();
+ reserve(__n);
+ std::uninitialized_value_construct_n(data(), __n);
+ __size_ = __n;
+ }
+
+ constexpr inplace_vector(size_type __n, const _Tp& __c) {
+ __init();
+ reserve(__n);
+ std::uninitialized_fill_n(data(), __n, __c);
+ __size_ = __n;
+ }
+
+ template <class _InputIterator>
+ requires __has_input_iterator_category<_InputIterator>::value
+ constexpr inplace_vector(_InputIterator __first, _InputIterator __last) {
+ __init();
+ if constexpr (std::sized_sentinel_for<_InputIterator, _InputIterator>) {
+ auto __n = std::ranges::distance(__first, __last);
+ reserve(__n);
+ std::uninitialized_copy(__first, __last, data());
+ __size_ = __n;
+ } else {
+ auto __guard = std::__make_exception_guard([this] { clear(); });
+
+ while (__first != __last) {
+ emplace_back(*__first);
+ __first++;
+ }
+
+ __guard.__complete();
+ }
+ }
+
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr inplace_vector(from_range_t, _Range&& __rg) {
+ __init();
+ append_range(__rg);
+ }
+
+ constexpr inplace_vector(const inplace_vector&)
+ requires is_trivially_copy_constructible_v<_Tp>
+ = default;
+
+ constexpr inplace_vector(const inplace_vector& __x) noexcept(is_nothrow_copy_constructible_v<_Tp>) {
+ __init();
+ std::uninitialized_copy(__x.begin(), __x.end(), data());
+ __size_ = __x.size();
+ }
+
+ constexpr inplace_vector(inplace_vector&&)
+ requires is_trivially_move_constructible_v<_Tp>
+ = default;
+
+ constexpr inplace_vector(inplace_vector&& __x) noexcept(is_nothrow_move_constructible_v<_Tp>) {
+ __init();
+ std::uninitialized_move(__x.begin(), __x.end(), data());
+ __size_ = __x.size();
+ }
+
+ constexpr inplace_vector(std::initializer_list<_Tp> __il) {
+ __init();
+ reserve(__il.size());
+ std::uninitialized_copy(__il.begin(), __il.end(), data());
+ __size_ = __il.size();
+ }
+
+ constexpr ~inplace_vector()
+ requires is_trivially_destructible_v<_Tp>
+ = default;
+
+ constexpr ~inplace_vector() { clear(); }
+
+ constexpr inplace_vector& operator=(const inplace_vector&)
+ requires is_trivially_destructible_v<_Tp> && is_trivially_copy_assignable_v<_Tp> &&
+ is_trivially_copy_constructible_v<_Tp>
+ = default;
+
+ constexpr inplace_vector& operator=(const inplace_vector& __x) noexcept(
+ is_nothrow_copy_constructible_v<_Tp> && is_nothrow_copy_assignable_v<_Tp>) {
+ if (std::addressof(__x) != this) {
+ assign(__x.begin(), __x.end());
+ }
+
+ return *this;
+ }
+
+ constexpr inplace_vector& operator=(inplace_vector&&)
+ requires is_trivially_destructible_v<_Tp> && is_trivially_move_assignable_v<_Tp> &&
+ is_trivially_move_constructible_v<_Tp>
+ = default;
+
+ constexpr inplace_vector&
+ operator=(inplace_vector&& __x) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_move_assignable_v<_Tp>) {
+ if (std::addressof(__x) != this) {
+ assign(std::make_move_iterator(__x.begin()), std::make_move_iterator(__x.end()));
+ }
+
+ return *this;
+ }
+
+ constexpr inplace_vector& operator=(std::initializer_list<_Tp> __il) {
+ assign(__il.begin(), __il.end());
+ return *this;
+ }
+
+ template <class _InputIterator>
+ requires __has_input_iterator_category<_InputIterator>::value
+ constexpr void assign(_InputIterator __first, _InputIterator __last) {
+ __assign(__first, __last);
+ }
+
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr void assign_range(_Range&& __rg) {
+ static_assert(std::assignable_from<_Tp&, std::ranges::range_reference_t<_Range>>);
+ __assign(std::ranges::begin(__rg), std::ranges::end(__rg));
+ }
+
+ constexpr void assign(size_type __n, const _Tp& __u) {
+ reserve(__n);
+ std::__fill_n(begin(), std::min(__n, static_cast<size_type>(__size_)), __u);
+
+ if (__n <= size()) {
+ std::destroy(begin() + __n, end());
+ } else {
+ std::uninitialized_fill(data() + size(), data() + __n, __u);
+ }
+ __size_ = __n;
+ }
+
+ constexpr void assign(std::initializer_list<_Tp> __il) { assign(__il.begin(), __il.end()); }
+
+ // iterators
+ [[nodiscard]] constexpr iterator begin() noexcept { return __make_iter(data()); }
+ [[nodiscard]] constexpr const_iterator begin() const noexcept { return __make_iter(data()); }
+ [[nodiscard]] constexpr iterator end() noexcept { return __make_iter(data() + __size_); }
+ [[nodiscard]] constexpr const_iterator end() const noexcept { return __make_iter(data() + __size_); }
+
+ [[nodiscard]] constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
+ [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ [[nodiscard]] constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
+ [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+
+ [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
+ [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }
+
+ // [inplace.vector.capacity], capacity
+ [[nodiscard]] constexpr bool empty() const noexcept { return __size_ == 0; }
+ [[nodiscard]] constexpr size_type size() const noexcept { return __size_; }
+ [[nodiscard]] static constexpr size_type max_size() noexcept { return _Cap; }
+ [[nodiscard]] static constexpr size_type capacity() noexcept { return _Cap; }
+
+ constexpr void resize(size_t __count) {
+ reserve(__count);
+ if (__count > __size_) {
+ std::uninitialized_value_construct_n(data() + __size_, __count - __size_);
+ } else if (__count < __size_) {
+ std::destroy_n(data() + __count, __size_ - __count);
+ }
+ __size_ = __count;
+ }
+
+ constexpr void resize(size_t __count, const _Tp& __v) {
+ reserve(__count);
+ if (__count > __size_) {
+ std::uninitialized_fill_n(data() + __size_, __count - __size_, __v);
+ } else if (__count < __size_) {
+ std::destroy_n(data() + __count, __size_ - __count);
+ }
+ __size_ = __count;
+ }
+
+ static constexpr void reserve(size_type __new_cap) {
+ if (__new_cap > _Cap) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ static constexpr void shrink_to_fit() noexcept {}
+
+ // element access
+ [[nodiscard]] constexpr reference operator[](size_type __pos) {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __pos < _Cap, "inplace_vector<T, N>::operator[](size_type pos): index with pos >= N");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __pos < __size_, "inplace_vector<T, N>::operator[](size_type pos): index with pos >= size()");
+ return data()[__pos];
+ }
+
+ [[nodiscard]] constexpr const_reference operator[](size_type __pos) const {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __pos < _Cap, "inplace_vector<T, N>::operator[](size_type pos) const: index with pos >= N");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __pos < __size_, "inplace_vector<T, N>::operator[](size_type pos) const: index with pos >= size()");
+ return data()[__pos];
+ }
+
+ [[nodiscard]] constexpr reference at(size_type __pos) {
+ if (__pos >= __size_) {
+ std::__throw_out_of_range("inplace_vector<T,N>::at(size_type pos): access with pos >= size()");
+ }
+ return data()[__pos];
+ }
+
+ [[nodiscard]] constexpr const_reference at(size_type __pos) const {
+ if (__pos >= __size_) {
+ std::__throw_out_of_range("inplace_vector<T,N>::at(size_type pos) const: access with pos >= size()");
+ }
+ return data()[__pos];
+ }
+
+ [[nodiscard]] constexpr reference front() {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__size_ > 0, "inplace_vector<T,N>::front(): access with size() == 0");
+ return *data();
+ }
+
+ [[nodiscard]] constexpr const_reference front() const {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__size_ > 0, "inplace_vector<T,N>::front() const: access with size() == 0");
+ return *data();
+ }
+
+ [[nodiscard]] constexpr reference back() {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__size_ > 0, "inplace_vector<T,N>::back(): access with size() == 0");
+ return *(data() + __size_ - 1);
+ }
+
+ [[nodiscard]] constexpr const_reference back() const {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__size_ > 0, "inplace_vector<T,N>::back() const: access with size() == 0");
+ return *(data() + __size_ - 1);
+ }
+
+ // [inplace.vector.data], data access
+ [[nodiscard]] constexpr pointer data() noexcept { return __elems_; }
+ [[nodiscard]] constexpr const_pointer data() const noexcept { return __elems_; }
+
+ // [inplace.vector.modifiers], modifiers
+ template <class... _Args>
+ constexpr reference emplace_back(_Args&&... __args) {
+ if (size() == capacity())
+ std::__throw_bad_alloc();
+ return unchecked_emplace_back(std::forward<_Args>(__args)...);
+ }
+
+ constexpr reference push_back(const _Tp& __x) { return emplace_back(__x); }
+ constexpr reference push_back(_Tp&& __x) { return emplace_back(std::move(__x)); }
+
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr void append_range(_Range&& __rg) {
+ if constexpr (std::ranges::sized_range<_Range> || std::ranges::forward_range<_Range>) {
+ const auto __d = std::ranges::distance(__rg);
+
+ if (__d > static_cast<difference_type>(_Cap - size())) {
+ std::__throw_bad_alloc();
+ }
+
+ std::ranges::uninitialized_copy(
+ std::ranges::begin(__rg), std::ranges::end(__rg), data() + __size_, data() + __size_ + __d);
+ __size_ += __d;
+ } else {
+ auto __guard = std::__make_exception_guard([__old_size = this->__size_, this] {
+ std::destroy(this->data() + __old_size, this->data() + this->__size_);
+ this->__size_ = __old_size;
+ });
+
+ auto [__it_in, __it_out] = std::ranges::uninitialized_copy(
+ std::ranges::begin(__rg), std::ranges::end(__rg), data() + __size_, data() + _Cap);
+
+ __size_ = __it_out - data();
+
+ if (__it_in != std::ranges::end(__rg)) {
+ std::__throw_bad_alloc();
+ }
+
+ __guard.__complete();
+ }
+ }
+
+ constexpr void pop_back() {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "inplace_vector<T,N>::pop_back(): Called on empty inplace_vector");
+ --__size_;
+ std::destroy_at(data() + __size_);
+ }
+
+ template <class... _Args>
+ [[nodiscard]] constexpr optional<reference> try_emplace_back(_Args&&... __args) {
+ if (size() == capacity()) {
+ return std::nullopt;
+ }
+
+ return std::optional<reference>(std::in_place, unchecked_emplace_back(std::forward<_Args>(__args)...));
+ }
+
+ [[nodiscard]] constexpr optional<reference> try_push_back(const _Tp& __x) { return try_emplace_back(__x); }
+ [[nodiscard]] constexpr optional<reference> try_push_back(_Tp&& __x) { return try_emplace_back(std::move(__x)); }
+
+ template <class... _Args>
+ constexpr reference unchecked_emplace_back(_Args&&... __args) {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ size() < capacity(),
+ "inplace_vector<T,N>::unchecked_emplace_back(Args...): Adding element when size() >= capacity()");
+ {
+ _ConstructTransaction __tx(*this, 1);
+ std::construct_at(data() + __size_, std::forward<_Args>(__args)...);
+ __tx.__pos_++;
+ }
+
+ return back();
+ }
+
+ constexpr reference unchecked_push_back(const _Tp& __x) { return unchecked_emplace_back(__x); }
+ constexpr reference unchecked_push_back(_Tp&& __x) { return unchecked_emplace_back(std::move(__x)); }
+
+ template <class... _Args>
+ constexpr iterator emplace(const_iterator __position, _Args&&... __args) {
+ if (size() == capacity()) {
+ std::__throw_bad_alloc();
+ }
+
+ pointer __p = data() + (__position - begin());
+
+ if (__position == end()) {
+ emplace_back(std::forward<_Args>(__args)...);
+ } else {
+ _Tp __temp_value = _Tp(std::forward<_Args>(__args)...);
+ __move_range(__p, data() + __size_, __p + 1);
+ *__p = std::move(__temp_value);
+ }
+
+ return __make_iter(__p);
+ }
+
+ constexpr iterator insert(const_iterator __position, const _Tp& __x) { return emplace(__position, __x); }
+ constexpr iterator insert(const_iterator __position, _Tp&& __x) { return emplace(__position, std::move(__x)); }
+
+ constexpr iterator insert(const_iterator __position, size_type __n, const _Tp& __x) {
+ if ((_Cap - __size_) < __n) {
+ std::__throw_bad_alloc();
+ }
+
+ pointer __p = data() + (__position - begin());
+
+ if (__n == 0) {
+ return __make_iter(__p);
+ }
+
+ std::uninitialized_fill_n(data() + __size_, __n, __x);
+ __size_ = __size_ + __n;
+
+ iterator __it = __make_iter(__p);
+
+ std::rotate(__it, end() - __n, end());
+
+ return __it;
+ }
+
+ template <class _InputIterator>
+ requires __has_input_iterator_category<_InputIterator>::value
+ constexpr iterator insert(const_iterator __position, _InputIterator __first, _InputIterator __last) {
+ return __insert(__position, __first, __last);
+ }
+
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr iterator insert_range(const_iterator __position, _Range&& __rg) {
+ return __insert(__position, std::ranges::begin(__rg), std::ranges::end(__rg));
+ }
+
+ constexpr iterator insert(const_iterator __position, std::initializer_list<_Tp> __il) {
+ return __insert(__position, __il.begin(), __il.end());
+ }
+
+ constexpr iterator erase(const_iterator __position) {
+ pointer __pos = data() + (__position - cbegin());
+
+ std::move(__pos + 1, data() + __size_, __pos);
+ pop_back();
+
+ return __make_iter(__pos);
+ }
+
+ constexpr iterator erase(const_iterator __first, const_iterator __last) {
+ __size_type __x = __last - __first;
+ pointer __pos = data() + (__first - cbegin());
+
+ if (__x == 0) {
+ return __make_iter(__pos);
+ }
+
+ pointer __end = std::move(__pos + __x, data() + __size_, __pos);
+ std::destroy_n(__end, __x);
+
+ __size_ -= __x;
+ return __make_iter(__pos);
+ }
+
+ constexpr void
+ swap(inplace_vector& __x) noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>) {
+ inplace_vector& __smaller = __x.size() < size() ? __x : *this;
+ inplace_vector& __bigger = __x.size() >= size() ? __x : *this;
+
+ size_type __n1 = __smaller.size();
+ size_type __n2 = __bigger.size();
+
+ std::swap_ranges(__smaller.begin(), __smaller.end(), __bigger.begin());
+
+ if (__n1 != __n2) {
+ using std::swap;
+ std::uninitialized_move(__bigger.data() + __n1, __bigger.data() + __n2, __smaller.data() + __n1);
+ __smaller.__size_ = __n2;
+ std::destroy(__bigger.data() + __n1, __bigger.data() + __n2);
+ __bigger.__size_ = __n1;
+ }
+ }
+
+ constexpr void clear() noexcept {
+ std::destroy(begin(), end());
+ __size_ = 0;
+ }
+
+ friend constexpr bool operator==(const inplace_vector& __x, const inplace_vector& __y) {
+ if (__x.size() != __y.size()) {
+ return false;
+ }
+
+ for (size_type __i{0}; __i < __x.size(); __i++) {
+ if (__x[__i] != __y[__i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ friend constexpr auto operator<=>(const inplace_vector& __x, const inplace_vector& __y)
+ requires requires(const _Tp __t) { std::__synth_three_way(__t, __t); }
+ {
+ return std::lexicographical_compare_three_way(
+ __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
+ }
+
+ friend constexpr void
+ swap(inplace_vector& __x,
+ inplace_vector& __y) noexcept(is_nothrow_swappable_v<_Tp> && is_nothrow_move_constructible_v<_Tp>) {
+ __x.swap(__y);
+ }
+};
+
+template <class _Tp>
+class inplace_vector<_Tp, 0> {
+public:
+ 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_IN_INPLACE_VECTOR
+ using iterator = __bounded_iter<pointer>;
+ using const_iterator = __bounded_iter<const_pointer>;
+# else
+ using iterator = __capacity_aware_iterator<pointer, inplace_vector<_Tp, 0>, 0>;
+ using const_iterator = __capacity_aware_iterator<const_pointer, inplace_vector<_Tp, 0>, 0>;
+# endif
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ constexpr inplace_vector() = default;
+ constexpr explicit inplace_vector(size_type __n) { reserve(__n); }
+ constexpr inplace_vector(size_type __n, const _Tp&) { reserve(__n); }
+
+ template <class _InputIterator>
+ requires __has_input_iterator_category<_InputIterator>::value
+ constexpr inplace_vector(_InputIterator __first, _InputIterator __last) {
+ if (__first != __last) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr inplace_vector(from_range_t, _Range&& __rg) {
+ if (std::ranges::begin(__rg) != std::ranges::end(__rg)) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ constexpr inplace_vector(const inplace_vector&) = default;
+ constexpr inplace_vector(inplace_vector&&) = default;
+ constexpr inplace_vector(std::initializer_list<_Tp> __il) { reserve(__il.size()); }
+ constexpr ~inplace_vector() = default;
+ constexpr inplace_vector& operator=(const inplace_vector&) = default;
+ constexpr inplace_vector& operator=(inplace_vector&&) = default;
+
+ constexpr inplace_vector& operator=(std::initializer_list<_Tp> __il) {
+ reserve(__il.size());
+ return *this;
+ }
+
+ template <class _InputIterator>
+ requires __has_input_iterator_category<_InputIterator>::value
+ constexpr void assign(_InputIterator __first, _InputIterator __last) {
+ if (__first != __last) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr void assign_range(_Range&& __rg) {
+ static_assert(std::assignable_from<_Tp&, std::ranges::range_reference_t<_Range>>);
+ if (std::ranges::begin(__rg) != std::ranges::end(__rg)) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ constexpr void assign(size_type __n, const _Tp&) { reserve(__n); }
+ constexpr void assign(std::initializer_list<_Tp> __il) { reserve(__il.size()); }
+
+private:
+ constexpr iterator __make_iter() {
+# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_INPLACE_VECTOR
+ return std::__make_bounded_iter(data(), data(), data());
+# else
+ return std::__make_capacity_aware_iterator<pointer, inplace_vector<_Tp, 0>, 0>(data());
+# endif
+ }
+
+ constexpr const_iterator __make_iter() const {
+# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_INPLACE_VECTOR
+ return std::__make_bounded_iter(data(), data(), data());
+# else
+ return std::__make_capacity_aware_iterator<const_pointer, inplace_vector<_Tp, 0>, 0>(data());
+# endif
+ }
+
+public:
+ // iterators
+ [[nodiscard]] constexpr iterator begin() noexcept { return __make_iter(); }
+ [[nodiscard]] constexpr const_iterator begin() const noexcept { return __make_iter(); }
+ [[nodiscard]] constexpr iterator end() noexcept { return __make_iter(); }
+ [[nodiscard]] constexpr const_iterator end() const noexcept { return __make_iter(); }
+
+ [[nodiscard]] constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
+ [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ [[nodiscard]] constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
+ [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+
+ [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
+ [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }
+
+ // [inplace.vector.capacity], capacity
+ [[nodiscard]] constexpr bool empty() const noexcept { return true; }
+ [[nodiscard]] constexpr size_type size() const noexcept { return 0; }
+ [[nodiscard]] static constexpr size_type max_size() noexcept { return 0; }
+ [[nodiscard]] static constexpr size_type capacity() noexcept { return 0; }
+
+ constexpr void resize(size_type __sz) {
+ if (__sz != 0) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ constexpr void resize(size_type __sz, const _Tp&) {
+ if (__sz != 0) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ static constexpr void reserve(size_type __n) {
+ if (__n != 0) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ static constexpr void shrink_to_fit() noexcept {}
+
+ // element access
+ [[nodiscard, noreturn]] constexpr reference operator[](size_type) {
+ _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::operator[]: access with N == 0");
+ }
+
+ [[nodiscard, noreturn]] constexpr const_reference operator[](size_type) const {
+ _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::operator[] const: access with N == 0");
+ }
+
+ [[nodiscard, noreturn]] constexpr reference at(size_type) {
+ std::__throw_out_of_range("inplace_vector<T,0>::at(size_type n): access with N == 0");
+ }
+
+ [[nodiscard, noreturn]] constexpr const_reference at(size_type) const {
+ std::__throw_out_of_range("inplace_vector<T,0>::at(size_type n) const: access with N == 0");
+ }
+
+ [[nodiscard, noreturn]] constexpr reference front() {
+ _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::front(): access with N == 0");
+ }
+
+ [[nodiscard, noreturn]] constexpr const_reference front() const {
+ _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::front() const: access with N == 0");
+ }
+
+ [[nodiscard, noreturn]] constexpr reference back() {
+ _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::back(): access with N == 0");
+ }
+
+ [[nodiscard, noreturn]] constexpr const_reference back() const {
+ _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::back() const: access with N == 0");
+ }
+
+ // [inplace.vector.data], data access
+ [[nodiscard]] constexpr pointer data() noexcept { return nullptr; }
+ [[nodiscard]] constexpr const_pointer data() const noexcept { return nullptr; }
+
+ // [inplace.vector.modifiers], modifiers
+
+ template <class... _Args>
+ constexpr reference emplace_back(_Args&&...) {
+ std::__throw_bad_alloc();
+ }
+
+ constexpr reference push_back(const _Tp&) { std::__throw_bad_alloc(); }
+ constexpr reference push_back(_Tp&&) { std::__throw_bad_alloc(); }
+
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr void append_range(_Range&& __rg) {
+ if (std::ranges::begin(__rg) != std::ranges::end(__rg)) {
+ std::__throw_bad_alloc();
+ }
+ }
+
+ constexpr void pop_back() { _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::pop_back(): use with N == 0"); }
+
+ template <class... _Args>
+ [[nodiscard]] constexpr optional<reference> try_emplace_back(_Args&&...) {
+ return std::nullopt;
+ }
+
+ [[nodiscard]] constexpr optional<reference> try_push_back(const _Tp&) { return std::nullopt; }
+ [[nodiscard]] constexpr optional<reference> try_push_back(_Tp&&) { return std::nullopt; }
+
+ template <class... _Args>
+ [[noreturn]] constexpr reference unchecked_emplace_back(_Args&&...) {
+ std::__throw_bad_alloc();
+ }
+
+ [[noreturn]] constexpr reference unchecked_push_back(const _Tp&) { std::__throw_bad_alloc(); }
+ [[noreturn]] constexpr reference unchecked_push_back(_Tp&&) { std::__throw_bad_alloc(); }
+
+ template <class... _Args>
+ [[noreturn]] constexpr iterator emplace(const_iterator, _Args&&...) {
+ std::__throw_bad_alloc();
+ }
+
+ [[noreturn]] constexpr iterator insert(const_iterator, const _Tp&) { std::__throw_bad_alloc(); }
+ [[noreturn]] constexpr iterator insert(const_iterator, _Tp&&) { std::__throw_bad_alloc(); }
+
+ constexpr iterator insert(const_iterator, size_type __n, const _Tp&) {
+ reserve(__n);
+ return begin();
+ }
+
+ template <class _InputIterator>
+ requires __has_input_iterator_category<_InputIterator>::value
+ constexpr iterator insert(const_iterator, _InputIterator __f, _InputIterator __l) {
+ if (__f != __l)
+ std::__throw_bad_alloc();
+
+ return begin();
+ }
+
+ template <_ContainerCompatibleRange<_Tp> _Range>
+ constexpr iterator insert_range(const_iterator, _Range&& __rg) {
+ if (std::ranges::begin(__rg) != std::ranges::end(__rg)) {
+ std::__throw_bad_alloc();
+ }
+ return begin();
+ }
+
+ constexpr iterator insert(const_iterator, initializer_list<_Tp> __il) {
+ reserve(__il.size());
+ return begin();
+ }
+
+ [[noreturn]] constexpr iterator erase(const_iterator) {
+ _LIBCPP_VERBOSE_ABORT("std::inplace_vector<T,0>::erase(const_iterator): use with N == 0");
+ }
+
+ constexpr iterator erase(const_iterator __f, const_iterator __l) {
+ if (__f != __l) {
+ _LIBCPP_VERBOSE_ABORT("std::inplace_vector<T,0>::erase(const_iterator, const_iterator): use with N == 0");
+ }
+
+ return begin();
+ }
+
+ constexpr void swap(inplace_vector&) noexcept {}
+
+ constexpr void clear() noexcept {}
+
+ constexpr friend bool operator==(const inplace_vector&, const inplace_vector&) { return true; }
+
+ constexpr friend auto operator<=>(const inplace_vector& __x, const inplace_vector& __y)
+ requires requires(const _Tp __t) { std::__synth_three_way(__t, __t); }
+ {
+ return std::lexicographical_compare_three_way(
+ __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
+ }
+
+ constexpr friend void swap(inplace_vector&, inplace_vector&) noexcept {}
+};
+
+template <class _Tp, std::size_t _Cap, class _Pred>
+constexpr typename std::inplace_vector<_Tp, _Cap>::size_type
+erase_if(std::inplace_vector<_Tp, _Cap>& __c, _Pred __pred) {
+ if constexpr (_Cap != 0) {
+ auto __it = std::remove_if(__c.begin(), __c.end(), __pred);
+ auto __r = std::distance(__it, __c.end());
+ __c.erase(__it, __c.end());
+
+ return __r;
+ }
+
+ return 0;
+}
+
+template <class _Tp, std::size_t _Cap, class _Up = _Tp>
+constexpr typename std::inplace_vector<_Tp, _Cap>::size_type
+erase(std::inplace_vector<_Tp, _Cap>& __c, const _Up& __value) {
+ return std::erase_if(__c, [&](const auto& __elem) { return __elem == __value; });
+}
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+# endif // _LIBCPP_STD_VER >= 26
+
+#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
+
+#endif // _LIBCPP_INPLACE_VECTOR
diff --git a/libcxx/include/version b/libcxx/include/version
index d4d29b4d31a72..320799ea52c9b 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -140,7 +140,7 @@ __cpp_lib_has_unique_object_representations 201606L <type_traits>
__cpp_lib_hazard_pointer 202306L <hazard_pointer>
__cpp_lib_hypot 201603L <cmath>
__cpp_lib_incomplete_container_elements 201505L <forward_list> <list> <vector>
-__cpp_lib_inplace_vector 202406L <inplace_vector>
+__cpp_lib_inplace_vector 202603L <inplace_vector>
__cpp_lib_int_pow2 202002L <bit>
__cpp_lib_integer_comparison_functions 202002L <utility>
__cpp_lib_integer_sequence 202511L <utility>
@@ -593,7 +593,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 202603L
# undef __cpp_lib_integer_sequence
# define __cpp_lib_integer_sequence 202511L
# define __cpp_lib_is_sufficiently_aligned 202411L
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.back.empty.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.back.empty.pass.cpp
new file mode 100644
index 0000000000000..1f49170059828
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.back.empty.pass.cpp
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers, std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+// <inplace_vector>
+
+// Call back() on an empty container.
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::inplace_vector<int, 4> c;
+ TEST_LIBCPP_ASSERT_FAILURE(c.back(), "inplace_vector<T,N>::back(): access with size() == 0");
+ TEST_LIBCPP_ASSERT_FAILURE(std::as_const(c).back(), "inplace_vector<T,N>::back() const: access with size() == 0");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.front.empty.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.front.empty.pass.cpp
new file mode 100644
index 0000000000000..6656581073cfb
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.front.empty.pass.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers, std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+// <inplace_vector>
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::inplace_vector<int, 4> c;
+ TEST_LIBCPP_ASSERT_FAILURE(c.front(), "inplace_vector<T,N>::front(): access with size() == 0");
+ TEST_LIBCPP_ASSERT_FAILURE(std::as_const(c).front(), "inplace_vector<T,N>::front() const: access with size() == 0");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.index.oob.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.index.oob.pass.cpp
new file mode 100644
index 0000000000000..45b07456d4ff3
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.index.oob.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers, std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+// <inplace_vector>
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::inplace_vector<int, 4> c{1};
+ TEST_LIBCPP_ASSERT_FAILURE(c[1], "inplace_vector<T, N>::operator[](size_type pos): index with pos >= size()");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ std::as_const(c)[1], "inplace_vector<T, N>::operator[](size_type pos) const: index with pos >= size()");
+
+ TEST_LIBCPP_ASSERT_FAILURE(c[5], "inplace_vector<T, N>::operator[](size_type pos): index with pos >= N");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ std::as_const(c)[5], "inplace_vector<T, N>::operator[](size_type pos) const: index with pos >= N");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.iterator.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.iterator.pass.cpp
new file mode 100644
index 0000000000000..78980fefdc78b
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.iterator.pass.cpp
@@ -0,0 +1,116 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers, std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: availability-verbose_abort-missing
+
+// <inplace_vector>
+
+// Check invalid iterator operations.
+
+#include <inplace_vector>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_INPLACE_VECTOR
+ { // operator++
+ std::inplace_vector<int, 4> c{1};
+ auto i = c.end();
+
+ TEST_LIBCPP_ASSERT_FAILURE(++i, "__bounded_iter::operator++: Attempt to advance an iterator past the end");
+ TEST_LIBCPP_ASSERT_FAILURE(i++, "__bounded_iter::operator++: Attempt to advance an iterator past the end");
+ }
+
+ { // operator--
+ std::inplace_vector<int, 4> c{1};
+ auto i = c.begin();
+
+ TEST_LIBCPP_ASSERT_FAILURE(--i, "__bounded_iter::operator--: Attempt to rewind an iterator past the start");
+ TEST_LIBCPP_ASSERT_FAILURE(i--, "__bounded_iter::operator--: Attempt to rewind an iterator past the start");
+ }
+
+ { // operator*
+ std::inplace_vector<int, 4> c;
+ auto i = c.begin();
+
+ TEST_LIBCPP_ASSERT_FAILURE(*i, "__bounded_iter::operator*: Attempt to dereference an iterator at the end");
+ }
+
+ { // operator[]
+ std::inplace_vector<int, 4> c{1};
+ auto i = c.begin();
+
+ TEST_LIBCPP_ASSERT_FAILURE(i[1], "__bounded_iter::operator[]: Attempt to index an iterator at or past the end");
+ TEST_LIBCPP_ASSERT_FAILURE(i[-1], "__bounded_iter::operator[]: Attempt to index an iterator past the start");
+ }
+
+ { // operator->
+ std::inplace_vector<int, 4> c{1};
+ auto i = c.end();
+
+ TEST_LIBCPP_ASSERT_FAILURE(
+ i.operator->(), "__bounded_iter::operator->: Attempt to dereference an iterator at the end");
+ }
+
+ { // operator+=
+ std::inplace_vector<int, 4> c{1};
+ auto i = c.begin();
+
+ TEST_LIBCPP_ASSERT_FAILURE(i += 2, "__bounded_iter::operator+=: Attempt to advance an iterator past the end");
+ TEST_LIBCPP_ASSERT_FAILURE(i += -1, "__bounded_iter::operator+=: Attempt to rewind an iterator past the start");
+ }
+
+ { // operator-=
+ std::inplace_vector<int, 4> c{1};
+ auto i = c.begin();
+
+ TEST_LIBCPP_ASSERT_FAILURE(i -= 1, "__bounded_iter::operator-=: Attempt to rewind an iterator past the start");
+ TEST_LIBCPP_ASSERT_FAILURE(i -= -2, "__bounded_iter::operator-=: Attempt to advance an iterator past the end");
+ }
+
+ {
+ std::inplace_vector<int, 0> c;
+
+ auto i = c.begin();
+ TEST_LIBCPP_ASSERT_FAILURE(++i, "__bounded_iter::operator++: Attempt to advance an iterator past the end");
+ TEST_LIBCPP_ASSERT_FAILURE(i++, "__bounded_iter::operator++: Attempt to advance an iterator past the end");
+ TEST_LIBCPP_ASSERT_FAILURE(--i, "__bounded_iter::operator--: Attempt to rewind an iterator past the start");
+ TEST_LIBCPP_ASSERT_FAILURE(i--, "__bounded_iter::operator--: Attempt to rewind an iterator past the start");
+ TEST_LIBCPP_ASSERT_FAILURE(i[0], "__bounded_iter::operator[]: Attempt to index an iterator at or past the end");
+ TEST_LIBCPP_ASSERT_FAILURE(i[0], "__bounded_iter::operator[]: Attempt to index an iterator past the start");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ i.operator->(), "__bounded_iter::operator->: Attempt to dereference an iterator at the end");
+ TEST_LIBCPP_ASSERT_FAILURE(i += 1, "__bounded_iter::operator+=: Attempt to advance an iterator past the end");
+ TEST_LIBCPP_ASSERT_FAILURE(i += -1, "__bounded_iter::operator+=: Attempt to rewind an iterator past the start");
+ TEST_LIBCPP_ASSERT_FAILURE(i -= 1, "__bounded_iter::operator-=: Attempt to rewind an iterator past the start");
+ TEST_LIBCPP_ASSERT_FAILURE(i -= -1, "__bounded_iter::operator-=: Attempt to advance an iterator past the end");
+ }
+#else
+ std::inplace_vector<int, 4> c{1};
+ auto i = c.begin();
+
+ TEST_LIBCPP_ASSERT_FAILURE(
+ i += 5, "__capacity_aware_iterator::operator+=: Attempting to move iterator past its container's possible range");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ i += -5,
+ "__capacity_aware_iterator::operator+=: Attempting to move iterator past its container's possible range");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ i -= 5, "__capacity_aware_iterator::operator-=: Attempting to move iterator past its container's possible range");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ i -= -5,
+ "__capacity_aware_iterator::operator-=: Attempting to move iterator past its container's possible range");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ i[4], "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ i[-5], "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.pop_back.empty.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.pop_back.empty.pass.cpp
new file mode 100644
index 0000000000000..2122618785d68
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.pop_back.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers, std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+// <inplace_vector>
+
+// Call pop_back() on an empty container.
+
+#include <inplace_vector>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::inplace_vector<int, 4> c;
+ TEST_LIBCPP_ASSERT_FAILURE(c.pop_back(), "inplace_vector<T,N>::pop_back(): Called on empty inplace_vector");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.unchecked_push_back.capacity.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.unchecked_push_back.capacity.pass.cpp
new file mode 100644
index 0000000000000..222e4181125a5
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.unchecked_push_back.capacity.pass.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers, std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+// <inplace_vector>
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::inplace_vector<int, 2> c{1, 2};
+ int value = 3;
+ TEST_LIBCPP_ASSERT_FAILURE(
+ c.unchecked_emplace_back(3),
+ "inplace_vector<T,N>::unchecked_emplace_back(Args...): Adding element when size() >= capacity()");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ c.unchecked_push_back(value),
+ "inplace_vector<T,N>::unchecked_emplace_back(Args...): Adding element when size() >= capacity()");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ c.unchecked_push_back(std::move(value)),
+ "inplace_vector<T,N>::unchecked_emplace_back(Args...): Adding element when size() >= capacity()");
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
new file mode 100644
index 0000000000000..fefe61e1eef53
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers, std-at-least-c++26
+
+// <inplace_vector>
+
+#include <inplace_vector>
+#include <utility>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::inplace_vector<int, 0> c;
+
+ EXPECT_ANY_DEATH((void)c[0]);
+ EXPECT_ANY_DEATH((void)c.front());
+ EXPECT_ANY_DEATH((void)c.back());
+ EXPECT_ANY_DEATH(c.pop_back());
+ EXPECT_ANY_DEATH(c.erase(c.begin()));
+ EXPECT_ANY_DEATH((void)std::as_const(c)[0]);
+ EXPECT_ANY_DEATH((void)std::as_const(c).front());
+ EXPECT_ANY_DEATH((void)std::as_const(c).back());
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/nodiscard.verify.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..4144f3be5d25c
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/nodiscard.verify.cpp
@@ -0,0 +1,90 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+#include <inplace_vector>
+
+void test() {
+ std::inplace_vector<int, 4> v;
+
+ v.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.back(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.capacity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.try_emplace_back(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.try_push_back(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::inplace_vector<int, 0> v0;
+ v0.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.capacity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.try_emplace_back(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.try_push_back(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ // Defined in lambdas because these are marked [[noreturn]], and would emit a 'code unreachable' warning if code followed any one of them.
+ (void)[&] {
+ v0.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ };
+
+ (void)[&] {
+ v0.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ };
+
+ (void)[&] {
+ v0.back(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ };
+
+ (void)[&] {
+ v0[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ };
+
+ // iterator [[nodiscard]]
+ {
+ std::inplace_vector<int, 4>::iterator it = v.begin();
+ *it; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it + 1; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 1 + it; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it - 1; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it - it; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
+
+ {
+ std::inplace_vector<int, 4>::const_iterator it = v.cbegin();
+ *it; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it + 1; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ 1 + it; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it - 1; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ it - it; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
+}
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 0000000000000..8d70255bad0bf
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/access.pass.cpp
@@ -0,0 +1,121 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// reference operator[](size_type n);
+// const_reference operator[](size_type n) const;
+// reference at(size_type n);
+// const_reference at(size_type n) const;
+// reference front();
+// const_reference front() const;
+// reference back();
+// const_reference back() const;
+
+#include <cassert>
+#include <inplace_vector>
+#include <stdexcept>
+#include <type_traits>
+
+#include "test_macros.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 C>
+constexpr void test_get_basic(C& 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 (!TEST_IS_CONSTANT_EVALUATED) {
+ try {
+ (void)c.at(n);
+ assert(false);
+ } catch (const std::out_of_range&) {
+ }
+ }
+#endif
+
+ assert(c.front() == start_value);
+ assert(c.back() == start_value + n - 1);
+}
+
+template <class C>
+constexpr void test_get() {
+ int start_value = 35;
+ C c = make<C>(10, start_value);
+ const C& cc = c;
+ test_get_basic(c, start_value);
+ test_get_basic(cc, start_value);
+}
+
+template <class C>
+constexpr void test_set() {
+ int start_value = 35;
+ const int n = 10;
+ C c = make<C>(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 C>
+constexpr void test() {
+ test_get<C>();
+ test_set<C>();
+
+ C c;
+ const C& cc = c;
+ ASSERT_SAME_TYPE(typename C::reference, decltype(c[0]));
+ ASSERT_SAME_TYPE(typename C::const_reference, decltype(cc[0]));
+ ASSERT_SAME_TYPE(typename C::reference, decltype(c.at(0)));
+ ASSERT_SAME_TYPE(typename C::const_reference, decltype(cc.at(0)));
+ ASSERT_SAME_TYPE(typename C::reference, decltype(c.front()));
+ ASSERT_SAME_TYPE(typename C::const_reference, decltype(cc.front()));
+ ASSERT_SAME_TYPE(typename C::reference, decltype(c.back()));
+ ASSERT_SAME_TYPE(typename C::const_reference, decltype(cc.back()));
+}
+
+constexpr bool tests() {
+ test<std::inplace_vector<int, 16> >();
+ return true;
+}
+
+int main(int, char**) {
+ tests();
+ static_assert(tests());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/addressof.compile.pass.cpp
new file mode 100644
index 0000000000000..94a722eea6d04
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/addressof.compile.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// Validate various member functions of std::inplace_vector with an ADL-hijacking operator&.
+
+#include <inplace_vector>
+#include <utility>
+
+#include "operator_hijacker.h"
+#include "test_iterators.h"
+
+using InplaceVector = std::inplace_vector<operator_hijacker, 16>;
+
+void test(
+ InplaceVector v,
+ InplaceVector::const_iterator it,
+ cpp17_input_iterator<operator_hijacker*> other_it,
+ operator_hijacker val) {
+ // emplace / insert
+ v.emplace(it);
+ v.insert(it, it, it);
+ v.insert(it, other_it, other_it);
+ v.insert(it, operator_hijacker());
+ v.insert(it, 1, val);
+ v.insert(it, val);
+
+ // erase
+ v.erase(it);
+ v.erase(it, it);
+
+ // assignment
+ v = static_cast<InplaceVector&>(v);
+ v = std::move(v);
+
+ // construction
+ {
+ InplaceVector v2(std::move(v));
+ (void)v2;
+ }
+
+ // swap
+ v.swap(v);
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/common.h b/libcxx/test/std/containers/sequences/inplace_vector/common.h
new file mode 100644
index 0000000000000..0b895580e19c1
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/common.h
@@ -0,0 +1,161 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 TEST_STD_CONTAINERS_SEQUENCES_INPLACE_VECTOR_COMMON_H
+#define TEST_STD_CONTAINERS_SEQUENCES_INPLACE_VECTOR_COMMON_H
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <iterator>
+#include <inplace_vector>
+#include <initializer_list>
+#include <new>
+#include <ranges>
+#include <stdexcept>
+#include <utility>
+
+#include "test_macros.h"
+
+// inplace_vector<T,N> usage for non-trivial T in constant expressions is gated by
+// implementations of P3074R7 (trivial unions), inplace_vector<T, N>
+#ifdef __cpp_trivial_union
+# define TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR 1
+#else
+# define TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR 0
+#endif
+
+template <class T>
+using InplaceVector = std::inplace_vector<T, 32>;
+
+template <class T>
+using SmallInplaceVector = std::inplace_vector<T, 8>;
+
+template <class T, class Expected>
+constexpr void assert_inplace_vector_equal(const T& c, const Expected& expected) {
+ assert(c.size() == std::ranges::size(expected));
+ assert(std::ranges::equal(c, expected));
+}
+
+template <class C, class T>
+constexpr void assert_inplace_vector_equal(const C& c, std::initializer_list<T> expected) {
+ assert(c.size() == expected.size());
+ assert(std::ranges::equal(c, expected));
+}
+
+template <class T, std::size_t N>
+constexpr std::inplace_vector<T, N> make_inplace_vector(std::initializer_list<T> il) {
+ std::inplace_vector<T, N> result;
+ result.insert(result.end(), il.begin(), il.end());
+ return result;
+}
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+struct ThrowingValue {
+ inline static int alive = 0;
+ inline static int throw_after = -1;
+
+ int value = 0;
+
+ static void reset() {
+ alive = 0;
+ throw_after = -1;
+ }
+
+ static void maybe_throw() {
+ if (throw_after == 0)
+ throw 1;
+ if (throw_after > 0)
+ --throw_after;
+ }
+
+ ThrowingValue() {
+ maybe_throw();
+ ++alive;
+ }
+
+ explicit ThrowingValue(int v) : value(v) {
+ maybe_throw();
+ ++alive;
+ }
+
+ ThrowingValue(const ThrowingValue& other) : value(other.value) {
+ maybe_throw();
+ ++alive;
+ }
+
+ ThrowingValue(ThrowingValue&& other) : value(other.value) {
+ maybe_throw();
+ ++alive;
+ }
+
+ ThrowingValue& operator=(const ThrowingValue& other) {
+ maybe_throw();
+ value = other.value;
+ return *this;
+ }
+
+ ThrowingValue& operator=(ThrowingValue&& other) {
+ maybe_throw();
+ value = other.value;
+ return *this;
+ }
+
+ ~ThrowingValue() { --alive; }
+
+ friend bool operator==(const ThrowingValue& lhs, const ThrowingValue& rhs) { return lhs.value == rhs.value; }
+};
+
+template <class T, class IterCat>
+struct throwing_iterator {
+ using iterator_category = IterCat;
+ using difference_type = std::ptrdiff_t;
+ using value_type = T;
+ using reference = T&;
+ using pointer = T*;
+
+ int i_;
+ T* ptr_;
+
+ throwing_iterator() : i_(0), ptr_(nullptr) {}
+
+ throwing_iterator(T* ptr, int i = 0) : i_(i), ptr_(ptr) {}
+
+ reference operator*() const {
+ if (i_ == 1)
+ throw 1;
+ return *ptr_;
+ }
+
+ friend bool operator==(const throwing_iterator& lhs, const throwing_iterator& rhs) { return lhs.i_ == rhs.i_; }
+ friend bool operator!=(const throwing_iterator& lhs, const throwing_iterator& rhs) { return !(lhs == rhs); }
+
+ throwing_iterator& operator++() {
+ ++i_;
+ ++ptr_;
+ return *this;
+ }
+
+ throwing_iterator operator++(int) {
+ auto tmp = *this;
+ ++*this;
+ return tmp;
+ }
+};
+
+template <class Func>
+void assert_throws_bad_alloc(Func func) {
+ try {
+ func();
+ assert(false);
+ } catch (const std::bad_alloc&) {
+ }
+}
+#endif
+
+#endif // TEST_STD_CONTAINERS_SEQUENCES_INPLACE_VECTOR_COMMON_H
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 0000000000000..208b41d94bbe4
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/compare.pass.cpp
@@ -0,0 +1,104 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class T, size_t N>
+// constexpr bool operator==(const inplace_vector<T, N>& x, const inplace_vector<T, N>& y);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "common.h"
+#include "test_comparisons.h"
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 8> c1;
+ std::inplace_vector<int, 8> c2;
+ std::same_as<bool> decltype(auto) result = c1 == c2;
+ assert(result);
+ assert(!(c1 != c2));
+ }
+ {
+ std::inplace_vector<int, 8> c1{1, 2, 3};
+ std::inplace_vector<int, 8> c2{1, 2, 3};
+ std::inplace_vector<int, 8> c3{1, 2, 4};
+ std::inplace_vector<int, 8> c4{1, 2};
+ assert(c1 == c2);
+ assert(c1 != c3);
+ assert(c1 != c4);
+ }
+ { // all six comparison operators (!=, <, <=, >, >= are rewritten in terms of == and <=>)
+ std::inplace_vector<int, 8> c1;
+ std::inplace_vector<int, 8> c2;
+ assert(testComparisons(c1, c2, true, false));
+ }
+ {
+ std::inplace_vector<int, 8> c1{1, 2, 1};
+ std::inplace_vector<int, 8> c2{1, 2, 2};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ {
+ std::inplace_vector<int, 8> c1{3, 2, 3};
+ std::inplace_vector<int, 8> c2{3, 1, 3};
+ assert(testComparisons(c1, c2, false, false));
+ }
+ { // a shorter inplace_vector that is a prefix of the longer one compares less
+ std::inplace_vector<int, 8> c1{1, 2};
+ std::inplace_vector<int, 8> c2{1, 2, 0};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ {
+ std::inplace_vector<int, 8> c1{1, 2, 0};
+ std::inplace_vector<int, 8> c2{3};
+ assert(testComparisons(c1, c2, false, true));
+ }
+
+ // types that only provide operator< and operator==
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ {
+ std::inplace_vector<LessAndEqComp, 8> c1;
+ std::inplace_vector<LessAndEqComp, 8> c2;
+ assert(testComparisons(c1, c2, true, false));
+ }
+ {
+ std::inplace_vector<LessAndEqComp, 8> c1{LessAndEqComp(1), LessAndEqComp(2)};
+ std::inplace_vector<LessAndEqComp, 8> c2{LessAndEqComp(1), LessAndEqComp(2)};
+ assert(testComparisons(c1, c2, true, false));
+ }
+ {
+ std::inplace_vector<LessAndEqComp, 8> c1{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(2)};
+ std::inplace_vector<LessAndEqComp, 8> c2{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(1)};
+ assert(testComparisons(c1, c2, false, false));
+ }
+ {
+ std::inplace_vector<LessAndEqComp, 8> c1{LessAndEqComp(1), LessAndEqComp(2)};
+ std::inplace_vector<LessAndEqComp, 8> c2{LessAndEqComp(1), LessAndEqComp(2), LessAndEqComp(0)};
+ assert(testComparisons(c1, c2, false, true));
+ }
+ }
+
+ { // zero capacity inplace_vectors are always equal
+ std::inplace_vector<int, 0> c1;
+ std::inplace_vector<int, 0> c2;
+ assert(testComparisons(c1, c2, true, false));
+ }
+
+ 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 0000000000000..9661db1e44e05
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/compare.three_way.pass.cpp
@@ -0,0 +1,108 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class T, size_t N>
+// constexpr synth-three-way-result<T>
+// operator<=>(const inplace_vector<T, N>& x, const inplace_vector<T, N>& y);
+
+#include <cassert>
+#include <compare>
+#include <concepts>
+#include <inplace_vector>
+#include <limits>
+#include <type_traits>
+
+#include "common.h"
+#include "test_comparisons.h"
+
+static_assert(std::three_way_comparable<std::inplace_vector<int, 8>>);
+static_assert(!std::three_way_comparable<std::inplace_vector<NonComparable, 8>>);
+
+template <class Elem, class Order>
+constexpr void test_with_type() {
+ {
+ std::inplace_vector<Elem, 8> c1;
+ std::inplace_vector<Elem, 8> c2;
+ std::same_as<Order> decltype(auto) result = c1 <=> c2;
+ assert(result == Order::equivalent);
+ }
+ {
+ std::inplace_vector<Elem, 8> c1{Elem(1), Elem(1)};
+ std::inplace_vector<Elem, 8> c2{Elem(1), Elem(1)};
+ assert(testOrder(c1, c2, Order::equivalent));
+ }
+ {
+ std::inplace_vector<Elem, 8> c1{Elem(1), Elem(1)};
+ std::inplace_vector<Elem, 8> c2{Elem(1), Elem(2)};
+ assert(testOrder(c1, c2, Order::less));
+ }
+ {
+ std::inplace_vector<Elem, 8> c1{Elem(1), Elem(3)};
+ std::inplace_vector<Elem, 8> c2{Elem(1), Elem(2)};
+ assert(testOrder(c1, c2, Order::greater));
+ }
+ {
+ std::inplace_vector<Elem, 8> c1{Elem(1)};
+ std::inplace_vector<Elem, 8> c2{Elem(1), Elem(2)};
+ assert(testOrder(c1, c2, Order::less));
+ }
+ {
+ std::inplace_vector<Elem, 8> c1{Elem(1), Elem(2)};
+ std::inplace_vector<Elem, 8> c2{Elem(1)};
+ assert(testOrder(c1, c2, Order::greater));
+ }
+
+ if constexpr (std::is_same_v<Elem, PartialOrder>) {
+ std::inplace_vector<Elem, 8> c1{Elem(1), Elem(std::numeric_limits<int>::min())};
+ std::inplace_vector<Elem, 8> c2{Elem(1), Elem(2)};
+ assert(testOrder(c1, c2, Order::unordered));
+ }
+}
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 8> c1{1, 2, 3};
+ std::inplace_vector<int, 8> c2{1, 2, 3};
+ std::inplace_vector<int, 8> c3{1, 2, 4};
+ std::inplace_vector<int, 8> c4{1, 2};
+
+ std::same_as<std::strong_ordering> decltype(auto) result = c1 <=> c2;
+ assert(result == std::strong_ordering::equal);
+ assert((c1 <=> c3) == std::strong_ordering::less);
+ assert((c3 <=> c1) == std::strong_ordering::greater);
+ assert((c4 <=> c1) == std::strong_ordering::less);
+ assert((c1 <=> c4) == std::strong_ordering::greater);
+ }
+
+ {
+ std::inplace_vector<int, 0> c1;
+ std::inplace_vector<int, 0> c2;
+ std::same_as<std::strong_ordering> decltype(auto) result = c1 <=> c2;
+ assert(result == std::strong_ordering::equal);
+ }
+
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ test_with_type<StrongOrder, std::strong_ordering>();
+ test_with_type<WeakOrder, std::weak_ordering>();
+ test_with_type<PartialOrder, std::partial_ordering>();
+ test_with_type<LessAndEqComp, std::weak_ordering>();
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ 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 0000000000000..36a30148e5920
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/constant_initialization.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+TEST_CONSTINIT std::inplace_vector<int, 4> v1;
+TEST_CONSTINIT const std::inplace_vector<int, 4> v2;
+
+int main(int, char**) {
+ assert(v1.empty());
+ assert(v2.empty());
+
+ return 0;
+}
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 0000000000000..d748fbe1f86d5
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/contiguous.pass.cpp
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+#include <cassert>
+#include <inplace_vector>
+#include <memory>
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 8> c{1, 2, 3};
+ assert(std::to_address(c.begin()) == c.data());
+ assert(std::to_address(c.begin() + 1) == c.data() + 1);
+ assert(std::to_address(c.end()) == c.data() + c.size());
+ }
+ {
+ const std::inplace_vector<int, 8> c{1, 2, 3};
+ assert(std::to_address(c.begin()) == c.data());
+ assert(std::to_address(c.begin() + 1) == c.data() + 1);
+ assert(std::to_address(c.end()) == c.data() + c.size());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 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 0000000000000..24f5732dd69a7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/capacity.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// static constexpr size_type capacity() noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ using C = std::inplace_vector<int, 0>;
+ ASSERT_SAME_TYPE(C::size_type, decltype(C::capacity()));
+ C c;
+ assert(c.capacity() == 0);
+ assert(C::capacity() == 0);
+ }
+ {
+ using C = std::inplace_vector<int, 42>;
+ ASSERT_SAME_TYPE(C::size_type, decltype(C::capacity()));
+ C c{1, 2, 3};
+ assert(c.capacity() == 42);
+ assert(C::capacity() == 42);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ 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 0000000000000..cbc7706965f36
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/empty.pass.cpp
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr bool empty() const noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 4> c;
+ ASSERT_SAME_TYPE(bool, decltype(c.empty()));
+ assert(c.empty());
+ c.push_back(1);
+ assert(!c.empty());
+ c.clear();
+ assert(c.empty());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
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 0000000000000..f756811b2e2aa
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/max_size.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// static constexpr size_type max_size() noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ using C = std::inplace_vector<int, 0>;
+ ASSERT_SAME_TYPE(C::size_type, decltype(C::max_size()));
+ C c;
+ assert(c.max_size() == 0);
+ assert(C::max_size() == 0);
+ }
+ {
+ using C = std::inplace_vector<int, 42>;
+ ASSERT_SAME_TYPE(C::size_type, decltype(C::max_size()));
+ C c{1, 2, 3};
+ assert(c.max_size() == 42);
+ assert(C::max_size() == 42);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ 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 0000000000000..1aecd1e72e30b
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/reserve.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// static constexpr void reserve(size_type n);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ using C = std::inplace_vector<int, 4>;
+ C c{1, 2};
+ auto* data = c.data();
+ c.reserve(0);
+ c.reserve(4);
+ C::reserve(4);
+ assert(c.size() == 2);
+ assert(c.capacity() == 4);
+ assert(c.data() == data);
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ assert_throws_bad_alloc([] { std::inplace_vector<int, 4>::reserve(5); });
+ std::inplace_vector<int, 4> c{1, 2};
+ auto* data = c.data();
+ assert_throws_bad_alloc([&] { c.reserve(5); });
+ assert(c.size() == 2);
+ assert(c.data() == data);
+#endif
+
+ 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 0000000000000..379ad216afed3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/resize_size.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void resize(size_type sz);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 5> c{1, 2, 3};
+ c.resize(5);
+ assert_inplace_vector_equal(c, {1, 2, 3, 0, 0});
+ c.resize(2);
+ assert_inplace_vector_equal(c, {1, 2});
+ c.resize(0);
+ assert(c.empty());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 5> c{1, 2, 3};
+ assert_throws_bad_alloc([&] { c.resize(6); });
+ assert_inplace_vector_equal(c, {1, 2, 3});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/resize_size_exceptions.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/resize_size_exceptions.pass.cpp
new file mode 100644
index 0000000000000..0102e003a87e2
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/resize_size_exceptions.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: no-exceptions
+
+// <inplace_vector>
+
+// constexpr void resize(size_type sz);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+
+int main(int, char**) {
+ ThrowingValue::reset();
+ {
+ std::inplace_vector<ThrowingValue, 4> c;
+ c.emplace_back(1);
+ c.emplace_back(2);
+
+ ThrowingValue::throw_after = 1;
+ try {
+ c.resize(4);
+ assert(false);
+ } catch (int) {
+ assert(c.size() == 2);
+ assert(c[0].value == 1);
+ assert(c[1].value == 2);
+ assert(ThrowingValue::alive == 2);
+ }
+ }
+ assert(ThrowingValue::alive == 0);
+
+ 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 0000000000000..98b705a949a99
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/resize_size_value.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void resize(size_type sz, const T& c);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 5> c{1, 2, 3};
+ c.resize(5, 9);
+ assert_inplace_vector_equal(c, {1, 2, 3, 9, 9});
+ c.resize(2, 7);
+ assert_inplace_vector_equal(c, {1, 2});
+ c.resize(5, 8);
+ assert_inplace_vector_equal(c, {1, 2, 8, 8, 8});
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 5> c{1, 2, 3};
+ assert_throws_bad_alloc([&] { c.resize(6, 4); });
+ assert_inplace_vector_equal(c, {1, 2, 3});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/resize_size_value_exceptions.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/resize_size_value_exceptions.pass.cpp
new file mode 100644
index 0000000000000..258bdd76f2188
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/resize_size_value_exceptions.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: no-exceptions
+
+// <inplace_vector>
+
+// constexpr void resize(size_type sz, const T& c);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+
+int main(int, char**) {
+ ThrowingValue::reset();
+ {
+ std::inplace_vector<ThrowingValue, 4> c;
+ c.emplace_back(1);
+ c.emplace_back(2);
+ ThrowingValue value(9);
+
+ ThrowingValue::throw_after = 1;
+ try {
+ c.resize(4, value);
+ assert(false);
+ } catch (int) {
+ assert(c.size() == 2);
+ assert(c[0].value == 1);
+ assert(c[1].value == 2);
+ assert(value.value == 9);
+ assert(ThrowingValue::alive == 3);
+ }
+ }
+ assert(ThrowingValue::alive == 0);
+
+ 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 0000000000000..88ae0db694ac5
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/shrink_to_fit.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// static constexpr void shrink_to_fit() noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ using C = std::inplace_vector<int, 8>;
+ C c{1, 2, 3};
+ auto* data = c.data();
+ c.shrink_to_fit();
+ C::shrink_to_fit();
+ assert(c.size() == 3);
+ assert(c.capacity() == 8);
+ assert(c.data() == data);
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ 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 0000000000000..ddc3f4730cf40
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/size.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr size_type size() const noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 4> c;
+ ASSERT_SAME_TYPE(std::inplace_vector<int, 4>::size_type, decltype(c.size()));
+ assert(c.size() == 0);
+ c.push_back(1);
+ assert(c.size() == 1);
+ c.push_back(2);
+ assert(c.size() == 2);
+ c.pop_back();
+ assert(c.size() == 1);
+ c.clear();
+ assert(c.size() == 0);
+
+ assert((std::inplace_vector<int, 0>().size() == 0));
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/swap.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/swap.pass.cpp
new file mode 100644
index 0000000000000..2b2cc6bc8fad7
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.capacity/swap.pass.cpp
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void swap(inplace_vector& x)
+// noexcept(N == 0 || (is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<T>));
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "../common.h"
+#include "test_macros.h"
+
+struct ThrowMove {
+ constexpr ThrowMove() = default;
+ constexpr ThrowMove(const ThrowMove&) = default;
+ constexpr ThrowMove& operator=(const ThrowMove&) = default;
+ constexpr ThrowMove(ThrowMove&&) {}
+ constexpr ThrowMove& operator=(ThrowMove&&) = default;
+ constexpr ~ThrowMove() = default;
+};
+
+namespace MyNS {
+struct M {
+ M(M const&) = delete;
+ M& operator=(M const&) = delete;
+};
+
+void swap(M&&, M&&) noexcept {}
+
+} // namespace MyNS
+
+constexpr bool test() {
+ std::inplace_vector<int, 8> c1{1, 2, 3};
+ std::inplace_vector<int, 8> c2{4, 5};
+ ASSERT_NOEXCEPT(c1.swap(c2));
+ c1.swap(c2);
+ assert(c1.capacity() == 8);
+ assert(c2.capacity() == 8);
+ assert_inplace_vector_equal(c1, {4, 5});
+ assert_inplace_vector_equal(c2, {1, 2, 3});
+
+ using namespace MyNS;
+ {
+ using C = std::inplace_vector<ThrowMove, 2>;
+ ASSERT_NOT_NOEXCEPT(std::declval<C&>().swap(std::declval<C&>()));
+ }
+
+ {
+ using C = std::inplace_vector<ThrowMove, 0>;
+ ASSERT_NOEXCEPT(std::declval<C&>().swap(std::declval<C&>()));
+ }
+
+ {
+ using C = std::inplace_vector<M, 4>;
+ ASSERT_NOT_NOEXCEPT(std::declval<C&>().swap(std::declval<C&>()));
+ }
+
+ 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_copy.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/assign_copy.pass.cpp
new file mode 100644
index 0000000000000..3710c383a6705
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/assign_copy.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector& operator=(const inplace_vector& other);
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "../common.h"
+#include "test_macros.h"
+
+struct ThrowCopyAssign {
+ ThrowCopyAssign(const ThrowCopyAssign&) = default;
+ ThrowCopyAssign& operator=(const ThrowCopyAssign&) { return *this; }
+};
+
+struct ThrowCopyCtor {
+ ThrowCopyCtor(const ThrowCopyCtor&) {}
+ ThrowCopyCtor& operator=(const ThrowCopyCtor&) = default;
+};
+
+constexpr bool test() {
+ {
+ using C = std::inplace_vector<int, 8>;
+ C c{1, 2, 3};
+ C other{4, 5};
+ ASSERT_SAME_TYPE(C&, decltype(c = other));
+ C& result = (c = other);
+ assert(&result == &c);
+ assert_inplace_vector_equal(c, {4, 5});
+ assert_inplace_vector_equal(other, {4, 5});
+
+ C& self = c;
+ c = self;
+ assert_inplace_vector_equal(c, {4, 5});
+ }
+
+ {
+ using C = std::inplace_vector<ThrowCopyAssign, 4>;
+ ASSERT_NOT_NOEXCEPT(std::declval<C>() = std::declval<const C&>());
+ }
+
+ {
+ using C = std::inplace_vector<ThrowCopyCtor, 4>;
+ ASSERT_NOT_NOEXCEPT(std::declval<C>() = std::declval<const C&>());
+ }
+ 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_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 0000000000000..a30368f0dbf0e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/assign_initializer_list.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void assign(initializer_list<T>);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 8> c{1, 2, 3};
+ c.assign({4, 5});
+ assert_inplace_vector_equal(c, {4, 5});
+ c.assign({});
+ assert(c.empty());
+ c.assign({6, 7, 8, 9});
+ assert_inplace_vector_equal(c, {6, 7, 8, 9});
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 3> c{1, 2};
+ assert_throws_bad_alloc([&] { c.assign({1, 2, 3, 4}); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ 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 0000000000000..54d228173c143
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/assign_iter_iter.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class InputIterator>
+// constexpr void assign(InputIterator first, InputIterator last);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+template <class Iter>
+constexpr void test_iterators() {
+ int a[] = {1, 2, 3, 4};
+ std::inplace_vector<int, 8> c{9, 8, 7};
+ c.assign(Iter(a), Iter(a + 4));
+ assert_inplace_vector_equal(c, a);
+
+ int b[] = {5};
+ c.assign(Iter(b), Iter(b + 1));
+ assert_inplace_vector_equal(c, b);
+
+ c.assign(Iter(b), Iter(b));
+ assert(c.empty());
+}
+
+constexpr bool test() {
+ test_iterators<cpp17_input_iterator<int*> >();
+ test_iterators<forward_iterator<int*> >();
+ test_iterators<int*>();
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ int a[] = {1, 2, 3, 4, 5};
+ std::inplace_vector<int, 4> c{9, 8};
+ assert_throws_bad_alloc([&] { c.assign(a, a + 5); });
+ assert_inplace_vector_equal(c, {9, 8});
+#endif
+
+ return 0;
+}
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 0000000000000..64d720ed68aa0
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/assign_move.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector& operator=(inplace_vector&& other)
+// noexcept(N == 0 || (is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>));
+
+#include <cassert>
+#include <inplace_vector>
+#include <type_traits>
+#include <utility>
+
+#include "../common.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+struct ThrowingMoveAssign {
+ ThrowingMoveAssign() = default;
+ ThrowingMoveAssign(ThrowingMoveAssign&&) noexcept(false) {}
+ ThrowingMoveAssign& operator=(ThrowingMoveAssign&&) noexcept(false) { return *this; }
+};
+
+struct ThrowingMoveCtorOnly {
+ ThrowingMoveCtorOnly() = default;
+ ThrowingMoveCtorOnly(ThrowingMoveCtorOnly&&) noexcept(false) {}
+ ThrowingMoveCtorOnly& operator=(ThrowingMoveCtorOnly&&) noexcept { return *this; }
+};
+
+struct ThrowingMoveAssignOnly {
+ ThrowingMoveAssignOnly() = default;
+ ThrowingMoveAssignOnly(ThrowingMoveAssignOnly&&) noexcept = default;
+ ThrowingMoveAssignOnly& operator=(ThrowingMoveAssignOnly&&) noexcept(false) { return *this; }
+};
+
+constexpr bool test() {
+ {
+ using C = std::inplace_vector<int, 8>;
+ C c{1, 2, 3};
+ C other{4, 5};
+ ASSERT_SAME_TYPE(C&, decltype(c = std::move(other)));
+ C& result = (c = std::move(other));
+ assert(&result == &c);
+ assert_inplace_vector_equal(c, {4, 5});
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ using C = std::inplace_vector<MoveOnly, 8>;
+ C c;
+ c.emplace_back(1);
+ C other;
+ other.emplace_back(4);
+ other.emplace_back(5);
+ c = std::move(other);
+ assert(c.size() == 2);
+ assert(c[0].get() == 4);
+ assert(c[1].get() == 5);
+ }
+
+ { // self-move-assignment leaves the container in a valid state
+ std::inplace_vector<int, 8> c{1, 2, 3};
+ std::inplace_vector<int, 8>& ref = c;
+ c = std::move(ref);
+ LIBCPP_ASSERT(c == (std::inplace_vector<int, 8>{1, 2, 3}));
+ }
+
+ { // noexcept(N == 0 || (is_nothrow_move_assignable_v<T> && is_nothrow_move_constructible_v<T>))
+ ASSERT_NOEXCEPT(std::declval<std::inplace_vector<int, 8>&>() = std::declval<std::inplace_vector<int, 8>&&>());
+ ASSERT_NOEXCEPT(std::declval<std::inplace_vector<ThrowingMoveAssign, 0>&>() =
+ std::declval<std::inplace_vector<ThrowingMoveAssign, 0>&&>());
+ ASSERT_NOT_NOEXCEPT(std::declval<std::inplace_vector<ThrowingMoveAssign, 8>&>() =
+ std::declval<std::inplace_vector<ThrowingMoveAssign, 8>&&>());
+
+ // both the move constructor and the move assignment of T must be noexcept
+ static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<ThrowingMoveCtorOnly, 8>>);
+ static_assert(!std::is_nothrow_move_assignable_v<std::inplace_vector<ThrowingMoveAssignOnly, 8>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<ThrowingMoveCtorOnly, 0>>);
+ static_assert(std::is_nothrow_move_assignable_v<std::inplace_vector<ThrowingMoveAssignOnly, 0>>);
+ }
+
+ 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_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 0000000000000..6d68c134260f6
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/assign_size_value.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void assign(size_type n, const T& u);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 8> c{1, 2, 3};
+ c.assign(4, 7);
+ assert_inplace_vector_equal(c, {7, 7, 7, 7});
+ c.assign(1, 8);
+ assert_inplace_vector_equal(c, {8});
+ c.assign(0, 9);
+ assert(c.empty());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 3> c{1, 2};
+ assert_throws_bad_alloc([&] { c.assign(4, 7); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ 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 0000000000000..0f0d460c22e60
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/construct_default.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector() noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "../../../NotConstructible.h"
+#include "../common.h"
+
+struct ThrowDefault {
+ constexpr ThrowDefault() {}
+};
+
+struct NoDefault {
+ NoDefault() = delete;
+};
+
+template <class C>
+constexpr void test() {
+ ASSERT_NOEXCEPT(C{});
+ C c;
+ assert(c.empty());
+ assert(c.size() == 0);
+ assert(c.capacity() == C::capacity());
+
+ C c1 = {};
+ assert(c1.empty());
+}
+
+constexpr bool tests() {
+ test<std::inplace_vector<int, 0> >();
+ test<std::inplace_vector<int, 8> >();
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ test<std::inplace_vector<NotConstructible, 8> >();
+ }
+
+ {
+ ASSERT_NOEXCEPT(std::inplace_vector<int, 0>());
+ ASSERT_NOEXCEPT(std::inplace_vector<int, 8>());
+ ASSERT_NOEXCEPT(std::inplace_vector<ThrowDefault, 1>());
+ ASSERT_NOEXCEPT(std::inplace_vector<ThrowDefault, 0>());
+ static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<NoDefault, 8>>);
+ static_assert(std::is_nothrow_default_constructible_v<std::inplace_vector<NoDefault, 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/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 0000000000000..fa0cf3f2eae2c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/construct_from_range.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<container-compatible-range<T> R>
+// constexpr inplace_vector(from_range_t, R&& rg);
+
+#include <cassert>
+#include <inplace_vector>
+#include <ranges>
+
+#include "../common.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ int a[] = {1, 2, 3, 4};
+ std::inplace_vector<int, 8> c(std::from_range, a);
+ assert_inplace_vector_equal(c, a);
+ }
+ {
+ using Iter = cpp20_input_iterator<int*>;
+ int a[] = {1, 2, 3, 4};
+ auto r = std::views::counted(Iter(a), 4);
+ std::inplace_vector<int, 8> c(std::from_range, r);
+ assert_inplace_vector_equal(c, a);
+ }
+ {
+ int a[] = {1, 2, 3, 4};
+ auto r = std::ranges::subrange(a, a + 4);
+ std::inplace_vector<int, 4> c(std::from_range, r);
+ assert_inplace_vector_equal(c, a);
+ }
+
+ 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/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 0000000000000..7d27e06e9bcef
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/construct_iter_iter.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class InputIterator>
+// constexpr inplace_vector(InputIterator first, InputIterator last);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+template <class Iter>
+constexpr void test_iterators() {
+ int a[] = {1, 2, 3, 4};
+ std::inplace_vector<int, 8> c(Iter(a), Iter(a + 4));
+ assert_inplace_vector_equal(c, a);
+}
+
+constexpr bool test() {
+ test_iterators<cpp17_input_iterator<int*> >();
+ test_iterators<forward_iterator<int*> >();
+ test_iterators<int*>();
+
+ {
+ int a[] = {1, 2, 3, 4};
+ std::inplace_vector<int, 4> c(a, a + 4);
+ assert_inplace_vector_equal(c, a);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ int a[] = {1, 2, 3, 4, 5};
+ assert_throws_bad_alloc([&] { std::inplace_vector<int, 4> c(a, a + 5); });
+#endif
+
+ 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 0000000000000..ff4aba7ca76e3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/construct_size.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr explicit inplace_vector(size_type n);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 5> c(0);
+ assert(c.empty());
+ }
+ {
+ std::inplace_vector<int, 5> c(3);
+ assert_inplace_vector_equal(c, {0, 0, 0});
+ }
+ {
+ std::inplace_vector<int, 5> c(5);
+ assert_inplace_vector_equal(c, {0, 0, 0, 0, 0});
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ assert_throws_bad_alloc([] { std::inplace_vector<int, 5> c(6); });
+#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 0000000000000..8eaac0b9136b2
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/construct_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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector(size_type n, const T& value);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 5> c(0, 7);
+ assert(c.empty());
+ }
+ {
+ std::inplace_vector<int, 5> c(3, 7);
+ assert_inplace_vector_equal(c, {7, 7, 7});
+ }
+ {
+ std::inplace_vector<int, 5> c(5, 7);
+ assert_inplace_vector_equal(c, {7, 7, 7, 7, 7});
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ assert_throws_bad_alloc([] { std::inplace_vector<int, 5> c(6, 7); });
+#endif
+
+ 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 0000000000000..33076f5a1c00f
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/copy.move_only.verify.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector(const inplace_vector&);
+//
+// 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, 4> v;
+ std::inplace_vector<MoveOnly, 4> copy =
+ v; // expected-error-re@* {{{{(no matching function for call to '__construct_at')|(call to deleted constructor of 'MoveOnly')}}}}
+}
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 0000000000000..89efc70dc65d8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/copy.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector(const inplace_vector&);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 8> c;
+ std::inplace_vector<int, 8> copy(c);
+ assert(copy.empty());
+ }
+ {
+ std::inplace_vector<int, 8> c{1, 2, 3};
+ std::inplace_vector<int, 8> copy(c);
+ assert_inplace_vector_equal(copy, {1, 2, 3});
+ assert_inplace_vector_equal(c, {1, 2, 3});
+ }
+
+ 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/exceptions.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/exceptions.pass.cpp
new file mode 100644
index 0000000000000..b82629f84ab3d
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/exceptions.pass.cpp
@@ -0,0 +1,128 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: no-exceptions
+
+// <inplace_vector>
+
+// constexpr explicit inplace_vector(size_type n);
+// constexpr inplace_vector(size_type n, const T& value);
+// template<class InputIterator>
+// constexpr inplace_vector(InputIterator first, InputIterator last);
+// constexpr inplace_vector(const inplace_vector&);
+// constexpr inplace_vector(initializer_list<T> il);
+
+#include <inplace_vector>
+
+#include "../common.h"
+
+void test_over_capacity_exceptions() {
+ assert_throws_bad_alloc([] { std::inplace_vector<int, 2> c(3); });
+ assert_throws_bad_alloc([] { std::inplace_vector<int, 2> c(3, 1); });
+ assert_throws_bad_alloc([] { std::inplace_vector<int, 2> c{1, 2, 3}; });
+
+ int a[] = {1, 2, 3};
+ assert_throws_bad_alloc([&] { std::inplace_vector<int, 2> c(a, a + 3); });
+}
+
+void test_element_constructor_exceptions() {
+ ThrowingValue::reset();
+ ThrowingValue::throw_after = 0;
+ try {
+ std::inplace_vector<ThrowingValue, 4> c(1);
+ assert(false);
+ } catch (int) {
+ assert(ThrowingValue::alive == 0);
+ }
+
+ ThrowingValue::reset();
+ {
+ ThrowingValue value(1);
+ ThrowingValue::throw_after = 0;
+ try {
+ std::inplace_vector<ThrowingValue, 4> c(1, value);
+ assert(false);
+ } catch (int) {
+ assert(ThrowingValue::alive == 1);
+ }
+ }
+ assert(ThrowingValue::alive == 0);
+}
+
+void test_iterator_constructor_exceptions() {
+ ThrowingValue::reset();
+ {
+ ThrowingValue values[] = {ThrowingValue(1), ThrowingValue(2)};
+ try {
+ std::inplace_vector<ThrowingValue, 4> c(
+ throwing_iterator<ThrowingValue, std::input_iterator_tag>(values),
+ throwing_iterator<ThrowingValue, std::input_iterator_tag>(values + 2, 2));
+ assert(false);
+ } catch (int) {
+ assert(ThrowingValue::alive == 2);
+ }
+ }
+ assert(ThrowingValue::alive == 0);
+
+ ThrowingValue::reset();
+ {
+ ThrowingValue values[] = {ThrowingValue(1), ThrowingValue(2)};
+ try {
+ std::inplace_vector<ThrowingValue, 4> c(
+ throwing_iterator<ThrowingValue, std::forward_iterator_tag>(values),
+ throwing_iterator<ThrowingValue, std::forward_iterator_tag>(values + 2, 2));
+ assert(false);
+ } catch (int) {
+ assert(ThrowingValue::alive == 2);
+ }
+ }
+ assert(ThrowingValue::alive == 0);
+}
+
+void test_copy_constructor_exceptions() {
+ ThrowingValue::reset();
+ {
+ std::inplace_vector<ThrowingValue, 4> source;
+ source.emplace_back(1);
+ source.emplace_back(2);
+
+ ThrowingValue::throw_after = 1;
+ try {
+ std::inplace_vector<ThrowingValue, 4> copy(source);
+ assert(false);
+ } catch (int) {
+ assert(source.size() == 2);
+ assert(source[0].value == 1);
+ assert(source[1].value == 2);
+ assert(ThrowingValue::alive == 2);
+ }
+ }
+ assert(ThrowingValue::alive == 0);
+}
+
+void test_initializer_list_constructor_exceptions() {
+ ThrowingValue::reset();
+ try {
+ ThrowingValue::throw_after = 3;
+ std::inplace_vector<ThrowingValue, 4> c{ThrowingValue(1), ThrowingValue(2)};
+ assert(false);
+ } catch (int) {
+ assert(ThrowingValue::alive == 0);
+ }
+}
+
+int main(int, char**) {
+ test_over_capacity_exceptions();
+ test_element_constructor_exceptions();
+ test_iterator_constructor_exceptions();
+ test_copy_constructor_exceptions();
+ test_initializer_list_constructor_exceptions();
+
+ 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 0000000000000..f808778a733be
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/initializer_list.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector(initializer_list<T> il);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 8> c{1, 2, 3};
+ assert_inplace_vector_equal(c, {1, 2, 3});
+
+ std::inplace_vector<int, 0> empty{};
+ assert(empty.empty());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ assert_throws_bad_alloc([] { std::inplace_vector<int, 2> c{1, 2, 3}; });
+#endif
+
+ return 0;
+}
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 0000000000000..64ca64f80fa0e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/move.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector(inplace_vector&&)
+// noexcept(N == 0 || is_nothrow_move_constructible_v<T>);
+
+#include <cassert>
+#include <inplace_vector>
+#include <type_traits>
+#include <utility>
+
+#include "../common.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+struct ThrowingMove {
+ ThrowingMove() = default;
+ ThrowingMove(ThrowingMove&&) noexcept(false) {}
+};
+
+struct ThrowingCopyNothrowMove {
+ ThrowingCopyNothrowMove() = default;
+ ThrowingCopyNothrowMove(const ThrowingCopyNothrowMove&) noexcept(false) {}
+ ThrowingCopyNothrowMove(ThrowingCopyNothrowMove&&) noexcept {}
+};
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 8> c{1, 2, 3};
+ std::inplace_vector<int, 8> moved(std::move(c));
+ assert_inplace_vector_equal(moved, {1, 2, 3});
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<MoveOnly, 8> c;
+ c.emplace_back(1);
+ c.emplace_back(2);
+ std::inplace_vector<MoveOnly, 8> moved(std::move(c));
+ assert(moved.size() == 2);
+ assert(moved[0].get() == 1);
+ assert(moved[1].get() == 2);
+ }
+
+ { // noexcept(N == 0 || is_nothrow_move_constructible_v<T>)
+ ASSERT_NOEXCEPT(std::inplace_vector<int, 8>(std::inplace_vector<int, 8>()));
+ ASSERT_NOEXCEPT(std::inplace_vector<ThrowingMove, 0>(std::inplace_vector<ThrowingMove, 0>()));
+ ASSERT_NOT_NOEXCEPT(std::inplace_vector<ThrowingMove, 8>(std::move(std::inplace_vector<ThrowingMove, 8>())));
+ static_assert(std::is_nothrow_move_constructible_v<std::inplace_vector<ThrowingCopyNothrowMove, 8>>);
+ }
+
+ 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/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 0000000000000..7e56944a81f67
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.cons/op_equal_initializer_list.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr inplace_vector& operator=(initializer_list<T>);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ using C = std::inplace_vector<int, 8>;
+ C c{1, 2, 3};
+ ASSERT_SAME_TYPE(C&, decltype(c = {4, 5}));
+ C& result = (c = {4, 5});
+ assert(&result == &c);
+ assert_inplace_vector_equal(c, {4, 5});
+ c = {};
+ assert(c.empty());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 3> c{1, 2};
+ assert_throws_bad_alloc([&] { c = {1, 2, 3, 4}; });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ 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 0000000000000..e84899b29d91c
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.data/data.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr T* data() noexcept;
+// constexpr const T* data() const noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 4> c{1, 2, 3};
+ ASSERT_SAME_TYPE(decltype(c.data()), int*);
+ ASSERT_SAME_TYPE(decltype(std::as_const(c).data()), const int*);
+
+ assert(c.data() == &c.front());
+ assert(std::as_const(c).data() == &c.front());
+ assert(std::as_const(c).data() == &std::as_const(c).front());
+
+ c.data()[1] = 5;
+ assert(c[1] == 5);
+ assert(std::as_const(c)[1] == 5);
+ c.push_back(6);
+ assert(c.data()[3] == 6);
+ assert(std::as_const(c).data()[3] == 6);
+
+ std::inplace_vector<int, 0> empty;
+ assert(empty.data() == empty.data());
+ assert(std::as_const(empty).data() == std::as_const(empty).data());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ 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 0000000000000..7f6a69f737a1d
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.data/data_const.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr T* inplace_vector<T,N>::data() const noexcept;
+// constexpr T* inplace_vector<T,0>::data() const noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+#include <memory>
+
+#include "../common.h"
+#include "test_macros.h"
+
+struct Nasty {
+ constexpr Nasty() : i_(0) {}
+ constexpr Nasty(int i) : i_(i) {}
+ constexpr ~Nasty() {}
+ Nasty* operator&() const {
+ assert(false);
+ return nullptr;
+ }
+ int i_;
+};
+
+constexpr bool tests() {
+ {
+ const std::inplace_vector<int, 4> v;
+ ASSERT_SAME_TYPE(decltype(v.data()), const int*);
+ ASSERT_NOEXCEPT(v.data());
+ assert(v.data() == v.data());
+ }
+ {
+ const std::inplace_vector<int, 100> v(100);
+ assert(v.data() == std::addressof(v.front()));
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ const std::inplace_vector<Nasty, 100> v(100);
+ assert(v.data() == std::addressof(v.front()));
+ }
+ {
+ const std::inplace_vector<int, 0> v;
+ assert(v.data() == v.data());
+ assert(v.data() == nullptr);
+ }
+
+ 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 0000000000000..323626556bba9
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.erasure/erase.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class T, size_t N, class U>
+// constexpr typename inplace_vector<T, N>::size_type
+// erase(inplace_vector<T, N>& c, const U& value);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 8> c{1, 2, 3, 2, 4, 2};
+ ASSERT_SAME_TYPE(std::inplace_vector<int, 8>::size_type, decltype(std::erase(c, 2)));
+ auto erased = std::erase(c, 2);
+ assert(erased == 3);
+ assert_inplace_vector_equal(c, {1, 3, 4});
+
+ erased = std::erase(c, 9);
+ assert(erased == 0);
+ assert_inplace_vector_equal(c, {1, 3, 4});
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ 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 0000000000000..84d7ab0a3d401
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.erasure/erase_if.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// 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);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 8> c{1, 2, 3, 4, 5, 6};
+ ASSERT_SAME_TYPE(std::inplace_vector<int, 8>::size_type, decltype(std::erase_if(c, [](int v) { return v % 2 == 0; })));
+ auto erased = std::erase_if(c, [](int v) { return v % 2 == 0; });
+ assert(erased == 3);
+ assert_inplace_vector_equal(c, {1, 3, 5});
+
+ erased = std::erase_if(c, [](int v) { return v > 10; });
+ assert(erased == 0);
+ assert_inplace_vector_equal(c, {1, 3, 5});
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/append_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/append_range.pass.cpp
new file mode 100644
index 0000000000000..b3b5cd455bd40
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/append_range.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// <inplace_vector>
+
+// template<container-compatible-range<T> R>
+// constexpr void append_range(R&& rg);
+
+#include <array>
+#include <cassert>
+#include <inplace_vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "../common.h"
+#include "test_macros.h"
+
+template <class Iter, class Sent>
+constexpr void test_iterators() {
+ test_sequence_append_range<InplaceVector<int>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+}
+
+constexpr bool test() {
+ static_assert(test_constraints_append_range<InplaceVector, int, double>());
+
+ test_iterators<cpp20_input_iterator<const int*>, sentinel_wrapper<cpp20_input_iterator<const int*> > >();
+ test_iterators<forward_iterator<const int*>, sentinel_wrapper<forward_iterator<const int*> > >();
+ test_iterators<const int*, const int*>();
+
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ test_sequence_append_range_move_only<InplaceVector>();
+ test_sequence_append_range_emplace_constructible_and_move_insertable<InplaceVector>();
+ }
+
+ {
+ int in[] = {-1, -2, -3};
+ std::inplace_vector<int, 8> c{1, 2, 3};
+ auto* ptr = c.data();
+ c.append_range(in);
+ assert(c.data() == ptr);
+ assert_inplace_vector_equal(c, {1, 2, 3, -1, -2, -3});
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ test_append_range_exception_safety_throwing_copy<InplaceVector>();
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ int in[] = {3, 4};
+ std::inplace_vector<int, 3> c{1, 2};
+ assert_throws_bad_alloc([&] { c.append_range(in); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/assign_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/assign_range.pass.cpp
new file mode 100644
index 0000000000000..ca76fb1bc7df3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/assign_range.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// <inplace_vector>
+
+// template<container-compatible-range<T> R>
+// constexpr void assign_range(R&& rg);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "../common.h"
+#include "test_macros.h"
+
+template <class Iter, class Sent>
+constexpr void test_iterators() {
+ test_sequence_assign_range<InplaceVector<int>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+}
+
+constexpr bool test() {
+ static_assert(test_constraints_assign_range<InplaceVector, int, double>());
+
+ test_iterators<cpp20_input_iterator<const int*>, sentinel_wrapper<cpp20_input_iterator<const int*> > >();
+ test_iterators<forward_iterator<const int*>, sentinel_wrapper<forward_iterator<const int*> > >();
+ test_iterators<const int*, const int*>();
+
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ test_sequence_assign_range_move_only<InplaceVector>();
+ }
+
+ {
+ int in[] = {-1, -2, -3};
+ std::inplace_vector<int, 8> c{1, 2, 3, 4, 5};
+ c.assign_range(in);
+ assert_inplace_vector_equal(c, in);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ test_assign_range_exception_safety_throwing_copy<InplaceVector>();
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ int in[] = {1, 2, 3, 4};
+ std::inplace_vector<int, 3> c{8, 9};
+ assert_throws_bad_alloc([&] { c.assign_range(in); });
+ assert_inplace_vector_equal(c, {8, 9});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/clear.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/clear.pass.cpp
new file mode 100644
index 0000000000000..175b471fd8e4e
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/clear.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void clear() noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 4> c{1, 2, 3};
+ ASSERT_NOEXCEPT(c.clear());
+ ASSERT_SAME_TYPE(decltype(c.clear()), void);
+ c.clear();
+ assert(c.empty());
+ assert(c.capacity() == 4);
+ c.clear();
+ assert(c.empty());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/destroy_elements.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/destroy_elements.pass.cpp
new file mode 100644
index 0000000000000..d4ab65621ec49
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/destroy_elements.pass.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void pop_back();
+// constexpr iterator iterator erase(const_iterator position);
+// constexpr void clear() noexcept;
+// constexpr ~inplace_vector();
+
+#include <cassert>
+#include <inplace_vector>
+#include <type_traits>
+
+#include "../common.h"
+#include "test_macros.h"
+
+struct Tracker {
+ int* alive_;
+
+ constexpr explicit Tracker(int& alive) : alive_(&alive) { ++*alive_; }
+ constexpr Tracker(const Tracker& other) : alive_(other.alive_) { ++*alive_; }
+ constexpr Tracker& operator=(const Tracker&) = default;
+ constexpr ~Tracker() { --*alive_; }
+};
+
+struct NonTrivialDtor {
+ ~NonTrivialDtor() {}
+};
+
+static_assert(std::is_nothrow_destructible_v<std::inplace_vector<int, 0> >);
+static_assert(std::is_nothrow_destructible_v<std::inplace_vector<int, 8> >);
+static_assert(std::is_nothrow_destructible_v<std::inplace_vector<NonTrivialDtor, 0> >);
+static_assert(std::is_nothrow_destructible_v<std::inplace_vector<NonTrivialDtor, 8> >);
+
+constexpr bool test() {
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ int alive = 0;
+ {
+ std::inplace_vector<Tracker, 8> c;
+ c.emplace_back(alive);
+ c.emplace_back(alive);
+ c.emplace_back(alive);
+ assert(alive == 3);
+
+ c.pop_back();
+ assert(alive == 2);
+
+ c.erase(c.begin());
+ assert(alive == 1);
+
+ c.clear();
+ assert(alive == 0);
+ }
+ assert(alive == 0);
+ }
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/emplace.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/emplace.pass.cpp
new file mode 100644
index 0000000000000..7de27c47142eb
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/emplace.pass.cpp
@@ -0,0 +1,62 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class... Args>
+// constexpr iterator emplace(const_iterator position, Args&&... args);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+struct A {
+ int i;
+ int j;
+
+ constexpr A(int ii, int jj) : i(ii), j(jj) {}
+};
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 5> c{1, 2, 4};
+ std::same_as<std::inplace_vector<int, 5>::iterator> decltype(auto) i = c.emplace(c.begin() + 2, 3);
+ assert(i == c.begin() + 2);
+ assert_inplace_vector_equal(c, {1, 2, 3, 4});
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<A, 5> c;
+ c.emplace_back(1, 2);
+ auto i = c.emplace(c.begin(), 3, 4);
+ assert(i == c.begin());
+ assert(c[0].i == 3);
+ assert(c[0].j == 4);
+ assert(c[1].i == 1);
+ assert(c[1].j == 2);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 2> c{1, 2};
+ assert_throws_bad_alloc([&] { c.emplace(c.begin(), 3); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/emplace_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/emplace_back.pass.cpp
new file mode 100644
index 0000000000000..11dc1688dd4c8
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/emplace_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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class... Args>
+// constexpr reference emplace_back(Args&&... args);
+
+#include <cassert>
+#include <inplace_vector>
+#include <tuple>
+
+#include "../common.h"
+#include "test_macros.h"
+
+struct A {
+ int i;
+ int j;
+
+ constexpr A(int ii, int jj) : i(ii), j(jj) {}
+};
+
+constexpr bool test() {
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<A, 3> c;
+ ASSERT_SAME_TYPE(A&, decltype(c.emplace_back(1, 2)));
+ A& r = c.emplace_back(1, 2);
+ assert(&r == &c.back());
+ assert(c.back().i == 1);
+ assert(c.back().j == 2);
+
+ c.emplace_back(3, 4);
+ assert(c.size() == 2);
+ assert(c[1].i == 3);
+ assert(c[1].j == 4);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 2> c{1, 2};
+ assert_throws_bad_alloc([&] { c.emplace_back(3); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/erase_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/erase_iter.pass.cpp
new file mode 100644
index 0000000000000..d011fc7013ea0
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/erase_iter.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr iterator erase(const_iterator position);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 5> c{1, 2, 3, 4};
+ std::same_as<std::inplace_vector<int, 5>::iterator> decltype(auto) i = c.erase(c.begin());
+ assert(i == c.begin());
+ assert_inplace_vector_equal(c, {2, 3, 4});
+ }
+ {
+ std::inplace_vector<int, 5> c{1, 2, 3, 4};
+ auto i = c.erase(c.begin() + 1);
+ assert(i == c.begin() + 1);
+ assert_inplace_vector_equal(c, {1, 3, 4});
+ }
+ {
+ std::inplace_vector<int, 5> c{1, 2, 3, 4};
+ auto i = c.erase(c.end() - 1);
+ assert(i == c.end());
+ assert_inplace_vector_equal(c, {1, 2, 3});
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/erase_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/erase_iter_iter.pass.cpp
new file mode 100644
index 0000000000000..399741849d62d
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/erase_iter_iter.pass.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr iterator erase(const_iterator first, const_iterator last);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 8> c{1, 2, 3, 4, 5};
+ std::same_as<std::inplace_vector<int, 8>::iterator> decltype(auto) i = c.erase(c.begin(), c.begin() + 2);
+ assert(i == c.begin());
+ assert_inplace_vector_equal(c, {3, 4, 5});
+ }
+ {
+ std::inplace_vector<int, 8> c{1, 2, 3, 4, 5};
+ auto i = c.erase(c.begin() + 1, c.begin() + 4);
+ assert(i == c.begin() + 1);
+ assert_inplace_vector_equal(c, {1, 5});
+ }
+ {
+ std::inplace_vector<int, 8> c{1, 2, 3, 4, 5};
+ auto i = c.erase(c.end(), c.end());
+ assert(i == c.end());
+ assert_inplace_vector_equal(c, {1, 2, 3, 4, 5});
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_initializer_list.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_initializer_list.pass.cpp
new file mode 100644
index 0000000000000..c088fd8a0f984
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_initializer_list.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr iterator insert(const_iterator position, initializer_list<T> il);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 8> c{1, 2, 5};
+ std::same_as<std::inplace_vector<int, 8>::iterator> decltype(auto) i = c.insert(c.begin() + 2, {3, 4});
+ assert(i == c.begin() + 2);
+ assert_inplace_vector_equal(c, {1, 2, 3, 4, 5});
+
+ i = c.insert(c.end(), {});
+ assert(i == c.end());
+ assert_inplace_vector_equal(c, {1, 2, 3, 4, 5});
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 4> c{1, 2, 3};
+ assert_throws_bad_alloc([&] { c.insert(c.begin(), {4, 5}); });
+ assert_inplace_vector_equal(c, {1, 2, 3});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_iter_iter.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_iter_iter.pass.cpp
new file mode 100644
index 0000000000000..5ed78169e2082
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_iter_iter.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class InputIterator>
+// constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+namespace adl {
+struct S {};
+void make_move_iterator(S*) {}
+} // namespace adl
+
+template <class Iter>
+constexpr void test_iterators() {
+ int a[] = {3, 4};
+ std::inplace_vector<int, 8> c{1, 2, 5};
+ std::same_as<std::inplace_vector<int, 8>::iterator> decltype(auto) i = c.insert(c.begin() + 2, Iter(a), Iter(a + 2));
+ assert(i == c.begin() + 2);
+ assert_inplace_vector_equal(c, {1, 2, 3, 4, 5});
+
+ i = c.insert(c.end(), Iter(a), Iter(a));
+ assert(i == c.end());
+ assert_inplace_vector_equal(c, {1, 2, 3, 4, 5});
+}
+
+constexpr bool test() {
+ test_iterators<cpp17_input_iterator<int*> >();
+ test_iterators<forward_iterator<int*> >();
+ test_iterators<int*>();
+
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ struct Wrapper {
+ constexpr Wrapper(int n) : n_(n) {}
+ void operator=(int) = delete;
+ int n_;
+ };
+
+ int a[] = {1, 2, 3};
+ std::inplace_vector<Wrapper, 4> c;
+ c.insert(c.end(), a, a + 3);
+ assert(c.size() == 3);
+ assert(c[0].n_ == 1);
+ assert(c[1].n_ == 2);
+ assert(c[2].n_ == 3);
+ }
+ {
+ std::inplace_vector<adl::S, 4> s;
+ s.insert(s.end(), cpp17_input_iterator<adl::S*>(nullptr), cpp17_input_iterator<adl::S*>(nullptr));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ int a[] = {3, 4};
+ std::inplace_vector<int, 4> c{1, 2, 5};
+ assert_throws_bad_alloc([&] { c.insert(c.begin() + 2, a, a + 2); });
+ assert_inplace_vector_equal(c, {1, 2, 5});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_lvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_lvalue.pass.cpp
new file mode 100644
index 0000000000000..37fefc1981900
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_lvalue.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr iterator insert(const_iterator position, const T& x);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 5> c{1, 2, 4};
+ int x = 3;
+ std::same_as<std::inplace_vector<int, 5>::iterator> decltype(auto) i = c.insert(c.begin() + 2, x);
+ assert(i == c.begin() + 2);
+ assert_inplace_vector_equal(c, {1, 2, 3, 4});
+
+ x = 5;
+ i = c.insert(c.end(), x);
+ assert(i == c.end() - 1);
+ assert_inplace_vector_equal(c, {1, 2, 3, 4, 5});
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 2> c{1, 2};
+ int x = 3;
+ assert_throws_bad_alloc([&] { c.insert(c.begin(), x); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_rvalue.pass.cpp
new file mode 100644
index 0000000000000..051b787d6b273
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_rvalue.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr iterator insert(const_iterator position, T&& x);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 5> c{1, 2, 4};
+ std::same_as<std::inplace_vector<int, 5>::iterator> decltype(auto) i = c.insert(c.begin() + 2, 3);
+ assert(i == c.begin() + 2);
+ assert_inplace_vector_equal(c, {1, 2, 3, 4});
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<MoveOnly, 5> c;
+ c.emplace_back(1);
+ c.emplace_back(3);
+ auto i = c.insert(c.begin() + 1, MoveOnly(2));
+ assert(i == c.begin() + 1);
+ assert(c[0].get() == 1);
+ assert(c[1].get() == 2);
+ assert(c[2].get() == 3);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 2> c{1, 2};
+ assert_throws_bad_alloc([&] { c.insert(c.begin(), 3); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_size_value.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_size_value.pass.cpp
new file mode 100644
index 0000000000000..5e0d7bbb75c4d
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_size_value.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr iterator insert(const_iterator position, size_type n, const T& x);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 8> c{1, 2, 5};
+ std::same_as<std::inplace_vector<int, 8>::iterator> decltype(auto) i = c.insert(c.begin() + 2, 2, 3);
+ assert(i == c.begin() + 2);
+ assert_inplace_vector_equal(c, {1, 2, 3, 3, 5});
+
+ i = c.insert(c.end(), 0, 9);
+ assert(i == c.end());
+ assert_inplace_vector_equal(c, {1, 2, 3, 3, 5});
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 4> c{1, 2, 3};
+ assert_throws_bad_alloc([&] { c.insert(c.begin() + 1, 2, 9); });
+ assert_inplace_vector_equal(c, {1, 2, 3});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_range.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_range.pass.cpp
new file mode 100644
index 0000000000000..a02378ffb8f32
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_range.pass.cpp
@@ -0,0 +1,84 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
+
+// <inplace_vector>
+
+// template<container-compatible-range<T> R>
+// constexpr iterator insert_range(const_iterator position, R&& rg);
+
+#include <array>
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+
+#include "../../insert_range_sequence_containers.h"
+#include "../common.h"
+#include "test_macros.h"
+
+template <class Iter, class Sent>
+constexpr void test_iterators() {
+ test_sequence_insert_range<InplaceVector<int>, Iter, Sent>([]([[maybe_unused]] auto&& c) {});
+}
+
+constexpr bool test() {
+ static_assert(test_constraints_insert_range<InplaceVector, int, double>());
+
+ test_iterators<cpp20_input_iterator<const int*>, sentinel_wrapper<cpp20_input_iterator<const int*> > >();
+ test_iterators<forward_iterator<const int*>, sentinel_wrapper<forward_iterator<const int*> > >();
+ test_iterators<const int*, const int*>();
+
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ test_sequence_insert_range_move_only<InplaceVector>();
+ }
+
+ {
+ int in[] = {-1, -2, -3};
+ std::inplace_vector<int, 8> c{1, 2, 6};
+ std::same_as<std::inplace_vector<int, 8>::iterator> decltype(auto) i = c.insert_range(c.begin() + 2, in);
+ assert(i == c.begin() + 2);
+ assert_inplace_vector_equal(c, {1, 2, -1, -2, -3, 6});
+ }
+
+ // Ensure that insert_range doesn't use unexpected assignment.
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ struct Wrapper {
+ constexpr Wrapper(int n) : n_(n) {}
+ void operator=(int) = delete;
+
+ int n_;
+ };
+
+ int a[]{1, 2, 3, 4, 5};
+ std::inplace_vector<Wrapper, 8> c;
+ c.insert_range(c.end(), a);
+ assert(c.size() == std::size(a));
+ for (std::size_t i = 0; i != std::size(a); ++i)
+ assert(c[i].n_ == a[i]);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ test_insert_range_exception_safety_throwing_copy<InplaceVector>();
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ int in[] = {3, 4};
+ std::inplace_vector<int, 3> c{1, 2};
+ assert_throws_bad_alloc([&] { c.insert_range(c.begin(), in); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/pop_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/pop_back.pass.cpp
new file mode 100644
index 0000000000000..e21321f1cc6e3
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/pop_back.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void pop_back();
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 4> c{1, 2, 3};
+ c.pop_back();
+ assert_inplace_vector_equal(c, {1, 2});
+ c.pop_back();
+ assert_inplace_vector_equal(c, {1});
+ c.pop_back();
+ assert(c.empty());
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back.pass.cpp
new file mode 100644
index 0000000000000..bb97c2fb6c8b6
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr reference push_back(const T& x);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ std::inplace_vector<int, 3> c;
+ int x = 1;
+ ASSERT_SAME_TYPE(int&, decltype(c.push_back(x)));
+ int& r1 = c.push_back(x);
+ assert(&r1 == &c.back());
+ assert(c.back() == 1);
+ x = 2;
+ int& r2 = c.push_back(x);
+ assert(&r2 == &c.back());
+ assert_inplace_vector_equal(c, {1, 2});
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 2> c{1, 2};
+ int x = 3;
+ assert_throws_bad_alloc([&] { c.push_back(x); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_exception_safety.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_exception_safety.pass.cpp
new file mode 100644
index 0000000000000..75ff8a5cfcfa5
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_exception_safety.pass.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: no-exceptions
+
+// <inplace_vector>
+
+// constexpr reference push_back(const T& x);
+// constexpr reference push_back(T&& x);
+// template<class... Args>
+// constexpr reference emplace_back(Args&&... args);
+
+#include <cassert>
+#include <inplace_vector>
+
+struct ThrowingCopy {
+ int value_;
+ static bool throw_now_;
+
+ explicit ThrowingCopy(int value) : value_(value) {}
+ ThrowingCopy(const ThrowingCopy& other) : value_(other.value_) {
+ if (throw_now_)
+ throw 1;
+ }
+ ThrowingCopy(ThrowingCopy&& other) : value_(other.value_) {
+ if (throw_now_)
+ throw 1;
+ }
+ ThrowingCopy& operator=(const ThrowingCopy&) = default;
+ ThrowingCopy& operator=(ThrowingCopy&&) = default;
+};
+
+bool ThrowingCopy::throw_now_ = false;
+
+struct ThrowingCtor {
+ explicit ThrowingCtor(int) { throw 1; }
+};
+
+int main(int, char**) {
+ {
+ std::inplace_vector<ThrowingCopy, 3> c;
+ c.emplace_back(1);
+ ThrowingCopy value(2);
+ ThrowingCopy::throw_now_ = true;
+ try {
+ c.push_back(value);
+ assert(false);
+ } catch (int) {
+ assert(c.size() == 1);
+ assert(c[0].value_ == 1);
+ }
+ ThrowingCopy::throw_now_ = false;
+ }
+ {
+ std::inplace_vector<ThrowingCtor, 3> c;
+ try {
+ c.emplace_back(1);
+ assert(false);
+ } catch (int) {
+ assert(c.empty());
+ }
+ }
+
+ return 0;
+}
+
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_rvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_rvalue.pass.cpp
new file mode 100644
index 0000000000000..98cfe7902cd79
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_rvalue.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr reference push_back(T&& x);
+
+#include <cassert>
+#include <inplace_vector>
+
+#include "../common.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 3> c;
+ ASSERT_SAME_TYPE(int&, decltype(c.push_back(1)));
+ int& r = c.push_back(1);
+ assert(&r == &c.back());
+ assert(c.back() == 1);
+ c.push_back(2);
+ assert_inplace_vector_equal(c, {1, 2});
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<MoveOnly, 3> c;
+ MoveOnly m(1);
+ MoveOnly& r = c.push_back(std::move(m));
+ assert(&r == &c.back());
+ assert(c.back().get() == 1);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ std::inplace_vector<int, 2> c{1, 2};
+ assert_throws_bad_alloc([&] { c.push_back(3); });
+ assert_inplace_vector_equal(c, {1, 2});
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/try_push_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/try_push_back.pass.cpp
new file mode 100644
index 0000000000000..dbc4fac080368
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/try_push_back.pass.cpp
@@ -0,0 +1,116 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class... Args>
+// constexpr optional<reference> try_emplace_back(Args&&... args);
+// constexpr optional<reference> try_push_back(const T& x);
+// constexpr optional<reference> try_push_back(T&& x);
+
+#include <cassert>
+#include <concepts>
+#include <inplace_vector>
+#include <optional>
+#include <utility>
+
+#include "../common.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+struct A {
+ int i;
+ int j;
+
+ constexpr A(int ii, int jj) : i(ii), j(jj) {}
+};
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 2> c;
+ int value = 1;
+ std::same_as<std::optional<int&>> decltype(auto) r1 = c.try_push_back(value);
+ assert(r1);
+ assert(&*r1 == &c.back());
+ assert_inplace_vector_equal(c, {1});
+
+ std::same_as<std::optional<int&>> decltype(auto) r2 = c.try_push_back(2);
+ assert(r2);
+ assert(&*r2 == &c.back());
+ assert_inplace_vector_equal(c, {1, 2});
+
+ auto r3 = c.try_push_back(3);
+ assert(!r3);
+ assert_inplace_vector_equal(c, {1, 2});
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<A, 1> c;
+ std::same_as<std::optional<A&>> decltype(auto) r = c.try_emplace_back(1, 2);
+ assert(r);
+ assert(&*r == &c.back());
+ assert(r->i == 1);
+ assert(r->j == 2);
+
+ auto r2 = c.try_emplace_back(3, 4);
+ assert(!r2);
+ assert(c.size() == 1);
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<MoveOnly, 1> c;
+ auto r = c.try_push_back(MoveOnly(1));
+ assert(r);
+ assert(r->get() == 1);
+ auto r2 = c.try_push_back(MoveOnly(2));
+ assert(!r2);
+ assert(c[0].get() == 1);
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ // when there is no effect, the argument is not moved from
+ std::inplace_vector<MoveOnly, 1> c;
+ (void)c.try_push_back(MoveOnly(1));
+ MoveOnly m(2);
+ auto r = c.try_push_back(std::move(m));
+ assert(!r);
+ assert(m.get() == 2);
+ assert(c[0].get() == 1);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ { // an exception thrown by T's constructor propagates and there are no effects
+ ThrowingValue::reset();
+ {
+ std::inplace_vector<ThrowingValue, 4> c;
+ (void)c.try_emplace_back(1);
+ assert(c.size() == 1);
+
+ ThrowingValue::throw_after = 0;
+ try {
+ (void)c.try_emplace_back(2);
+ assert(false);
+ } catch (int) {
+ }
+ ThrowingValue::throw_after = -1;
+ assert(c.size() == 1);
+ assert(c[0].value == 1);
+ }
+ assert(ThrowingValue::alive == 0);
+ ThrowingValue::reset();
+ }
+#endif
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/unchecked_push_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/unchecked_push_back.pass.cpp
new file mode 100644
index 0000000000000..ecbfc335db5ca
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/unchecked_push_back.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// 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);
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "../common.h"
+#include "MoveOnly.h"
+#include "test_macros.h"
+
+struct A {
+ int i;
+ int j;
+
+ constexpr A(int ii, int jj) : i(ii), j(jj) {}
+};
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 3> c;
+ int value = 1;
+ ASSERT_SAME_TYPE(int&, decltype(c.unchecked_push_back(value)));
+ ASSERT_SAME_TYPE(int&, decltype(c.unchecked_push_back(1)));
+ int& r1 = c.unchecked_push_back(value);
+ assert(&r1 == &c.back());
+ int& r2 = c.unchecked_push_back(2);
+ assert(&r2 == &c.back());
+ assert_inplace_vector_equal(c, {1, 2});
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<A, 2> c;
+ ASSERT_SAME_TYPE(A&, decltype(c.unchecked_emplace_back(1, 2)));
+ A& r = c.unchecked_emplace_back(1, 2);
+ assert(&r == &c.back());
+ assert(c[0].i == 1);
+ assert(c[0].j == 2);
+ }
+ if (!TEST_IS_CONSTANT_EVALUATED || TEST_INPLACE_VECTOR_NONTRIVIAL_CONSTEXPR) {
+ std::inplace_vector<MoveOnly, 1> c;
+ MoveOnly& r = c.unchecked_push_back(MoveOnly(1));
+ assert(&r == &c.back());
+ assert(c[0].get() == 1);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.special/swap.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.special/swap.pass.cpp
new file mode 100644
index 0000000000000..ed59a8a81bada
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.special/swap.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// constexpr void swap(inplace_vector& x)
+// noexcept(N == 0 || (is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<T>));
+
+#include <cassert>
+#include <inplace_vector>
+#include <utility>
+
+#include "../common.h"
+#include "test_macros.h"
+
+struct ThrowingMove {
+ ThrowingMove() = default;
+ ThrowingMove(ThrowingMove&&) noexcept(false) {}
+ ThrowingMove& operator=(ThrowingMove&&) noexcept(false) { return *this; }
+};
+
+constexpr bool test() {
+ {
+ std::inplace_vector<int, 8> c1{1, 2, 3};
+ std::inplace_vector<int, 8> c2{4, 5};
+ c1.swap(c2);
+ assert_inplace_vector_equal(c1, {4, 5});
+ assert_inplace_vector_equal(c2, {1, 2, 3});
+ }
+ {
+ std::inplace_vector<int, 8> c1{1, 2, 3};
+ std::inplace_vector<int, 8> c2{4, 5};
+ swap(c1, c2);
+ assert_inplace_vector_equal(c1, {4, 5});
+ assert_inplace_vector_equal(c2, {1, 2, 3});
+ }
+
+ { // noexcept(N == 0 || (is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<T>))
+ using C0 = std::inplace_vector<ThrowingMove, 0>;
+ using C8 = std::inplace_vector<ThrowingMove, 8>;
+ std::inplace_vector<int, 8> c1;
+ std::inplace_vector<int, 8> c2;
+ ASSERT_NOEXCEPT(swap(c1, c2));
+ ASSERT_NOEXCEPT(swap(std::declval<C0&>(), std::declval<C0&>()));
+ ASSERT_NOT_NOEXCEPT(swap(std::declval<C8&>(), std::declval<C8&>()));
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ 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 0000000000000..70c4d593af0a2
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/iterator_concept_conformance.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// inplace_vector<T,N>::iterator
+// inplace_vector<T,N>::const_iterator
+
+#include <inplace_vector>
+#include <iterator>
+
+template <class C>
+constexpr bool test() {
+ static_assert(std::contiguous_iterator<typename C::iterator>);
+ static_assert(std::contiguous_iterator<typename C::const_iterator>);
+ static_assert(std::sentinel_for<typename C::iterator, typename C::iterator>);
+ static_assert(std::sentinel_for<typename C::const_iterator, typename C::iterator>);
+ static_assert(std::sentinel_for<typename C::iterator, typename C::const_iterator>);
+ static_assert(std::sentinel_for<typename C::const_iterator, typename C::const_iterator>);
+
+ return true;
+}
+
+static_assert(test<std::inplace_vector<int, 0> >());
+static_assert(test<std::inplace_vector<int, 8> >());
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 0000000000000..5377f55d75538
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/iterators.pass.cpp
@@ -0,0 +1,128 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <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 <cassert>
+#include <compare>
+#include <concepts>
+#include <inplace_vector>
+#include <iterator>
+
+#include "test_macros.h"
+
+struct A {
+ int first;
+ int second;
+};
+
+constexpr bool test() {
+ {
+ using C = std::inplace_vector<int, 8>;
+ C c;
+ const C& cc = c;
+ ASSERT_SAME_TYPE(C::iterator, decltype(c.begin()));
+ ASSERT_SAME_TYPE(C::iterator, decltype(c.end()));
+ ASSERT_SAME_TYPE(C::const_iterator, decltype(cc.begin()));
+ ASSERT_SAME_TYPE(C::const_iterator, decltype(cc.end()));
+ ASSERT_SAME_TYPE(C::const_iterator, decltype(c.cbegin()));
+ ASSERT_SAME_TYPE(C::const_iterator, decltype(c.cend()));
+ C::iterator i = c.begin();
+ C::iterator j = c.end();
+ assert(std::distance(i, j) == 0);
+ assert(i == j);
+ }
+ {
+ using C = std::inplace_vector<int, 8>;
+ const C c;
+ C::const_iterator i = c.begin();
+ C::const_iterator j = c.end();
+ assert(std::distance(i, j) == 0);
+ assert(i == j);
+ }
+ {
+ using C = std::inplace_vector<int, 8>;
+ C c;
+ C::const_iterator 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, 16>;
+ C c{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ 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, 8>;
+ C::iterator i{};
+ C::const_iterator j{};
+ assert(i == i);
+ assert(j == j);
+ }
+ {
+ using C = std::inplace_vector<A, 4>;
+ 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, 8>;
+ C::iterator i{};
+ C::iterator j{};
+ C::const_iterator ci{};
+
+ assert(i == j);
+ assert(i == ci);
+ assert(ci == i);
+ assert(!(i != ci));
+ assert(!(ci != i));
+ assert(!(i < ci));
+ assert(!(ci < i));
+ assert(i <= ci);
+ assert(ci <= i);
+ assert(!(i > ci));
+ assert(!(ci > i));
+ assert(i >= ci);
+ assert(ci >= i);
+ assert(ci - i == 0);
+ assert(i - ci == 0);
+
+ std::same_as<std::strong_ordering> decltype(auto) r1 = i <=> j;
+ assert(r1 == std::strong_ordering::equal);
+ std::same_as<std::strong_ordering> decltype(auto) r2 = ci <=> j;
+ assert(r2 == std::strong_ordering::equal);
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ 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 0000000000000..a3925db592927
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/range_concept_conformance.compile.pass.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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+#include <inplace_vector>
+#include <ranges>
+
+template <class C>
+constexpr bool test() {
+ static_assert(std::ranges::contiguous_range<C>);
+ static_assert(std::ranges::contiguous_range<const C>);
+ static_assert(std::ranges::sized_range<C>);
+ static_assert(std::ranges::sized_range<const C>);
+ static_assert(std::ranges::common_range<C>);
+ static_assert(std::ranges::common_range<const C>);
+ static_assert(!std::ranges::view<C>);
+ static_assert(!std::ranges::borrowed_range<C>);
+ return true;
+}
+
+static_assert(test<std::inplace_vector<int, 0> >());
+static_assert(test<std::inplace_vector<int, 8> >());
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 0000000000000..7ae9c0dd34c73
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/reverse_iterators.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// reverse_iterator rbegin() noexcept;
+// reverse_iterator rend() noexcept;
+// const_reverse_iterator rbegin() const noexcept;
+// const_reverse_iterator rend() const noexcept;
+// const_reverse_iterator crbegin() const noexcept;
+// const_reverse_iterator crend() const noexcept;
+
+#include <cassert>
+#include <inplace_vector>
+#include <iterator>
+
+#include "test_macros.h"
+
+constexpr bool test() {
+ {
+ using C = std::inplace_vector<int, 8>;
+ C c;
+ const C& cc = c;
+ ASSERT_SAME_TYPE(C::reverse_iterator, decltype(c.rbegin()));
+ ASSERT_SAME_TYPE(C::reverse_iterator, decltype(c.rend()));
+ ASSERT_SAME_TYPE(C::const_reverse_iterator, decltype(cc.rbegin()));
+ ASSERT_SAME_TYPE(C::const_reverse_iterator, decltype(cc.rend()));
+ ASSERT_SAME_TYPE(C::const_reverse_iterator, decltype(c.crbegin()));
+ ASSERT_SAME_TYPE(C::const_reverse_iterator, decltype(c.crend()));
+ assert(c.rbegin() == c.rend());
+ assert(c.crbegin() == c.crend());
+ }
+ {
+ using C = std::inplace_vector<int, 8>;
+ C c{1, 2, 3};
+ C::reverse_iterator i = c.rbegin();
+ assert(*i == 3);
+ *i = 4;
+ assert(c.back() == 4);
+ ++i;
+ assert(*i == 2);
+ assert(std::distance(c.rbegin(), c.rend()) == 3);
+ }
+ {
+ using C = std::inplace_vector<int, 8>;
+ const C c{1, 2, 3};
+ C::const_reverse_iterator i = c.rbegin();
+ assert(*i == 3);
+ assert(c.crbegin() == c.rbegin());
+ assert(c.crend() == c.rend());
+ }
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/triviality.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/triviality.compile.pass.cpp
new file mode 100644
index 0000000000000..01cee8651c027
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/triviality.compile.pass.cpp
@@ -0,0 +1,141 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+#include <inplace_vector>
+#include <type_traits>
+
+struct Trivial {
+ int value;
+};
+
+struct NonTrivialDtor {
+ NonTrivialDtor() = default;
+ NonTrivialDtor(const NonTrivialDtor&) = default;
+ NonTrivialDtor(NonTrivialDtor&&) = default;
+ NonTrivialDtor& operator=(const NonTrivialDtor&) = default;
+ NonTrivialDtor& operator=(NonTrivialDtor&&) = default;
+ ~NonTrivialDtor() {}
+};
+
+struct NonTrivialCopyCtor {
+ NonTrivialCopyCtor() = default;
+ NonTrivialCopyCtor(const NonTrivialCopyCtor&) {}
+ NonTrivialCopyCtor(NonTrivialCopyCtor&&) = default;
+ NonTrivialCopyCtor& operator=(const NonTrivialCopyCtor&) = default;
+ NonTrivialCopyCtor& operator=(NonTrivialCopyCtor&&) = default;
+ ~NonTrivialCopyCtor() = default;
+};
+
+struct NonTrivialMoveCtor {
+ NonTrivialMoveCtor() = default;
+ NonTrivialMoveCtor(const NonTrivialMoveCtor&) = default;
+ NonTrivialMoveCtor(NonTrivialMoveCtor&&) {}
+ NonTrivialMoveCtor& operator=(const NonTrivialMoveCtor&) = default;
+ NonTrivialMoveCtor& operator=(NonTrivialMoveCtor&&) = default;
+ ~NonTrivialMoveCtor() = default;
+};
+
+struct NonTrivialCopyAssign {
+ NonTrivialCopyAssign() = default;
+ NonTrivialCopyAssign(const NonTrivialCopyAssign&) = default;
+ NonTrivialCopyAssign(NonTrivialCopyAssign&&) = default;
+ NonTrivialCopyAssign& operator=(const NonTrivialCopyAssign&) { return *this; }
+ NonTrivialCopyAssign& operator=(NonTrivialCopyAssign&&) = default;
+ ~NonTrivialCopyAssign() = default;
+};
+
+struct NonTrivialMoveAssign {
+ NonTrivialMoveAssign() = default;
+ NonTrivialMoveAssign(const NonTrivialMoveAssign&) = default;
+ NonTrivialMoveAssign(NonTrivialMoveAssign&&) = default;
+ NonTrivialMoveAssign& operator=(const NonTrivialMoveAssign&) = default;
+ NonTrivialMoveAssign& operator=(NonTrivialMoveAssign&&) { return *this; }
+ ~NonTrivialMoveAssign() = default;
+};
+
+struct MoveOnlyTrivial {
+ MoveOnlyTrivial() = default;
+ MoveOnlyTrivial(const MoveOnlyTrivial&) = delete;
+ MoveOnlyTrivial(MoveOnlyTrivial&&) = default;
+ MoveOnlyTrivial& operator=(const MoveOnlyTrivial&) = delete;
+ MoveOnlyTrivial& operator=(MoveOnlyTrivial&&) = default;
+ ~MoveOnlyTrivial() = default;
+};
+
+struct NonTrivialAll {
+ NonTrivialAll() {}
+ NonTrivialAll(const NonTrivialAll&) {}
+ NonTrivialAll(NonTrivialAll&&) {}
+ NonTrivialAll& operator=(const NonTrivialAll&) { return *this; }
+ NonTrivialAll& operator=(NonTrivialAll&&) { return *this; }
+ ~NonTrivialAll() {}
+};
+
+struct NoDefaultCtor {
+ explicit NoDefaultCtor(int);
+};
+
+template <class T, unsigned long long _Size>
+constexpr bool check() {
+ using V = std::inplace_vector<T, _Size>;
+
+ static_assert(std::is_trivially_copy_constructible_v<V> == std::is_trivially_copy_constructible_v<T>);
+ static_assert(std::is_trivially_move_constructible_v<V> == std::is_trivially_move_constructible_v<T>);
+ static_assert(std::is_trivially_destructible_v<V> == std::is_trivially_destructible_v<T>);
+ static_assert(std::is_trivially_copy_assignable_v<V> ==
+ (std::is_trivially_destructible_v<T> && std::is_trivially_copy_constructible_v<T> &&
+ std::is_trivially_copy_assignable_v<T>));
+ static_assert(std::is_trivially_move_assignable_v<V> ==
+ (std::is_trivially_destructible_v<T> && std::is_trivially_move_constructible_v<T> &&
+ std::is_trivially_move_assignable_v<T>));
+
+ static_assert(!std::is_trivially_default_constructible_v<V>);
+
+ return true;
+}
+
+// N == 0 always trivial
+template <class T>
+constexpr bool zero_capacity() {
+ using V = std::inplace_vector<T, 0>;
+
+ static_assert(std::is_trivially_copyable_v<V>);
+ static_assert(std::is_trivially_default_constructible_v<V>);
+ static_assert(std::is_trivially_copy_constructible_v<V>);
+ static_assert(std::is_trivially_move_constructible_v<V>);
+ static_assert(std::is_trivially_copy_assignable_v<V>);
+ static_assert(std::is_trivially_move_assignable_v<V>);
+ static_assert(std::is_trivially_destructible_v<V>);
+
+ return true;
+}
+
+static_assert(check<int, 4>());
+static_assert(check<Trivial, 4>());
+static_assert(check<NonTrivialDtor, 4>());
+static_assert(check<NonTrivialCopyCtor, 4>());
+static_assert(check<NonTrivialMoveCtor, 4>());
+static_assert(check<NonTrivialCopyAssign, 4>());
+static_assert(check<NonTrivialMoveAssign, 4>());
+static_assert(check<MoveOnlyTrivial, 4>());
+static_assert(check<NonTrivialAll, 4>());
+
+static_assert(zero_capacity<int>());
+static_assert(zero_capacity<Trivial>());
+static_assert(zero_capacity<NonTrivialDtor>());
+static_assert(zero_capacity<NonTrivialCopyCtor>());
+static_assert(zero_capacity<NonTrivialMoveCtor>());
+static_assert(zero_capacity<NonTrivialCopyAssign>());
+static_assert(zero_capacity<NonTrivialMoveAssign>());
+static_assert(zero_capacity<MoveOnlyTrivial>());
+static_assert(zero_capacity<NonTrivialAll>());
+static_assert(zero_capacity<NoDefaultCtor>());
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/types.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/types.compile.pass.cpp
new file mode 100644
index 0000000000000..320bb0d6fde74
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/types.compile.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// <inplace_vector>
+
+// template<class T, size_t N> class inplace_vector;
+
+#include <concepts>
+#include <cstddef>
+#include <inplace_vector>
+#include <iterator>
+#include <type_traits>
+
+#include "test_macros.h"
+#include "../../Copyable.h"
+
+template <class T, std::size_t _Cap>
+void test() {
+ using C = std::inplace_vector<T, _Cap>;
+
+ static_assert(std::is_same_v<typename C::value_type, 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 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::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> >);
+
+ static_assert(std::contiguous_iterator<typename C::iterator>);
+ static_assert(std::contiguous_iterator<typename C::const_iterator>);
+ static_assert(std::same_as<typename std::iterator_traits<typename C::iterator>::iterator_category,
+ std::random_access_iterator_tag>);
+ static_assert(std::same_as<typename std::iterator_traits<typename C::const_iterator>::iterator_category,
+ std::random_access_iterator_tag>);
+}
+
+int main(int, char**) {
+ test<int, 0>();
+ test<int, 42>();
+ test<int*, 42>();
+ test<Copyable, 42>();
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/zero_capacity.exceptions.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/zero_capacity.exceptions.pass.cpp
new file mode 100644
index 0000000000000..8a552f5bf5709
--- /dev/null
+++ b/libcxx/test/std/containers/sequences/inplace_vector/zero_capacity.exceptions.pass.cpp
@@ -0,0 +1,124 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// UNSUPPORTED: no-exceptions
+
+// Clang's -Wunreachable-code does not model exceptional exits from [[noreturn]] members
+// (e.g. at() in this specialization), flagging the catch handlers below.
+// ADDITIONAL_COMPILE_FLAGS: -Wno-unreachable-code
+
+// <inplace_vector>
+
+#include <cassert>
+#include <inplace_vector>
+#include <new>
+#include <stdexcept>
+#include <utility>
+
+#include "common.h"
+#include "test_macros.h"
+
+using C = std::inplace_vector<int, 0>;
+
+void test_throwing_members() {
+ int a[] = {1, 2};
+
+ assert_throws_bad_alloc([] { C c(1); });
+ assert_throws_bad_alloc([] { C c(1, 42); });
+ assert_throws_bad_alloc([&] { C c(a, a + 2); });
+ assert_throws_bad_alloc([&] { C c(std::from_range, a); });
+ assert_throws_bad_alloc([] { C c{1, 2}; });
+
+ C c;
+ assert_throws_bad_alloc([&] { c = {1, 2}; });
+ assert_throws_bad_alloc([&] { c.assign(a, a + 2); });
+ assert_throws_bad_alloc([&] { c.assign_range(a); });
+ assert_throws_bad_alloc([&] { c.assign(2, 42); });
+ assert_throws_bad_alloc([&] { c.assign({1, 2}); });
+
+ assert_throws_bad_alloc([&] { c.resize(1); });
+ assert_throws_bad_alloc([&] { c.resize(1, 42); });
+ assert_throws_bad_alloc([&] { c.reserve(1); });
+ assert_throws_bad_alloc([&] { C::reserve(1); });
+
+ int value = 42;
+ assert_throws_bad_alloc([&] { c.emplace_back(42); });
+ assert_throws_bad_alloc([&] { c.push_back(value); });
+ assert_throws_bad_alloc([&] { c.push_back(42); });
+ assert_throws_bad_alloc([&] { c.append_range(a); });
+
+ assert_throws_bad_alloc([&] { c.emplace(c.begin(), 42); });
+ assert_throws_bad_alloc([&] { c.insert(c.begin(), value); });
+ assert_throws_bad_alloc([&] { c.insert(c.begin(), 42); });
+ assert_throws_bad_alloc([&] { c.insert(c.begin(), 2, 42); });
+ assert_throws_bad_alloc([&] { c.insert(c.begin(), a, a + 2); });
+ assert_throws_bad_alloc([&] { c.insert_range(c.begin(), a); });
+ assert_throws_bad_alloc([&] { c.insert(c.begin(), {1, 2}); });
+
+ assert(c.empty());
+
+ bool threw = false;
+ try {
+ (void)c.at(0);
+ } catch (const std::out_of_range&) {
+ threw = true;
+ }
+ assert(threw);
+
+ threw = false;
+ try {
+ (void)std::as_const(c).at(0);
+ } catch (const std::out_of_range&) {
+ threw = true;
+ }
+ assert(threw);
+}
+
+constexpr bool test_non_throwing_members() {
+ int a[] = {1, 2};
+
+ // Requests for zero elements and empty inputs must not throw.
+ C c(0);
+ C c2(0, 42);
+ C c3(a, a);
+ C c4{};
+ assert(c2.empty() && c3.empty() && c4.empty());
+ c = {};
+ c.assign(a, a);
+ c.assign(0, 42);
+ c.assign(std::initializer_list<int>{});
+ c.resize(0);
+ c.resize(0, 42);
+ c.reserve(0);
+ c.shrink_to_fit();
+
+ assert(c.insert(c.begin(), 0, 42) == c.begin());
+ assert(c.insert(c.begin(), a, a) == c.begin());
+ assert(c.insert(c.begin(), std::initializer_list<int>{}) == c.begin());
+ assert(c.erase(c.begin(), c.begin()) == c.begin());
+
+ // The try_* forms report a full container instead of throwing.
+ int value = 42;
+ assert(!c.try_emplace_back(42).has_value());
+ assert(!c.try_push_back(value).has_value());
+ assert(!c.try_push_back(42).has_value());
+
+ assert(c.empty());
+
+ return true;
+}
+
+int main(int, char**) {
+ test_throwing_members();
+
+ test_non_throwing_members();
+ static_assert(test_non_throwing_members());
+
+ return 0;
+}
diff --git a/libcxx/utils/libcxx/test/features/libcxx_macros.py b/libcxx/utils/libcxx/test/features/libcxx_macros.py
index aeb4696501a83..e6c461979dcd5 100644
--- a/libcxx/utils/libcxx/test/features/libcxx_macros.py
+++ b/libcxx/utils/libcxx/test/features/libcxx_macros.py
@@ -29,6 +29,7 @@
"_LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL": "libcpp-has-abi-bounded-iterators-in-optional",
"_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR": "libcpp-has-abi-bounded-iterators-in-vector",
"_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY": "libcpp-has-abi-bounded-iterators-in-std-array",
+ "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_INPLACE_VECTOR": "libcpp-has-abi-bounded-iterators-in-inplace-vector",
"_LIBCPP_ABI_BOUNDED_UNIQUE_PTR": "libcpp-has-abi-bounded-unique_ptr",
"_LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE": "libcpp-has-abi-fix-unordered-container-size-type",
"_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR": "libcpp-deprecated-abi-disable-pair-trivial-copy-ctor",
>From 2d8271c6a00d52d034a28a2d46287e0dd4f98530 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 12 Jun 2026 22:51:08 -0400
Subject: [PATCH 03/11] Clang treats string literals as a variable in constant
expression
---
libcxx/include/inplace_vector | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
index 0d0f0418274dd..b06ce41ca4f50 100644
--- a/libcxx/include/inplace_vector
+++ b/libcxx/include/inplace_vector
@@ -247,7 +247,9 @@ private:
}
} else {
# if !defined(__cpp_trivial_union)
- _LIBCPP_VERBOSE_ABORT("std::inplace_vector<T,N> currently cannot be used in constant expressions for "
+ // TODO: Clang emits a -Wformat-security warning for this when it's in a consteval block. File bug for this
+ _LIBCPP_VERBOSE_ABORT("%s",
+ "std::inplace_vector<T,N> currently cannot be used in constant expressions for "
"non-trivial T on compilers where P3074 is not implemented.");
# endif
}
>From 5cbb5257877ba837d7f0907ae65f2e59f9029bab Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 15 Jun 2026 18:35:07 -0400
Subject: [PATCH 04/11] Formatting and pop macros at right place
---
libcxx/include/inplace_vector | 4 +-
libcxx/modules/std/inplace_vector.inc | 2 +-
.../inplace_vector/nodiscard.verify.cpp | 60 +++++++++----------
.../inplace_vector/addressof.compile.pass.cpp | 9 ++-
.../inplace.vector.cons/assign_move.pass.cpp | 4 +-
.../inplace.vector.cons/exceptions.pass.cpp | 5 +-
.../inplace.vector.erasure/erase_if.pass.cpp | 3 +-
.../insert_iter_lvalue.pass.cpp | 1 +
.../push_back.pass.cpp | 2 +
.../push_back_exception_safety.pass.cpp | 1 -
.../try_push_back.pass.cpp | 1 +
.../inplace_vector/iterators.pass.cpp | 2 +-
12 files changed, 48 insertions(+), 46 deletions(-)
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
index b06ce41ca4f50..a2e857e738e29 100644
--- a/libcxx/include/inplace_vector
+++ b/libcxx/include/inplace_vector
@@ -1123,10 +1123,10 @@ erase(std::inplace_vector<_Tp, _Cap>& __c, const _Up& __value) {
_LIBCPP_END_NAMESPACE_STD
-_LIBCPP_POP_MACROS
-
# endif // _LIBCPP_STD_VER >= 26
+_LIBCPP_POP_MACROS
+
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
#endif // _LIBCPP_INPLACE_VECTOR
diff --git a/libcxx/modules/std/inplace_vector.inc b/libcxx/modules/std/inplace_vector.inc
index 458ca4488fb46..d213d4d43c624 100644
--- a/libcxx/modules/std/inplace_vector.inc
+++ b/libcxx/modules/std/inplace_vector.inc
@@ -12,4 +12,4 @@ export namespace std {
using std::inplace_vector;
#endif
-}
+} // namespace std
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/nodiscard.verify.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/nodiscard.verify.cpp
index 4144f3be5d25c..67e6cfc7629d8 100644
--- a/libcxx/test/libcxx/containers/sequences/inplace_vector/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/nodiscard.verify.cpp
@@ -13,40 +13,40 @@
void test() {
std::inplace_vector<int, 4> v;
- v.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.back(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.capacity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.back(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.capacity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
v.try_emplace_back(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
v.try_push_back(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::inplace_vector<int, 0> v0;
- v0.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.capacity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
- v0.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.capacity(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.cbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.cend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.crbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.crend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.max_size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v0.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
v0.try_emplace_back(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
v0.try_push_back(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/addressof.compile.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/addressof.compile.pass.cpp
index 94a722eea6d04..986e6a131a3fa 100644
--- a/libcxx/test/std/containers/sequences/inplace_vector/addressof.compile.pass.cpp
+++ b/libcxx/test/std/containers/sequences/inplace_vector/addressof.compile.pass.cpp
@@ -20,11 +20,10 @@
using InplaceVector = std::inplace_vector<operator_hijacker, 16>;
-void test(
- InplaceVector v,
- InplaceVector::const_iterator it,
- cpp17_input_iterator<operator_hijacker*> other_it,
- operator_hijacker val) {
+void test(InplaceVector v,
+ InplaceVector::const_iterator it,
+ cpp17_input_iterator<operator_hijacker*> other_it,
+ operator_hijacker val) {
// emplace / insert
v.emplace(it);
v.insert(it, it, it);
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
index 64d720ed68aa0..02554a06e7683 100644
--- 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
@@ -35,7 +35,7 @@ struct ThrowingMoveCtorOnly {
};
struct ThrowingMoveAssignOnly {
- ThrowingMoveAssignOnly() = default;
+ ThrowingMoveAssignOnly() = default;
ThrowingMoveAssignOnly(ThrowingMoveAssignOnly&&) noexcept = default;
ThrowingMoveAssignOnly& operator=(ThrowingMoveAssignOnly&&) noexcept(false) { return *this; }
};
@@ -66,7 +66,7 @@ constexpr bool test() {
{ // self-move-assignment leaves the container in a valid state
std::inplace_vector<int, 8> c{1, 2, 3};
std::inplace_vector<int, 8>& ref = c;
- c = std::move(ref);
+ c = std::move(ref);
LIBCPP_ASSERT(c == (std::inplace_vector<int, 8>{1, 2, 3}));
}
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
index b82629f84ab3d..1257c14ad8dc7 100644
--- 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
@@ -60,9 +60,8 @@ void test_iterator_constructor_exceptions() {
{
ThrowingValue values[] = {ThrowingValue(1), ThrowingValue(2)};
try {
- std::inplace_vector<ThrowingValue, 4> c(
- throwing_iterator<ThrowingValue, std::input_iterator_tag>(values),
- throwing_iterator<ThrowingValue, std::input_iterator_tag>(values + 2, 2));
+ std::inplace_vector<ThrowingValue, 4> c(throwing_iterator<ThrowingValue, std::input_iterator_tag>(values),
+ throwing_iterator<ThrowingValue, std::input_iterator_tag>(values + 2, 2));
assert(false);
} catch (int) {
assert(ThrowingValue::alive == 2);
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
index 84d7ab0a3d401..65beb5711a084 100644
--- 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
@@ -22,7 +22,8 @@
constexpr bool test() {
std::inplace_vector<int, 8> c{1, 2, 3, 4, 5, 6};
- ASSERT_SAME_TYPE(std::inplace_vector<int, 8>::size_type, decltype(std::erase_if(c, [](int v) { return v % 2 == 0; })));
+ ASSERT_SAME_TYPE(
+ std::inplace_vector<int, 8>::size_type, decltype(std::erase_if(c, [](int v) { return v % 2 == 0; })));
auto erased = std::erase_if(c, [](int v) { return v % 2 == 0; });
assert(erased == 3);
assert_inplace_vector_equal(c, {1, 3, 5});
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_lvalue.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_lvalue.pass.cpp
index 37fefc1981900..698662d24dc93 100644
--- a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_lvalue.pass.cpp
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/insert_iter_lvalue.pass.cpp
@@ -22,6 +22,7 @@
constexpr bool test() {
std::inplace_vector<int, 5> c{1, 2, 4};
int x = 3;
+
std::same_as<std::inplace_vector<int, 5>::iterator> decltype(auto) i = c.insert(c.begin() + 2, x);
assert(i == c.begin() + 2);
assert_inplace_vector_equal(c, {1, 2, 3, 4});
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back.pass.cpp
index bb97c2fb6c8b6..8d4bb8a7304cd 100644
--- a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back.pass.cpp
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back.pass.cpp
@@ -25,7 +25,9 @@ constexpr bool test() {
int& r1 = c.push_back(x);
assert(&r1 == &c.back());
assert(c.back() == 1);
+
x = 2;
+
int& r2 = c.push_back(x);
assert(&r2 == &c.back());
assert_inplace_vector_equal(c, {1, 2});
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_exception_safety.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_exception_safety.pass.cpp
index 75ff8a5cfcfa5..8b9fb3cff4f4a 100644
--- a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_exception_safety.pass.cpp
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/push_back_exception_safety.pass.cpp
@@ -69,4 +69,3 @@ int main(int, char**) {
return 0;
}
-
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/try_push_back.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/try_push_back.pass.cpp
index dbc4fac080368..46882cc405bc0 100644
--- a/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/try_push_back.pass.cpp
+++ b/libcxx/test/std/containers/sequences/inplace_vector/inplace.vector.modifiers/try_push_back.pass.cpp
@@ -36,6 +36,7 @@ constexpr bool test() {
{
std::inplace_vector<int, 2> c;
int value = 1;
+
std::same_as<std::optional<int&>> decltype(auto) r1 = c.try_push_back(value);
assert(r1);
assert(&*r1 == &c.back());
diff --git a/libcxx/test/std/containers/sequences/inplace_vector/iterators.pass.cpp b/libcxx/test/std/containers/sequences/inplace_vector/iterators.pass.cpp
index 5377f55d75538..5030cb5dca46d 100644
--- a/libcxx/test/std/containers/sequences/inplace_vector/iterators.pass.cpp
+++ b/libcxx/test/std/containers/sequences/inplace_vector/iterators.pass.cpp
@@ -82,7 +82,7 @@ constexpr bool test() {
assert(j == j);
}
{
- using C = std::inplace_vector<A, 4>;
+ using C = std::inplace_vector<A, 4>;
C c = {A{1, 2}};
C::iterator i = c.begin();
i->first = 3;
>From 514b7209e45a3bf3933966d511b51022ada5f680 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 15 Jun 2026 21:29:13 -0400
Subject: [PATCH 05/11] check_assertion.h doesn't compile on llvm-libc
---
.../sequences/inplace_vector/assert.zero_capacity.pass.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
index fefe61e1eef53..7a1419c27c79c 100644
--- a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
@@ -10,6 +10,9 @@
// <inplace_vector>
+// No member named 'regex'.
+// XFAIL: LLVM-LIBC-FIXME
+
#include <inplace_vector>
#include <utility>
>From 42aa1bc7cb3350734871f36a16589d08a86f5031 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 15 Jun 2026 22:32:29 -0400
Subject: [PATCH 06/11] Code-related comments
---
libcxx/include/inplace_vector | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
index a2e857e738e29..f9ad3022c8654 100644
--- a/libcxx/include/inplace_vector
+++ b/libcxx/include/inplace_vector
@@ -231,7 +231,7 @@ private:
return static_cast<std::size_t>(0);
}
- using __size_type = decltype(__get_size_type());
+ using __size_type _LIBCPP_NODEBUG = decltype(__get_size_type());
union {
_Tp __elems_[_Cap];
@@ -254,7 +254,6 @@ private:
# endif
}
}
- // std::start_lifetime_as_array?
}
public:
>From f04094ad429c4a98c4f6bf85f7724b7621fc8c12 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 17 Jun 2026 22:26:57 -0400
Subject: [PATCH 07/11] Resolve more issues
---
libcxx/docs/Status/Cxx2cIssues.csv | 6 +++---
libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 6a836c0491bb6..ce57d21f9aed8 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -102,7 +102,7 @@
"`LWG4141 <https://wg21.link/LWG4141>`__","Improve prohibitions on ""additional storage""","2024-11 (Wrocław)","","","`#118357 <https://github.com/llvm/llvm-project/issues/118357>`__",""
"`LWG4142 <https://wg21.link/LWG4142>`__","``format_parse_context::check_dynamic_spec`` should require at least one type","2024-11 (Wrocław)","","","`#118358 <https://github.com/llvm/llvm-project/issues/118358>`__",""
"`LWG4144 <https://wg21.link/LWG4144>`__","Disallow ``unique_ptr<T&, D>``","2024-11 (Wrocław)","","","`#118359 <https://github.com/llvm/llvm-project/issues/118359>`__",""
-"`LWG4147 <https://wg21.link/LWG4147>`__","Precondition on ``inplace_vector::emplace``","2024-11 (Wrocław)","","","`#118361 <https://github.com/llvm/llvm-project/issues/118361>`__",""
+"`LWG4147 <https://wg21.link/LWG4147>`__","Precondition on ``inplace_vector::emplace``","2024-11 (Wrocław)","|Complete|","23","`#118361 <https://github.com/llvm/llvm-project/issues/118361>`__",""
"`LWG4148 <https://wg21.link/LWG4148>`__","``unique_ptr::operator*`` should not allow dangling references","2024-11 (Wrocław)","","","`#118362 <https://github.com/llvm/llvm-project/issues/118362>`__",""
"`LWG4153 <https://wg21.link/LWG4153>`__","Fix extra ""-1"" for ``philox_engine::max()``","2024-11 (Wrocław)","","","`#118363 <https://github.com/llvm/llvm-project/issues/118363>`__",""
"`LWG4154 <https://wg21.link/LWG4154>`__","The Mandates for ``std::packaged_task``'s constructor from a callable entity should consider decaying","2024-11 (Wrocław)","","","`#118364 <https://github.com/llvm/llvm-project/issues/118364>`__",""
@@ -271,11 +271,11 @@
"`LWG3891 <https://wg21.link/LWG3891>`__","LWG3870 breaks ``std::expected<cv T, E>``","2026-03 (Croydon)","","","`#189813 <https://github.com/llvm/llvm-project/issues/189813>`__",""
"`LWG4026 <https://wg21.link/LWG4026>`__","Assignment operators of ``std::expected`` should propagate triviality","2026-03 (Croydon)","","","`#189814 <https://github.com/llvm/llvm-project/issues/189814>`__",""
"`LWG4090 <https://wg21.link/LWG4090>`__","Underspecified use of locale facets for locale-dependent ``std::format``","2026-03 (Croydon)","","","`#189815 <https://github.com/llvm/llvm-project/issues/189815>`__",""
-"`LWG4122 <https://wg21.link/LWG4122>`__","Ill-formed ``operator<=>`` can cause hard error when instantiating ``std::inplace_vector``","2026-03 (Croydon)","","","`#189816 <https://github.com/llvm/llvm-project/issues/189816>`__",""
+"`LWG4122 <https://wg21.link/LWG4122>`__","Ill-formed ``operator<=>`` can cause hard error when instantiating ``std::inplace_vector``","2026-03 (Croydon)","|Complete|","23","`#189816 <https://github.com/llvm/llvm-project/issues/189816>`__",""
"`LWG4130 <https://wg21.link/LWG4130>`__","Preconditions for ``std::launder`` might be overly strict","2026-03 (Croydon)","","","`#189817 <https://github.com/llvm/llvm-project/issues/189817>`__",""
"`LWG4133 <https://wg21.link/LWG4133>`__","``awaitable-receiver``'s members are potentially throwing","2026-03 (Croydon)","","","`#189818 <https://github.com/llvm/llvm-project/issues/189818>`__",""
"`LWG4143 <https://wg21.link/LWG4143>`__","``execution::set_value/set_error/set_stopped/start`` should always return void","2026-03 (Croydon)","","","`#189819 <https://github.com/llvm/llvm-project/issues/189819>`__",""
-"`LWG4151 <https://wg21.link/LWG4151>`__","Precondition of ``inplace_vector::swap``","2026-03 (Croydon)","","","`#189820 <https://github.com/llvm/llvm-project/issues/189820>`__",""
+"`LWG4151 <https://wg21.link/LWG4151>`__","Precondition of ``inplace_vector::swap``","2026-03 (Croydon)","|Complete|","23","`#189820 <https://github.com/llvm/llvm-project/issues/189820>`__",""
"`LWG4223 <https://wg21.link/LWG4223>`__","Deduction guides for maps are mishandling tuples and references","2026-03 (Croydon)","","","`#189821 <https://github.com/llvm/llvm-project/issues/189821>`__",""
"`LWG4259 <https://wg21.link/LWG4259>`__","P1148R0 changed the return values of searching functions of ``std::basic_string`` on some platforms","2026-03 (Croydon)","","","`#189822 <https://github.com/llvm/llvm-project/issues/189822>`__",""
"`LWG4290 <https://wg21.link/LWG4290>`__","Missing *Mandates* clauses on ``is_sufficiently_aligned``","2026-03 (Croydon)","","","`#189823 <https://github.com/llvm/llvm-project/issues/189823>`__",""
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 337a28eae5889..886ec17b167cd 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)","|Complete|","22","`#105430 <https://github.com/llvm/llvm-project/issues/105430>`__",""
"`P3217R0 <https://wg21.link/P3217R0>`__","Adjoints to 'Enabling list-initialization for algorithms': find_last","2024-06 (St. Louis)","","","`#105431 <https://github.com/llvm/llvm-project/issues/105431>`__",""
"`P2985R0 <https://wg21.link/P2985R0>`__","A type trait for detecting virtual base classes","2024-06 (St. Louis)","|Complete|","20","`#105432 <https://github.com/llvm/llvm-project/issues/105432>`__",""
-"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","|Partial|","23","`#105433 <https://github.com/llvm/llvm-project/issues/105433>`__","inplace_vector<T,N> where T is not a trivial type cannot be used in a constant expression."
+"`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","|Complete|","23","`#105433 <https://github.com/llvm/llvm-project/issues/105433>`__",""
"`P3235R3 <https://wg21.link/P3235R3>`__","``std::print`` more types faster with less memory","2024-06 (St. Louis)","","","`#105435 <https://github.com/llvm/llvm-project/issues/105435>`__",""
"`P2968R2 <https://wg21.link/P2968R2>`__","Make ``std::ignore`` a first-class object","2024-06 (St. Louis)","|Complete|","19","`#105436 <https://github.com/llvm/llvm-project/issues/105436>`__",""
"`P2075R6 <https://wg21.link/P2075R6>`__","Philox as an extension of the C++ RNG engines","2024-06 (St. Louis)","","","`#105437 <https://github.com/llvm/llvm-project/issues/105437>`__",""
>From 5b497f3c240609548428e90dca47fa3364c63354 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 17 Jun 2026 23:21:03 -0400
Subject: [PATCH 08/11] Address more code-related comments
---
libcxx/include/inplace_vector | 148 +++++++-----------
.../assert.zero_capacity.pass.cpp | 26 +--
2 files changed, 72 insertions(+), 102 deletions(-)
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
index f9ad3022c8654..1c792c9dc8c4c 100644
--- a/libcxx/include/inplace_vector
+++ b/libcxx/include/inplace_vector
@@ -163,11 +163,11 @@ _LIBCPP_PUSH_MACROS
# include <__undef_macros>
# if _LIBCPP_STD_VER >= 26
+# include <__algorithm/equal.h>
# include <__algorithm/fill_n.h>
# include <__algorithm/lexicographical_compare_three_way.h>
# include <__algorithm/min.h>
# include <__algorithm/move.h>
-# include <__algorithm/move_backward.h>
# include <__algorithm/ranges_copy.h>
# include <__algorithm/ranges_copy_n.h>
# include <__algorithm/remove.h>
@@ -217,7 +217,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, size_t _Cap>
class inplace_vector {
private:
- static constexpr decltype(auto) __get_size_type() {
+ static constexpr auto __get_size_type() {
if constexpr (_Cap <= std::numeric_limits<unsigned char>::max() && sizeof(unsigned char) < sizeof(std::size_t))
return static_cast<unsigned char>(0);
else if constexpr (_Cap <= std::numeric_limits<unsigned short>::max() &&
@@ -238,24 +238,6 @@ private:
};
__size_type __size_{0};
- constexpr void __init() {
- if consteval {
- if constexpr (is_trivially_copyable_v<_Tp> && is_trivially_default_constructible_v<_Tp> &&
- is_trivially_assignable_v<_Tp&, _Tp>) {
- for (size_t __i{0}; __i < _Cap; ++__i) {
- __elems_[__i] = _Tp();
- }
- } else {
-# if !defined(__cpp_trivial_union)
- // TODO: Clang emits a -Wformat-security warning for this when it's in a consteval block. File bug for this
- _LIBCPP_VERBOSE_ABORT("%s",
- "std::inplace_vector<T,N> currently cannot be used in constant expressions for "
- "non-trivial T on compilers where P3074 is not implemented.");
-# endif
- }
- }
- }
-
public:
using value_type = _Tp;
using pointer = _Tp*;
@@ -275,33 +257,6 @@ public:
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
private:
- struct _ConstructTransaction {
- constexpr explicit _ConstructTransaction(inplace_vector& __v, size_type __n)
- : __v_(__v), __pos_(__v.data() + __v.__size_), __new_end_(__v.data() + __v.__size_ + __n) {}
-
- constexpr ~_ConstructTransaction() { __v_.__size_ = __pos_ - __v_.data(); }
-
- inplace_vector& __v_;
- pointer __pos_;
- const_pointer const __new_end_;
-
- _ConstructTransaction(_ConstructTransaction const&) = delete;
- _ConstructTransaction& operator=(_ConstructTransaction const&) = delete;
- };
-
- constexpr void __move_range(pointer __from_s, pointer __from_e, pointer __to) {
- pointer __old_last = data() + __size_;
- difference_type __n = __old_last - __to;
- {
- pointer __i = __from_s + __n;
- _ConstructTransaction __tx(*this, __from_e - __i);
- for (pointer __pos = __tx.__pos_; __i < __from_e; ++__i, ++__pos, __tx.__pos_ = __pos) {
- std::construct_at(__pos, std::move(*__i));
- }
- }
- std::move_backward(__from_s, __from_s + __n, __old_last);
- }
-
template <class _It, class _Sentinel>
constexpr void __assign(_It __first, _Sentinel __last) {
if constexpr (std::sized_sentinel_for<_Sentinel, _It>) {
@@ -317,7 +272,7 @@ private:
}
__size_ = __d;
} else {
- size_t __d = 0;
+ size_type __d = 0;
for (; __first != __last && __d < __size_; (void)++__first, ++__d) {
data()[__d] = *__first;
}
@@ -385,17 +340,31 @@ private:
public:
// [inplace.vector.cons], construct/copy/destroy
- constexpr inplace_vector() noexcept { __init(); }
+ constexpr inplace_vector() noexcept {
+ if consteval {
+ if constexpr (is_trivially_copyable_v<_Tp> && is_trivially_default_constructible_v<_Tp> &&
+ is_trivially_assignable_v<_Tp&, _Tp>) {
+ for (size_t __i{0}; __i < _Cap; ++__i) {
+ __elems_[__i] = _Tp();
+ }
+ } else {
+# if !defined(__cpp_trivial_union)
+ // TODO: Clang emits a -Wformat-security warning for this when it's in a consteval block. File bug for this
+ _LIBCPP_VERBOSE_ABORT("%s",
+ "std::inplace_vector<T,N> currently cannot be used in constant expressions for "
+ "non-trivial T on compilers where P3074 is not implemented.");
+# endif
+ }
+ }
+ }
- constexpr explicit inplace_vector(size_type __n) {
- __init();
+ constexpr explicit inplace_vector(size_type __n) : inplace_vector() {
reserve(__n);
std::uninitialized_value_construct_n(data(), __n);
__size_ = __n;
}
- constexpr inplace_vector(size_type __n, const _Tp& __c) {
- __init();
+ constexpr inplace_vector(size_type __n, const _Tp& __c) : inplace_vector() {
reserve(__n);
std::uninitialized_fill_n(data(), __n, __c);
__size_ = __n;
@@ -403,8 +372,7 @@ public:
template <class _InputIterator>
requires __has_input_iterator_category<_InputIterator>::value
- constexpr inplace_vector(_InputIterator __first, _InputIterator __last) {
- __init();
+ constexpr inplace_vector(_InputIterator __first, _InputIterator __last) : inplace_vector() {
if constexpr (std::sized_sentinel_for<_InputIterator, _InputIterator>) {
auto __n = std::ranges::distance(__first, __last);
reserve(__n);
@@ -423,8 +391,7 @@ public:
}
template <_ContainerCompatibleRange<_Tp> _Range>
- constexpr inplace_vector(from_range_t, _Range&& __rg) {
- __init();
+ constexpr inplace_vector(from_range_t, _Range&& __rg) : inplace_vector() {
append_range(__rg);
}
@@ -432,8 +399,8 @@ public:
requires is_trivially_copy_constructible_v<_Tp>
= default;
- constexpr inplace_vector(const inplace_vector& __x) noexcept(is_nothrow_copy_constructible_v<_Tp>) {
- __init();
+ constexpr inplace_vector(const inplace_vector& __x) noexcept(is_nothrow_copy_constructible_v<_Tp>)
+ : inplace_vector() {
std::uninitialized_copy(__x.begin(), __x.end(), data());
__size_ = __x.size();
}
@@ -442,14 +409,12 @@ public:
requires is_trivially_move_constructible_v<_Tp>
= default;
- constexpr inplace_vector(inplace_vector&& __x) noexcept(is_nothrow_move_constructible_v<_Tp>) {
- __init();
+ constexpr inplace_vector(inplace_vector&& __x) noexcept(is_nothrow_move_constructible_v<_Tp>) : inplace_vector() {
std::uninitialized_move(__x.begin(), __x.end(), data());
__size_ = __x.size();
}
- constexpr inplace_vector(std::initializer_list<_Tp> __il) {
- __init();
+ constexpr inplace_vector(std::initializer_list<_Tp> __il) : inplace_vector() {
reserve(__il.size());
std::uninitialized_copy(__il.begin(), __il.end(), data());
__size_ = __il.size();
@@ -690,11 +655,9 @@ public:
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
size() < capacity(),
"inplace_vector<T,N>::unchecked_emplace_back(Args...): Adding element when size() >= capacity()");
- {
- _ConstructTransaction __tx(*this, 1);
- std::construct_at(data() + __size_, std::forward<_Args>(__args)...);
- __tx.__pos_++;
- }
+
+ std::construct_at(data() + __size_, std::forward<_Args>(__args)...);
+ ++__size_;
return back();
}
@@ -713,9 +676,9 @@ public:
if (__position == end()) {
emplace_back(std::forward<_Args>(__args)...);
} else {
- _Tp __temp_value = _Tp(std::forward<_Args>(__args)...);
- __move_range(__p, data() + __size_, __p + 1);
- *__p = std::move(__temp_value);
+ std::construct_at(data() + __size_, std::forward<_Args>(__args)...);
+ __size_++;
+ std::rotate(__p, data() + __size_ - 1, data() + __size_);
}
return __make_iter(__p);
@@ -757,7 +720,7 @@ public:
}
constexpr iterator insert(const_iterator __position, std::initializer_list<_Tp> __il) {
- return __insert(__position, __il.begin(), __il.end());
+ return insert(__position, __il.begin(), __il.end());
}
constexpr iterator erase(const_iterator __position) {
@@ -809,16 +772,7 @@ public:
}
friend constexpr bool operator==(const inplace_vector& __x, const inplace_vector& __y) {
- if (__x.size() != __y.size()) {
- return false;
- }
-
- for (size_type __i{0}; __i < __x.size(); __i++) {
- if (__x[__i] != __y[__i]) {
- return false;
- }
- }
- return true;
+ return __x.size() == __y.size() && std::equal(__x.begin(), __x.end(), __y.begin(), __y.end());
}
friend constexpr auto operator<=>(const inplace_vector& __x, const inplace_vector& __y)
@@ -967,11 +921,13 @@ public:
// element access
[[nodiscard, noreturn]] constexpr reference operator[](size_type) {
- _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::operator[]: access with N == 0");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "inplace_vector<T,0>::operator[]: access with N == 0");
+ __libcpp_unreachable();
}
[[nodiscard, noreturn]] constexpr const_reference operator[](size_type) const {
- _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::operator[] const: access with N == 0");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "inplace_vector<T,0>::operator[] const: access with N == 0");
+ __libcpp_unreachable();
}
[[nodiscard, noreturn]] constexpr reference at(size_type) {
@@ -983,19 +939,23 @@ public:
}
[[nodiscard, noreturn]] constexpr reference front() {
- _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::front(): access with N == 0");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "inplace_vector<T,0>::front(): access with N == 0");
+ __libcpp_unreachable();
}
[[nodiscard, noreturn]] constexpr const_reference front() const {
- _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::front() const: access with N == 0");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "inplace_vector<T,0>::front() const: access with N == 0");
+ __libcpp_unreachable();
}
[[nodiscard, noreturn]] constexpr reference back() {
- _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::back(): access with N == 0");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "inplace_vector<T,0>::back(): access with N == 0");
+ __libcpp_unreachable();
}
[[nodiscard, noreturn]] constexpr const_reference back() const {
- _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::back() const: access with N == 0");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "inplace_vector<T,0>::back() const: access with N == 0");
+ __libcpp_unreachable();
}
// [inplace.vector.data], data access
@@ -1019,7 +979,10 @@ public:
}
}
- constexpr void pop_back() { _LIBCPP_VERBOSE_ABORT("inplace_vector<T,0>::pop_back(): use with N == 0"); }
+ constexpr void pop_back() {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "inplace_vector<T,0>::pop_back(): use with N == 0");
+ __libcpp_unreachable();
+ }
template <class... _Args>
[[nodiscard]] constexpr optional<reference> try_emplace_back(_Args&&...) {
@@ -1073,12 +1036,15 @@ public:
}
[[noreturn]] constexpr iterator erase(const_iterator) {
- _LIBCPP_VERBOSE_ABORT("std::inplace_vector<T,0>::erase(const_iterator): use with N == 0");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "inplace_vector<T,0>::erase(): use with N == 0");
+ __libcpp_unreachable();
}
constexpr iterator erase(const_iterator __f, const_iterator __l) {
if (__f != __l) {
- _LIBCPP_VERBOSE_ABORT("std::inplace_vector<T,0>::erase(const_iterator, const_iterator): use with N == 0");
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ false, "inplace_vector<T,0>::erase(const_iterator, const_iterator): use with N == 0");
+ __libcpp_unreachable();
}
return begin();
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
index 7a1419c27c79c..25947cf4c0040 100644
--- a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
@@ -7,12 +7,11 @@
//===----------------------------------------------------------------------===//
// REQUIRES: has-unix-headers, std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// <inplace_vector>
-// No member named 'regex'.
-// XFAIL: LLVM-LIBC-FIXME
-
#include <inplace_vector>
#include <utility>
@@ -21,14 +20,19 @@
int main(int, char**) {
std::inplace_vector<int, 0> c;
- EXPECT_ANY_DEATH((void)c[0]);
- EXPECT_ANY_DEATH((void)c.front());
- EXPECT_ANY_DEATH((void)c.back());
- EXPECT_ANY_DEATH(c.pop_back());
- EXPECT_ANY_DEATH(c.erase(c.begin()));
- EXPECT_ANY_DEATH((void)std::as_const(c)[0]);
- EXPECT_ANY_DEATH((void)std::as_const(c).front());
- EXPECT_ANY_DEATH((void)std::as_const(c).back());
+ TEST_LIBCPP_ASSERT_FAILURE((void)c[0], "inplace_vector<T,0>::operator[]: access with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE((void)std::as_const(c)[0], "inplace_vector<T,0>::operator[] const: access with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE((void)c.at(0), "inplace_vector<T,0>::at(size_type n): access with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ (void)std::as_const(c).at(0), "inplace_vector<T,0>::at(size_type n) const: access with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE((void)c.front(), "inplace_vector<T,0>::front(): access with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE((void)std::as_const(c).front(), "inplace_vector<T,0>::front() const: access with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE((void)c.back(), "inplace_vector<T,0>::back(): access with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE((void)std::as_const(c).back(), "inplace_vector<T,0>::back() const: access with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE(c.pop_back(), "inplace_vector<T,0>::erase(): use with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE(c.erase(c.begin()), "inplace_vector<T,0>::erase(): use with N == 0");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ c.erase(c.begin(), c.begin() + 1), "inplace_vector<T,0>::erase(const_iterator, const_iterator): use with N == 0");
return 0;
}
>From ed7c23997de81dfe6d94028eed4d3ffc39418323 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 18 Jun 2026 00:11:08 -0400
Subject: [PATCH 09/11] Clean up unused std::swap
---
libcxx/include/inplace_vector | 1 -
1 file changed, 1 deletion(-)
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
index 1c792c9dc8c4c..e5d54b0c64bcc 100644
--- a/libcxx/include/inplace_vector
+++ b/libcxx/include/inplace_vector
@@ -758,7 +758,6 @@ public:
std::swap_ranges(__smaller.begin(), __smaller.end(), __bigger.begin());
if (__n1 != __n2) {
- using std::swap;
std::uninitialized_move(__bigger.data() + __n1, __bigger.data() + __n2, __smaller.data() + __n1);
__smaller.__size_ = __n2;
std::destroy(__bigger.data() + __n1, __bigger.data() + __n2);
>From 8bac69d3d514b8e234a1c25f16907f4eb7152bea Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 18 Jun 2026 00:16:17 -0400
Subject: [PATCH 10/11] Add hardening asserts for erase() like in vector
---
libcxx/include/inplace_vector | 5 ++++
.../inplace_vector/assert.erase.pass.cpp | 28 +++++++++++++++++++
2 files changed, 33 insertions(+)
create mode 100644 libcxx/test/libcxx/containers/sequences/inplace_vector/assert.erase.pass.cpp
diff --git a/libcxx/include/inplace_vector b/libcxx/include/inplace_vector
index e5d54b0c64bcc..160265fd06a8c 100644
--- a/libcxx/include/inplace_vector
+++ b/libcxx/include/inplace_vector
@@ -724,6 +724,9 @@ public:
}
constexpr iterator erase(const_iterator __position) {
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
+ __position != end(), "inplace_vector<T,N>::erase(iterator) called with a non-dereferenceable iterator");
+
pointer __pos = data() + (__position - cbegin());
std::move(__pos + 1, data() + __size_, __pos);
@@ -733,6 +736,8 @@ public:
}
constexpr iterator erase(const_iterator __first, const_iterator __last) {
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(
+ __first <= __last, "inplace_vector<T,N>::erase(first, last) called with invalid range");
__size_type __x = __last - __first;
pointer __pos = data() + (__first - cbegin());
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.erase.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.erase.pass.cpp
new file mode 100644
index 0000000000000..87df7d8fc2464
--- /dev/null
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.erase.pass.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: has-unix-headers, std-at-least-c++26
+// UNSUPPORTED: libcpp-hardening-mode=none
+// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
+
+// <inplace_vector>
+
+#include <inplace_vector>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ std::inplace_vector<int, 2> v{1, 2};
+
+ TEST_LIBCPP_ASSERT_FAILURE(
+ v.erase(v.end()), "inplace_vector<T,N>::erase(iterator) called with a non-dereferenceable iterator");
+ TEST_LIBCPP_ASSERT_FAILURE(
+ v.erase(v.end(), v.begin()), "inplace_vector<T,N>::erase(first, last) called with invalid range");
+
+ return 0;
+}
>From 7eff88b82d385af0dd46f31ccac312fd773f6313 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 18 Jun 2026 01:55:24 -0400
Subject: [PATCH 11/11] Remove at from assert test
---
.../sequences/inplace_vector/assert.zero_capacity.pass.cpp | 3 ---
1 file changed, 3 deletions(-)
diff --git a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
index 25947cf4c0040..b765a0d367a96 100644
--- a/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
+++ b/libcxx/test/libcxx/containers/sequences/inplace_vector/assert.zero_capacity.pass.cpp
@@ -22,9 +22,6 @@ int main(int, char**) {
TEST_LIBCPP_ASSERT_FAILURE((void)c[0], "inplace_vector<T,0>::operator[]: access with N == 0");
TEST_LIBCPP_ASSERT_FAILURE((void)std::as_const(c)[0], "inplace_vector<T,0>::operator[] const: access with N == 0");
- TEST_LIBCPP_ASSERT_FAILURE((void)c.at(0), "inplace_vector<T,0>::at(size_type n): access with N == 0");
- TEST_LIBCPP_ASSERT_FAILURE(
- (void)std::as_const(c).at(0), "inplace_vector<T,0>::at(size_type n) const: access with N == 0");
TEST_LIBCPP_ASSERT_FAILURE((void)c.front(), "inplace_vector<T,0>::front(): access with N == 0");
TEST_LIBCPP_ASSERT_FAILURE((void)std::as_const(c).front(), "inplace_vector<T,0>::front() const: access with N == 0");
TEST_LIBCPP_ASSERT_FAILURE((void)c.back(), "inplace_vector<T,0>::back(): access with N == 0");
More information about the libcxx-commits
mailing list