[libc-commits] [libc] [libc][CPP] Align span copy and conversion with std::span (PR #220619)

via libc-commits libc-commits at lists.llvm.org
Wed Sep 2 10:47:33 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Jeff Bailey (kaladron)

<details>
<summary>Changes</summary>

Bring cpp::span copy and converting operations in line with C++20 std::span ([span.overview], [span.cons]):

* Add defaulted copy assignment operator: C++20 std::span declares constexpr span& operator=(const span&) noexcept = default; Providing an explicit defaulted copy assignment operator matches std::span and avoids -Wdeprecated-copy-with-dtor warnings in consuming code when copy-assigning spans.

* Take const span<U>& in converting constructor and operator=: C++20 [span.cons] specifies converting construction from const span&. Previously taking span<U>& prevented converting from const spans and binding to rvalue temporaries (such as s = s.subspan(1)).

* Update span.h and span_test.cpp headers to standard LLVM style.

* Add unit tests for copy assignment, rvalue temporaries, and converting assignment.

Assisted-by: Automated tooling, human reviewed.

---
Full diff: https://github.com/llvm/llvm-project/pull/220619.diff


2 Files Affected:

- (modified) libc/src/__support/CPP/span.h (+9-3) 
- (modified) libc/test/src/__support/CPP/span_test.cpp (+80-3) 


``````````diff
diff --git a/libc/src/__support/CPP/span.h b/libc/src/__support/CPP/span.h
index 9234a26d201cd..859ba24d1442e 100644
--- a/libc/src/__support/CPP/span.h
+++ b/libc/src/__support/CPP/span.h
@@ -1,10 +1,15 @@
-//===-- Standalone implementation std::span ---------------------*- C++ -*-===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation of cpp::span.
+///
+//===----------------------------------------------------------------------===//
 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_SPAN_H
 #define LLVM_LIBC_SRC___SUPPORT_CPP_SPAN_H
 
@@ -55,6 +60,7 @@ template <typename T> class span {
   LIBC_INLINE constexpr span() : span_data(nullptr), span_size(0) {}
 
   LIBC_INLINE constexpr span(const span &) = default;
+  LIBC_INLINE constexpr span &operator=(const span &) = default;
 
   LIBC_INLINE constexpr span(pointer first, size_type count)
       : span_data(first), span_size(count) {}
@@ -72,11 +78,11 @@ template <typename T> class span {
       : span_data(arr.data()), span_size(arr.size()) {}
 
   template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
-  LIBC_INLINE constexpr span(span<U> &s)
+  LIBC_INLINE constexpr span(const span<U> &s)
       : span_data(s.data()), span_size(s.size()) {}
 
   template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
-  LIBC_INLINE constexpr span &operator=(span<U> &s) {
+  LIBC_INLINE constexpr span &operator=(const span<U> &s) {
     span_data = s.data();
     span_size = s.size();
     return *this;
diff --git a/libc/test/src/__support/CPP/span_test.cpp b/libc/test/src/__support/CPP/span_test.cpp
index 6da06c31e7adf..9d83e722c69c6 100644
--- a/libc/test/src/__support/CPP/span_test.cpp
+++ b/libc/test/src/__support/CPP/span_test.cpp
@@ -1,10 +1,15 @@
-//===-- Unittests for span ------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unit tests for cpp::span.
+///
+//===----------------------------------------------------------------------===//
 
 #include "src/__support/CPP/array.h"
 #include "src/__support/CPP/span.h"
@@ -82,9 +87,25 @@ TEST(LlvmLibcSpanTest, InitializeViewFormMutableArray) {
 }
 
 TEST(LlvmLibcSpanTest, InitializeFromMutable) {
-  span<int> s;
+  int a[] = {1, 2, 3};
+  span<int> s(a);
   span<const int> view(s);
-  (void)view;
+  ASSERT_EQ(view.size(), size_t(3));
+  ASSERT_TRUE(view.data() == &a[0]);
+  ASSERT_EQ(view[0], 1);
+  ASSERT_EQ(view[1], 2);
+  ASSERT_EQ(view[2], 3);
+
+  const span<int> const_s(a);
+  span<const int> view_from_const(const_s);
+  ASSERT_EQ(view_from_const.size(), size_t(3));
+  ASSERT_TRUE(view_from_const.data() == &a[0]);
+
+  span<const int> view_from_rvalue(s.subspan(1));
+  ASSERT_EQ(view_from_rvalue.size(), size_t(2));
+  ASSERT_TRUE(view_from_rvalue.data() == &a[1]);
+  ASSERT_EQ(view_from_rvalue[0], 2);
+  ASSERT_EQ(view_from_rvalue[1], 3);
 }
 
 TEST(LlvmLibcSpanTest, Assign) {
@@ -93,12 +114,68 @@ TEST(LlvmLibcSpanTest, Assign) {
   other = s;
 }
 
+TEST(LlvmLibcSpanTest, CopyAssignment) {
+  int a[] = {1, 2, 3};
+  span<int> s1(a);
+  span<int> s2;
+  s2 = s1;
+  ASSERT_EQ(s2.size(), size_t(3));
+  ASSERT_TRUE(s2.data() == &a[0]);
+  ASSERT_EQ(s2[0], 1);
+  ASSERT_EQ(s2[1], 2);
+  ASSERT_EQ(s2[2], 3);
+}
+
+TEST(LlvmLibcSpanTest, ReassignFromRValueTemporary) {
+  int a[] = {1, 2, 3, 4};
+  span<int> s(a);
+  s = s.subspan(1);
+  ASSERT_EQ(s.size(), size_t(3));
+  ASSERT_TRUE(s.data() == &a[1]);
+  ASSERT_EQ(s[0], 2);
+  ASSERT_EQ(s[1], 3);
+  ASSERT_EQ(s[2], 4);
+
+  s = span<int>();
+  ASSERT_EQ(s.size(), size_t(0));
+  ASSERT_TRUE(s.empty());
+  ASSERT_TRUE(s.data() == nullptr);
+}
+
 TEST(LlvmLibcSpanTest, AssignFromMutable) {
   span<int> s;
   span<const int> view;
   view = s;
 }
 
+TEST(LlvmLibcSpanTest, ConvertingAssignment) {
+  int a[] = {1, 2, 3};
+  span<int> s(a);
+  span<const int> view;
+  view = s;
+  ASSERT_EQ(view.size(), size_t(3));
+  ASSERT_TRUE(view.data() == &a[0]);
+  ASSERT_EQ(view[0], 1);
+  ASSERT_EQ(view[1], 2);
+  ASSERT_EQ(view[2], 3);
+
+  view = s.subspan(1);
+  ASSERT_EQ(view.size(), size_t(2));
+  ASSERT_TRUE(view.data() == &a[1]);
+  ASSERT_EQ(view[0], 2);
+  ASSERT_EQ(view[1], 3);
+
+  const span<int> const_s(a);
+  view = const_s;
+  ASSERT_EQ(view.size(), size_t(3));
+  ASSERT_TRUE(view.data() == &a[0]);
+
+  view = span<int>();
+  ASSERT_EQ(view.size(), size_t(0));
+  ASSERT_TRUE(view.empty());
+  ASSERT_TRUE(view.data() == nullptr);
+}
+
 TEST(LlvmLibcSpanTest, Modify) {
   int a[] = {1, 2, 3};
   span<int> s(a);

``````````

</details>


https://github.com/llvm/llvm-project/pull/220619


More information about the libc-commits mailing list