aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Dionne <ldionne.2@gmail.com>2024-04-03 06:06:52 -0400
committerGitHub <noreply@github.com>2024-04-03 06:06:52 -0400
commitca48d4dfd3148d83f9a74737f08174f16177200f (patch)
tree682cedffddbbef0654e7ac73c09d9f184133a536
parentbf1df250487584ec77b0ab567cd3cca5c2863270 (diff)
downloadllvm-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.h6
-rw-r--r--libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/generate.mandates.verify.cpp58
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
+ }
+}