Skip to content

[libc++] Make <map> std::map constexpr as part of P3372R3 #134330

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 191 commits into
base: main
Choose a base branch
from

Conversation

vinay-deshmukh
Copy link
Contributor

@vinay-deshmukh vinay-deshmukh commented Apr 4, 2025

Fixes #128660

Summary:

  1. Apply _LIBCPP_CONSTEXPR_SINCE_CXX26 to map, __tree and node-handle

  2. map.modifiers/try.emplace.pass.cpp : Start using the previously unused mv3. (Should this be a separate patch?)

  3. Has a TODO for multimap
    a. libcxx/test/std/containers/associative/map/map.ops/contains.pass.cpp
    b. libcxx/test/std/containers/associative/map/map.ops/contains_transparent.pass.cpp

  4. TODO: for multimap and others:
    a. libcxx/test/std/containers/container.node/node_handle.pass.cpp

  5. Fix typo in libcxx/include/__memory/pointer_traits.h

  6. pair<const MoveOnly, ...>
    a. move_assign.pass.cpp
    b. move_alloc.pass.cpp
    c. Fails to compile if static_assert(test()); is called in the test file
    d. Has a // FIXME with commented code

  7. Based on this comment, I tried replacing:
    a. __node_traits::construct(__na, std::addressof(__h->__value_), std::forward<_Args>(__args)...);
    b. with
    c. std::__construct_at(std::addressof(__h->__value_), std::forward<_Args>(__args)...);
    d. Fails with:

  # .---command stderr------------
  # | t.tmp.exe: /home/runner/_work/llvm-project/llvm-project/libcxx/test/support/container_test_types.h:399: CopyInsertable<1>::CopyInsertable(const CopyInsertable<Dummy> &) [Dummy = 1]: Assertion `getConstructController()->isInAllocatorConstruct()' failed.
  # `-----------------------------
  # error: command failed with exit status: 250

Copy link

github-actions bot commented Apr 4, 2025

⚠️ We detected that you are using a GitHub private e-mail address to contribute to the repo.
Please turn off Keep my email addresses private setting in your account.
See LLVM Discourse for more information.

Copy link

github-actions bot commented Apr 4, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@vinay-deshmukh vinay-deshmukh force-pushed the vinay-issue-128660-P3372-constexpr-map branch from 181a08d to 6560dd5 Compare April 4, 2025 00:53
@vinay-deshmukh vinay-deshmukh force-pushed the vinay-issue-128660-P3372-constexpr-map branch from 46d0bb9 to 9ea718f Compare April 7, 2025 22:25
@vinay-deshmukh vinay-deshmukh changed the title [libc++] Make map constexpr as part of P3372R3 [libc++] Make <map> std::map constexpr as part of P3372R3 Aug 11, 2025
…d.`Revert "PR review comment"

This reverts commit 4fbb472.

Fails with:

```
  # .---command stderr------------
  # | t.tmp.exe: /home/runner/_work/llvm-project/llvm-project/libcxx/test/support/container_test_types.h:399: CopyInsertable<1>::CopyInsertable(const CopyInsertable<Dummy> &) [Dummy = 1]: Assertion `getConstructController()->isInAllocatorConstruct()' failed.
  # `-----------------------------
  # error: command failed with exit status: 250
