]> git.ipfire.org Git - thirdparty/gcc.git/commit
libstdc++: Implement std::out_ptr and std::inout_ptr for C++23 [PR111667]
authorJonathan Wakely <jwakely@redhat.com>
Wed, 15 Nov 2023 23:02:34 +0000 (23:02 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Thu, 16 Nov 2023 08:10:26 +0000 (08:10 +0000)
commitc7f6537db94f7c6320a5a8ecaa387c9b9ce1f0ac
tree95b4ebb068d99c71edd6a06ddedf24cbdc7112ea
parent7ffa63df8f5281bcd81bbb9842b698bc91fbb4fd
libstdc++: Implement std::out_ptr and std::inout_ptr for C++23 [PR111667]

This implements that changes from P1132R8, including optimized paths for
std::shared_ptr and std::unique_ptr.

For std::shared_ptr we pre-allocate a new control block in the
std::out_ptr_t constructor so that the destructor is non-throwing. This
requires some care because unlike the shared_ptr(Y*, D, A) constructor,
we don't want to invoke the deleter if allocating the control block
throws, because we don't own any pointer yet. In order to avoid the
unwanted deleter invocation, we create the control block manually. We
also want to avoid invoking the deleter on a null pointer on
destruction, so we destroy the control block manually if there is no
pointer to take ownership of.

For std::unique_ptr and for raw pointers, the out_ptr_t object hands out
direct access to the pointer, so that we don't have anything to do
(except possibly assign a new deleter) in the ~out_ptr_t destructor.

These optimizations avoid requiring additional temporary storage for the
pointer (and optional arguments), and avoid additional instructions to
copy that pointer into the smart pointer at the end.

libstdc++-v3/ChangeLog:

PR libstdc++/111667
* include/Makefile.am: Add new header.
* include/Makefile.in: Regenerate.
* include/bits/out_ptr.h: New file.
* include/bits/shared_ptr.h (__is_shared_ptr): Move definition
to here ...
* include/bits/shared_ptr_atomic.h (__is_shared_ptr): ... from
here.
* include/bits/shared_ptr_base.h (__shared_count): Declare
out_ptr_t as a friend.
(_Sp_counted_deleter, __shared_ptr): Likewise.
* include/bits/unique_ptr.h (unique_ptr, unique_ptr<T[], D>):
Declare out_ptr_t and inout_ptr_t as friends.
(__is_unique_ptr): Define new variable template.
* include/bits/version.def (out_ptr): Define.
* include/bits/version.h: Regenerate.
* include/std/memory: Include new header.
* testsuite/20_util/smartptr.adapt/inout_ptr/1.cc: New test.
* testsuite/20_util/smartptr.adapt/inout_ptr/2.cc: New test.
* testsuite/20_util/smartptr.adapt/inout_ptr/shared_ptr_neg.cc:
New test.
* testsuite/20_util/smartptr.adapt/inout_ptr/void_ptr.cc: New
test.
* testsuite/20_util/smartptr.adapt/out_ptr/1.cc: New test.
* testsuite/20_util/smartptr.adapt/out_ptr/2.cc: New test.
* testsuite/20_util/smartptr.adapt/out_ptr/shared_ptr_neg.cc:
New test.
* testsuite/20_util/smartptr.adapt/out_ptr/void_ptr.cc: New
test.
18 files changed:
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/bits/out_ptr.h [new file with mode: 0644]
libstdc++-v3/include/bits/shared_ptr.h
libstdc++-v3/include/bits/shared_ptr_atomic.h
libstdc++-v3/include/bits/shared_ptr_base.h
libstdc++-v3/include/bits/unique_ptr.h
libstdc++-v3/include/bits/version.def
libstdc++-v3/include/bits/version.h
libstdc++-v3/include/std/memory
libstdc++-v3/testsuite/20_util/smartptr.adapt/inout_ptr/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/smartptr.adapt/inout_ptr/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/smartptr.adapt/inout_ptr/shared_ptr_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/smartptr.adapt/inout_ptr/void_ptr.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/smartptr.adapt/out_ptr/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/smartptr.adapt/out_ptr/2.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/smartptr.adapt/out_ptr/shared_ptr_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/smartptr.adapt/out_ptr/void_ptr.cc [new file with mode: 0644]