Skip to content

[libc++] Add missing noexcept to span constructor #94381

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 5, 2024

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Jun 4, 2024

Thanks to Marshall Clow for noticing.
Fixes #94364

Thanks to Marshal Clow for noticing.
Fixes llvm#94364
@ldionne ldionne requested a review from a team as a code owner June 4, 2024 16:57
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jun 4, 2024
@llvmbot
Copy link
Member

llvmbot commented Jun 4, 2024

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

Thanks to Marshal Clow for noticing.
Fixes #94364


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

2 Files Affected:

  • (modified) libcxx/include/span (+2-1)
  • (modified) libcxx/test/std/containers/views/views.span/span.cons/span.pass.cpp (+74-71)
diff --git a/libcxx/include/span b/libcxx/include/span
index 0307edcb55c30..11006b74fbb58 100644
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -294,7 +294,8 @@ public:
   }
 
   template <__span_array_convertible<element_type> _OtherElementType>
-  _LIBCPP_HIDE_FROM_ABI constexpr span(const span<_OtherElementType, _Extent>& __other) : __data_{__other.data()} {}
+  _LIBCPP_HIDE_FROM_ABI constexpr span(const span<_OtherElementType, _Extent>& __other) noexcept
+      : __data_{__other.data()} {}
 
   template <__span_array_convertible<element_type> _OtherElementType>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other) noexcept
diff --git a/libcxx/test/std/containers/views/views.span/span.cons/span.pass.cpp b/libcxx/test/std/containers/views/views.span/span.cons/span.pass.cpp
index edf983ec3e243..a1ac0dd11b2d1 100644
--- a/libcxx/test/std/containers/views/views.span/span.cons/span.pass.cpp
+++ b/libcxx/test/std/containers/views/views.span/span.cons/span.pass.cpp
@@ -16,103 +16,106 @@
 //      Extent == dynamic_extent || Extent == OtherExtent is true, and
 //      OtherElementType(*)[] is convertible to ElementType(*)[].
 
-
 #include <span>
 #include <cassert>
 #include <string>
 
 #include "test_macros.h"
 
