[libcxx-commits] [libcxx] 8b29b84 - [libc++] Fix LWG3422 "Issues of seed_seq's constructors"

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jan 24 17:14:35 PST 2022


Author: Arthur O'Dwyer
Date: 2022-01-24T20:14:25-05:00
New Revision: 8b29b84c99ac8140c9820fd34b733bdedf5bb0f5

URL: https://github.com/llvm/llvm-project/commit/8b29b84c99ac8140c9820fd34b733bdedf5bb0f5
DIFF: https://github.com/llvm/llvm-project/commit/8b29b84c99ac8140c9820fd34b733bdedf5bb0f5.diff

LOG: [libc++] Fix LWG3422 "Issues of seed_seq's constructors"

https://cplusplus.github.io/LWG/issue3422

Also add a static_assert to check the "Mandates:" on the
iterator-pair constructor. Oddly, the `InputIterator` parameter
itself is merely preconditioned, not constrained, to satisfy the
input iterator requirements.

Also drive-by rename `init` to `__init`.

Differential Revision: https://reviews.llvm.org/D117962

Added: 
    libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.verify.cpp

Modified: 
    libcxx/docs/Status/Cxx2bIssues.csv
    libcxx/include/__random/seed_seq.h
    libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/default.pass.cpp
    libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv
index 9baefabe05da8..0ce504816fe3b 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -108,7 +108,7 @@
 `3361 <https://wg21.link/LWG3361>`__,"``safe_range<SomeRange&>`` case","October 2021","","","|ranges|"
 `3392 <https://wg21.link/LWG3392>`__,"``ranges::distance()`` cannot be used on a move-only iterator with a sized sentinel","October 2021","","","|ranges|"
 `3407 <https://wg21.link/LWG3407>`__,"Some problems with the wording changes of P1739R4","October 2021","","","|ranges|"
-`3422 <https://wg21.link/LWG3422>`__,"Issues of ``seed_seq``'s constructors","October 2021","",""
+`3422 <https://wg21.link/LWG3422>`__,"Issues of ``seed_seq``'s constructors","October 2021","|Complete|","14.0"
 `3470 <https://wg21.link/LWG3470>`__,"``convertible-to-non-slicing`` seems to reject valid case","October 2021","","","|ranges|"
 `3480 <https://wg21.link/LWG3480>`__,"``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","October 2021","|Complete|","14.0","|ranges|"
 `3498 <https://wg21.link/LWG3498>`__,"Inconsistent ``noexcept``-specifiers for ``basic_syncbuf``","October 2021","",""

diff  --git a/libcxx/include/__random/seed_seq.h b/libcxx/include/__random/seed_seq.h
index bf27af6627a54..1a0877995650e 100644
--- a/libcxx/include/__random/seed_seq.h
+++ b/libcxx/include/__random/seed_seq.h
@@ -31,25 +31,24 @@ class _LIBCPP_TEMPLATE_VIS seed_seq
     // types
     typedef uint32_t result_type;
 
-private:
-    vector<result_type> __v_;
-
-    template<class _InputIterator>
-        void init(_InputIterator __first, _InputIterator __last);
-public:
     // constructors
     _LIBCPP_INLINE_VISIBILITY
     seed_seq() _NOEXCEPT {}
 #ifndef _LIBCPP_CXX03_LANG
-    template<class _Tp>
-        _LIBCPP_INLINE_VISIBILITY
-        seed_seq(initializer_list<_Tp> __il) {init(__il.begin(), __il.end());}
+    template<class _Tp, __enable_if_t<is_integral<_Tp>::value>* = nullptr>
+    _LIBCPP_INLINE_VISIBILITY
+    seed_seq(initializer_list<_Tp> __il) {
+        __init(__il.begin(), __il.end());
+    }
 #endif // _LIBCPP_CXX03_LANG
 
     template<class _InputIterator>
-        _LIBCPP_INLINE_VISIBILITY
-        seed_seq(_InputIterator __first, _InputIterator __last)
-             {init(__first, __last);}
+    _LIBCPP_INLINE_VISIBILITY
+    seed_seq(_InputIterator __first, _InputIterator __last) {
+        static_assert(is_integral<typename iterator_traits<_InputIterator>::value_type>::value,
+            "Mandates: iterator_traits<InputIterator>::value_type is an integer type");
+        __init(__first, __last);
+    }
 
     // generating functions
     template<class _RandomAccessIterator>
