diff options
author | Louis Dionne <ldionne.2@gmail.com> | 2024-04-03 06:06:52 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-03 06:06:52 -0400 |
commit | ca48d4dfd3148d83f9a74737f08174f16177200f (patch) | |
tree | 682cedffddbbef0654e7ac73c09d9f184133a536 | |
parent | bf1df250487584ec77b0ab567cd3cca5c2863270 (diff) | |
download | llvm-ca48d4dfd3148d83f9a74737f08174f16177200f.zip llvm-ca48d4dfd3148d83f9a74737f08174f16177200f.tar.gz llvm-ca48d4dfd3148d83f9a74737f08174f16177200f.tar.bz2 |
[libc++] Add a static_assert for a Mandates in seed_seq (#86992)
Fixes #84843
-rw-r--r-- | libcxx/include/__random/seed_seq.h | 6 | ||||
-rw-r--r-- | libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/generate.mandates.verify.cpp | 58 |
2 files changed, 64 insertions, 0 deletions
diff --git a/libcxx/include/__random/seed_seq.h b/libcxx/include/__random/seed_seq.h index 7e98887..5cf84ae 100644 --- a/libcxx/include/__random/seed_seq.h +++ b/libcxx/include/__random/seed_seq.h @@ -14,6 +14,7 @@ #include <__algorithm/max.h> #include <__config> #include <__iterator/iterator_traits.h> +#include <__type_traits/is_unsigned.h> #include <cstdint> #include <initializer_list> #include <vector> @@ -79,6 +80,11 @@ void seed_seq::__init(_InputIterator __first, _InputIterator __last) { template <class _RandomAccessIterator> void seed_seq::generate(_RandomAccessIterator __first, _RandomAccessIterator __last) { + using _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type; + static_assert(is_unsigned<_ValueType>::value && sizeof(_ValueType) >= sizeof(uint32_t), + "[rand.util.seedseq]/7 requires the value_type of the iterator to be an unsigned " + "integer capable of accommodating 32-bit quantities."); + if (__first != __last) { std::fill(__first, __last, 0x8b8b8b8b); const size_t __n = static_cast<size_t>(__last - __first); diff --git a/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/generate.mandates.verify.cpp b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/generate.mandates.verify.cpp new file mode 100644 index 0000000..a8ea31b --- /dev/null +++ b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/generate.mandates.verify.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// 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 RandomAccessIterator> +// void generate(RandomAccessIterator begin, RandomAccessIterator end); + +// Check the following requirement: https://eel.is/c++draft/rand.util.seedseq#7 +// +// Mandates: iterator_traits<RandomAccessIterator>::value_type is an unsigned integer +// type capable of accommodating 32-bit quantities. + +// UNSUPPORTED: c++03 +// REQUIRES: stdlib=libc++ + +#include <random> +#include <climits> + +#include "test_macros.h" + +void f() { + std::seed_seq seq; + + // Not an integral type + { + double* p = nullptr; + seq.generate(p, p); // expected-error-re@*:* {{static assertion failed{{.+}}: [rand.util.seedseq]/7 requires{{.+}}}} + // expected-error@*:* 0+ {{invalid operands to}} + } + + // Not an unsigned type + { + long long* p = nullptr; + seq.generate(p, p); // expected-error-re@*:* {{static assertion failed{{.+}}: [rand.util.seedseq]/7 requires{{.+}}}} + } + + // Not a 32-bit type + { +#if UCHAR_MAX < UINT32_MAX + unsigned char* p = nullptr; + seq.generate(p, p); // expected-error-re@*:* {{static assertion failed{{.+}}: [rand.util.seedseq]/7 requires{{.+}}}} +#endif + } + + // Everything satisfied + { + unsigned long* p = nullptr; + seq.generate(p, p); // no diagnostic + } +} |