https://wg21.link/LWG3088 requires that `forward_list::merge()` is a no-op when passed
`*this`, which aligns with the behavior of `list::merge`. Although libc++'s implementation
of `forward_list::merge()` already meets this requirement, there were no tests to verify
this behavior. This patch adds the necessary tests to ensure that self-merging remains a
no-op and prevents any future regressions on this.
Closes#104942.
The existing tests for `vector<bool>` copy- and move-assignment
operators are limited to 3 bits only, which are inadequate to cover
realistic scenarios. Most `vector<bool>` operations have code paths that
are executed only when multiple storage words are involved, with each
storage word typically comprising 64 bits on a 64-bit platform.
Furthermore, the existing tests fail to cover all combinations
`POCCA`/`POCMA`, along with different allocator equality and/or
reallocation scenarios, leaving some critical code paths untested.
This patch enhances the test coverage by introducing new tests covering
up to 5 storage words, ensuring that partial words in the front or tail,
and whole words in the middle are all properly tested. Moreover, these
new tests ensure that the copy- and move-assignment operators are tested
under all combinations of `POCCA`/`POCMA` and various allocator equality
scenarios, both with or without reallocations.
According to the commit history, the constructors removed by LWG4140
have never been added to libc++.
Existence of non-public or deleted default constructor is observable,
this patch tests that there's no such default constructor at all.
We've been improving these the tests for vector quite a bit and we are
probably not done improving our container tests. Formatting everything
at once will make subsequent reviews easier.
Currently `std::hash<Emplaceable>::operator()` relies implicit
conversion from `int` to `size_t`, which makes MSVC compelling. This PR
switches to use `static_cast`.
In `flat.map/flat.map.access/at_transparent.pass.cpp`, there's one
value-discarding use of `at` that wasn't marked `TEST_IGNORE_NODISCARD`.
This PR adds the missing `TEST_IGNORE_NODISCARD`.
This PR slightly simplifies the implementation of `vector<bool>::max_size`
and adds extensive tests for the `max_size()` function for both `vector<bool>`
and `vector<T>`. The main purposes of the new tests include:
- Verify correctness of `max_size()` under various `size_type` and
`difference_type` definitions: check that `max_size()` works properly
with allocators that have custom `size_type` and `difference_type`. This
is particularly useful for `vector<bool>`, as different `size_type` lead
to different `__storage_type` of different word lengths, resulting in
varying `max_size()` values for `vector<bool>`. Additionally, different
`difference_type` also sets different upper limit of `max_size()` for
both `vector<bool>` and `std::vector`. These tests were previously
missing.
- Eliminate incorrect implementations: Special tests are added to identify and
reject incorrect implementations of `vector<bool>::max_size` that unconditionally
return `std::min<size_type>(size-max, __internal_cap_to_external(allocator-max-size))`.
This can cause overflow in the `__internal_cap_to_external()` call and lead
to incorrect results. The new tests ensure that such incorrect
implementations are identified.
The __is_trivially_relocatable builtin has semantics that do not
correspond to any current or future notion of trivial relocation.
Furthermore, it currently leads to incorrect optimizations for some
types on supported compilers:
- Clang on Windows where types with non-trivial destructors get
incorrectly optimized
- AppleClang where types with non-trivial move constructors get
incorrectly optimized
Until there is an agreed upon and bugfree implementation of what it
means to be trivially relocatable, it is safer to simply use trivially
copyable instead. This doesn't leave a lot of types behind and is
definitely correct.
Changes:
- Carve out sized but input-only ranges for C++23.
- Call `std::move` for related functions when the iterator is possibly input-only.
Fixes#115727
This PR addresses an issue where the `shrink_to_fit` function in
`vector<bool>` is effectively a no-op, meaning it will never shrink the
capacity.
Fixes#122502
As a follow-up to #113852, this PR optimizes the performance of the
`insert(const_iterator pos, InputIt first, InputIt last)` function for
`input_iterator`-pair inputs in `std::vector` for cases where
reallocation occurs during insertion. Additionally, this optimization
enhances exception safety by replacing the traditional `try-catch`
mechanism with a modern exception guard for the `insert` function.
The optimization targets cases where insertion trigger reallocation. In
scenarios without reallocation, the implementation remains unchanged.
Previous implementation
-----------------------
The previous implementation of `insert` is inefficient in reallocation
scenarios because it performs the following steps separately:
- `reserve()`: This leads to the first round of relocating old
elements to new memory;
- `rotate()`: This leads to the second round of reorganizing the
existing elements;
- Move-forward: Moves the elements after the insertion position to
their final positions.
- Insert: performs the actual insertion.
This approach results in a lot of redundant operations, requiring the
elements to undergo three rounds of relocations/reorganizations to be
placed in their final positions.
Proposed implementation
-----------------------
The proposed implementation jointly optimize the above 4 steps in the
previous implementation such that each element is placed in its final
position in just one round of relocation. Specifically, this
optimization reduces the total cost from 2 relocations + 1 std::rotate
call to just 1 relocation, without needing to call `std::rotate`,
thereby significantly improving overall performance.
As a follow-up to #117662, this PR provides a comprehensive set of
exception tests for the following capacity-related functions in
`std::vector`. Specifically, it includes tests for the following
functions:
- `reserve(size_type)`
- `resize(size_type)` and `resize(size_type, const_reference)`
- `shrink_to_fit()`
Previously, the exception safety tests for these functions were either
missing or inadequate. We need a thorough coverage of exception tests to
validate that these operations provide strong exception guarantees under
various exceptional scenarios.
This PR fixes the erroneous internal capacity evaluation in
`vector<bool>`, which caused a subsequent SIGSEGV error when calling
`flip()` on `vector<bool>`. By fixing the internal capacity evaluation,
the SIGSEGV is automatically resolved.
This patch implements the forwarding to frozen C++03 headers as
discussed in
https://discourse.llvm.org/t/rfc-freezing-c-03-headers-in-libc. In the
RFC, we initially proposed selecting the right headers from the Clang
driver, however consensus seemed to steer towards handling this in the
library itself. This patch implements that direction.
At a high level, the changes basically amount to making each public
header look like this:
```
// inside <vector>
#ifdef _LIBCPP_CXX03_LANG
# include <__cxx03/vector>
#else
// normal <vector> content
#endif
```
In most cases, public headers are simple umbrella headers so there isn't
much code in the #else branch. In other cases, the #else branch contains
the actual implementation of the header.
This PR enhances the test coverage for std::vector::assign by adding new
tests for several important test cases that were previously missing, as
shown in the following table:
| test cases | forward_iterator | input_iterator |
|-----------------------------------|------------------|----------------|
| new_size > capacity() | Yes | Yes |
| size() < new_size <= capacity() | No | No |
| new_size <= size() | No | No |
Similarly, no tests have previously covered `assign(InputIterator, InputIterator)`
and `assign(size_type, const value_type&)` for `vector<bool>`.
With this patch applied, all missing tests are covered.
The existing exceptions tests for `vector<T>` have several issues: some
tests did not throw exceptions at all, making them not useful for
exception-safety testing, and some tests did not throw exceptions at the
intended points, failing to serve their expected purpose. This PR fixes
those tests for vector's constructors. Morever, this PR extracted common
classes and utilities into a separate header file, and renamed those
classes using more descriptive names.
The increasing_allocator<T> class, originally introduced to test shrink_to_fit()
for std::vector, std::vector<bool>, and std::basic_string, has duplicated
definitions across several test files. Given the potential utility of this
class for capacity-related tests in various sequence containers, this patch
refactors the definition of increasing_allocator<T> into a single, reusable
location.
This PR simplifies the implementation of std::vector's move constructor
with an alternative allocator by invoking __init_with_size() instead of
calling assign(), which ultimately calls __assign_with_size(). The
advantage of using __init_with_size() lies in its internal use of
an exception guard, which simplifies the code. Furthermore, from a
semantic standpoint, it is more intuitive for a constructor to call
an initialization function than an assignment function.
In particular, test everything with both a normal and a min_allocator,
add tests for a few corner cases and add tests with types that are
trivially relocatable. Also add tests that count the number of
assignments performed by vector::erase, since that is mandated by the
Standard.
This patch is a preparation for optimizing vector::erase.
This patch introduces a new kind of bounded iterator that knows the size
of its valid range at compile-time, as in std::array. This allows computing
the end of the range from the start of the range and the size, which requires
storing only the start of the range in the iterator instead of both the start
and the size (or start and end). The iterator wrapper is otherwise identical
in design to the existing __bounded_iter.
Since this requires changing the type of the iterators returned by
std::array, this new bounded iterator is controlled by an ABI flag.
As a drive-by, centralize the tests for std::array::operator[] and add
missing tests for OOB operator[] on non-empty arrays.
Fixes#70864
This PR fixes the `ThrowingT` class, which currently fails to raise
exceptions after a specified number of copy construction operations. The
class is intended to throw in a controlled manner based on a specified
counter value `throw_after`. However, its current implementation of the
copy constructor fails to achieve this goal.
The problem arises because the copy constructor does not initialize the
`throw_after_n_` member, leaving `throw_after_n_` to default to `nullptr`
as defined by the in-class initializer. As a result, its copy constructor
always checks against `nullptr`, causing an immediate exception rather
than throwing after the specified number `throw_after` of uses. The fix
is straightforward: simply initialize the `throw_after_n_` member in the
member initializer list.
This issue was previously uncovered because all exception tests for
`std::vector` in `exceptions.pass.cpp` used a `throw_after` value of 1,
which coincidentally aligned with the class's behavior.
Summary:
The GPU runs these tests using the files built from the `libc` project.
These will be placed in `include/<triple>` and `lib/<triple>`. We use
the `amdhsa-loader` and `nvptx-loader` tools, which are also provided by
`libc`. These launch a kernel called `_start` which calls `main` so we
can pretend like GPU programs are normal terminal applications.
We force serial exeuction here, because `llvm-lit` runs way too many
processes in parallel, which has a bad habit of making the GPU drivers
hang or run out of resources. This allows the compilation to be run in
parallel while the jobs themselves are serialized via a file lock.
In the future this can likely be refined to accept user specified
architectures, or better handle including the root directory by exposing
that instead of just `include/<triple>/c++/v1/`.
This currently fails ~1% of the tests on AMDGPU and ~3% of the tests on
NVPTX. This will hopefully be reduced further, and later patches can
XFAIL a lot of them once it's down to a reasonable number.
Future support will likely want to allow passing in a custom
architecture instead of simply relying on `-mcpu=native`.
Not all the code path has been exercised by the tests for
`flat_map::emplace_hint`
Adding more test coverage.
At the same time, adding more test cases for `flat_map::emplace`
Added exception guard to the `vector(n, x, a)` constructor to enhance
exception safety. This change ensures that the `vector(n, x, a)`
constructor is consistent with other constructors, such as `vector(n)`,
`vector(n, x)`, `vector(n, a)`, in terms of exception safety.
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
Currently, libc++'s `bitset`, `forward_list`, and `list` have
non-conforming member typedef name `base`. The typedef is private, but
can cause ambiguity in name lookup.
Some other classes in libc++ that are either implementation details or
not precisely specified by the standard also have member typdef `base`.
I think this can still be conforming.
Follows up #80706 and #111127.
Previous PR #107344 fixed move constructor of `test_allocator` but
dropped test coverage for move construction in some cases. This PR
attempts to restore the test coverage.
Thanks @Quuxplusone for reminding.
The paper was implemented by commit b0386a515b60c
(https://reviews.llvm.org/D46845) in LLVM 7.0. But it would be nice to
have test coverage for desired properties of `insert_return_type`.
Closes#99944
This patch adds a large number of missing includes in the libc++ headers
and the test suite. Those were found as part of the effort to move
towards a mostly monolithic top-level std module.
The poisoned_hash_helper header was relying on an implicit forward
declaration of std::hash located in <type_traits>. When we improve the
modularization of the library, that causes issues, in addition to being
a fundamentally non-portable assumption in the test suite.
It turns out that the reason for relying on a forward declaration is to
be able to test that std::hash is *not* provided if we don't include any
header that provides it. But testing that is actually both non-portable
and not really useful.
Indeed, what harm does it make if additional headers provide std::hash
specializations? That would certainly be conforming -- the Standard
never requires an implementation to avoid providing a declaration when a
given header is included, instead it mandates what *must* be provided
for sure. In that spirit, it would be conforming for e.g. `<cstddef>` to
define the hash specializations if that was our desire. I also don't
read https://wg21.link/P0513R0 as going against that statement. Hence,
this patch just removes that test which doesn't carry its weight.
Fixes#56938
The resolution of LWG2593 didn't require the standard library
implementation to change. It merely strengthened requirements on
user-defined allocator types and allowed the implementation to make
stronger assumptions. The status is tentatively set to Nothing To Do.
However, `test_allocator` in libc++'s test suit needs to be fixed to
conform to the strengthened requirements.
Closes#100220.
Some modules are leaf modules in the sense that they are not used by any
other part of the headers. These leaf modules are easy to consolidate
since there is no risk to create a cycle. As a result of regrouping
these modules, several missing includes were found and fixed in this
patch.
#78086 provided the trait we want to use for this: `__libcpp_integer`.
In some `libcxx/containers/views/mdspan` tests, improper uses of `char`
are replaced with `signed char`.
Fixes#73715