465 Commits

Author SHA1 Message Date
A. Jiang
26ee552ef5
[libc++] Fix includes in <string> for no-wchar_t modes (#187650)
Since befaa35212dbaac39cd76a8dc748e4df7c90a0d9, the CI stably failed for
the generic-no-wide-characters build, because in no-`wchar_t` modes, the
header for `__remove_cv_t` wasn't properly included.

This PR adds the missing include of `<__type_traits/remove_cv.h>`.

As drive-by, `<__cstddef/size_t.h>` and
`<__type_traits/is_constant_evaluated.h>`, which are included by
`<cwchar>`, are also made included by `<string>` to avoid potential
regression as we're using `size_t` and
`__libcpp_is_constant_evaluated()` in `<string>`.
2026-03-22 20:29:25 +08:00
Nikolas Klauser
befaa35212
[libc++] Fix passing through object to comparisons in __tree (#186341)
Fixes #180659
2026-03-18 14:23:01 -04:00
Nikolas Klauser
e830ee8006
[libc++] Don't double-wrap iterators when bounded iterators are used (#182264)
There is no reason to double-wrap iterators, since we can already
achieve anything we want within `__bounded_iter`itself.

This is technically ABI breaking, but people using bounded iterators
shouldn't require ABI stability currently.

Fixes #178521
2026-03-07 09:12:25 +01:00
Vitaly Buka
fb7d25556a
[libc++][string] Replace ASAN volatile wrapper with memory barrier (#184693)
The previous `_LIBCPP_ASAN_VOLATILE_WRAPPER` approach was used to
prevent
speculative loads of string data before the short/long state was
determined. This patch replaces that mechanism with a more explicit
`__annotate_memory_barrier()` using an empty volatile assembly block.

This PR is inspired by #183457 and by downstream false positive on
`__get_long_size`. It fails same way as `__get_long_pointer` before we
have
`_LIBCPP_ASAN_VOLATILE_WRAPPER`. Barrier approach avoids
expanding `_LIBCPP_ASAN_VOLATILE_WRAPPER` for size_t, and to
in general looks more readable.

I failed to create reasonable reproducer for test, I suspect it requires
precise set of compiler flags, and libc++ site_config which will be hard
to maintain in test.
2026-03-05 21:09:53 -08:00
Nikolas Klauser
8fcb60aa47
[libc++][NFC] Introduce __data() to std::string to replace std::__to_address(__get_pointer()) (#178212)
`std::__to_address(__get_pointer())` is an extremely common pattern
inside `string` and is basically equivalent to `data()`, except that
`data()` only returns a non-const pointer since C++17. This patch
introduces `__data()` to back-port returning a non-const pointer.
2026-03-04 10:19:34 +01:00
Louis Dionne
20014885c3
[libc++] Honor __SANITIZER_DISABLE_CONTAINER_OVERFLOW__ in libc++ (#168955)
Address sanitizer recently got a new macro __SANITIZER_DISABLE_CONTAINER_OVERFLOW__
which is intended to disable container overflow checks in libraries (either the
standard library or user libraries that might provide such checks). This patch makes
libc++ honor that macro and, in addition, cleans up how these checks are enabled for
string (which is special) by introducing a macro just for string.

rdar://166234942
2026-01-27 16:04:03 +00:00
Nikolas Klauser
05443a9807
[libc++] Refactor how we do amortized growth (#171117)
When doing amortized growth we currently have separate functions for
calculating the new capacity and allocating. However, we set the size to
the calculated capacity that way instead of the actually required size.
This makes the interface quite confusing, since the size has to be set
manually. Instead, this patch refactors the function to get the
amortized growth capacity to instead allocate and set the size
correctly.
2026-01-27 14:27:48 +01:00
Nikolas Klauser
2e5eb5d212
[libc++][NFC] Forward string observer functions when appropriate (#171120)
Instead of unwrapping the arguments to string's observer functions
everywhere, simply unwrap the specific argument and then forward all of
them to a single function which does the final unwrapping of `*this`.
This simplifies the code a bit.
2026-01-26 22:09:08 +01:00
Nikolas Klauser
46016e63b7
[libc++] Make basic_string::__erase_external_with_move noexcept (#171591)
`__erase_external_with_move` is in the dylib, so the compiler doesn't
see the definition. Marking it `noexcept` sometimes allows clang to
remove exceptions related code, improving code size slightly.
2026-01-12 15:47:23 +01:00
Louis Dionne
a04627621e
[libc++] Add missing %{flags} substitution to clang-tidy (#171689)
Flags that should be used both for compiling and for linking are
provided through the %{flags} substitution. Our clang-tidy tests should
be using them, not only %{compile_flags}.
2025-12-18 19:15:04 -05:00
Hristo Hristov
d7f6301390
[libc++][string] Applied [[nodiscard]] to non-member functions (#169330)
`[[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
2025-11-25 04:02:40 +02:00
Nikolas Klauser
121e2e9e37
[libc++] Introduce basic_string::__allocate_long_buffer_for_growing (#162633)
Introducing this utility makes the `__grow_by{,_and_replace}`
significantly easier to understand and allows us to migrate away from
these functions in the future.
2025-11-24 11:09:00 +01:00
Nikolas Klauser
e95c5c8511
[libc++] Refactor basic_string::__recommend (#162631)
This does a couple of things:
- code that is only useful for `shrink_to_fit` is moved into that
function
- `shrink_to_fit` is simplified a bit
- `__recommend` is renamed to better reflect what the function actually
does
- `__allocate_long_buffer` asserts that the passed capacity doesn't fit
into the SSO
2025-11-17 16:01:25 +01:00
Nikolas Klauser
36c127387a
[libc++] Mark string functions as [[nodiscard]] (#166524)
This applies `[[nodiscard]]` according to our coding guidelines to
`basic_string`.
2025-11-12 10:18:56 +01: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
Aiden Grossman
d200df0557
[libcxx] Remove Redundant Reset in ~basic_string (#164718)
8dae17be2991cd7f0d7fd9aa5aecd064520a14f6 refactors basic_string for more
code reuse. This makes sense in most cases, but has performance overhead
in the case of ~basic_string. The refactoring of ~basic_string to call
__reset_internal_buffer() added a redundant (inside the destructor)
reset of the object, which the optimizer is unable to optimize away in
many cases. This patch prevents a ~1% regression we observed on an
internal workload when applying the original refactoring. This does
slightly pessimize the code readability, but I think this change is
worth it given the performance impact.

I'm hoping to add a benchmark(s) to the upstream libc++ benchmark suite
around string construction/destruction to ensure that this case does not
regress as it seems common in real world applications. I will put up a
separate PR for that when I figure out a reasonable way to write it.
2025-11-03 11:04:22 -08:00
Nikolas Klauser
28d3194d11
[libc++] Merge basic_string::__{replace,reset}_internal_buffer (#165404) 2025-11-03 16:47:12 +01:00
NagaChaitanya Vellanki
9146ef5df0
[libc++][string] Assert resize_and_overwrite operation returns integer-like type (#162030)
Verify that the operation passed to resize_and_overwrite returns an
integer-like type, matching the behavior of other standard library
implementations like GCC's libstdc++

Fixes #160577
2025-10-10 07:32:50 +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
Nikolas Klauser
70b7874ab2
[libc++] Make the naming of the iterator_traits aliases consistent (#161661)
This renames all the `iterator_traits` alises to be
`__iterator_<type-name>`. e.g `iterator_traits<T>::value_type` will be
`__iterator_value_type<T>`.
2025-10-07 14:42:11 +02:00
Nikolas Klauser
55803b8af1
Reapply "[libc++] Avoid constructing additional objects when using map::at" (#160738) (#161485)
This reverts commit b86aaacf28b358b187071bc87075f1faa2d65c4e.

The issue in LLVM has been fixed now.
2025-10-02 11:15:33 +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
Andrew Lazarev
b86aaacf28
Revert "[libc++] Avoid constructing additional objects when using map::at" (#160738)
Reverts llvm/llvm-project#157866

It breaks a lot of sanitizer buildbots
2025-09-25 15:10:37 -07:00
Nikolas Klauser
833d5f0cd8
[libc++] Avoid constructing additional objects when using map::at (#157866)
This patch adds additional overloads to `map::at` in case its known that
the argument is transparently comparable to the key type. This avoids
actually constructing the key type in some cases, potentially removing
allocations.

```
--------------------------------------------------------
Benchmark                            old             new
--------------------------------------------------------
BM_map_find_string_literal       12.8 ns         2.68 ns
```
2025-09-25 11:35:41 +02:00
Hristo Hristov
804b46bb45
[libc++][string] P3044R2: sub-string_view from string (#147095)
Implements [P3044R2](https://wg21.link/P3044R2)

Note: `substr.pass.cpp` is refactored to accommodate the test of
`basic_string_view`'s `subview` which is an alias of `substr` without
changing the test cases.

Closes #148140

# References

- https://github.com/cplusplus/draft/pull/7975
- https://wg21.link/string.substr
- https://wg21.link/string.view.ops

---------

Co-authored-by: Hristo Hristov <zingam@outlook.com>
Co-authored-by: Nikolas Klauser <nikolasklauser@berlin.de>
2025-09-25 03:08:15 +03:00
Nikolas Klauser
8cb03a05ff
[libc++][NFC] Refactor __is_allocator to be a variable template (#159584) 2025-09-24 10:41:29 +02:00
Nikolas Klauser
ebcf1bf2ec
[libc++] Remove a few unused includes from <string> and <vector> (#160087) 2025-09-23 09:37:24 +02:00
Nikolas Klauser
8dae17be29
[libc++] Refactor memory allocation in basic_string (#128423)
This patch introduces a string-internal API to make the allocation and
deallocation the long string simpler. Before this we had a lot of code
duplication, so ensuring that things were actually correct was
non-trivial.
2025-09-18 14:36:46 +02:00
Nikolas Klauser
92f5d8df36
[libc++] Replace __resize_default_init with resize_and_overwrite (#157121)
Since `__resize_default_init` is only ever used inside the dylib we can
remove the libc++-internal API and switch to the public one. This patch
inlines a bunch of functions that aren't required anymore and simplifies
the code that way.
2025-09-16 13:38:42 +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
34d4f0c136
[libc++][NFC] Use llvm.org/PR to link to bug reports (#156288)
We've built up quite a few links directly to github within the code
base. We should instead use `llvm.org/PR<issue-number>` to link to bugs,
since that is resilient to the bug tracker changing in the future. This
is especially relevant for tests linking to bugs, since they will
probably be there for decades to come. A nice side effect is that these
links are significantly shorter than the GH links, making them much less
of an eyesore.

This patch also replaces a few links that linked to the old bugzilla
instance on llvm.org.
2025-09-04 09:20:02 +02:00
Nikolas Klauser
f5e687d7bf
[libc++] Fix ABI break introduced by switching to _LIBCPP_COMPRESSED_PAIR (#154686)
LLVM 20 contained an ABI break that can result in the size of
`std::unordered_{map,set,multimap,multiset}` and `std::deque` changing
when used with an allocator type that is empty and contains a base class
that is the same across rebound allocator instantiations (e.g.
``Allocator<int>`` and ``Allocator<char>`` are both empty and contain
the same base class).

In addition, the layout of a user-defined type that:
- contains one of the following containers:
`std::unordered_{map,set,multimap,multiset}`, `std::deque`, `std::map`,
`std::set`, `std::multimap`, `std::multiset`, `std::list` or
`std::vector`, and
- passes an empty allocator, comparator or hasher type to that
container, and
- has a member of that same empty allocator, comparator or hasher type
inside the enclosing struct, and
- that member is either marked with `[[no_unique_address]]` or optimized
out via the EBO (empty base optimization) technique
saw its size increase from LLVM 19 to LLVM 20. This was caused by the
usage of `[[no_unique_address]]` within some of libc++'s containers in a
way that allowed subtle interactions with enclosing objects. This is
fixed in LLVM 21 on Clang (returning to the LLVM 19 ABI), however that
implies an ABI break from LLVM 20 to LLVM 21.
Furthermore, fixing this causes a slight regression to constant
evaluation support in `std::unique_ptr`. Specifically, constant
evaluation will now fail when the deleter relies on being
value-initialized for constant-evaluation admissibility. If a
default-initialized deleter can be used during constant evaluation, or
if the default constructor is non-trivial, the `unique_ptr` is not
affected by this regression. In particular, this regression does not
impact any `unique_ptr` using the default deleter.

Note that there is currently no way to realistically fix this ABI break
on GCC, therefore GCC will remain on the ABI introduced in LLVM 19. That
also means that Clang and GCC will have a slightly different ABI for the
small subset of types listed above until we are able to apply the same
fix we did with Clang on GCC.

We fix this regression by surrounding the members of the
`_LIBCPP_COMPRESSED_PAIR` with an anonymous struct. This restricts the
shifting of empty types to the front of the `_LIBCPP_COMPRESSED_PAIR`
instead of throughout the surrounding object. This "frees up" the zero
offset to contain another object of the same type, restoring the ability
to perform EBO or to elide the storage for a type with
`[[no_unique_address]]` in the enclosing (user-defined) struct.

Fixes #154146

Co-authored-by: Louis Dionne <ldionne.2@gmail.com>
2025-08-23 07:58:37 +02:00
Nikolas Klauser
2dc0a5f3cd
[libc++][NFC] Use early returns in a few basic_string functions (#137299)
Using early returns tends to make the code easier to read, without any
changes to the generated code.
2025-08-20 10:16:13 +02:00
Nikolas Klauser
b5348e7622
[libc++] Diagnose passing null pointers to a bunch of APIs (#148585) 2025-07-19 11:12:20 +02:00
Nikolas Klauser
4993f5b12c
[libc++][NFC] Use variable templates in <string> (#149038)
Variable templates are a bit lighter on the compiler than class
templates.
2025-07-17 11:11:30 +02:00
Nikolas Klauser
1f8e2a4b10
[libc++][NFC] Remove __remove_uncvref (#140531)
The use-case for `__is_same_uncvref` seems rather dubious, since not a
single use-cases needed the `remove_cvref_t` to be applied to both of
the arguments. Removing the alias makes it clearer what actually
happens, since we're not using an internal name anymore and it's clear
what the `remove_cvref_t` should apply to.
2025-07-04 11:16:47 +02:00
Nikolas Klauser
040e9e02cc
[libc++] Inline __has_feature and __has_extension uses (#133634)
Since GCC now supports `__has_feature` and `__has_extension` as well,
there isn't much of a reason to define new macros to test for the
features.
2025-06-10 05:54:15 +02:00
A. Jiang
479f992291
[libc++] Fix basic_string::shrink_to_fit for constant evaluation (#142712)
Currently, when the string shrink into the SSO buffer, the `__rep_.__s`
member isn't activated before the `traits_type::copy` call
yet, so internal `__builtin_memmove` call writing to the buffer causes
constant evaluation failure. The existing test coverage seems a bit
defective and doesn't cover this case - `shrink_to_fit` is called on the
copy of string after erasure, not the original string object.

This PR reorders the `__set_short_size` call, which starts the lifetime
of the SSO buffer, before the copy operation. Test coverage is achieved
by calling `shrink_to_fit` on the original erased string.
2025-06-05 07:23:49 +08:00
James Y Knight
c3656afdf1
Revert "[libc++] Introduce ABI sensitive areas to avoid requiring _LIBCPP_HIDE_FROM_ABI everywhere (#131156)" (#141756)
This reverts commit c861fe8a71e64f3d2108c58147e7375cd9314521.

Unfortunately, this use of hidden visibility attributes causes
user-defined specializations of standard-library types to also be marked
hidden by default, which is incorrect. See discussion thread on #131156.

...and also reverts the follow-up commits:

Revert "[libc++] Add explicit ABI annotations to functions from the block runtime declared in <__functional/function.h> (#140592)"
This reverts commit 3e4c9dc299c35155934688184319d391b298fff7.

Revert "[libc++] Make ABI annotations explicit for windows-specific code (#140507)"
This reverts commit f73287e623a6c2e4a3485832bc3e10860cd26eb5.

Revert "[libc++][NFC] Replace a few "namespace std" with the correct macro (#140510)"
This reverts commit 1d411f27c769a32cb22ce50b9dc4421e34fd40dd.
2025-05-28 12:04:51 -04:00
Nikolas Klauser
c861fe8a71
[libc++] Introduce ABI sensitive areas to avoid requiring _LIBCPP_HIDE_FROM_ABI everywhere (#131156)
This patch introduces `_LIBCPP_{BEGIN,END}_EXPLICIT_ABI_ANNOTATIONS`,
which allow us to have implicit annotations for most functions, and just
where it's not "hide_from_abi everything" we add explicit annotations.
This allows us to drop the `_LIBCPP_HIDE_FROM_ABI` macro from most
functions in libc++.
2025-05-18 15:47:05 +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
Nikolas Klauser
f25f9e480b
[libc++][NFC] Remove a bunch of redundant ASan existence checks (#128504)
There are currently lots of `_LIBCPP_HAS_ASAN` and
`__libcpp_is_constant_evaluated()` checks which aren't needed, since it
is centrally checked inside `__debug_utils/sanitizers.h`.
2025-05-06 22:16:58 +02:00
Nikolas Klauser
166e5b1f0f
[libc++][NFC] Refactor string's extern template lists (#137264)
This patch moves the functions common between our two extern template
lists into a common list and avoids some unnecessary _Uglification. This
makes the code a lot nicer to read and makes the differences between the
two lists obvious.
2025-04-25 10:43:13 +02:00
Nikolas Klauser
c4d44ecb98
[libc++][NFC] Use early returns in basic_string::operator= (#137145)
This makes the code a lot easier to read.
2025-04-25 10:38:58 +02:00
Peng Liu
e9280a1d39
[libc++] Backport segmented iterator optimization for std::for_each to C++11 (#134960)
Previously, the segmented iterator optimization for `std::for_each` was restricted to C++23 and later due to its dependency on `__movable_box`, which is not available in earlier standards. This patch eliminates that restriction, enabling consistent optimizations starting from C++11. 

By backporting this enhancement, we improve performance across older standards and create opportunities to extend similar optimizations to other algorithms by forwarding their calls to `std::for_each`.
2025-04-19 07:12:43 -04:00
A. Jiang
ab95005a05
[libc++] P3247R2: Deprecate is_trivial(_v) (#130573)
Requirements on character-like types are updated unconditionally,
because `basic_string` does requires the default-constructibility. It
might be possible to make `basic_string_view` support classes with
non-public trivial default constructor, but this doesn't seem sensible.

libcxxabi's `ItaniumDemangle.h` is also updated to avoid deprecated
features.
2025-04-09 07:40:01 +08:00
Nikolas Klauser
16d10546d2
[libc++] Remove _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS (#111964)
This macro isn't required if we define all the functions inline. In
fact, quite a few of the marked functions have already been inlined.

This patch basically only moves code around and adds
`_LIBCPP_HIDE_FROM_ABI` to the places where it's been missing so far.

This also removes inlining hints, since it dropps `inline` in some
places, but that shouldn't make much of a difference. The functions tend
to be either really small, so should be inlined anyways, or are big
enough that they shouldn't be inlined even with an inlinehint.
2025-04-08 18:16:18 +02:00
Peng Liu
e30a5d6570
[libc++][NFC] Simplify string a bit (#127135)
This PR refactors `basic_string` a bit to simplify its implementation in
the following ways:
- Instead of manually checking whether a string is short or long,
followed by calling the specific functions (e.g., `__get_short_size()`,
`__get_long_size()`), we call the general functions (`size()`) to hide
the conditional checks and make the code more concise.
- Once a string is determined to be short or long, we directly call the
specific functions instead of the general versions to get rid of
unnecessary internal conditional checks. For example, for a long string,
we would directly call `{__set, __get}_long_pointer` instead of `{__set,
__get}_pointer()`.
- Variables that are defined in both the `if` and `else` branches are
now declared in a common scope to reduce redundancy.
- When the string size is calculated multiple times using
`traits_type::length(__s)`, a variable is introduced to store its
length. While modern compilers can optimize this with constant folding,
explicitly storing the length improves code readability and makes the
logic clearer.
- Fixed synopsis with missing default arguments.
2025-03-15 22:10:57 -04:00
A. Jiang
e739ce2e10
[libc++] Add missed constexpr to erase(_if) in <string> (#129666)
`std::erase(_if)` for `basic_string` were made `constexpr` in C++20 by
cplusplus/draft@2c1ab9775c as follow-up
changes of P0980R1.

This patch implements the missed changes that were not tracked in a
specific paper.
2025-03-05 08:31:28 +08:00