https://gcc.gnu.org/g:a72d0e1a8bf0770ddf1d8d0ebe589f92a4fab4ef
commit r16-2152-ga72d0e1a8bf0770ddf1d8d0ebe589f92a4fab4ef Author: Jonathan Wakely <jwak...@redhat.com> Date: Tue Jul 8 14:56:39 2025 +0100 libstdc++: Do not use list-initialization in std::span members [PR120997] 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. Diff: --- libstdc++-v3/include/std/span | 15 +++---- .../testsuite/23_containers/span/120997.cc | 46 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) 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(); +}