-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[libc++] Add a static_assert for a Mandates in seed_seq #86992
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
Conversation
@llvm/pr-subscribers-libcxx Author: Louis Dionne (ldionne) ChangesFixes #84843 Full diff: https://github.com/llvm/llvm-project/pull/86992.diff 2 Files Affected:
diff --git a/libcxx/include/__random/seed_seq.h b/libcxx/include/__random/seed_seq.h
index 7e9888768ed931..d0dee4c3c0baad 100644
--- a/libcxx/include/__random/seed_seq.h
+++ b/libcxx/include/__random/seed_seq.h
@@ -14,6 +14,8 @@
#include <__algorithm/max.h>
#include <__config>
#include <__iterator/iterator_traits.h>
+#include <__type_traits/is_unsigned.h>
+#include <climits>
#include <cstdint>
#include <initializer_list>
#include <vector>
@@ -79,6 +81,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) * CHAR_BIT >= 32,
+ "[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 00000000000000..4320f4e32377dd
--- /dev/null
+++ b/libcxx/test/std/numerics/rand/rand.util/rand.util.seedseq/generate.mandates.verify.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 the value_type of the iterator {{.+}}}}
+ // 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 the value_type of the iterator {{.+}}}}
+ }
+
+ // Not a 32-bit type
+ {
+ static_assert(sizeof(unsigned char) * CHAR_BIT < 32, "the test doesn't work on this platform");
+ unsigned char* p = nullptr;
+ seq.generate(p, p); // expected-error-re@*:* {{static assertion failed{{.+}}: [rand.util.seedseq]/7 requires the value_type of the iterator {{.+}}}}
+ }
+
+ // Everything satisfied
+ {
+ unsigned long* p = nullptr;
+ seq.generate(p, p); // no diagnostic
+ }
+}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM modulo some comments.
// type capable of accommodating 32-bit quantities. | ||
|
||
// UNSUPPORTED: c++03 | ||
// REQUIRES: stdlib=libc++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an implicit requirement of verify
tests.
// REQUIRES: stdlib=libc++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a requirement of Clang (until/unless we start implementing these kinds of tests for GCC too, which would be doable). But technically we could totally have .verify.cpp
tests for other standard libraries as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, I've never seen it in other verify tests.
|
||
// Not a 32-bit type | ||
{ | ||
static_assert(sizeof(unsigned char) * CHAR_BIT < 32, "the test doesn't work on this platform"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use std::uint32_t
here too.
Or maybe if this works with FileCheck.
#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
Fixes #84843