From aeedf0770557f01e46b95c220496e1b6d8b96149 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 31 May 2019 11:34:53 +0100 Subject: [PATCH] Fix random_device to work with COW strings again Instead of duplicating the initialization functions that take string, add a new member taking a raw pointer that can be used to convert the constructor token from the old string to the new. Also fix "mt19337" typos in a testcase. * include/bits/random.h (random_device::_M_init(const char*, size_t)): Add new private member function. * src/c++11/cow-string-inst.cc (random_device::_M_init(const string&)) (random_device::_M_init_pretr1(const string&)): Call new private member with string data. * src/c++11/random.cc (random_device::_M_init(const char*, size_t)): Define. * testsuite/26_numerics/random/random_device/cons/default-cow.cc: New test using COW strings. * testsuite/26_numerics/random/random_device/cons/default.cc: Generate a value from the device. * testsuite/26_numerics/random/random_device/cons/token.cc: Likewise. Fix typo in token string. From-SVN: r271805 --- libstdc++-v3/ChangeLog | 16 +++++++ libstdc++-v3/include/bits/random.h | 2 + libstdc++-v3/src/c++11/cow-string-inst.cc | 50 +--------------------- libstdc++-v3/src/c++11/random.cc | 12 ++++++ .../random/random_device/cons/default-cow.cc | 38 ++++++++++++++++ .../random/random_device/cons/default.cc | 10 +++-- .../26_numerics/random/random_device/cons/token.cc | 16 ++++--- 7 files changed, 86 insertions(+), 58 deletions(-) create mode 100644 libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default-cow.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index cd535fe..71ef811 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,19 @@ +2019-05-31 Jonathan Wakely + + * include/bits/random.h (random_device::_M_init(const char*, size_t)): + Add new private member function. + * src/c++11/cow-string-inst.cc (random_device::_M_init(const string&)) + (random_device::_M_init_pretr1(const string&)): Call new private + member with string data. + * src/c++11/random.cc (random_device::_M_init(const char*, size_t)): + Define. + * testsuite/26_numerics/random/random_device/cons/default-cow.cc: New + test using COW strings. + * testsuite/26_numerics/random/random_device/cons/default.cc: Generate + a value from the device. + * testsuite/26_numerics/random/random_device/cons/token.cc: Likewise. + Fix typo in token string. + 2019-05-30 Nina Dinka Ranns LWG2788 basic_string spurious use of a default constructible allocator diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 9c959d6..e63dbcf 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -1648,6 +1648,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION result_type _M_getval_pretr1(); double _M_getentropy() const noexcept; + void _M_init(const char*, size_t); // not exported from the shared library + union { struct diff --git a/libstdc++-v3/src/c++11/cow-string-inst.cc b/libstdc++-v3/src/c++11/cow-string-inst.cc index c36f297..107a457 100644 --- a/libstdc++-v3/src/c++11/cow-string-inst.cc +++ b/libstdc++-v3/src/c++11/cow-string-inst.cc @@ -35,61 +35,15 @@ #ifdef _GLIBCXX_USE_C99_STDINT_TR1 #include -#if defined __i386__ || defined __x86_64__ -# include -#endif -#include namespace std _GLIBCXX_VISIBILITY(default) { void random_device::_M_init(const std::string& token) - { - const char *fname = token.c_str(); - - if (token == "default") - { -#if (defined __i386__ || defined __x86_64__) && defined _GLIBCXX_X86_RDRAND - unsigned int eax, ebx, ecx, edx; - // Check availability of cpuid and, for now at least, also the - // CPU signature for Intel's - if (__get_cpuid_max(0, &ebx) > 0 && ebx == signature_INTEL_ebx) - { - __cpuid(1, eax, ebx, ecx, edx); - if (ecx & bit_RDRND) - { - _M_file = nullptr; - return; - } - } -#endif - - fname = "/dev/urandom"; - } - else if (token != "/dev/urandom" && token != "/dev/random") - fail: - std::__throw_runtime_error(__N("random_device::" - "random_device(const std::string&)")); - - _M_file = static_cast(std::fopen(fname, "rb")); - if (!_M_file) - goto fail; - } + { _M_init(token.c_str(), token.length()); } void random_device::_M_init_pretr1(const std::string& token) - { - unsigned long __seed = 5489UL; - if (token != "mt19937") - { - const char* __nptr = token.c_str(); - char* __endptr; - __seed = std::strtoul(__nptr, &__endptr, 0); - if (*__nptr == '\0' || *__endptr != '\0') - std::__throw_runtime_error(__N("random_device::random_device" - "(const std::string&)")); - } - _M_mt.seed(__seed); - } + { _M_init(token.c_str(), token.length()); } } // namespace #endif diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc index 85cb2df..10fbe1d 100644 --- a/libstdc++-v3/src/c++11/random.cc +++ b/libstdc++-v3/src/c++11/random.cc @@ -293,6 +293,18 @@ namespace std _GLIBCXX_VISIBILITY(default) #endif } + // Called by old ABI version of random_device::_M_init(const std::string&). + void + random_device::_M_init(const char* s, size_t len) + { + const std::string token(s, len); +#ifdef USE_MT19937 + _M_init_pretr1(token); +#else + _M_init(token); +#endif + } + void random_device::_M_fini() { diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default-cow.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default-cow.cc new file mode 100644 index 0000000..622801d --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default-cow.cc @@ -0,0 +1,38 @@ +// { dg-options "-D_GLIBCXX_USE_CXX11_ABI=0" } +// { dg-do run { target c++11 } } +// { dg-require-effective-target random_device } +// { dg-require-cstdint "" } +// +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// C++11 26.5.6 class random_device [rand.device] + +#include +#include + +void +test01() +{ + std::random_device x; + auto n [[gnu::unused]] = x(); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default.cc index 4fa1adf..ed03c54 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default.cc @@ -21,8 +21,7 @@ // with this library; see the file COPYING3. If not see // . -// 26.4.6 class random_device [rand.device] -// 26.4.2.2 Concept RandomNumberEngine [rand.concept.eng] +// C++11 26.5.6 class random_device [rand.device] #include #include @@ -32,8 +31,11 @@ test01() { std::random_device x; - VERIFY( x.min() == std::numeric_limits::min() ); - VERIFY( x.max() == std::numeric_limits::max() ); + using result_type = std::random_device::result_type; + VERIFY( x.min() == std::numeric_limits::min() ); + VERIFY( x.max() == std::numeric_limits::max() ); + + result_type n [[gnu::unused]] = x(); } int main() diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc index cf5e81e..31a86b0 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc @@ -30,10 +30,9 @@ void test01() { std::random_device x("default"); - - VERIFY( x.min() == std::numeric_limits::min() ); - VERIFY( x.max() == std::numeric_limits::max() ); - + using result_type = std::random_device::result_type; + VERIFY( x.min() == std::numeric_limits::min() ); + VERIFY( x.max() == std::numeric_limits::max() ); } void @@ -42,6 +41,7 @@ test02() #ifdef _GLIBCXX_USE_DEV_RANDOM std::random_device x1("/dev/urandom"); std::random_device x2("/dev/random"); + VERIFY( x1() != x2() ); #endif } @@ -50,7 +50,7 @@ test03() { // At least one of these tokens should be valid. const std::string tokens[] = { - "rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19337" + "rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19937" }; int count = 0; for (const std::string& token : tokens) @@ -71,21 +71,25 @@ void test04() { bool can_use_mt19937 = true; + std::random_device::result_type xval; try { std::random_device x("mt19937"); + xval = x(); } catch (const std::runtime_error&) { can_use_mt19937 = false; } - // If "mt19337" is a valid token then numeric seeds should be too. + // If "mt19937" is a valid token then numeric seeds should be too. if (can_use_mt19937) { std::random_device x1("0"); std::random_device x2("1234"); std::random_device x3("0xc0fefe"); + VERIFY( xval != x1() ); + VERIFY( x2() != x3() ); } } -- 2.7.4