On Tue, Jul 8, 2025 at 11:46 PM Jonathan Wakely <jwak...@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 > >