[PATCH] libstdc++: Do not use list-initialization in std::span members [PR120997]
Tomasz Kaminski
tkaminsk@redhat.com
Mon Jul 14 06:17:46 GMT 2025
On Tue, Jul 8, 2025 at 11:46 PM Jonathan Wakely <jwakely@redhat.com> wrote:
> As the bug report shows, for span<const bool> the return statements of
> the form `return {data(), count};` will use the new C++26 constructor,
> span(initializer_list<element_type>).
>
> Although the conversions from data() to bool and count to bool are
> narrowing and should be ill-formed, in system headers the narrowing
> diagnostics are suppressed. In any case, even if the compiler diagnosed
> them as ill-formed, we still don't want the initializer_list constructor
> to be used. We want to use the span(element_type*, size_t) constructor
> instead.
>
> Replace the braced-init-list uses with S(data(), count) where S is the
> correct return type. We need to make similar changes in the C++26
> working draft, which will be taken care of via an LWG issue.
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/120997
> * include/std/span (span::first, span::last, span::subspan): Do
> not use braced-init-list for return statements.
> * testsuite/23_containers/span/120997.cc: New test.
> ---
>
> Tested x86_64-linux.
>
LGTM.
>
> libstdc++-v3/include/std/span | 15 +++---
> .../testsuite/23_containers/span/120997.cc | 46 +++++++++++++++++++
> 2 files changed, 54 insertions(+), 7 deletions(-)
> create mode 100644 libstdc++-v3/testsuite/23_containers/span/120997.cc
>
> diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
> index 5629a71b9bd2..44f9b36a7efe 100644
> --- a/libstdc++-v3/include/std/span
> +++ b/libstdc++-v3/include/std/span
> @@ -376,7 +376,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> else
> static_assert(_Count <= extent);
> using _Sp = span<element_type, _Count>;
> - return _Sp{ _SizedPtr{this->data()} };
> + return _Sp(_SizedPtr{this->data()});
> }
>
> [[nodiscard]]
> @@ -384,7 +384,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> first(size_type __count) const noexcept
> {
> __glibcxx_assert(__count <= size());
> - return { this->data(), __count };
> + return span<element_type>(this->data(), __count);
> }
>
> template<size_t _Count>
> @@ -397,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> else
> static_assert(_Count <= extent);
> using _Sp = span<element_type, _Count>;
> - return _Sp{ _SizedPtr{this->data() + (this->size() - _Count)} };
> + return _Sp(_SizedPtr{this->data() + (this->size() - _Count)});
> }
>
> [[nodiscard]]
> @@ -405,7 +405,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> last(size_type __count) const noexcept
> {
> __glibcxx_assert(__count <= size());
> - return { this->data() + (this->size() - __count), __count };
> + return span<element_type>(this->data() + (this->size() - __count),
> + __count);
> }
>
> template<size_t _Offset, size_t _Count = dynamic_extent>
> @@ -424,7 +425,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> using _Sp = span<element_type, _S_subspan_extent<_Offset,
> _Count>()>;
>
> if constexpr (_Count == dynamic_extent)
> - return _Sp{ this->data() + _Offset, this->size() - _Offset };
> + return _Sp(this->data() + _Offset, this->size() - _Offset);
> else
> {
> if constexpr (_Extent == dynamic_extent)
> @@ -437,7 +438,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> static_assert(_Count <= extent);
> static_assert(_Count <= (extent - _Offset));
> }
> - return _Sp{ _SizedPtr{this->data() + _Offset} };
> + return _Sp(_SizedPtr{this->data() + _Offset});
> }
> }
>
> @@ -454,7 +455,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> __glibcxx_assert(__count <= size());
> __glibcxx_assert(__offset + __count <= size());
> }
> - return {this->data() + __offset, __count};
> + return span<element_type>(this->data() + __offset, __count);
> }
>
> private:
> diff --git a/libstdc++-v3/testsuite/23_containers/span/120997.cc
> b/libstdc++-v3/testsuite/23_containers/span/120997.cc
> new file mode 100644
> index 000000000000..fbf194c87388
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/23_containers/span/120997.cc
> @@ -0,0 +1,46 @@
> +// { dg-do run { target c++26 } }
> +
> +#include <span>
> +#include <testsuite_hooks.h>
> +
> +void
> +test_first()
> +{
> + bool arr[5];
> + std::span<const bool> s(arr);
> + std::span<const bool> s2 = s.first(5);
> + VERIFY( s2.data() == s.data() );
> + std::span<const bool> s3 = s.first<5>();
> + VERIFY( s3.data() == s.data() );
> +}
> +
> +void
> +test_last()
> +{
> + bool arr[5];
> + std::span<const bool> s(arr);
> + std::span<const bool> s2 = s.last(5);
> + VERIFY( s2.data() == s.data() );
> + std::span<const bool> s3 = s.last<5>();
> + VERIFY( s3.data() == s.data() );
> +}
> +
> +void
> +test_subspan()
> +{
> + bool arr[5];
> + std::span<const bool> s(arr);
> + std::span<const bool> s2 = s.subspan(0, 5);
> + VERIFY( s2.data() == s.data() );
> + std::span<const bool> s3 = s.subspan<0>();
> + VERIFY( s3.data() == s.data() );
> + std::span<const bool> s4 = s.subspan<0, 5>();
> + VERIFY( s4.data() == s.data() );
> +}
> +
> +int main()
> +{
> + test_first();
> + test_last();
> + test_subspan();
> +}
> --
> 2.50.0
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20250714/ff9bca9b/attachment.htm>
More information about the Libstdc++
mailing list