Fix random_device to work with COW strings again
authorJonathan Wakely <jwakely@redhat.com>
Fri, 31 May 2019 10:34:53 +0000 (11:34 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 31 May 2019 10:34:53 +0000 (11:34 +0100)
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
libstdc++-v3/include/bits/random.h
libstdc++-v3/src/c++11/cow-string-inst.cc
libstdc++-v3/src/c++11/random.cc
libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default-cow.cc [new file with mode: 0644]
libstdc++-v3/testsuite/26_numerics/random/random_device/cons/default.cc
libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc

index cd535fe0887d46cc23487cf055f9af9101198a4d..71ef811e052acc5bf8a8458c6fb0e1ee0a3012be 100644 (file)
@@ -1,3 +1,19 @@
+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>
 
        LWG2788 basic_string spurious use of a default constructible allocator
index 9c959d6dc84a7da7d57fcb2eb00e4af60cc79f45..e63dbcf5a257a1d684f9fa3aab2ef7686c21af62 100644 (file)
@@ -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
index c36f297438eca6868ed2154c9d6eba72d999bc36..107a45750f28ff8c8393f8e69d50b9602fde7015 100644 (file)
 
 #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
index 85cb2df4287a1ec7c28545487871d6ab430aad5f..10fbe1dc4c43f61bd5ed3f42ee4c3cd6e1253435 100644 (file)
@@ -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 (file)
index 0000000..622801d
--- /dev/null
@@ -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();
+}
index 4fa1adf52eba9bb6a4a1f9c2689502c5511c41af..ed03c54a5d73404fb04f826bc66ed7edcaf4f0a5 100644 (file)
@@ -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()
index cf5e81edd7b2460a87efbcef772a6543e213c2d0..31a86b0b4ab409e75a4854d278382d49f92c6866 100644 (file)
@@ -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() );
   }
 }