diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv --- a/libcxx/docs/Status/Cxx2bIssues.csv +++ b/libcxx/docs/Status/Cxx2bIssues.csv @@ -108,7 +108,7 @@ `3361 `__,"``safe_range`` case","October 2021","","","|ranges|" `3392 `__,"``ranges::distance()`` cannot be used on a move-only iterator with a sized sentinel","October 2021","","","|ranges|" `3407 `__,"Some problems with the wording changes of P1739R4","October 2021","","","|ranges|" -`3422 `__,"Issues of ``seed_seq``'s constructors","October 2021","","" +`3422 `__,"Issues of ``seed_seq``'s constructors","October 2021","|Complete|","14.0" `3470 `__,"``convertible-to-non-slicing`` seems to reject valid case","October 2021","","","|ranges|" `3480 `__,"``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","October 2021","|Complete|","14.0","|ranges|" `3498 `__,"Inconsistent ``noexcept``-specifiers for ``basic_syncbuf``","October 2021","","" diff --git a/libcxx/include/__random/seed_seq.h b/libcxx/include/__random/seed_seq.h --- a/libcxx/include/__random/seed_seq.h +++ b/libcxx/include/__random/seed_seq.h @@ -31,25 +31,24 @@ // types typedef uint32_t result_type; -private: - vector __v_; - - template - void init(_InputIterator __first, _InputIterator __last); -public: // constructors _LIBCPP_INLINE_VISIBILITY seed_seq() _NOEXCEPT {} #ifndef _LIBCPP_CXX03_LANG - template - _LIBCPP_INLINE_VISIBILITY - seed_seq(initializer_list<_Tp> __il) {init(__il.begin(), __il.end());} + template::value>* = nullptr> + _LIBCPP_INLINE_VISIBILITY + seed_seq(initializer_list<_Tp> __il) { + __init(__il.begin(), __il.end()); + } #endif // _LIBCPP_CXX03_LANG template - _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::value_type>::value, + "Mandates: iterator_traits::value_type is an integer type"); + __init(__first, __last); + } // generating functions template @@ -68,11 +67,17 @@ _LIBCPP_INLINE_VISIBILITY static result_type _Tp(result_type __x) {return __x ^ (__x >> 27);} + +private: + template + void __init(_InputIterator __first, _InputIterator __last); + + vector __v_; }; template 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 --- 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 --- 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 @@ 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 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// class seed_seq; + +// template +// seed_seq(InputIterator begin, InputIterator end); +// Mandates: iterator_traits::value_type is an integer type. + +#include + +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::value_type is an integer type}} + // expected-error@*:* {{invalid operands to binary expression ('double' and 'unsigned int')}} + } +}