Commit aeedf077 by Jonathan Wakely Committed by Jonathan Wakely

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
parent decc53df
2019-05-31 Jonathan Wakely <jwakely@redhat.com>
* 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 <dinka.ranns@gmail.com> 2019-05-30 Nina Dinka Ranns <dinka.ranns@gmail.com>
LWG2788 basic_string spurious use of a default constructible allocator LWG2788 basic_string spurious use of a default constructible allocator
......
...@@ -1648,6 +1648,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1648,6 +1648,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
result_type _M_getval_pretr1(); result_type _M_getval_pretr1();
double _M_getentropy() const noexcept; double _M_getentropy() const noexcept;
void _M_init(const char*, size_t); // not exported from the shared library
union union
{ {
struct struct
......
...@@ -35,61 +35,15 @@ ...@@ -35,61 +35,15 @@
#ifdef _GLIBCXX_USE_C99_STDINT_TR1 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
#include <random> #include <random>
#if defined __i386__ || defined __x86_64__
# include <cpuid.h>
#endif
#include <cstdio>
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
{ {
void void
random_device::_M_init(const std::string& token) random_device::_M_init(const std::string& token)
{ { _M_init(token.c_str(), token.length()); }
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<void*>(std::fopen(fname, "rb"));
if (!_M_file)
goto fail;
}
void void
random_device::_M_init_pretr1(const std::string& token) random_device::_M_init_pretr1(const std::string& token)
{ { _M_init(token.c_str(), token.length()); }
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);
}
} // namespace } // namespace
#endif #endif
...@@ -293,6 +293,18 @@ namespace std _GLIBCXX_VISIBILITY(default) ...@@ -293,6 +293,18 @@ namespace std _GLIBCXX_VISIBILITY(default)
#endif #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 void
random_device::_M_fini() random_device::_M_fini()
{ {
......
// { 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
// <http://www.gnu.org/licenses/>.
// C++11 26.5.6 class random_device [rand.device]
#include <random>
#include <testsuite_hooks.h>
void
test01()
{
std::random_device x;
auto n [[gnu::unused]] = x();
}
int main()
{
test01();
}
...@@ -21,8 +21,7 @@ ...@@ -21,8 +21,7 @@
// with this library; see the file COPYING3. If not see // with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// 26.4.6 class random_device [rand.device] // C++11 26.5.6 class random_device [rand.device]
// 26.4.2.2 Concept RandomNumberEngine [rand.concept.eng]
#include <random> #include <random>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
...@@ -32,8 +31,11 @@ test01() ...@@ -32,8 +31,11 @@ test01()
{ {
std::random_device x; std::random_device x;
VERIFY( x.min() == std::numeric_limits<std::random_device::result_type>::min() ); using result_type = std::random_device::result_type;
VERIFY( x.max() == std::numeric_limits<std::random_device::result_type>::max() ); VERIFY( x.min() == std::numeric_limits<result_type>::min() );
VERIFY( x.max() == std::numeric_limits<result_type>::max() );
result_type n [[gnu::unused]] = x();
} }
int main() int main()
......
...@@ -30,10 +30,9 @@ void ...@@ -30,10 +30,9 @@ void
test01() test01()
{ {
std::random_device x("default"); std::random_device x("default");
using result_type = std::random_device::result_type;
VERIFY( x.min() == std::numeric_limits<std::random_device::result_type>::min() ); VERIFY( x.min() == std::numeric_limits<result_type>::min() );
VERIFY( x.max() == std::numeric_limits<std::random_device::result_type>::max() ); VERIFY( x.max() == std::numeric_limits<result_type>::max() );
} }
void void
...@@ -42,6 +41,7 @@ test02() ...@@ -42,6 +41,7 @@ test02()
#ifdef _GLIBCXX_USE_DEV_RANDOM #ifdef _GLIBCXX_USE_DEV_RANDOM
std::random_device x1("/dev/urandom"); std::random_device x1("/dev/urandom");
std::random_device x2("/dev/random"); std::random_device x2("/dev/random");
VERIFY( x1() != x2() );
#endif #endif
} }
...@@ -50,7 +50,7 @@ test03() ...@@ -50,7 +50,7 @@ test03()
{ {
// At least one of these tokens should be valid. // At least one of these tokens should be valid.
const std::string tokens[] = { 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; int count = 0;
for (const std::string& token : tokens) for (const std::string& token : tokens)
...@@ -71,21 +71,25 @@ void ...@@ -71,21 +71,25 @@ void
test04() test04()
{ {
bool can_use_mt19937 = true; bool can_use_mt19937 = true;
std::random_device::result_type xval;
try try
{ {
std::random_device x("mt19937"); std::random_device x("mt19937");
xval = x();
} }
catch (const std::runtime_error&) catch (const std::runtime_error&)
{ {
can_use_mt19937 = false; 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) if (can_use_mt19937)
{ {
std::random_device x1("0"); std::random_device x1("0");
std::random_device x2("1234"); std::random_device x2("1234");
std::random_device x3("0xc0fefe"); std::random_device x3("0xc0fefe");
VERIFY( xval != x1() );
VERIFY( x2() != x3() );
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment