Skip to content

[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

Merged
merged 4 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions libcxx/include/__random/seed_seq.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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++
Copy link
Member

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.

Suggested change
// REQUIRES: stdlib=libc++

Copy link
Member Author

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.

Copy link
Member

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.


#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
}
}