diff options
author | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-08-01 09:21:27 +0200 |
---|---|---|
committer | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-08-04 13:19:24 +0200 |
commit | d49d359b0c5266b314bcf31405746909d99927a1 (patch) | |
tree | 4cca382922bf8fd8c66ba8d2564b82f23a316dc4 /libstdc++-v3/testsuite/std | |
parent | d9f34c951ab1f5ba67f3a1c95e2533cff6230b85 (diff) | |
download | gcc-d49d359b0c5266b314bcf31405746909d99927a1.zip gcc-d49d359b0c5266b314bcf31405746909d99927a1.tar.gz gcc-d49d359b0c5266b314bcf31405746909d99927a1.tar.bz2 |
libstdc++: Fix dereferencing of std::indirect xvalues [PR121128]
Forr rvalues the _Self parameter deduces a non-reference type. Consequently,
((_Self)__self) moved the object to a temporary, which then destroyed on
function exit.
This patch fixes this by using a C-style cast __self to (const indirect&).
This not only resolves the above issue but also correctly handles types that
are derived (publicly and privately) from indirect. Allocator requirements in
[allocator.requirements.general] p22 guarantee that dereferencing const _M_objp
works with equivalent semantics to dereferencing _M_objp.
PR libstdc++/121128
libstdc++-v3/ChangeLog:
* include/bits/indirect.h (indirect::operator*):
Cast __self to approparietly qualified indirect.
* testsuite/std/memory/indirect/access.cc: New test.
* testsuite/std/memory/polymorphic/access.cc: New test.
Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
Diffstat (limited to 'libstdc++-v3/testsuite/std')
-rw-r--r-- | libstdc++-v3/testsuite/std/memory/indirect/access.cc | 58 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/memory/polymorphic/access.cc | 53 |
2 files changed, 111 insertions, 0 deletions
diff --git a/libstdc++-v3/testsuite/std/memory/indirect/access.cc b/libstdc++-v3/testsuite/std/memory/indirect/access.cc new file mode 100644 index 0000000..cf21275 --- /dev/null +++ b/libstdc++-v3/testsuite/std/memory/indirect/access.cc @@ -0,0 +1,58 @@ +// { dg-do run { target c++26 } } + +#include <memory> +#include <vector> + +#include <testsuite_hooks.h> + +template<template<typename> class Indirect> +constexpr void +test_access() +{ + const std::vector<int> src{1, 2, 3, 4, 5}; + Indirect<std::vector<int>> i(src); + auto const& ci = i; + VERIFY( *i == src ); + VERIFY( *ci == src ); + VERIFY( *std::move(ci) == src ); + + std::vector<int>&& vr = *std::move(i); + VERIFY( vr == src ); + VERIFY( *i == src ); + + std::vector<int> vc = *std::move(i); + VERIFY( vc == src ); + VERIFY( vr.empty() ); + VERIFY( i->empty() ); + VERIFY( ci->empty() ); +} + +template<typename T> +struct PublicBase : std::indirect<T> +{ + using std::indirect<T>::indirect; +}; + +template<typename T> +class PrivateBase : std::indirect<T> +{ +public: + using std::indirect<T>::indirect; + using std::indirect<T>::operator*; + using std::indirect<T>::operator->; +}; + +constexpr bool +test_all() +{ + test_access<std::indirect>(); + test_access<PublicBase>(); + test_access<PrivateBase>(); + return true; +} + +int main() +{ + test_all(); + static_assert(test_all()); +} diff --git a/libstdc++-v3/testsuite/std/memory/polymorphic/access.cc b/libstdc++-v3/testsuite/std/memory/polymorphic/access.cc new file mode 100644 index 0000000..7b95bb1 --- /dev/null +++ b/libstdc++-v3/testsuite/std/memory/polymorphic/access.cc @@ -0,0 +1,53 @@ +// { dg-do run { target c++26 } } + +#include <memory> +#include <vector> + +#include <testsuite_hooks.h> + +template<template<typename> class Polymorhpic> +constexpr void +test_access() +{ + const std::vector<int> src{1, 2, 3, 4, 5}; + Polymorhpic<std::vector<int>> i(src); + auto const& ci = i; + VERIFY( *i == src ); + VERIFY( *ci == src ); + VERIFY( *std::move(ci) == src ); + + auto&& vr = *std::move(i); + static_assert( std::is_same_v<decltype(vr), std::vector<int>&> ); + VERIFY( vr == src ); + VERIFY( *i == src ); +} + +template<typename T> +struct PublicBase : std::polymorphic<T> +{ + using std::polymorphic<T>::polymorphic; +}; + +template<typename T> +class PrivateBase : std::polymorphic<T> +{ +public: + using std::polymorphic<T>::polymorphic; + using std::polymorphic<T>::operator*; + using std::polymorphic<T>::operator->; +}; + +constexpr bool +test_all() +{ + test_access<std::polymorphic>(); + test_access<PublicBase>(); + test_access<PrivateBase>(); + return true; +} + +int main() +{ + test_all(); +// static_assert(test_all()); +} |