-void checkCV()
-{
-    std::span<               int>   sp;
-//  std::span<const          int>  csp;
-    std::span<      volatile int>  vsp;
-//  std::span<const volatile int> cvsp;
+template <class T, class From>
+TEST_CONSTEXPR_CXX20 void check() {
+  // dynamic -> dynamic
+  {
+    {
+      std::span<From> from;
+      std::span<T> span{from};
+      ASSERT_NOEXCEPT(std::span<T>(from));
+      assert(span.data() == nullptr);
+      assert(span.size() == 0);
+    }
+    {
+      From array[3] = {};
+      std::span<From> from(array);
+      std::span<T> span{from};
+      ASSERT_NOEXCEPT(std::span<T>(from));
+      assert(span.data() == array);
+      assert(span.size() == 3);
+    }
+  }
 
-    std::span<               int, 0>   sp0;
-//  std::span<const          int, 0>  csp0;
-    std::span<      volatile int, 0>  vsp0;
-//  std::span<const volatile int, 0> cvsp0;
+  // static -> static
+  {
+    {
+      std::span<From, 0> from;
+      std::span<T, 0> span{from};
+      ASSERT_NOEXCEPT(std::span<T, 0>(from));
+      assert(span.data() == nullptr);
+      assert(span.size() == 0);
+    }
 
-//  dynamic -> dynamic
     {
-        std::span<const          int> s1{  sp}; // a span<const          int> pointing at int.
-        std::span<      volatile int> s2{  sp}; // a span<      volatile int> pointing at int.
-        std::span<const volatile int> s3{  sp}; // a span<const volatile int> pointing at int.
-        std::span<const volatile int> s4{ vsp}; // a span<const volatile int> pointing at volatile int.
-        assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+      From array[3] = {};
+      std::span<From, 3> from(array);
+      std::span<T, 3> span{from};
+      ASSERT_NOEXCEPT(std::span<T, 3>(from));
+      assert(span.data() == array);
+      assert(span.size() == 3);
     }
+  }
 
-//  static -> static
+  // static -> dynamic
+  {
     {
-        std::span<const          int, 0> s1{  sp0}; // a span<const          int> pointing at int.
-        std::span<      volatile int, 0> s2{  sp0}; // a span<      volatile int> pointing at int.
-        std::span<const volatile int, 0> s3{  sp0}; // a span<const volatile int> pointing at int.
-        std::span<const volatile int, 0> s4{ vsp0}; // a span<const volatile int> pointing at volatile int.
-        assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+      std::span<From, 0> from;
+      std::span<T> span{from};
+      ASSERT_NOEXCEPT(std::span<T>(from));
+      assert(span.data() == nullptr);
+      assert(span.size() == 0);
     }
 
-//  static -> dynamic
     {
-        std::span<const          int> s1{  sp0};    // a span<const          int> pointing at int.
-        std::span<      volatile int> s2{  sp0};    // a span<      volatile int> pointing at int.
-        std::span<const volatile int> s3{  sp0};    // a span<const volatile int> pointing at int.
-        std::span<const volatile int> s4{ vsp0};    // a span<const volatile int> pointing at volatile int.
-        assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
+      From array[3] = {};
+      std::span<From, 3> from(array);
+      std::span<T> span{from};
+      ASSERT_NOEXCEPT(std::span<T>(from));
+      assert(span.data() == array);
+      assert(span.size() == 3);
     }
+  }
 
-//  dynamic -> static (not allowed)
+  // dynamic -> static (not allowed)
 }
 
+template <class T>
+TEST_CONSTEXPR_CXX20 void check_cvs() {
+  check<T, T>();
 
-template <typename T>
-constexpr bool testConstexprSpan()
-{
-    std::span<T>    s0{};
-    std::span<T, 0> s1{};
-    std::span<T>    s2(s1); // static -> dynamic
-    ASSERT_NOEXCEPT(std::span<T>   {s0});
-    ASSERT_NOEXCEPT(std::span<T, 0>{s1});
-    ASSERT_NOEXCEPT(std::span<T>   {s1});
+  check<T const, T>();
+  check<T const, T const>();
 
-    return
-        s1.data() == nullptr && s1.size() == 0
-    &&  s2.data() == nullptr && s2.size() == 0;
-}
-
-
-template <typename T>
-void testRuntimeSpan()
-{
-    std::span<T>    s0{};
-    std::span<T, 0> s1{};
-    std::span<T>    s2(s1); // static -> dynamic
-    ASSERT_NOEXCEPT(std::span<T>   {s0});
-    ASSERT_NOEXCEPT(std::span<T, 0>{s1});
-    ASSERT_NOEXCEPT(std::span<T>   {s1});
+  check<T volatile, T>();
+  check<T volatile, T volatile>();
 
-    assert(s1.data() == nullptr && s1.size() == 0);
-    assert(s2.data() == nullptr && s2.size() == 0);
+  check<T const volatile, T>();
+  check<T const volatile, T const>();
+  check<T const volatile, T volatile>();
+  check<T const volatile, T const volatile>();
 }
 
+struct A {};
 
-struct A{};
-
-int main(int, char**)
-{
-    static_assert(testConstexprSpan<int>(),    "");
-    static_assert(testConstexprSpan<long>(),   "");
-    static_assert(testConstexprSpan<double>(), "");
-    static_assert(testConstexprSpan<A>(),      "");
-
-    testRuntimeSpan<int>();
-    testRuntimeSpan<long>();
-    testRuntimeSpan<double>();
-    testRuntimeSpan<std::string>();
-    testRuntimeSpan<A>();
+TEST_CONSTEXPR_CXX20 bool test() {
+  check_cvs<int>();
+  check_cvs<long>();
+  check_cvs<double>();
+  check_cvs<std::string>();
+  check_cvs<A>();
+  return true;
+}
 
-    checkCV();
+int main(int, char**) {
+  static_assert(test());
+  test();
 
   return 0;
 }

Copy link
Member

@EricWF EricWF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@ldionne ldionne merged commit 38bf684 into llvm:main Jun 5, 2024
57 checks passed
@ldionne ldionne deleted the review/span-noexcept-constructor branch June 5, 2024 14:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Does libc++'s span have a non-standard converting constructor?
3 participants