```
@vinay-deshmukh vinay-deshmukh force-pushed the vinay-issue-128660-P3372-constexpr-map branch from 990228b to efd9f96 Compare August 12, 2025 01:25
@vinay-deshmukh
Copy link
Contributor Author

vinay-deshmukh commented Aug 12, 2025

Not sure what this failure is in gcc-15 tests:

 # .---command stderr------------
  # | /home/runner/_work/llvm-project/llvm-project/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp: In function ‘int main(int, char**)’:
  # | /home/runner/_work/llvm-project/llvm-project/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp:83:27: error: non-constant condition for static assertion
  # |    83 |   static_assert(test_upper());
  # |       |                 ~~~~~~~~~~^~
  # | In file included from /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/map:599,
  # |                  from /home/runner/_work/llvm-project/llvm-project/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp:16:
  # | /home/runner/_work/llvm-project/llvm-project/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp:83:27:   in ‘constexpr’ expansion of ‘test_upper()’
  # | /home/runner/_work/llvm-project/llvm-project/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp:70:27:   in ‘constexpr’ expansion of ‘test<std::__1::map<int, int> >()’
  # | /home/runner/_work/llvm-project/llvm-project/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp:50:11:   in ‘constexpr’ expansion of ‘test0<std::__1::map<int, int>, test<std::__1::map<int, int> >()::<lambda(auto:32)> >(Init{((const int*)(& const int [1]{1})), 1}, (is1, test<std::__1::map<int, int> >()::<lambda(auto:32)>()), Init{0, 0}, 1)’
  # | /home/runner/_work/llvm-project/llvm-project/libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp:35:3:   in ‘constexpr’ expansion of ‘std::__1::erase_if<int, int, less<int>, allocator<pair<const int, int> >, test<std::__1::map<int, int> >()::<lambda(auto:32)> >(s, (p, test<std::__1::map<int, int> >()::<lambda(auto:32)>()))’
  # | /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/map:1605:42:   in ‘constexpr’ expansion of ‘std::__1::__libcpp_erase_if_container<map<int, int>, test<std::__1::map<int, int> >()::<lambda(auto:32)> >((* & __c), __pred)’
  # | /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/__iterator/erase_if_container.h:32:25:   in ‘constexpr’ expansion of ‘(& __c)->std::__1::map<int, int>::erase(__iter)’
  # | /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/map:1256:106:   in ‘constexpr’ expansion of ‘((std::__1::map<int, int>*)this)->std::__1::map<int, int>::__tree_.std::__1::__tree<std::__1::__value_type<int, int>, std::__1::__map_value_compare<int, std::__1::pair<const int, int>, std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<const int, int> > >::erase(std::__1::__tree_const_iterator<std::__1::__value_type<int, int>, std::__1::__tree_node<std::__1::__value_type<int, int>, void*>*, long int>(__p.std::__1::__map_iterator<std::__1::__tree_iterator<std::__1::__value_type<int, int>, std::__1::__tree_node<std::__1::__value_type<int, int>, void*>*, long int> >::__i_))’
  # | /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/__tree:2132:49:   in ‘constexpr’ expansion of ‘((std::__1::__tree<std::__1::__value_type<int, int>, std::__1::__map_value_compare<int, std::__1::pair<const int, int>, std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<const int, int> > >*)this)->std::__1::__tree<std::__1::__value_type<int, int>, std::__1::__map_value_compare<int, std::__1::pair<const int, int>, std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<const int, int> > >::__remove_node_pointer(__np)’
  # | /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/__tree:1997:3:   in ‘constexpr’ expansion of ‘__r.std::__1::__tree_iterator<std::__1::__value_type<int, int>, std::__1::__tree_node<std::__1::__value_type<int, int>, void*>*, long int>::operator++()’
  # | /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/__tree:644:55:   in ‘constexpr’ expansion of ‘std::__1::__tree_next_iter<__tree_end_node<__tree_node_base<void*>*>*, __tree_node_base<void*>*>(std::__1::__static_fancy_pointer_cast<__tree_node_base<void*>*, __tree_end_node<__tree_node_base<void*>*>*>(((std::__1::__tree_iterator<std::__1::__value_type<int, int>, std::__1::__tree_node<std::__1::__value_type<int, int>, void*>*, long int>*)this)->std::__1::__tree_iterator<std::__1::__value_type<int, int>, std::__1::__tree_node<std::__1::__value_type<int, int>, void*>*, long int>::__ptr_))’
  # | /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/__tree:178:36:   in ‘constexpr’ expansion of ‘std::__1::__tree_is_left_child<__tree_node_base<void*>*>(__x)’
  # | /home/runner/_work/llvm-project/llvm-project/build/generic-gcc/libcxx/test-suite-install/include/c++/v1/__tree:90:33: error: ‘‘result_decl’ not supported by dump_expr<expression error>’ is not a constant expression
  # |    90 |   return __x == __x->__parent_->__left_;
  # |       |                 ~~~~~~~~~~~~~~~~^~~~~~~
  # | At global scope:
  # | cc1plus: note: unrecognized command-line option ‘-Wno-nullability-completeness’ may have been intended to silence earlier diagnostics
  # | cc1plus: note: unrecognized command-line option ‘-Wno-pass-failed’ may have been intended to silence earlier diagnostics
  # | cc1plus: note: unrecognized command-line option ‘-Wno-local-type-template-args’ may have been intended to silence earlier diagnostics
  # | cc1plus: note: unrecognized command-line option ‘-Wno-unused-local-typedef’ may have been intended to silence earlier diagnostics
  # | cc1plus: note: unrecognized command-line option ‘-Wno-user-defined-literals’ may have been intended to silence earlier diagnostics
  # | cc1plus: note: unrecognized command-line option ‘-Wno-reserved-module-identifier’ may have been intended to silence earlier diagnostics
  # | cc1plus: note: unrecognized command-line option ‘-Wno-atomic-alignment’ may have been intended to silence earlier diagnostics
  # | cc1plus: note: unrecognized command-line option ‘-Wno-aligned-allocation-unavailable’ may have been intended to silence earlier diagnostics
  # | cc1plus: note: unrecognized command-line option ‘-Wno-unused-command-line-argument’ may have been intended to silence earlier diagnostics
  # `-----------------------------
  # error: command failed with exit status: 1
  

AIX 32 fails with the following and basically the whole test suite(not sure if it has the up to date compiler)

AIX is using Clang 19, so about a year old and that may be the cause of this failure:


