diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -58,6 +58,13 @@ namespace ``std``, it might be because one of your source files now needs to ``#include `` and/or ``#include ``. +- The integer distributions ``binomial_distribution``, ``discrete_distribution``, + ``geometric_distribution``, ``negative_binomial_distribution``, ``poisson_distribution``, + and ``uniform_int_distribution`` now conform to the Standard by rejecting + template parameter types other than ``short``, ``int``, ``long``, ``long long``, + (as an extension) ``__int128_t``, and the unsigned versions thereof. + In particular, ``uniform_int_distribution`` is no longer supported. + ABI Changes ----------- diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -313,6 +313,7 @@ __random/geometric_distribution.h __random/independent_bits_engine.h __random/is_seed_sequence.h + __random/is_valid.h __random/knuth_b.h __random/linear_congruential_engine.h __random/log2.h diff --git a/libcxx/include/__random/binomial_distribution.h b/libcxx/include/__random/binomial_distribution.h --- a/libcxx/include/__random/binomial_distribution.h +++ b/libcxx/include/__random/binomial_distribution.h @@ -10,6 +10,7 @@ #define _LIBCPP___RANDOM_BINOMIAL_DISTRIBUTION_H #include <__config> +#include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> #include #include @@ -27,6 +28,7 @@ template class _LIBCPP_TEMPLATE_VIS binomial_distribution { + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); public: // types typedef _IntType result_type; diff --git a/libcxx/include/__random/discrete_distribution.h b/libcxx/include/__random/discrete_distribution.h --- a/libcxx/include/__random/discrete_distribution.h +++ b/libcxx/include/__random/discrete_distribution.h @@ -11,6 +11,7 @@ #include <__algorithm/upper_bound.h> #include <__config> +#include <__random/is_valid.h> #include <__random/uniform_real_distribution.h> #include #include @@ -30,6 +31,7 @@ template class _LIBCPP_TEMPLATE_VIS discrete_distribution { + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); public: // types typedef _IntType result_type; diff --git a/libcxx/include/__random/geometric_distribution.h b/libcxx/include/__random/geometric_distribution.h --- a/libcxx/include/__random/geometric_distribution.h +++ b/libcxx/include/__random/geometric_distribution.h @@ -10,6 +10,7 @@ #define _LIBCPP___RANDOM_GEOMETRIC_DISTRIBUTION_H #include <__config> +#include <__random/is_valid.h> #include <__random/negative_binomial_distribution.h> #include #include @@ -27,6 +28,7 @@ template class _LIBCPP_TEMPLATE_VIS geometric_distribution { + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); public: // types typedef _IntType result_type; diff --git a/libcxx/include/__random/is_valid.h b/libcxx/include/__random/is_valid.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__random/is_valid.h @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANDOM_IS_VALID_H +#define _LIBCPP___RANDOM_IS_VALID_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// [rand.req.genl]/1.5: +// The effect of instantiating a template that has a template type parameter +// named IntType is undefined unless the corresponding template argument is +// cv-unqualified and is one of short, int, long, long long, unsigned short, +// unsigned int, unsigned long, or unsigned long long. + +template struct __libcpp_random_is_valid_inttype : false_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; +template<> struct __libcpp_random_is_valid_inttype : true_type {}; + +#ifndef _LIBCPP_HAS_NO_INT128 +template<> struct __libcpp_random_is_valid_inttype<__int128_t> : true_type {}; +template<> struct __libcpp_random_is_valid_inttype<__uint128_t> : true_type {}; +#endif // _LIBCPP_HAS_NO_INT128 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANDOM_IS_VALID_H diff --git a/libcxx/include/__random/negative_binomial_distribution.h b/libcxx/include/__random/negative_binomial_distribution.h --- a/libcxx/include/__random/negative_binomial_distribution.h +++ b/libcxx/include/__random/negative_binomial_distribution.h @@ -12,6 +12,7 @@ #include <__config> #include <__random/bernoulli_distribution.h> #include <__random/gamma_distribution.h> +#include <__random/is_valid.h> #include <__random/poisson_distribution.h> #include #include @@ -29,6 +30,7 @@ template class _LIBCPP_TEMPLATE_VIS negative_binomial_distribution { + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); public: // types typedef _IntType result_type; diff --git a/libcxx/include/__random/poisson_distribution.h b/libcxx/include/__random/poisson_distribution.h --- a/libcxx/include/__random/poisson_distribution.h +++ b/libcxx/include/__random/poisson_distribution.h @@ -12,6 +12,7 @@ #include <__config> #include <__random/clamp_to_integral.h> #include <__random/exponential_distribution.h> +#include <__random/is_valid.h> #include <__random/normal_distribution.h> #include <__random/uniform_real_distribution.h> #include @@ -31,6 +32,7 @@ template class _LIBCPP_TEMPLATE_VIS poisson_distribution { + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); public: // types typedef _IntType result_type; diff --git a/libcxx/include/__random/uniform_int_distribution.h b/libcxx/include/__random/uniform_int_distribution.h --- a/libcxx/include/__random/uniform_int_distribution.h +++ b/libcxx/include/__random/uniform_int_distribution.h @@ -11,6 +11,7 @@ #include <__bits> #include <__config> +#include <__random/is_valid.h> #include <__random/log2.h> #include #include @@ -156,9 +157,10 @@ return _Sp; } -template // __int128_t is also supported as an extension here +template class uniform_int_distribution { + static_assert(__libcpp_random_is_valid_inttype<_IntType>::value, "IntType must be an integer type larger than char"); public: // types typedef _IntType result_type; diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -764,6 +764,7 @@ module geometric_distribution { private header "__random/geometric_distribution.h" } module independent_bits_engine { private header "__random/independent_bits_engine.h" } module is_seed_sequence { private header "__random/is_seed_sequence.h" } + module is_valid { private header "__random/is_valid.h" } module knuth_b { private header "__random/knuth_b.h" } module linear_congruential_engine { private header "__random/linear_congruential_engine.h" } module log2 { private header "__random/log2.h" } diff --git a/libcxx/include/random b/libcxx/include/random --- a/libcxx/include/random +++ b/libcxx/include/random @@ -1694,6 +1694,7 @@ #include <__random/geometric_distribution.h> #include <__random/independent_bits_engine.h> #include <__random/is_seed_sequence.h> +#include <__random/is_valid.h> #include <__random/knuth_b.h> #include <__random/linear_congruential_engine.h> #include <__random/log2.h> diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/random/is_valid.header.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/random/is_valid.header.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/random/is_valid.header.verify.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: modules-build +// UNSUPPORTED: clang-11, clang-12, clang-13 +// UNSUPPORTED: apple-clang-11, apple-clang-12, apple-clang-13 +// UNSUPPORTED: gcc-11 +// UNSUPPORTED: libcpp-has-no-localization, libcpp-has-no-threads +// ADDITIONAL_COMPILE_FLAGS: -U_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +#include <__random/is_valid.h> +// expected-error@-1 {{header '<__random/is_valid.h>' is an implementation detail; #include '' instead}} diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/random/is_valid.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/random/is_valid.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/random/is_valid.module.verify.cpp @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__random/is_valid.h'}} +#include <__random/is_valid.h> diff --git a/libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp b/libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +#include + +void test() +{ + { + std::binomial_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::binomial_distribution okdist; + (void)baddist; + (void)okdist; + } + { + std::discrete_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::discrete_distribution okdist; + (void)baddist; + (void)okdist; + } + { + std::geometric_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::geometric_distribution okdist; + (void)baddist; + (void)okdist; + } + { + std::negative_binomial_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::negative_binomial_distribution okdist; + (void)baddist; + (void)okdist; + } + { + std::poisson_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::poisson_distribution okdist; + (void)baddist; + (void)okdist; + } + { + std::uniform_int_distribution baddist; //expected-error@*:* {{IntType must be an integer type larger than char}} + std::uniform_int_distribution okdist; + (void)baddist; + (void)okdist; + } +}