184 Commits

Author SHA1 Message Date
Nikolas Klauser
4304106dc2
Reapply "[libc++] Optimize std::find_if" (#175903) (#175921)
#175913 removed that `__builtin_assume_dereferenceable(ptr, 0)` implies
`ptr != nullptr`, which should allow us to use the builtin with LLVM 23.

This reverts commit 776c09c212e945fdceeae240b42c38df3dd34727.
2026-01-15 10:16:45 +01:00
Nikolas Klauser
776c09c212
Revert "[libc++] Optimize std::find_if" (#175903)
`__builtin_assume_dereferenceable` currently implies that the pointer
given to it is non-null, even if the size is zero. This causes
miscompilations, since we consider [nullptr, nullptr) to be a valid
range.

Reverts llvm/llvm-project#167697
2026-01-14 11:15:21 +01:00
Nikolas Klauser
6189512f73
[libc++] Optimize std::find_if (#167697)
```
Benchmark                       4ecfaa602f56    80d5ac247d34    Difference    % Difference
----------------------------  --------------  --------------  ------------  --------------
bm_find_if_autovectorization         1901.51          306.12      -1595.39         -83.90%
```
2026-01-13 11:13:54 +01:00
Matthias Wippich
617b446176
[libc++] Implement P1789R3: Library Support for Expansion Statements (#167184)
[P1789R3](https://isocpp.org/files/papers/P1789R3.pdf) was accepted for
C++26 through LWG motion 14 at the 2025 Kona meeting. This patch
implements it, along with tests and documentation changes.

Closes #167268

---------

Co-authored-by: Tsche <che@pydong.org>
2025-12-26 09:07:13 +08:00
Hristo Hristov
59fb3bc3e7
[libc++][pair] Applied [[nodiscard]] (#171999)
`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.

- https://libcxx.llvm.org/CodingGuidelines.html
- https://wg21.link/pairs
2025-12-15 10:42:48 +08:00
Hristo Hristov
4125e73cdc
[libc++] Applied [[nodiscard]] to hash<shared_ptr>, hash<unique_ptr>, etc. (#170674)
`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.

- https://libcxx.llvm.org/CodingGuidelines.html


1. `hash<shared_ptr>`, `hash<unique_ptr>`, `std::integer_sequence<>`
etc.
2. Also implements fixes to
https://github.com/llvm/llvm-project/issues/169634 on the go (issues
discovered during current implementation)

---------

Co-authored-by: A. Jiang <de34@live.cn>
Co-authored-by: Hristo Hristov <zingam@outlook.com>
2025-12-08 06:56:33 +02:00
Nikolas Klauser
c2a0350d86
[libc++] Simplify a few places where we use __index_sequence (#167213)
This is done in two ways:
1) `index_sequence_for` is back-ported as `__index_sequence_for`
2) Extra functions just to expand the parameter pack are replaced with
lambdas
2025-12-02 15:02:04 +01:00
Hristo Hristov
8706d82bd4
[libc++] Applied [[nodiscard]] to Language Support (partially) (#169611)
https://wg21.link/#support

`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.

- https://libcxx.llvm.org/CodingGuidelines.html#apply-nodiscard-where-relevant

The following was implemented in this patch:

- [x] `<compare>`
- [x] `<corotine>`
- [x] `<initializer_list>`
- [x] Integer comparisons

---------

Co-authored-by: Hristo Hristov <zingam@outlook.com>
Co-authored-by: A. Jiang <de34@live.cn>
2025-11-26 22:17:38 +02:00
Louis Dionne
17ce48f2b6
[libc++] Remove __is_replaceable emulation (#167355)
The Trivial Relocation feature has been removed from the C++26 working
draft. Based on discussions in Kona, it is unlikely that the
"replaceable" type concept will come back in the C++29 time frame.

Since we don't have a use for the type trait in the library at the
moment, remove the code associated to it. If we end up needing something
like it in the future, we can always add it back.
2025-11-11 07:53:56 -05:00
kisuhorikka
95eb2db232
[libc++] std::cmp_less and other integer comparison functions could be improved (#151332)
Fix #65136 

|Benchmark | Baseline | Candidate | Difference | % Difference
|------------------------- | ---------- | ----------- | ------------ |
--------------
|BM_CmpEqual_int_int | 0.46 | 0.46 | -0.00 | -0.62
|BM_CmpEqual_int_schar | 0.45 | 0.45 | -0.00 | -0.40
|BM_CmpEqual_int_short | 0.45 | 0.45 | 0.00 | 0.34
|BM_CmpEqual_int_uchar | 0.78 | 0.44 | -0.34 | -43.18
|BM_CmpEqual_int_uint | 0.90 | 0.66 | -0.24 | -26.84
|BM_CmpEqual_int_ushort | 0.78 | 0.45 | -0.33 | -42.20
|BM_CmpEqual_schar_int | 0.45 | 0.45 | -0.00 | -0.77
|BM_CmpEqual_schar_schar | 0.54 | 0.57 | 0.03 | 5.64
|BM_CmpEqual_schar_short | 0.92 | 0.88 | -0.04 | -4.80
|BM_CmpEqual_schar_uchar | 1.84 | 0.66 | -1.18 | -64.16
|BM_CmpEqual_schar_uint | 0.78 | 0.66 | -0.12 | -15.18
|BM_CmpEqual_schar_ushort | 1.01 | 0.66 | -0.35 | -34.53
|BM_CmpEqual_short_int | 0.45 | 0.45 | 0.00 | 0.03
|BM_CmpEqual_short_schar | 0.89 | 0.88 | -0.01 | -0.80
|BM_CmpEqual_short_short | 0.47 | 0.46 | -0.01 | -1.28
|BM_CmpEqual_short_uchar | 1.11 | 0.66 | -0.45 | -40.63
|BM_CmpEqual_short_uint | 0.77 | 0.66 | -0.12 | -14.88
|BM_CmpEqual_short_ushort | 1.76 | 0.66 | -1.10 | -62.64
|BM_CmpEqual_uchar_int | 0.79 | 0.44 | -0.35 | -44.06
|BM_CmpEqual_uchar_schar | 1.76 | 0.66 | -1.11 | -62.68
|BM_CmpEqual_uchar_short | 1.11 | 0.66 | -0.45 | -40.33
|BM_CmpEqual_uchar_uchar | 0.57 | 0.51 | -0.06 | -10.61
|BM_CmpEqual_uchar_uint | 0.45 | 0.44 | -0.01 | -1.74
|BM_CmpEqual_uchar_ushort | 0.77 | 0.77 | -0.00 | -0.64
|BM_CmpEqual_uint_int | 0.88 | 0.66 | -0.23 | -25.69
|BM_CmpEqual_uint_schar | 0.77 | 0.66 | -0.11 | -14.85
|BM_CmpEqual_uint_short | 0.77 | 0.66 | -0.11 | -14.56
|BM_CmpEqual_uint_uchar | 0.44 | 0.44 | -0.00 | -0.57
|BM_CmpEqual_uint_uint | 0.47 | 0.51 | 0.04 | 8.62
|BM_CmpEqual_uint_ushort | 0.45 | 0.44 | -0.00 | -0.47
|BM_CmpEqual_ushort_int | 0.77 | 0.45 | -0.33 | -42.02
|BM_CmpEqual_ushort_schar | 1.02 | 0.66 | -0.36 | -35.30
|BM_CmpEqual_ushort_short | 1.76 | 0.66 | -1.10 | -62.60
|BM_CmpEqual_ushort_uchar | 0.78 | 0.77 | -0.01 | -1.84
|BM_CmpEqual_ushort_uint | 0.45 | 0.45 | 0.00 | 0.24
|BM_CmpEqual_ushort_ushort | 0.46 | 0.51 | 0.05 | 11.00
|BM_CmpLess_int_int | 0.67 | 0.66 | -0.01 | -0.99
|BM_CmpLess_int_schar | 0.66 | 0.66 | -0.01 | -0.86
|BM_CmpLess_int_short | 0.66 | 0.66 | -0.00 | -0.57
|BM_CmpLess_int_uchar | 0.88 | 0.66 | -0.23 | -25.48
|BM_CmpLess_int_uint | 1.76 | 0.66 | -1.11 | -62.68
|BM_CmpLess_int_ushort | 0.89 | 0.66 | -0.23 | -25.50
|BM_CmpLess_schar_int | 0.66 | 0.66 | -0.00 | -0.44
|BM_CmpLess_schar_schar | 0.66 | 0.66 | -0.00 | -0.40
|BM_CmpLess_schar_short | 0.88 | 0.88 | -0.00 | -0.50
|BM_CmpLess_schar_uchar | 1.10 | 0.71 | -0.39 | -35.24
|BM_CmpLess_schar_uint | 0.89 | 0.66 | -0.23 | -25.66
|BM_CmpLess_schar_ushort | 0.99 | 0.77 | -0.22 | -22.49
|BM_CmpLess_short_int | 0.66 | 0.66 | -0.00 | -0.35
|BM_CmpLess_short_schar | 0.89 | 0.88 | -0.00 | -0.48
|BM_CmpLess_short_short | 0.66 | 0.66 | -0.00 | -0.34
|BM_CmpLess_short_uchar | 1.10 | 0.71 | -0.39 | -35.36
|BM_CmpLess_short_uint | 0.88 | 0.66 | -0.22 | -25.39
|BM_CmpLess_short_ushort | 1.77 | 0.77 | -1.00 | -56.42
|BM_CmpLess_uchar_int | 0.97 | 0.66 | -0.31 | -31.95
|BM_CmpLess_uchar_schar | 1.11 | 0.66 | -0.44 | -40.17
|BM_CmpLess_uchar_short | 1.19 | 0.66 | -0.53 | -44.59
|BM_CmpLess_uchar_uchar | 0.66 | 0.66 | -0.00 | -0.67
|BM_CmpLess_uchar_uint | 0.67 | 0.66 | -0.01 | -1.19
|BM_CmpLess_uchar_ushort | 0.77 | 0.77 | -0.00 | -0.40
|BM_CmpLess_uint_int | 1.76 | 0.66 | -1.10 | -62.59
|BM_CmpLess_uint_schar | 0.89 | 0.66 | -0.23 | -25.99
|BM_CmpLess_uint_short | 0.88 | 0.66 | -0.22 | -25.41
|BM_CmpLess_uint_uchar | 0.66 | 0.66 | -0.01 | -0.81
|BM_CmpLess_uint_uint | 0.66 | 0.66 | -0.00 | -0.71
|BM_CmpLess_uint_ushort | 0.66 | 0.66 | -0.00 | -0.29
|BM_CmpLess_ushort_int | 0.98 | 0.66 | -0.32 | -33.00
|BM_CmpLess_ushort_schar | 1.29 | 0.77 | -0.52 | -40.56
|BM_CmpLess_ushort_short | 1.77 | 0.77 | -1.00 | -56.55
|BM_CmpLess_ushort_uchar | 0.77 | 0.77 | -0.01 | -0.72
|BM_CmpLess_ushort_uint | 0.66 | 0.66 | -0.00 | -0.46
|BM_CmpLess_ushort_ushort | 0.66 | 0.66 | -0.00 | -0.71
2025-10-16 16:44:09 +08:00
Nikolas Klauser
446d950524
[libc++] Use std::__{scope,exception}_guard throughout the code base (#161322)
This simplifies the code quite a bit and seems to improve code size
slightly in some cases.
2025-10-09 09:32:40 +02:00
halbi2
b9e41ae6f9
[clang][libc++] Fix spelling of "synthesize" (#158523)
There is a tradition to use U.S. English spellings for APIs. For
example, it's uninitialized_fill and not uninitialised_fill,
specialization not specialisation, etcetera.
2025-09-30 08:29:59 +02:00
Nikolas Klauser
53a4e4a77b
[libc++] Specialize __lazy_synth_three_way_comparator for std::greater and friends (#157624)
This specializes `__lazy_synth_three_way_comparator` to forward to
`__default_three_way_comparator` if the comparator desugars to
`__greater_tag`. This is the same as the desugaring to `__less_tag`
except that the sign has to be inverted.
2025-09-15 15:56:15 +02:00
Nikolas Klauser
4884d6cbce
[libc++] Extend __default_three_way_comparator to any types that only implements operator<=> (#157602)
This uses the new `__builtin_lt_synthesises_from_spaceship` builtin from
clang to use three way comparison for arbitrary user-defined types that
only provide a spaceship operator.
2025-09-12 10:57:34 +02:00
Nikolas Klauser
1d131ffff8
[libc++] Optimize most of the __tree search algorithms (#155245)
This patch introduces a new comparator, namely `__lazy_synth_three_way`,
which tries to provide an efficient three way comparator for known types
and falls back to using the provided comparator if it doesn't know how
to do that. Currently, an efficient three way comparison is only
provided when using one of the `less` comparions object from the
standard library and `std::string`. This will be extended in future
patches.

```
------------------------------------------------------------------------------------------------------------------------------
Benchmark                                                                                                  old             new
------------------------------------------------------------------------------------------------------------------------------
std::map<std::string, int>::ctor(const&)/0                                                             12.6 ns         12.6 ns
std::map<std::string, int>::ctor(const&)/32                                                             858 ns          837 ns
std::map<std::string, int>::ctor(const&)/1024                                                         46700 ns        46739 ns
std::map<std::string, int>::ctor(const&)/8192                                                        458100 ns       449806 ns
std::map<std::string, int>::ctor(iterator, iterator) (unsorted sequence)/0                             12.8 ns         12.7 ns
std::map<std::string, int>::ctor(iterator, iterator) (unsorted sequence)/32                            1286 ns         1266 ns
std::map<std::string, int>::ctor(iterator, iterator) (unsorted sequence)/1024                         93812 ns        84686 ns
std::map<std::string, int>::ctor(iterator, iterator) (unsorted sequence)/8192                       1480346 ns      1385924 ns
std::map<std::string, int>::ctor(iterator, iterator) (sorted sequence)/0                               12.9 ns         12.8 ns
std::map<std::string, int>::ctor(iterator, iterator) (sorted sequence)/32                              1044 ns         1055 ns
std::map<std::string, int>::ctor(iterator, iterator) (sorted sequence)/1024                           63071 ns        62861 ns
std::map<std::string, int>::ctor(iterator, iterator) (sorted sequence)/8192                          595046 ns       590223 ns
std::map<std::string, int>::operator=(const&) (into cleared Container)/0                               13.6 ns         13.6 ns
std::map<std::string, int>::operator=(const&) (into cleared Container)/32                               880 ns          911 ns
std::map<std::string, int>::operator=(const&) (into cleared Container)/1024                           48627 ns        47808 ns
std::map<std::string, int>::operator=(const&) (into cleared Container)/8192                          458552 ns       454497 ns
std::map<std::string, int>::operator=(const&) (into partially populated Container)/0                   13.8 ns         13.6 ns
std::map<std::string, int>::operator=(const&) (into partially populated Container)/32                   864 ns          851 ns
std::map<std::string, int>::operator=(const&) (into partially populated Container)/1024               49483 ns        49555 ns
std::map<std::string, int>::operator=(const&) (into partially populated Container)/8192              456977 ns       457894 ns
std::map<std::string, int>::operator=(const&) (into populated Container)/0                             1.31 ns         1.31 ns
std::map<std::string, int>::operator=(const&) (into populated Container)/32                             425 ns          415 ns
std::map<std::string, int>::operator=(const&) (into populated Container)/1024                         14248 ns        14225 ns
std::map<std::string, int>::operator=(const&) (into populated Container)/8192                        136684 ns       133696 ns
std::map<std::string, int>::insert(value) (already present)/0                                          21.5 ns         16.2 ns
std::map<std::string, int>::insert(value) (already present)/32                                         22.7 ns         25.1 ns
std::map<std::string, int>::insert(value) (already present)/1024                                       54.5 ns         29.1 ns
std::map<std::string, int>::insert(value) (already present)/8192                                       78.4 ns         30.4 ns
std::map<std::string, int>::insert(value) (new value)/0                                                40.9 ns         39.0 ns
std::map<std::string, int>::insert(value) (new value)/32                                               58.3 ns         47.2 ns
std::map<std::string, int>::insert(value) (new value)/1024                                              120 ns         71.3 ns
std::map<std::string, int>::insert(value) (new value)/8192                                              157 ns          129 ns
std::map<std::string, int>::insert(hint, value) (good hint)/0                                          40.3 ns         40.7 ns
std::map<std::string, int>::insert(hint, value) (good hint)/32                                         48.0 ns         30.0 ns
std::map<std::string, int>::insert(hint, value) (good hint)/1024                                        107 ns         63.2 ns
std::map<std::string, int>::insert(hint, value) (good hint)/8192                                        132 ns          107 ns
std::map<std::string, int>::insert(hint, value) (bad hint)/0                                           27.0 ns         40.9 ns
std::map<std::string, int>::insert(hint, value) (bad hint)/32                                          68.3 ns         58.4 ns
std::map<std::string, int>::insert(hint, value) (bad hint)/1024                                         125 ns         82.0 ns
std::map<std::string, int>::insert(hint, value) (bad hint)/8192                                         155 ns          150 ns
std::map<std::string, int>::insert(iterator, iterator) (all new keys)/0                                 404 ns          405 ns
std::map<std::string, int>::insert(iterator, iterator) (all new keys)/32                               2004 ns         1805 ns
std::map<std::string, int>::insert(iterator, iterator) (all new keys)/1024                           102820 ns        76102 ns
std::map<std::string, int>::insert(iterator, iterator) (all new keys)/8192                          1144590 ns       949266 ns
std::map<std::string, int>::insert(iterator, iterator) (half new keys)/0                                408 ns          404 ns
std::map<std::string, int>::insert(iterator, iterator) (half new keys)/32                              1592 ns         1377 ns
std::map<std::string, int>::insert(iterator, iterator) (half new keys)/1024                           74847 ns        53921 ns
std::map<std::string, int>::insert(iterator, iterator) (half new keys)/8192                          828505 ns       698716 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from same type)/0              407 ns          407 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from same type)/32            1584 ns         1557 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from same type)/1024         47157 ns        47443 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from same type)/8192        623887 ns       628385 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from zip_view)/0               405 ns          403 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from zip_view)/32             1478 ns         1510 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from zip_view)/1024          47852 ns        47835 ns
std::map<std::string, int>::insert(iterator, iterator) (product_iterator from zip_view)/8192         605311 ns       606951 ns
std::map<std::string, int>::erase(key) (existent)/0                                                     129 ns         94.0 ns
std::map<std::string, int>::erase(key) (existent)/32                                                    110 ns          106 ns
std::map<std::string, int>::erase(key) (existent)/1024                                                  121 ns          128 ns
std::map<std::string, int>::erase(key) (existent)/8192                                                  165 ns         66.9 ns
std::map<std::string, int>::erase(key) (non-existent)/0                                               0.269 ns        0.257 ns
std::map<std::string, int>::erase(key) (non-existent)/32                                               21.9 ns         11.3 ns
std::map<std::string, int>::erase(key) (non-existent)/1024                                             53.5 ns         25.4 ns
std::map<std::string, int>::erase(key) (non-existent)/8192                                             67.3 ns         31.9 ns
std::map<std::string, int>::erase(iterator)/0                                                          46.3 ns         46.7 ns
std::map<std::string, int>::erase(iterator)/32                                                         44.4 ns         41.8 ns
std::map<std::string, int>::erase(iterator)/1024                                                       43.7 ns         46.4 ns
std::map<std::string, int>::erase(iterator)/8192                                                       45.2 ns         44.1 ns
std::map<std::string, int>::erase(iterator, iterator) (erase half the container)/0                      407 ns          407 ns
std::map<std::string, int>::erase(iterator, iterator) (erase half the container)/32                     876 ns          906 ns
std::map<std::string, int>::erase(iterator, iterator) (erase half the container)/1024                 20880 ns        20444 ns
std::map<std::string, int>::erase(iterator, iterator) (erase half the container)/8192                252881 ns       241583 ns
std::map<std::string, int>::clear()/0                                                                   407 ns          408 ns
std::map<std::string, int>::clear()/32                                                                 1252 ns         1323 ns
std::map<std::string, int>::clear()/1024                                                              38488 ns        38017 ns
std::map<std::string, int>::clear()/8192                                                             416492 ns       428534 ns
std::map<std::string, int>::find(key) (existent)/0                                                    0.008 ns        0.008 ns
std::map<std::string, int>::find(key) (existent)/32                                                    33.9 ns         15.3 ns
std::map<std::string, int>::find(key) (existent)/1024                                                  43.0 ns         25.5 ns
std::map<std::string, int>::find(key) (existent)/8192                                                  44.6 ns         29.3 ns
std::map<std::string, int>::find(key) (non-existent)/0                                                0.259 ns        0.257 ns
std::map<std::string, int>::find(key) (non-existent)/32                                                22.6 ns         11.4 ns
std::map<std::string, int>::find(key) (non-existent)/1024                                              48.6 ns         25.1 ns
std::map<std::string, int>::find(key) (non-existent)/8192                                              64.1 ns         31.1 ns
std::map<std::string, int>::count(key) (existent)/0                                                   0.008 ns        0.008 ns
std::map<std::string, int>::count(key) (existent)/32                                                   32.2 ns         17.3 ns
std::map<std::string, int>::count(key) (existent)/1024                                                 42.4 ns         25.3 ns
std::map<std::string, int>::count(key) (existent)/8192                                                 44.4 ns         31.6 ns
std::map<std::string, int>::count(key) (non-existent)/0                                               0.260 ns        0.259 ns
std::map<std::string, int>::count(key) (non-existent)/32                                               22.9 ns         11.3 ns
std::map<std::string, int>::count(key) (non-existent)/1024                                             49.8 ns         25.5 ns
std::map<std::string, int>::count(key) (non-existent)/8192                                             66.3 ns         31.9 ns
std::map<std::string, int>::contains(key) (existent)/0                                                0.008 ns        0.008 ns
std::map<std::string, int>::contains(key) (existent)/32                                                31.4 ns         18.0 ns
std::map<std::string, int>::contains(key) (existent)/1024                                              44.3 ns         26.5 ns
std::map<std::string, int>::contains(key) (existent)/8192                                              47.4 ns         30.2 ns
std::map<std::string, int>::contains(key) (non-existent)/0                                            0.452 ns        0.441 ns
std::map<std::string, int>::contains(key) (non-existent)/32                                            23.1 ns         11.5 ns
std::map<std::string, int>::contains(key) (non-existent)/1024                                          46.2 ns         26.3 ns
std::map<std::string, int>::contains(key) (non-existent)/8192                                          63.4 ns         31.4 ns
std::map<std::string, int>::lower_bound(key) (existent)/0                                             0.008 ns        0.008 ns
std::map<std::string, int>::lower_bound(key) (existent)/32                                             17.2 ns         19.0 ns
std::map<std::string, int>::lower_bound(key) (existent)/1024                                           27.1 ns         26.2 ns
std::map<std::string, int>::lower_bound(key) (existent)/8192                                           34.0 ns         36.0 ns
std::map<std::string, int>::lower_bound(key) (non-existent)/0                                         0.259 ns        0.257 ns
std::map<std::string, int>::lower_bound(key) (non-existent)/32                                         11.6 ns         11.5 ns
std::map<std::string, int>::lower_bound(key) (non-existent)/1024                                       24.8 ns         25.6 ns
std::map<std::string, int>::lower_bound(key) (non-existent)/8192                                       31.7 ns         31.6 ns
std::map<std::string, int>::upper_bound(key) (existent)/0                                             0.008 ns        0.008 ns
std::map<std::string, int>::upper_bound(key) (existent)/32                                             18.8 ns         19.7 ns
std::map<std::string, int>::upper_bound(key) (existent)/1024                                           25.3 ns         27.7 ns
std::map<std::string, int>::upper_bound(key) (existent)/8192                                           30.2 ns         29.9 ns
std::map<std::string, int>::upper_bound(key) (non-existent)/0                                         0.260 ns        0.259 ns
std::map<std::string, int>::upper_bound(key) (non-existent)/32                                         11.3 ns         12.0 ns
std::map<std::string, int>::upper_bound(key) (non-existent)/1024                                       25.6 ns         25.9 ns
std::map<std::string, int>::upper_bound(key) (non-existent)/8192                                       33.1 ns         34.2 ns
std::map<std::string, int>::equal_range(key) (existent)/0                                             0.008 ns        0.008 ns
std::map<std::string, int>::equal_range(key) (existent)/32                                             33.5 ns         15.8 ns
std::map<std::string, int>::equal_range(key) (existent)/1024                                           43.0 ns         25.1 ns
std::map<std::string, int>::equal_range(key) (existent)/8192                                           54.1 ns         30.7 ns
std::map<std::string, int>::equal_range(key) (non-existent)/0                                         0.265 ns        0.259 ns
std::map<std::string, int>::equal_range(key) (non-existent)/32                                         22.1 ns         12.1 ns
std::map<std::string, int>::equal_range(key) (non-existent)/1024                                       44.8 ns         24.4 ns
std::map<std::string, int>::equal_range(key) (non-existent)/8192                                       62.2 ns         40.1 ns
```

Fixes #66577
2025-09-08 09:56:14 +02:00
Nikolas Klauser
823e44401a
Reapply "[libc++] Refactor key extraction for __hash_table and __tree (#154512)" (#155565)
The original PR has been reverted because of an LLDB test failure. This
patch now works around the test failure by simply allowing the new
symbols to show up in a stack trace.

This reverts commit 72c04bb882ad70230bce309c3013d9cc2c99e9a7.

Original commit message:

This patch replaces `__can_extract_key` with an overload set to try to
extract the key. This simplifies the code, since we don't need to have
separate overload sets for the unordered and associative containers. It
also allows extending the set of extraction cases more easily, since we
have a single place to define how the key is extracted.
2025-08-27 14:38:14 +02:00
Aiden Grossman
72c04bb882 Revert "[libc++] Refactor key extraction for __hash_table and __tree (#154512)"
This reverts commit af1f06e41b05c267480f1629dc0fcdf18f3b59f6.

This is causing some build failures in premerge as some of the LLDB
tests fail.
2025-08-26 16:13:56 +00:00
Nikolas Klauser
af1f06e41b
[libc++] Refactor key extraction for __hash_table and __tree (#154512)
This patch replaces `__can_extract_key` with an overload set to try to
extract the key. This simplifies the code, since we don't need to have
separate overload sets for the unordered and associative containers. It
also allows extending the set of extraction cases more easily, since we
have a single place to define how the key is extracted.
2025-08-26 16:26:59 +02:00
Nikolas Klauser
3c4bad0504
[libc++] Remove a few incorrect _LIBCPP_EXPORTED_FROM_ABI annotations (#132602)
This has two benefits:
- It is less likely that the macro will be copy-pasted around when
unnecessary
- We can drop `_LIBCPP_HIDE_FROM_ABI` from any member functions once we
are able to make `_LIBCPP_HIDE_FROM_ABI` the default within libc++
2025-08-26 08:04:28 +02:00
Nikolas Klauser
6c257754d9
[libc++] Refactor internal index_sequence API to match the public one (#149475)
The internal API is a lot more complicated than it actually needs to be.
This refactors the internal API to match the features and names of the
public one.
2025-07-20 11:23:31 +02:00
Nikolas Klauser
79a2b15a4c
[libc++] Remove a few workarounds for old Clang versions (#143858) 2025-06-16 11:12:15 +02:00
Nikolas Klauser
3c56437eaf
[libc++] Refactor signed/unsigned integer traits (#142750)
This patch does a few things:
- `__libcpp_is_signed_integer` and `__libcpp_is_unsigned_integer` are
refactored to be variable templates instead of class templates.
- the two traits are merged into a single header
`<__type_traits/integer_traits.h>`.
- `__libcpp_signed_integer`, `__libcpp_unsigned_integer` and
`__libcpp_integer` are moved into the same header.
- The above mentioned concepts are renamed to `__signed_integer`,
`__unsigned_integer` and `__signed_or_unsigned_integer` respectively.
2025-06-11 14:31:13 +02:00
Nikolas Klauser
c8f2cdafd4
[libc++] Simplify the implementation of std::get for pairs (#114984)
This makes it clearer what the functions actually do. As a nice
side-effect it also avoids a function call. If the C++03 header split is
successful we could drop `__get_pair` entirely.
2025-05-12 22:40:17 +02:00
Louis Dionne
45d493b680
[libc++] Add the __is_replaceable type trait (#132408)
That type trait represents whether move-assigning an object is
equivalent to destroying it and then move-constructing a new one from
the same argument. This will be useful in a few places where we may want
to destroy + construct instead of doing an assignment, in particular
when implementing some container operations in terms of relocation.

This is effectively adding a library emulation of P2786R12's
is_replaceable trait, similarly to what we do for trivial relocation.
Eventually, we can replace this library emulation by the real
compiler-backed trait.

This is building towards #129328.
2025-05-08 16:35:00 -04:00
Hristo Hristov
4ed8f38e81
[libc++][pair] P2944R3: Constrain std::pair's equality operator (#136672)
Implements https://wg21.link/P2944R3 (partially):
- [pairs.spec](https://eel.is/c++draft/pairs.spec)

Related issues:
- Related to #105424
- Related to #118135
  - PR https://github.com/llvm/llvm-project/pull/135759
  - PR https://github.com/llvm/llvm-project/pull/117664

Closes: [#136763](https://github.com/llvm/llvm-project/issues/136763)

# References
- https://eel.is/c++draft/concept.booleantestable
- https://eel.is/c++draft/concept.equalitycomparable

---------

Co-authored-by: Hristo Hristov <zingam@outlook.com>
Co-authored-by: Nikolas Klauser <nikolasklauser@berlin.de>
2025-04-29 22:00:16 +03:00
A. Jiang
06de4d52d5
[libc++] Properly decay functions in CTAD for pair (#134544)
This patch makes instantiation of `pair` in CTAD a bit lazier to avoid
instantiating invalid `pair` specialization before the decaying explicit
deduction guide works.
2025-04-19 10:01:48 +08:00
Nikolas Klauser
4e0876ee43
[libc++] Use __underlying_type directly in underyling_type_t (#135423)
This avoids instantiating multiple classes, reducing compile times. This
patch also introduces `__underyling_type_t` for internal use, similar to
other type traits.
2025-04-13 11:01:17 +02:00
Nikolas Klauser
af9c04fa68
[libc++] Remove _LIBCPP_TEMPLATE_VIS (#134885)
The need for `_LIBCPP_TEMPLATE_VIS` has been removed in #133233.
2025-04-09 23:47:57 +02:00
Nikolas Klauser
fb44f00641
[libc++] Add [[gnu::nodebug]] on type traits (#128502) 2025-03-23 21:01:25 +01:00
Hui
5bc8db884e
[libc++][NFC] fix exception_guard include guard name (#131370) 2025-03-15 16:14:44 +00:00
Nikolas Klauser
29dde55c5d
[libc++] Remove a few unused includes in <utility> headers (#129674) 2025-03-04 16:09:13 +01:00
Louis Dionne
cedb44af53
[libc++] Pass type information down to __libcpp_allocate (#118837)
Currently, places where we call __libcpp_allocate must drop type
information on the ground even when they actually have such information
available. That is unfortunate since some toolchains and system
allocators are able to provide improved security when they know what
type is being allocated.

This is the purpose of http://wg21.link/p2719, where we introduce a new
variant of `operator new` which takes a type in its interface. A
different but related issue is that `std::allocator` does not honor any
in-class `T::operator new` since it is specified to call the global
`::operator new` instead.

This patch closes the gap to make it trivial for implementations that
provide typed memory allocators to actually benefit from that
information in more contexts, and also makes libc++ forward-compatible
with future proposals that would fix the existing defects in
`std::allocator`. It also makes the internal allocation API higher level
by operating on objects instead of operating on bytes of memory.

Since this is a widely-used function and making this a template could
have an impact on debug info sizes, I tried minimizing the number of
templated layers by removing `__do_deallocate_handle_size`, which was
easy to replace with a macro (and IMO this leads to cleaner code).
2025-01-13 09:10:36 -05:00
Nikolas Klauser
f69585235e
[libc++] Put _LIBCPP_NODEBUG on all internal aliases (#118710)
This significantly reduces the amount of debug information generated
for codebases using libc++, without hurting the debugging experience.
2025-01-08 11:12:59 -05:00
Nikolas Klauser
ef2afa1e83
[libc++] Simplify unwrap_ref_decay a bit (#121623) 2025-01-06 12:12:40 +01:00
Nikolas Klauser
3b8faee6c6
[libc++] Switch _LIBCPP_NODEBUG to [[gnu::nodebug]] (#120720)
This makes the placement of the attribute more consistent. This also
avoids clang dropping the attribute silently (see #120722).
2024-12-22 00:55:35 +01:00
Nikolas Klauser
59890c1334
[libc++] Granularize <new> includes (#119964) 2024-12-17 11:29:16 +01:00
Nikolas Klauser
6157dbe48c
[libc++] Introduce __forward_as (#118168)
This allows forwarding an object as a specific type. This is usually
useful when using `deducing this` to avoid calling any functions in a
deriving class.
2024-12-14 15:09:16 +01:00
Louis Dionne
9474e09459
[libc++] Granularize the <new> header (#119270)
This disentangles the code which previously had a mix of many #ifdefs, a
non-versioned namespace and a versioned namespace. It also makes it
clearer which parts of <new> are implemented on Windows by including <new.h>.
2024-12-13 14:17:56 -05:00
Nikolas Klauser
adb80d8a4c
[libc++] Address post-commit comments for __scope_guard (#116291)
Fixes #116204
2024-11-16 19:23:58 +01:00
Nikolas Klauser
5098b56d22
[libc++] Introduce a standalone __scope_guard and use it in <string> (#114867)
This introduces a new `__scope_guard` without any fancy features. The
scope guard is used in `<string>` to simplify some of the ASan
annotations (especially by making it harder to forget them where
exceptions are thrown).
2024-11-12 00:00:34 +01:00
Nikolas Klauser
2c10664afa
[libc++][NFC] Merge add_{const, cv, volatile}.h into a single header (#115610)
There isn't much benefit in having granular headers for only a few
simple lines of code.
2024-11-10 13:21:42 +01:00
Zibi Sarbinowski
ef73533f36
[z/OS][libc++] Remove align_val_t dependency in small_buffer.h (#114396)
Rewriting `__alloc()` and `__dealloc()` template functions to avoid errors when `small_buffer.h` is
included in the modules LIT tests. For example:

```
test-suite-install/include/c++/v1/__utility/small_buffer.h:69:81: error: use of undeclared identifier 'align_val_t'
# |    69 |       byte* __allocation = static_cast<byte*>(::operator new[](sizeof(_Stored), align_val_t{alignof(_Stored)}));
# |       |                                                                                 ^
```
2024-11-07 13:44:49 -05:00
Nikolas Klauser
7bc10b920a
[libc++] Remove a few includes from pair.h (#114708) 2024-11-04 14:01:54 +01:00
Nikolas Klauser
33af68a476
[libc++] Add a few _LIBCPP_ASSERT_INTERNALs to make sure internal invariants are kept (#114575)
This can make it significanly easier to find bugs when working on
string.
2024-11-03 15:57:58 +01:00
Nikolas Klauser
e99c4906e4
[libc++] Granularize <cstddef> includes (#108696) 2024-10-31 02:20:10 +01:00
Hui
0be1883c36
[libc++] Implement P0429R9 std::flat_map (#98643)
Around half of the tests are based on the tests Arthur O'Dwyer's
original implementation of std::flat_map, with modifications and
removals.

partially implement #105190
2024-10-26 18:58:53 +01:00
Nikolas Klauser
ba87515fea
[libc++][RFC] Always define internal feature test macros (#89178)
Currently, the library-internal feature test macros are only defined if
the feature is not available, and always have the prefix
`_LIBCPP_HAS_NO_`. This patch changes that, so that they are always
defined and have the prefix `_LIBCPP_HAS_` instead. This changes the
canonical use of these macros to `#if _LIBCPP_HAS_FEATURE`, which means
that using an undefined macro (e.g. due to a missing include) is
diagnosed now. While this is rather unlikely currently, a similar change
in `<__configuration/availability.h>` caught a few bugs. This also
improves readability, since it removes the double-negation of `#ifndef
_LIBCPP_HAS_NO_FEATURE`.