# .---command stderr------------
--
  | # \| /scratch/powerllvm/cpap8006/llvm-project/libcxx-ci/libcxx/test/std/containers/associative/map/compare.pass.cpp:59:17: error: static assertion expression is not an integral constant expression
  | # \|    59 \|   static_assert(test());
  | # \|       \|                 ^~~~~~
  | # \| /scratch/powerllvm/cpap8006/llvm-project/libcxx-ci/build/aix/libcxx/test-suite-install/include/c++/v1/__memory/construct_at.h:38:49: note: non-literal type 'std::__tree_node<std::__value_type<Key, int>, void *>' cannot be used in a constant expression
  | # \|    38 \|   return ::new (static_cast<void*>(__location)) _Tp(std::forward<_Args>(__args)...);
  | # \|       \|                                                 ^
  | # \| /scratch/powerllvm/cpap8006/llvm-project/libcxx-ci/build/aix/libcxx/test-suite-install/include/c++/v1/__memory/construct_at.h:46:10: note: in call to 'construct_at<std::__tree_node<std::__value_type<Key, int>, void *>, const std::piecewise_construct_t &, std::tuple<Key &&>, std::tuple<>, std::__tree_node<std::__value_type<Key, int>, void *> *>(&{*new std::__tree_node<std::__value_type<Key, int>, void *>[1]#0}[0], piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple())'
  | # \|    46 \|   return std::construct_at(__location, std::forward<_Args>(__args)...);
  | # \|       \|          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  | # \| /scratch/powerllvm/cpap8006/llvm-project/libcxx-ci/build/aix/libcxx/test-suite-install/include/c++/v1/__tree:1893:5: note: in call to '__construct_at<std::__tree_node<std::__value_type<Key, int>, void *>, const std::piecewise_construct_t &, std::tuple<Key &&>, std::tuple<>, std::__tree_node<std::__value_type<Key, int>, void *> *>(&{*new std::__tree_node<std::__value_type<Key, int>, void *>[1]#0}[0], piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple())'
  | # \|  1893 \|     std::__construct_at(std::addressof(*__h), std::forward<_Args>(__args)...);
  | # \|       \|     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  | # \| /scratch/powerllvm/cpap8006/llvm-project/libcxx-ci/build/aix/libcxx/test-suite-install/include/c++/v1/__tree:1856:25: note: in call to 'this->__construct_node<const std::piecewise_construct_t &, std::tuple<Key &&>, std::tuple<>>(piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple())'
  | # \|  1856 \|     __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
  | # \|       \|                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  | # \| /scratch/powerllvm/cpap8006/llvm-project/libcxx-ci/build/aix/libcxx/test-suite-install/include/c++/v1/map:1492:10: note: in call to 'this->__tree_.__emplace_unique_key_args<Key, const std::piecewise_construct_t &, std::tuple<Key &&>, std::tuple<>>(Key(0), piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple())'
  | # \|  1492 \|   return __tree_
  | # \|       \|          ^~~~~~~
  | # \|  1493 \|       .__emplace_unique_key_args(
  | # \|       \|       ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  | # \|  1494 \|           __k, std::piecewise_construct, std::forward_as_tuple(std::move(__k)), std::forward_as_tuple())
  | # \|       \|           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  | # \| /scratch/powerllvm/cpap8006/llvm-project/libcxx-ci/libcxx/test/std/containers/associative/map/compare.pass.cpp:37:5: note: in call to 'm_contains.operator[](Key(0))'
  | # \|    37 \|     m_contains[Key(0)] = 42;
  | # \|       \|     ^~~~~~~~~~~~~~~~~~
  | # \| /scratch/powerllvm/cpap8006/llvm-project/libcxx-ci/libcxx/test/std/containers/associative/map/compare.pass.cpp:59:17: note: in call to 'test()'
  | # \|    59 \|   static_assert(test());
  | # \|       \|                 ^~~~~~
  | # \| 1 error generated.
  | # `-----------------------------
  | # error: command failed with exit status: 1
  |  
  | --


@vinay-deshmukh vinay-deshmukh marked this pull request as ready for review August 12, 2025 02:39
@vinay-deshmukh vinay-deshmukh requested a review from a team as a code owner August 12, 2025 02:39
@frederick-vs-ja frederick-vs-ja added libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. c++26 labels Aug 15, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 15, 2025

@llvm/pr-subscribers-libcxx

Author: Vinay Deshmukh (vinay-deshmukh)

Changes

Fixes #128660

