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();
+}

Reply via email to