[libcxx-commits] [libcxx] a3255f2 - [libc++] Explicitly reject `uniform_int_distribution<bool>` and `<char>`.

Arthur O'Dwyer via libcxx-commits libcxx-commits at lists.llvm.org
Mon Feb 28 11:59:19 PST 2022


Author: Arthur O'Dwyer
Date: 2022-02-28T14:57:53-05:00
New Revision: a3255f219a861fd91423def693e1b3ab3e012bec

URL: https://github.com/llvm/llvm-project/commit/a3255f219a861fd91423def693e1b3ab3e012bec
DIFF: https://github.com/llvm/llvm-project/commit/a3255f219a861fd91423def693e1b3ab3e012bec.diff

LOG: [libc++] Explicitly reject `uniform_int_distribution<bool>` and `<char>`.

`uniform_int_distribution<T>` is UB unless `T` is one of the non-character,
non-boolean integer types (`short` or larger). However, libc++ has never
enforced this. D114129 accidentally made `uniform_int_distribution<bool>`
into an error. Make it now *intentionally* an error; and likewise for the
character types and all user-defined class and enum types; but permit
`__[u]int128_t` to continue working.

Apply the same static_assert to all the integer distributions.

Differential Revision: https://reviews.llvm.org/D114920

Added: 
    libcxx/include/__random/is_valid.h
    libcxx/test/libcxx/diagnostics/detail.headers/random/is_valid.header.verify.cpp
    libcxx/test/libcxx/diagnostics/detail.headers/random/is_valid.module.verify.cpp
    libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp

Modified: 
    libcxx/docs/ReleaseNotes.rst
    libcxx/include/CMakeLists.txt
    libcxx/include/__random/binomial_distribution.h
    libcxx/include/__random/discrete_distribution.h
    libcxx/include/__random/geometric_distribution.h
    libcxx/include/__random/negative_binomial_distribution.h
    libcxx/include/__random/poisson_distribution.h
    libcxx/include/__random/uniform_int_distribution.h
    libcxx/include/module.modulemap
    libcxx/include/random

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index 86a9bc0c504f6..42280671f3bc3 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -58,6 +58,13 @@ API Changes
   namespace ``std``, it might be because one of your source files now needs to
   ``#include <algorithm>`` and/or ``#include <chrono>``.
 
+- 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<int8_t>`` is no longer supported.
+
 ABI Changes
 -----------
 

diff  --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index ce7954b0440f1..bf8a7c8d5bac3 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -313,6 +313,7 @@ set(files
   __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
index 31a11f7a99655..6447d3d22eb28 100644
--- 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 <cmath>
 #include <iosfwd>
@@ -27,6 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template<class _IntType = int>
 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
index 95e19da0b88c8..7e5a6b77ae9b7 100644
--- 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 <cstddef>
 #include <iosfwd>
@@ -30,6 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template<class _IntType = int>
 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
index 72838176aabfc..e565eb783a7f0 100644
--- 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 <iosfwd>
 #include <limits>
@@ -27,6 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template<class _IntType = int>
 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
index 0000000000000..553f5dde80f09
--- /dev/null
+++ b/libcxx/include/__random/is_valid.h
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#  pragma clang include_instead(<random>)
+#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<class> struct __libcpp_random_is_valid_inttype : false_type {};
+template<> struct __libcpp_random_is_valid_inttype<short> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<int> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<long> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<long long> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<unsigned short> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<unsigned int> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<unsigned long> : true_type {};
+template<> struct __libcpp_random_is_valid_inttype<unsigned long long> : 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
index b16e0be7a74df..3aff91089666d 100644
--- 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 <iosfwd>
 #include <limits>
@@ -29,6 +30,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template<class _IntType = int>
 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
index 72173c6733018..e2df27f4d70ca 100644
--- 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 <cmath>
@@ -31,6 +32,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template<class _IntType = int>
 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
index 630d724c20eef..844ad5f70cb28 100644
--- 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 <bit>
 #include <cstddef>
@@ -156,9 +157,10 @@ __independent_bits_engine<_Engine, _UIntType>::__eval(true_type)
     return _Sp;
 }
 
-template<class _IntType = int> // __int128_t is also supported as an extension here
+template<class _IntType = int>
 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
index ecfe080d325a0..294abd4db9bec 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -764,6 +764,7 @@ module std [system] {
       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
index cf1ac2443afc2..0323c447618cb 100644
--- a/libcxx/include/random
+++ b/libcxx/include/random
@@ -1694,6 +1694,7 @@ class piecewise_linear_distribution
 #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
index 0000000000000..dab714a0f041b
--- /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 at -1 {{header '<__random/is_valid.h>' is an implementation detail; #include '<random>' 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
index 0000000000000..0f1b3c67a3672
--- /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
index 0000000000000..1c3be49f089ec
--- /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
+//
+//===----------------------------------------------------------------------===//
+
+// <random>
+
+#include <random>
+
+void test()
+{
+  {
+    std::binomial_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+    std::binomial_distribution<int> okdist;
+    (void)baddist;
+    (void)okdist;
+  }
+  {
+    std::discrete_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+    std::discrete_distribution<int> okdist;
+    (void)baddist;
+    (void)okdist;
+  }
+  {
+    std::geometric_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+    std::geometric_distribution<int> okdist;
+    (void)baddist;
+    (void)okdist;
+  }
+  {
+    std::negative_binomial_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+    std::negative_binomial_distribution<int> okdist;
+    (void)baddist;
+    (void)okdist;
+  }
+  {
+    std::poisson_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+    std::poisson_distribution<int> okdist;
+    (void)baddist;
+    (void)okdist;
+  }
+  {
+    std::uniform_int_distribution<bool> baddist; //expected-error@*:* {{IntType must be an integer type larger than char}}
+    std::uniform_int_distribution<int> okdist;
+    (void)baddist;
+    (void)okdist;
+  }
+}


        


More information about the libcxx-commits mailing list