Summary:

  1. Apply _LIBCPP_CONSTEXPR_SINCE_CXX26 to map, __tree and node-handle

  2. map.modifiers/try.emplace.pass.cpp : Start using the previously unused mv3. (Should this be a separate patch?)

  3. Has a TODO for multimap
    a. libcxx/test/std/containers/associative/map/map.ops/contains.pass.cpp
    b. libcxx/test/std/containers/associative/map/map.ops/contains_transparent.pass.cpp

  4. TODO: for multimap and others:
    a. libcxx/test/std/containers/container.node/node_handle.pass.cpp

  5. Fix typo in libcxx/include/__memory/pointer_traits.h

  6. pair&lt;const MoveOnly, ...&gt;
    a. move_assign.pass.cpp
    b. move_alloc.pass.cpp
    c. Fails to compile if static_assert(test()); is called in the test file
    d. Has a // FIXME with commented code

  7. Based on this comment, I tried replacing:
    a. __node_traits::construct(__na, std::addressof(__h-&gt;__value_), std::forward&lt;_Args&gt;(__args)...);
    b. with
    c. std::__construct_at(std::addressof(__h-&gt;__value_), std::forward&lt;_Args&gt;(__args)...);
    d. Fails with:

  # .---command stderr------------
  # | t.tmp.exe: /home/runner/_work/llvm-project/llvm-project/libcxx/test/support/container_test_types.h:399: CopyInsertable&lt;1&gt;::CopyInsertable(const CopyInsertable&lt;Dummy&gt; &amp;) [Dummy = 1]: Assertion `getConstructController()-&gt;isInAllocatorConstruct()' failed.
  # `-----------------------------
  # error: command failed with exit status: 250

Patch is 294.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/134330.diff