@@ -68,11 +67,17 @@ class _LIBCPP_TEMPLATE_VIS seed_seq
 
     _LIBCPP_INLINE_VISIBILITY
     static result_type _Tp(result_type __x) {return __x ^ (__x >> 27);}
+
+private:
+    template<class _InputIterator>
+    void __init(_InputIterator __first, _InputIterator __last);
+
+    vector<result_type> __v_;
 };
 
 template<class _InputIterator>
 void
-seed_seq::init(_InputIterator __first, _InputIterator __last)
+seed_seq::__init(_InputIterator __first, _InputIterator __last)
 {
     for (_InputIterator __s = __first; __s != __last; ++__s)
         __v_.push_back(*__s & 0xFFFFFFFF);

diff  --git a/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/default.pass.cpp b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/default.pass.cpp
index 33f855bab30c3..c99d5e276b2b5 100644
--- a/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/default.pass.cpp
+++ b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/default.pass.cpp
@@ -19,8 +19,11 @@
 
 int main(int, char**)
 {
+  ASSERT_NOEXCEPT(std::seed_seq());
+  {
     std::seed_seq s;
     assert(s.size() == 0);
+  }
 
   return 0;
 }

diff  --git a/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.pass.cpp b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.pass.cpp
index 2e2c6365eb4f0..1dd9a055f7ca3 100644
--- a/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.pass.cpp
+++ b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.pass.cpp
@@ -18,11 +18,13 @@
 
 #include "test_macros.h"
 
-int main(int, char**)
+void test()
 {
+  {
     unsigned a[5] = {5, 4, 3, 2, 1};
     std::seed_seq s(a, a+5);
     assert(s.size() == 5);
+
     unsigned b[5] = {0};
     s.param(b);
     assert(b[0] == 5);
@@ -30,6 +32,44 @@ int main(int, char**)
     assert(b[2] == 3);
     assert(b[3] == 2);
     assert(b[4] == 1);
+  }
+  {
+    // Test truncation to 32 bits
+    unsigned long long a[4] = {
+      0x1234000056780000uLL,
+      0x0000001234567800uLL,
+      0xFFFFFFFFFFFFFFFFuLL,
+      0x0000000180000000uLL,
+    };
+    std::seed_seq s(a, a+4);
+    assert(s.size() == 4);
+
+    unsigned b[4] = {0};
+    s.param(b);
+    assert(b[0] == 0x56780000u);
+    assert(b[1] == 0x34567800u);
+    assert(b[2] == 0xFFFFFFFFu);
+    assert(b[3] == 0x80000000u);
+  }
+#if TEST_STD_VER >= 11
+  {
+    // Test uniform initialization syntax (LWG 3422)
+    unsigned a[3] = {1, 2, 3};
+    std::seed_seq s{a, a+3};  // uniform initialization
+    assert(s.size() == 3);
+
+    unsigned b[3] = {0};
+    s.param(b);
+    assert(b[0] == 1);
+    assert(b[1] == 2);
+    assert(b[2] == 3);
+  }
+#endif // TEST_STD_VER >= 11
+}
+
+int main(int, char**)
+{
+  test();
 
   return 0;
 }

diff  --git a/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.verify.cpp b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.verify.cpp
new file mode 100644
index 0000000000000..d5c57841c8fa2
--- /dev/null
+++ b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/iterator.verify.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <random>
+
+// class seed_seq;
+
+// template<class InputIterator>
+//   seed_seq(InputIterator begin, InputIterator end);
+// Mandates: iterator_traits<InputIterator>::value_type is an integer type.
+
+#include <random>
+
+void test()
+{
+  {
+    bool a[2] = {true, false};
+    std::seed_seq s(a, a+2); // OK
+  }
+  {
+    double a[2] = {1, 2};
+    std::seed_seq s(a, a+2); // expected-error@*:* {{Mandates: iterator_traits<InputIterator>::value_type is an integer type}}
+        // expected-error@*:* {{invalid operands to binary expression ('double' and 'unsigned int')}}
+  }
+}


        


More information about the libcxx-commits mailing list