The current patch only touches the macros defined in `<__config>`. If
people are happy with this approach, I'll make a follow-up PR to also
change the macros defined in `<__config_site>`.
2024-10-12 09:49:52 +02:00
Nikolas Klauser
17e0686ab1
[libc++][NFC] Use [[__nodiscard__]] unconditionally (#80454)
`__has_cpp_attribute(__nodiscard__)` is always true now, so we might as
well replace `_LIBCPP_NODISCARD`. It's one less macro that can result in
bad diagnostics.
2024-09-12 21:18:43 +02:00
Nikolas Klauser
748023dc32
[libc++][NFC] Replace _LIBCPP_NORETURN and TEST_NORETURN with [[noreturn]] (#80455)
`[[__noreturn__]]` is now always available, so we can simply use the
attribute directly instead of through a macro.
2024-09-11 08:59:46 +02:00
Louis Dionne
d6832a611a
[libc++][modules] Modularize <cstddef> (#107254)
Many headers include `<cstddef>` just for size_t, and pulling in
additional content (e.g. the traits used for std::byte) is unnecessary.
To solve this problem, this patch splits up `<cstddef>` into
subcomponents so that headers can include only the parts that they
actually require.

This has the added benefit of making the modules build a lot stricter
with respect to IWYU, and also providing a canonical location where we
define `std::size_t` and friends (which were previously defined in
multiple headers like `<cstddef>` and `<ctime>`).

After this patch, there's still many places in the codebase where we
include `<cstddef>` when `<__cstddef/size_t.h>` would be sufficient.
This patch focuses on removing `<cstddef>` includes from __type_traits
to make these headers non-circular with `<cstddef>`. Additional
refactorings can be tackled separately.
2024-09-05 08:28:33 -04:00