91 Files Affected:

  • (modified) libcxx/docs/FeatureTestMacroTable.rst (+2)
  • (modified) libcxx/docs/ReleaseNotes/22.rst (+1)
  • (modified) libcxx/include/__iterator/erase_if_container.h (+2-1)
  • (modified) libcxx/include/__memory/pointer_traits.h (+1-1)
  • (modified) libcxx/include/__node_handle (+15-12)
  • (modified) libcxx/include/__tree (+449-308)
  • (modified) libcxx/include/map (+311-196)
  • (modified) libcxx/include/version (+2)
  • (modified) libcxx/test/std/containers/associative/from_range_associative_containers.h (+5-5)
  • (modified) libcxx/test/std/containers/associative/map/compare.pass.cpp (+11-4)
  • (modified) libcxx/test/std/containers/associative/map/get_allocator.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/incomplete_type.pass.cpp (+12-2)
  • (modified) libcxx/test/std/containers/associative/map/map.access/at.pass.cpp (+44-4)
  • (modified) libcxx/test/std/containers/associative/map/map.access/empty.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.access/index_key.pass.cpp (+11-2)
  • (modified) libcxx/test/std/containers/associative/map/map.access/index_rv_key.pass.cpp (+19-2)
  • (modified) libcxx/test/std/containers/associative/map/map.access/index_tuple.pass.cpp (+12-2)
  • (modified) libcxx/test/std/containers/associative/map/map.access/iterator.pass.cpp (+20-13)
  • (modified) libcxx/test/std/containers/associative/map/map.access/max_size.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.access/size.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/alloc.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/assign_initializer_list.pass.cpp (+13-4)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/compare.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/compare_alloc.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/copy.pass.cpp (+14-5)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/copy_alloc.pass.cpp (+18-5)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/copy_assign.pass.cpp (+25-16)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/deduct.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/deduct_const.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/default.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/default_noexcept.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/dtor_noexcept.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/from_range.pass.cpp (+15-6)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/initializer_list.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/initializer_list_compare.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/initializer_list_compare_alloc.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/iter_iter.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/iter_iter_comp.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/iter_iter_comp_alloc.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/move.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/move_alloc.pass.cpp (+10-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/move_assign.pass.cpp (+11-2)
  • (modified) libcxx/test/std/containers/associative/map/map.cons/move_noexcept.pass.cpp (+9-3)
  • (modified) libcxx/test/std/containers/associative/map/map.erasure/erase_if.pass.cpp (+17-5)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/clear.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/emplace.pass.cpp (+67-54)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/emplace_hint.pass.cpp (+62-48)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/erase_iter.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/erase_iter_iter.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/erase_key.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/extract_iterator.pass.cpp (+17-7)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/extract_key.pass.cpp (+16-7)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/insert_cv.pass.cpp (+12-3)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/insert_initializer_list.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/insert_iter_cv.pass.cpp (+12-3)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/insert_iter_iter.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/insert_iter_rv.pass.cpp (+12-3)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/insert_or_assign.pass.cpp (+22-13)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/insert_range.pass.cpp (+12-2)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/insert_rv.pass.cpp (+12-3)
  • (modified) libcxx/test/std/containers/associative/map/map.modifiers/try.emplace.pass.cpp (+24-15)
  • (modified) libcxx/test/std/containers/associative/map/map.nonmember/compare.three_way.pass.cpp (+6-1)
  • (modified) libcxx/test/std/containers/associative/map/map.nonmember/op_compare.pass.cpp (+11-1)
  • (modified) libcxx/test/std/containers/associative/map/map.observers/key_comp.pass.cpp (+11-2)
  • (modified) libcxx/test/std/containers/associative/map/map.observers/value_comp.pass.cpp (+11-2)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/contains.pass.cpp (+16-4)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/contains_transparent.pass.cpp (+24-7)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/count.pass.cpp (+15-4)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/count0.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/count_transparent.pass.cpp (+17-5)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/equal_range.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/equal_range0.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/equal_range_transparent.pass.cpp (+17-6)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/find.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/find0.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/lower_bound.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/lower_bound0.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/upper_bound.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.ops/upper_bound0.pass.cpp (+10-4)
  • (modified) libcxx/test/std/containers/associative/map/map.special/member_swap.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.special/non_member_swap.pass.cpp (+9-2)
  • (modified) libcxx/test/std/containers/associative/map/map.special/swap_noexcept.pass.cpp (+10-3)
  • (modified) libcxx/test/std/containers/associative/map/map.value_compare/invoke.pass.cpp (+13-4)
  • (modified) libcxx/test/std/containers/associative/map/types.pass.cpp (+8-1)
  • (modified) libcxx/test/std/containers/container.node/node_handle.pass.cpp (+37-15)
  • (modified) libcxx/test/std/containers/insert_range_maps_sets.h (+3-2)
  • (modified) libcxx/test/std/language.support/support.limits/support.limits.general/map.version.compile.pass.cpp (+27)
  • (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+27)
  • (modified) libcxx/test/support/is_transparent.h (+7-6)
  • (modified) libcxx/test/support/private_constructor.h (+11-7)
  • (modified) libcxx/utils/generate_feature_test_macro_components.py (+5)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index a36848ebd24b4..07ec543c008ce 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -428,6 +428,8 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_list``                               ``202502L``
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_constexpr_map``                                ``202502L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_new``                                ``202406L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_queue``                              ``202502L``
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index 8b8dce5083149..41239be9c9ba8 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -45,6 +45,7 @@ Improvements and New Features
 
 - The performance of ``map::map(const map&)`` has been improved up to 2.3x
 - The performance of ``map::operator=(const map&)`` has been improved by up to 11x
+- P3372R3: ``constexpr map``(`Github <https://github.com/llvm/llvm-project/issues/128660>`__) (The paper is partially implemented. ``constexpr map`` is implemented in this release)
 
 Deprecations and Removals
 -------------------------
diff --git a/libcxx/include/__iterator/erase_if_container.h b/libcxx/include/__iterator/erase_if_container.h
index 0f87f50cd1c16..8d92d3f1b9dbe 100644
--- a/libcxx/include/__iterator/erase_if_container.h
+++ b/libcxx/include/__iterator/erase_if_container.h
@@ -22,7 +22,8 @@ _LIBCPP_PUSH_MACROS
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Container, class _Predicate>
-_LIBCPP_HIDE_FROM_ABI typename _Container::size_type __libcpp_erase_if_container(_Container& __c, _Predicate& __pred) {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename _Container::size_type
+__libcpp_erase_if_container(_Container& __c, _Predicate& __pred) {
   typename _Container::size_type __old_size = __c.size();
 
   const typename _Container::iterator __last = __c.end();
diff --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h
index 8c7f8dff1b76b..62fcd93263b02 100644
--- a/libcxx/include/__memory/pointer_traits.h
+++ b/libcxx/include/__memory/pointer_traits.h
@@ -255,7 +255,7 @@ concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p
 // This function ensures safe conversions between fancy pointers at compile-time, where we avoid casts from/to
 // `__void_pointer` by obtaining the underlying raw pointer from the fancy pointer using `std::to_address`,
 // then dereferencing it to retrieve the pointed-to object, and finally constructing the target fancy pointer
-// to that object using the `std::pointer_traits<>::pinter_to` function.
+// to that object using the `std::pointer_traits<>::pointer_to` function.
 template <class _PtrTo, class _PtrFrom>
 _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _PtrTo __static_fancy_pointer_cast(const _PtrFrom& __p) {
   using __ptr_traits   = pointer_traits<_PtrTo>;
diff --git a/libcxx/include/__node_handle b/libcxx/include/__node_handle
index b20b0c73a0518..6ce2e1b7d459c 100644
--- a/libcxx/include/__node_handle
+++ b/libcxx/include/__node_handle
@@ -99,12 +99,12 @@ private:
   __node_pointer_type __ptr_ = nullptr;
   optional<allocator_type> __alloc_;
 
-  _LIBCPP_HIDE_FROM_ABI void __release_ptr() {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __release_ptr() {
     __ptr_   = nullptr;
     __alloc_ = std::nullopt;
   }
 
-  _LIBCPP_HIDE_FROM_ABI void __destroy_node_pointer() {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __destroy_node_pointer() {
     if (__ptr_ != nullptr) {
       typedef typename __allocator_traits_rebind< allocator_type, _NodeType>::type __node_alloc_type;
       __node_alloc_type __alloc(*__alloc_);
@@ -113,19 +113,20 @@ private:
     }
   }
 
-  _LIBCPP_HIDE_FROM_ABI __basic_node_handle(__node_pointer_type __ptr, allocator_type const& __alloc)
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
+  __basic_node_handle(__node_pointer_type __ptr, allocator_type const& __alloc)
       : __ptr_(__ptr), __alloc_(__alloc) {}
 
 public:
-  _LIBCPP_HIDE_FROM_ABI __basic_node_handle() = default;
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __basic_node_handle() = default;
 
-  _LIBCPP_HIDE_FROM_ABI __basic_node_handle(__basic_node_handle&& __other) noexcept
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __basic_node_handle(__basic_node_handle&& __other) noexcept
       : __ptr_(__other.__ptr_), __alloc_(std::move(__other.__alloc_)) {
     __other.__ptr_   = nullptr;
     __other.__alloc_ = std::nullopt;
   }
 
-  _LIBCPP_HIDE_FROM_ABI __basic_node_handle& operator=(__basic_node_handle&& __other) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __basic_node_handle& operator=(__basic_node_handle&& __other) {
     _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
         __alloc_ == std::nullopt || __alloc_traits::propagate_on_container_move_assignment::value ||
             __alloc_ == __other.__alloc_,
@@ -144,13 +145,13 @@ public:
     return *this;
   }
 
-  _LIBCPP_HIDE_FROM_ABI allocator_type get_allocator() const { return *__alloc_; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 allocator_type get_allocator() const { return *__alloc_; }
 
-  _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return __ptr_ != nullptr; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit operator bool() const { return __ptr_ != nullptr; }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const { return __ptr_ == nullptr; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const { return __ptr_ == nullptr; }
 
-  _LIBCPP_HIDE_FROM_ABI void swap(__basic_node_handle& __other) noexcept(
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(__basic_node_handle& __other) noexcept(
       __alloc_traits::propagate_on_container_swap::value || __alloc_traits::is_always_equal::value) {
     using std::swap;
     swap(__ptr_, __other.__ptr_);
@@ -159,12 +160,12 @@ public:
       swap(__alloc_, __other.__alloc_);
   }
 
-  _LIBCPP_HIDE_FROM_ABI friend void
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend void
   swap(__basic_node_handle& __a, __basic_node_handle& __b) noexcept(noexcept(__a.swap(__b))) {
     __a.swap(__b);
   }
 
-  _LIBCPP_HIDE_FROM_ABI ~__basic_node_handle() { __destroy_node_pointer(); }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~__basic_node_handle() { __destroy_node_pointer(); }
 };
 
 template <class _NodeType, class _Derived>
@@ -179,6 +180,8 @@ struct __map_node_handle_specifics {
   using key_type    = __remove_const_t<typename _NodeType::__node_value_type::first_type>;
   using mapped_type = typename _NodeType::__node_value_type::second_type;
 
+  // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3372r3.html#node-handle-key
+  // https://cplusplus.github.io/CWG/issues/2514.html
   _LIBCPP_HIDE_FROM_ABI key_type& key() const {
     return const_cast<key_type&>(static_cast<_Derived const*>(this)->__ptr_->__get_value().first);
   }
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 6dadd0915c984..e3499f3a4769c 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -20,6 +20,7 @@
 #include <__memory/addressof.h>
 #include <__memory/allocator_traits.h>
 #include <__memory/compressed_pair.h>
+#include <__memory/construct_at.h>
 #include <__memory/pointer_traits.h>
 #include <__memory/swap_allocator.h>
 #include <__memory/unique_ptr.h>
@@ -27,6 +28,8 @@
 #include <__type_traits/copy_cvref.h>
 #include <__type_traits/enable_if.h>
 #include <__type_traits/invoke.h>
+#include <__type_traits/is_const.h>
+#include <__type_traits/is_constant_evaluated.h>
 #include <__type_traits/is_constructible.h>
 #include <__type_traits/is_nothrow_assignable.h>
 #include <__type_traits/is_nothrow_constructible.h>
@@ -83,7 +86,7 @@ __root, have a non-null __parent_ field.
 // Returns:  true if __x is a left child of its parent, else false
 // Precondition:  __x != nullptr.
 template <class _NodePtr>
-inline _LIBCPP_HIDE_FROM_ABI bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __tree_is_left_child(_NodePtr __x) _NOEXCEPT {
   return __x == __x->__parent_->__left_;
 }
 
@@ -140,7 +143,7 @@ _LIBCPP_HIDE_FROM_ABI bool __tree_invariant(_NodePtr __root) {
 
 // Returns:  pointer to the left-most node under __x.
 template <class _NodePtr>
-inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null");
   while (__x->__left_ != nullptr)
     __x = __x->__left_;
@@ -149,7 +152,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_min(_NodePtr __x) _NOEXCEPT {
 
 // Returns:  pointer to the right-most node under __x.
 template <class _NodePtr>
-inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Root node shouldn't be null");
   while (__x->__right_ != nullptr)
     __x = __x->__right_;
@@ -158,7 +161,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_max(_NodePtr __x) _NOEXCEPT {
 
 // Returns:  pointer to the next in-order node after __x.
 template <class _NodePtr>
-_LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
   if (__x->__right_ != nullptr)
     return std::__tree_min(__x->__right_);
@@ -168,10 +171,10 @@ _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_next(_NodePtr __x) _NOEXCEPT {
 }
 
 template <class _EndNodePtr, class _NodePtr>
-inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
   if (__x->__right_ != nullptr)
-    return static_cast<_EndNodePtr>(std::__tree_min(__x->__right_));
+    return std::__static_fancy_pointer_cast<_EndNodePtr>(std::__tree_min(__x->__right_));
   while (!std::__tree_is_left_child(__x))
     __x = __x->__parent_unsafe();
   return static_cast<_EndNodePtr>(__x->__parent_);
@@ -180,11 +183,11 @@ inline _LIBCPP_HIDE_FROM_ABI _EndNodePtr __tree_next_iter(_NodePtr __x) _NOEXCEP
 // Returns:  pointer to the previous in-order node before __x.
 // Note: __x may be the end node.
 template <class _NodePtr, class _EndNodePtr>
-inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEPT {
+inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
   if (__x->__left_ != nullptr)
     return std::__tree_max(__x->__left_);
-  _NodePtr __xx = static_cast<_NodePtr>(__x);
+  _NodePtr __xx = std::__static_fancy_pointer_cast<_NodePtr>(__x);
   while (std::__tree_is_left_child(__xx))
     __xx = __xx->__parent_unsafe();
   return __xx->__parent_unsafe();
@@ -192,7 +195,7 @@ inline _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_prev_iter(_EndNodePtr __x) _NOEXCEP
 
 // Returns:  pointer to a node which has no children
 template <class _NodePtr>
-_LIBCPP_HIDE_FROM_ABI _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
   while (true) {
     if (__x->__left_ != nullptr) {
@@ -211,7 +214,7 @@ _LIBCPP_HIDE_FROM_ABI _NodePtr __tree_leaf(_NodePtr __x) _NOEXCEPT {
 // Effects:  Makes __x->__right_ the subtree root with __x as its left child
 //           while preserving in-order order.
 template <class _NodePtr>
-_LIBCPP_HIDE_FROM_ABI void __tree_left_rotate(_NodePtr __x) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree_left_rotate(_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
   _LIBCPP_ASSERT_INTERNAL(__x->__right_ != nullptr, "node should have a right child");
   _NodePtr __y  = __x->__right_;
@@ -230,7 +233,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree_left_rotate(_NodePtr __x) _NOEXCEPT {
 // Effects:  Makes __x->__left_ the subtree root with __x as its right child
 //           while preserving in-order order.
 template <class _NodePtr>
-_LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr __x) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX26 _LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "node shouldn't be null");
   _LIBCPP_ASSERT_INTERNAL(__x->__left_ != nullptr, "node should have a left child");
   _NodePtr __y = __x->__left_;
@@ -254,7 +257,8 @@ _LIBCPP_HIDE_FROM_ABI void __tree_right_rotate(_NodePtr __x) _NOEXCEPT {
 // Postcondition: __tree_invariant(end_node->__left_) == true.  end_node->__left_
 //                may be different than the value passed in as __root.
 template <class _NodePtr>
-_LIBCPP_HIDE_FROM_ABI void __tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
+__tree_balance_after_insert(_NodePtr __root, _NodePtr __x) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root of the tree shouldn't be null");
   _LIBCPP_ASSERT_INTERNAL(__x != nullptr, "Can't attach null node to a leaf");
   __x->__is_black_ = __x == __root;
@@ -310,7 +314,7 @@ _LIBCPP_HIDE_FROM_ABI void __tree_balance_after_insert(_NodePtr __root, _NodePtr
 //                nor any of its children refer to __z.  end_node->__left_
 //                may be different than the value passed in as __root.
 template <class _NodePtr>
-_LIBCPP_HIDE_FROM_ABI void __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT {
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __tree_remove(_NodePtr __root, _NodePtr __z) _NOEXCEPT {
   _LIBCPP_ASSERT_INTERNAL(__root != nullptr, "Root node should not be null");
   _LIBCPP_ASSERT_INTERNAL(__z != nullptr, "The node to remove should not be null");
   _LIBCPP_ASSERT_INTERNAL(std::__tree_invariant(__root), "The tree invariants should hold");
@@ -525,7 +529,7 @@ public:
   typedef _Pointer pointer;
   pointer __left_;
 
-  _LIBCPP_HIDE_FROM_ABI __tree_end_node() _NOEXCEPT : __left_() {}
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_end_node() _NOEXCEPT : __left_() {}
 };
 
 template <class _VoidPtr>
@@ -539,11 +543,16 @@ public:
   __end_node_pointer __parent_;
   bool __is_black_;
 
-  _LIBCPP_HIDE_FROM_ABI pointer __parent_unsafe() const { return static_cast<pointer>(__parent_); }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer __parent_unsafe() const {
+    return std::__static_fancy_pointer_cast<pointer>(__parent_);
+  }
 
-  _LIBCPP_HIDE_FROM_ABI void __set_parent(pointer __p) { __parent_ = static_cast<__end_node_pointer>(__p); }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __set_parent(pointer __p) {
+    __parent_ = std::__static_fancy_pointer_cast<__end_node_pointer>(__p);
+  }
 
-  ~__tree_node_base()                                  = delete;
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node_base()  = default;
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 ~__tree_node_base() = default;
   __tree_node_base(__tree_node_base const&)            = delete;
   __tree_node_base& operator=(__tree_node_base const&) = delete;
 };
@@ -553,10 +562,16 @@ class _LIBCPP_STANDALONE_DEBUG __tree_node : public __tree_node_base<_VoidPtr> {
 public:
   using __node_value_type _LIBCPP_NODEBUG = __get_node_value_type_t<_Tp>;
 
-  __node_value_type __value_;
+  union {
+    __node_value_type __value_;
+  };
 
   _LIBCPP_HIDE_FROM_ABI __node_value_type& __get_value() { return __value_; }
 
+  template <class _Alloc, class... _Args>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_node(_Alloc& __na, _Args&&... __args) {
+    allocator_traits<_Alloc>::construct(__na, std::addressof(__value_), std::forward<_Args>(__args)...);
+  }
   ~__tree_node()                             = delete;
   __tree_node(__tree_node const&)            = delete;
   __tree_node& operator=(__tree_node const&) = delete;
@@ -576,14 +591,15 @@ private:
 public:
   bool __value_constructed;
 
-  _LIBCPP_HIDE_FROM_ABI __tree_node_destructor(const __tree_node_destructor&) = default;
-  __tree_node_destructor& operator=(const __tree_node_destructor&)            = delete;
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node_destructor(const __tree_node_destructor&) = default;
+  _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_node_destructor& operator=(const __tree_node_destructor&)            = delete;
 
-  _LIBCPP_HIDE_FROM_ABI explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT
+  _LIBCPP_HIDE_FROM_ABI
+  _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit __tree_node_destructor(allocator_type& __na, bool __val = false) _NOEXCEPT
       : __na_(__na),
         __value_constructed(__val) {}
 
-  _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void operator()(pointer __p) _NOEXCEPT {
     if (__value_constructed)
       __alloc_traits::destroy(__na_, std::addressof(__p->__value_));
     if (__p)
@@ -619,42 +635,50 @@ public:
   using reference         = value_type&;
   using pointer           = __rebind_pointer_t<_NodePtr, value_type>;
 
-  _LIBCPP_HIDE_FROM_ABI __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {}
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator() _NOEXCEPT : __ptr_(nullptr) {}
 
-  _LIBCPP_HIDE_FROM_ABI reference operator*() const { return __get_np()->__value_; }
-  _LIBCPP_HIDE_FROM_ABI pointer operator->() const { return pointer_traits<pointer>::pointer_to(__get_np()->__value_); }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reference operator*() const { return __get_np()->__value_; }
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pointer operator->() const {
+    return pointer_traits<pointer>::pointer_to(__get_np()->__value_);
+  }
 
-  _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator++() {
-    __ptr_ = std::__tree_next_iter<__end_node_pointer>(static_cast<__node_base_pointer>(__ptr_));
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator& operator++() {
+    __ptr_ = std::__tree_next_iter<__end_node_pointer>(std::__static_fancy_pointer_cast<__node_base_pointer>(__ptr_));
     return *this;
   }
-  _LIBCPP_HIDE_FROM_ABI __tree_iterator operator++(int) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator operator++(int) {
     __tree_iterator __t(*this);
     ++(*this);
     return __t;
   }
 
-  _LIBCPP_HIDE_FROM_ABI __tree_iterator& operator--() {
-    __ptr_ = static_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_));
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator& operator--() {
+    __ptr_ = std::__static_fancy_pointer_cast<__end_node_pointer>(std::__tree_prev_iter<__node_base_pointer>(__ptr_));
     return *this;
   }
-  _LIBCPP_HIDE_FROM_ABI __tree_iterator operator--(int) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __tree_iterator operator--(int) {
     __tree_iterator __t(*this);
     --(*this);
     return __t;
   }
 
-  friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __tree_iterator& __x, const __tree_iterator& __y) {
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool
+  operator==(const __tree_iterator& __x, const __tree_iterator& __y) {
     return __x.__ptr_ == __y.__ptr_;
   }
-  friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __tree_iterator& __x, const __tree_iterator& __y) {
+  friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool
+  operator!=...
[truncated]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++26 libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc++] P3372R3: constexpr map
3 participants