This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] PR libstdc++/85494 use rdseed and rand_s in std::random_device
On 31/05/19 10:47 +0100, Jonathan Wakely wrote:
On 31/05/19 10:46 +0100, Jonathan Wakely wrote:
On 31/05/19 09:26 +0000, Szabolcs Nagy wrote:
On 29/05/2019 23:03, Jonathan Wakely wrote:
This fixes a test that started to fail in mingw.
Tested x86_64-linux, powerpc64le-linux and x86_64-w64-ming32.
Committed to trunk.
note that the updated test fails on baremetal
FAIL: 26_numerics/random/random_device/cons/token.cc execution test
26_numerics/random/random_device/cons/token.cc:67: void test03(): Assertion 'count != 0' failed.
(if i add "default" to the token list in test03 then it passes)
Hmm, then I messed something up. If the "default" token works then one
of the others should too (I would expect that to be "mt19937" for bare
metal).
I'll take a look, thanks.
Doh:
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
@@ -51,7 +51,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)
Here's what I've committed to fix the COW string failures and the
baremetal failure. Tested powerpc64le-linux and x86_64-linux, old and
new ABIs.
commit a7d8558fdd74dc96dc0bd73c4a663b658f4155ba
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri May 31 08:47:47 2019 +0100
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.
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h
index 9c959d6dc84..e63dbcf5a25 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 c36f297438e..107a45750f2 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 <random>
-#if defined __i386__ || defined __x86_64__
-# include <cpuid.h>
-#endif
-#include <cstdio>
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<void*>(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 85cb2df4287..10fbe1dc4c4 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 00000000000..622801d8382
--- /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
+// <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();
+}
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 4fa1adf52eb..ed03c54a5d7 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
// <http://www.gnu.org/licenses/>.
-// 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 <random>
#include <testsuite_hooks.h>
@@ -32,8 +31,11 @@ test01()
{
std::random_device x;
- VERIFY( x.min() == std::numeric_limits<std::random_device::result_type>::min() );
- VERIFY( x.max() == std::numeric_limits<std::random_device::result_type>::max() );
+ using result_type = std::random_device::result_type;
+ 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()
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 cf5e81edd7b..31a86b0b4ab 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<std::random_device::result_type>::min() );
- VERIFY( x.max() == std::numeric_limits<std::random_device::result_type>::max() );
-
+ using result_type = std::random_device::result_type;
+ VERIFY( x.min() == std::numeric_limits<result_type>::min() );
+ VERIFY( x.max() == std::numeric_limits<result_type>::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() );
}
}