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 <jwak...@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() );
   }
 }
 

Reply via email to