diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2024-10-09 12:55:54 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2024-10-18 14:49:34 +0100 |
commit | 3abe751ea86e3472fa2c97bf2014f9f93f569019 (patch) | |
tree | f82620061f019bcb9d4112a1618052fe20f43aa6 /libstdc++-v3/testsuite/23_containers | |
parent | 2608fcfe5fcff260d62379d8f74efb9be8df70f4 (diff) | |
download | gcc-3abe751ea86e3472fa2c97bf2014f9f93f569019.zip gcc-3abe751ea86e3472fa2c97bf2014f9f93f569019.tar.gz gcc-3abe751ea86e3472fa2c97bf2014f9f93f569019.tar.bz2 |
libstdc++: Refactor std::uninitialized_{copy,fill,fill_n} algos [PR68350]
This refactors the std::uninitialized_copy, std::uninitialized_fill and
std::uninitialized_fill_n algorithms to directly perform memcpy/memset
optimizations instead of dispatching to std::copy/std::fill/std::fill_n.
The reasons for this are:
- Use 'if constexpr' to simplify and optimize compilation throughput, so
dispatching to specialized class templates is only needed for C++98
mode.
- Use memcpy instead of memmove, because the conditions on
non-overlapping ranges are stronger for std::uninitialized_copy than
for std::copy. Using memcpy might be a minor optimization.
- No special case for creating a range of one element, which std::copy
needs to deal with (see PR libstdc++/108846). The uninitialized algos
create new objects, which reuses storage and is allowed to clobber
tail padding.
- Relax the conditions for using memcpy/memset, because the C++20 rules
on implicit-lifetime types mean that we can rely on memcpy to begin
lifetimes of trivially copyable types. We don't need to require
trivially default constructible, so don't need to limit the
optimization to trivial types. See PR 68350 for more details.
- Remove the dependency on std::copy and std::fill. This should mean
that stl_uninitialized.h no longer needs to include all of
stl_algobase.h. This isn't quite true yet, because we still use
std::fill in __uninitialized_default and still use std::fill_n in
__uninitialized_default_n. That will be fixed later.
Several tests need changes to the diagnostics matched by dg-error
because we no longer use the __constructible() function that had a
static assert in. Now we just get straightforward errors for attempting
to use a deleted constructor.
Two tests needed more signficant changes to the actual expected results
of executing the tests, because they were checking for old behaviour
which was incorrect according to the standard.
20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting
std::copy to be used for a call to std::uninitialized_copy involving two
trivially copyable types. That was incorrect behaviour, because a
non-trivial constructor should have been used, but using std::copy used
trivial default initialization followed by assignment.
20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing
the behaviour with a non-integral Size passed to uninitialized_fill_n,
but I wrote the test looking at the requirements of uninitialized_copy_n
which are not the same as uninitialized_fill_n. The former uses --n and
tests n > 0, but the latter just tests n-- (which will never be false
for a floating-point value with a fractional part).
libstdc++-v3/ChangeLog:
PR libstdc++/68350
PR libstdc++/93059
* include/bits/stl_uninitialized.h (__check_constructible)
(_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove.
[C++98] (__unwrappable_niter): New trait.
(__uninitialized_copy<true>): Replace use of std::copy.
(uninitialized_copy): Fix Doxygen comments. Open-code memcpy
optimization for C++11 and later.
(__uninitialized_fill<true>): Replace use of std::fill.
(uninitialized_fill): Fix Doxygen comments. Open-code memset
optimization for C++11 and later.
(__uninitialized_fill_n<true>): Replace use of std::fill_n.
(uninitialized_fill_n): Fix Doxygen comments. Open-code memset
optimization for C++11 and later.
* testsuite/20_util/specialized_algorithms/uninitialized_copy/64476.cc:
Adjust expected behaviour to match what the standard specifies.
* testsuite/20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc:
Likewise.
* testsuite/20_util/specialized_algorithms/uninitialized_copy/1.cc:
Adjust dg-error directives.
* testsuite/20_util/specialized_algorithms/uninitialized_copy/89164.cc:
Likewise.
* testsuite/20_util/specialized_algorithms/uninitialized_copy_n/89164.cc:
Likewise.
* testsuite/20_util/specialized_algorithms/uninitialized_fill/89164.cc:
Likewise.
* testsuite/20_util/specialized_algorithms/uninitialized_fill_n/89164.cc:
Likewise.
* testsuite/23_containers/vector/cons/89164.cc: Likewise.
* testsuite/23_containers/vector/cons/89164_c++17.cc: Likewise.
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite/23_containers')
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc | 5 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc | 3 |
2 files changed, 3 insertions, 5 deletions
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc index 106963e..36907dc 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/89164.cc @@ -32,7 +32,7 @@ void test01() X x[1]; // Should not be able to create vector using uninitialized_copy: std::vector<X> v1{x, x+1}; // { dg-error "here" "" { target c++17_down } } - // { dg-error "deleted function 'X::X" "" { target c++20 } 0 } + // { dg-error "deleted function 'X::X" "" { target *-*-* } 0 } } void test02() @@ -41,8 +41,7 @@ void test02() // Should not be able to create vector using uninitialized_fill_n: std::vector<Y> v2{2u, Y{}}; // { dg-error "here" "" { target c++17_down } } - // { dg-error "deleted function .*Y::Y" "" { target c++20 } 0 } + // { dg-error "deleted function .*Y::Y" "" { target *-*-* } 0 } } -// { dg-error "must be constructible from input type" "" { target *-*-* } 0 } // { dg-prune-output "construct_at" } diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc index 09d3dc6..07d4bab 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/89164_c++17.cc @@ -32,8 +32,7 @@ void test03() // Can create initializer_list<Y> with C++17 guaranteed copy elision, // but shouldn't be able to copy from it with uninitialized_copy: std::vector<X> v3{X{}, X{}, X{}}; // { dg-error "here" "" { target c++17_only } } - // { dg-error "deleted function .*X::X" "" { target c++20 } 0 } + // { dg-error "deleted function .*X::X" "" { target *-*-* } 0 } } -// { dg-error "must be constructible from input type" "" { target *-*-* } 0 } // { dg-prune-output "construct_at" } |