[libcxx-commits] [libcxx] [libc++] Use glibc random APIs for std::random_device on Linux (PR #222567)

QIU Chaofan via libcxx-commits libcxx-commits at lists.llvm.org
Sat Oct 10 02:48:20 PDT 2026


https://github.com/ecnelises updated https://github.com/llvm/llvm-project/pull/222567

>From e4885f6460cf75b25729c095798739e2996a4891 Mon Sep 17 00:00:00 2001
From: Qiu Chaofan <qcf at ecnelises.com>
Date: Thu, 10 Sep 2026 17:36:57 +0800
Subject: [PATCH 1/3] [libc++] Use glibc random APIs for std::random_device on
 Linux

Use arc4random with glibc 2.36 and later, and getentropy with glibc
2.25 through 2.35. Retain current urandom file based implementation
on other Linux libc and older glibc versions.

Co-authored-by: Codex <codex at users.noreply.github.com>
---
 libcxx/docs/ReleaseNotes/24.rst               |  4 +++
 libcxx/include/__config                       |  8 ++++++
 libcxx/include/__cxx03/__config               |  8 ++++++
 .../include/__cxx03/__random/random_device.h  |  8 +++---
 libcxx/include/__random/random_device.h       |  8 +++---
 .../rand/rand.device/abi.compile.pass.cpp     | 28 +++++++++++++++++++
 .../rand/rand.device/abi.compile.pass.cpp     | 28 +++++++++++++++++++
 7 files changed, 84 insertions(+), 8 deletions(-)
 create mode 100644 libcxx/test/libcxx-03/numerics/rand/rand.device/abi.compile.pass.cpp
 create mode 100644 libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp

diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index a7b9e8731d555d..ee3b7ef7c60a4c 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -67,6 +67,10 @@ Deprecations and Removals
 Potentially breaking changes
 ----------------------------
 
+- On Linux, ``std::random_device`` now uses ``arc4random`` when libc++ is built against glibc 2.36+, and ``getentropy``
+  when built against glibc 2.25 through 2.35, instead of reading from ``/dev/urandom``. Behavior with older glibc versions
+  and other C libraries on Linux remain unchanged.
+
 - In LLVM 23, libc++ dropped a lot of transitive includes in all language modes. This improves compile time significantly,
   but causes programs which rely on these includes to not compile anymore. The ``_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23``
   macro that was provided in LLVM 23 to ease the transition has been removed in this release.
diff --git a/libcxx/include/__config b/libcxx/include/__config
index e98aea7be8531d..2383840a27f57c 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -85,6 +85,14 @@
 #  if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ||                     \
       defined(__DragonFly__) || defined(__BIONIC__)
 #    define _LIBCPP_USING_ARC4_RANDOM
+#  elif defined(__linux__) && defined(_LIBCPP_GLIBC_PREREQ)
+#    if _LIBCPP_GLIBC_PREREQ(2, 36)
+#      define _LIBCPP_USING_ARC4_RANDOM
+#    elif _LIBCPP_GLIBC_PREREQ(2, 25)
+#      define _LIBCPP_USING_GETENTROPY
+#    else
+#      define _LIBCPP_USING_DEV_RANDOM
+#    endif
 #  elif defined(__wasi__) || defined(__EMSCRIPTEN__)
 #    define _LIBCPP_USING_GETENTROPY
 #  elif defined(__Fuchsia__)
diff --git a/libcxx/include/__cxx03/__config b/libcxx/include/__cxx03/__config
index 46c7c4440e7b93..7bcc2ea2ceafa7 100644
--- a/libcxx/include/__cxx03/__config
+++ b/libcxx/include/__cxx03/__config
@@ -265,6 +265,14 @@ _LIBCPP_HARDENING_MODE_DEBUG
 #  if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ||                     \
       defined(__DragonFly__) || defined(__BIONIC__)
 #    define _LIBCPP_USING_ARC4_RANDOM
+#  elif defined(__linux__) && defined(_LIBCPP_GLIBC_PREREQ)
+#    if _LIBCPP_GLIBC_PREREQ(2, 36)
+#      define _LIBCPP_USING_ARC4_RANDOM
+#    elif _LIBCPP_GLIBC_PREREQ(2, 25)
+#      define _LIBCPP_USING_GETENTROPY
+#    else
+#      define _LIBCPP_USING_DEV_RANDOM
+#    endif
 #  elif defined(__wasi__) || defined(__EMSCRIPTEN__)
 #    define _LIBCPP_USING_GETENTROPY
 #  elif defined(__Fuchsia__)
diff --git a/libcxx/include/__cxx03/__random/random_device.h b/libcxx/include/__cxx03/__random/random_device.h
index f898c072b023e6..9a79aaefed3548 100644
--- a/libcxx/include/__cxx03/__random/random_device.h
+++ b/libcxx/include/__cxx03/__random/random_device.h
@@ -30,10 +30,10 @@ class _LIBCPP_EXPORTED_FROM_ABI random_device {
   _LIBCPP_DIAGNOSTIC_PUSH
   _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field")
 
-  // Apple platforms used to use the `_LIBCPP_USING_DEV_RANDOM` code path, and now
-  // use `arc4random()` as of this comment. In order to avoid breaking the ABI, we
-  // retain the same layout as before.
-#    if defined(__APPLE__)
+  // Apple platforms and GNU/Linux used to use the `_LIBCPP_USING_DEV_RANDOM`
+  // code path, and now use `arc4random` or `getentropy`. In order to avoid
+  // breaking the ABI, we retain the same layout as before.
+#    if defined(__APPLE__) || defined(__GLIBC__)
   int __padding_; // padding to fake the `__f_` field above
 #    endif
 
diff --git a/libcxx/include/__random/random_device.h b/libcxx/include/__random/random_device.h
index f28e5fca140e56..28e53d746a32db 100644
--- a/libcxx/include/__random/random_device.h
+++ b/libcxx/include/__random/random_device.h
@@ -28,10 +28,10 @@ class _LIBCPP_EXPORTED_FROM_ABI random_device {
 #  ifdef _LIBCPP_USING_DEV_RANDOM
   int __f_;
 #  elif !defined(_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT)
-  // Apple platforms used to use the `_LIBCPP_USING_DEV_RANDOM` code path, and now
-  // use `arc4random()` as of this comment. In order to avoid breaking the ABI, we
-  // retain the same layout as before.
-#    if defined(__APPLE__)
+  // Apple platforms and GNU/Linux used to use the `_LIBCPP_USING_DEV_RANDOM`
+  // code path, and now use `arc4random` or `getentropy`. In order to avoid
+  // breaking the ABI, we retain the same layout as before.
+#    if defined(__APPLE__) || defined(__GLIBC__)
   [[__maybe_unused__]] int __padding_; // padding to fake the `__f_` field above
 #    endif
 
diff --git a/libcxx/test/libcxx-03/numerics/rand/rand.device/abi.compile.pass.cpp b/libcxx/test/libcxx-03/numerics/rand/rand.device/abi.compile.pass.cpp
new file mode 100644
index 00000000000000..c9555b174dfe6b
--- /dev/null
+++ b/libcxx/test/libcxx-03/numerics/rand/rand.device/abi.compile.pass.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-random-device
+
+// Ensure layout of std::random_device is compatible.
+
+#include <random>
+
+#include "test_macros.h"
+
+#if defined(_LIBCPP_USING_DEV_RANDOM) ||                                                                               \
+    (!defined(_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT) && (defined(__APPLE__) || defined(__GLIBC__)))
+
+static_assert(sizeof(std::random_device) == sizeof(int), "");
+static_assert(TEST_ALIGNOF(std::random_device) == TEST_ALIGNOF(int), "");
+
+#else
+
+static_assert(sizeof(std::random_device) == 1, "");
+static_assert(TEST_ALIGNOF(std::random_device) == 1, "");
+
+#endif
diff --git a/libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp b/libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp
new file mode 100644
index 00000000000000..c9555b174dfe6b
--- /dev/null
+++ b/libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: no-random-device
+
+// Ensure layout of std::random_device is compatible.
+
+#include <random>
+
+#include "test_macros.h"
+
+#if defined(_LIBCPP_USING_DEV_RANDOM) ||                                                                               \
+    (!defined(_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT) && (defined(__APPLE__) || defined(__GLIBC__)))
+
+static_assert(sizeof(std::random_device) == sizeof(int), "");
+static_assert(TEST_ALIGNOF(std::random_device) == TEST_ALIGNOF(int), "");
+
+#else
+
+static_assert(sizeof(std::random_device) == 1, "");
+static_assert(TEST_ALIGNOF(std::random_device) == 1, "");
+
+#endif

>From 0dcf06f2d6fda7d2c4e149640f9454757ce1dd61 Mon Sep 17 00:00:00 2001
From: Qiu Chaofan <qcf at ecnelises.com>
Date: Sat, 10 Oct 2026 17:47:05 +0800
Subject: [PATCH 2/3] fixup! [libc++] Use glibc random APIs for
 std::random_device on Linux

---
 libcxx/include/__cxx03/__config               |  8 ------
 .../include/__cxx03/__random/random_device.h  |  8 +++---
 .../rand/rand.device/abi.compile.pass.cpp     | 28 -------------------
 3 files changed, 4 insertions(+), 40 deletions(-)
 delete mode 100644 libcxx/test/libcxx-03/numerics/rand/rand.device/abi.compile.pass.cpp

diff --git a/libcxx/include/__cxx03/__config b/libcxx/include/__cxx03/__config
index 7bcc2ea2ceafa7..46c7c4440e7b93 100644
--- a/libcxx/include/__cxx03/__config
+++ b/libcxx/include/__cxx03/__config
@@ -265,14 +265,6 @@ _LIBCPP_HARDENING_MODE_DEBUG
 #  if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) ||                     \
       defined(__DragonFly__) || defined(__BIONIC__)
 #    define _LIBCPP_USING_ARC4_RANDOM
-#  elif defined(__linux__) && defined(_LIBCPP_GLIBC_PREREQ)
-#    if _LIBCPP_GLIBC_PREREQ(2, 36)
-#      define _LIBCPP_USING_ARC4_RANDOM
-#    elif _LIBCPP_GLIBC_PREREQ(2, 25)
-#      define _LIBCPP_USING_GETENTROPY
-#    else
-#      define _LIBCPP_USING_DEV_RANDOM
-#    endif
 #  elif defined(__wasi__) || defined(__EMSCRIPTEN__)
 #    define _LIBCPP_USING_GETENTROPY
 #  elif defined(__Fuchsia__)
diff --git a/libcxx/include/__cxx03/__random/random_device.h b/libcxx/include/__cxx03/__random/random_device.h
index 9a79aaefed3548..f898c072b023e6 100644
--- a/libcxx/include/__cxx03/__random/random_device.h
+++ b/libcxx/include/__cxx03/__random/random_device.h
@@ -30,10 +30,10 @@ class _LIBCPP_EXPORTED_FROM_ABI random_device {
   _LIBCPP_DIAGNOSTIC_PUSH
   _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field")
 
-  // Apple platforms and GNU/Linux used to use the `_LIBCPP_USING_DEV_RANDOM`
-  // code path, and now use `arc4random` or `getentropy`. In order to avoid
-  // breaking the ABI, we retain the same layout as before.
-#    if defined(__APPLE__) || defined(__GLIBC__)
+  // Apple platforms used to use the `_LIBCPP_USING_DEV_RANDOM` code path, and now
+  // use `arc4random()` as of this comment. In order to avoid breaking the ABI, we
+  // retain the same layout as before.
+#    if defined(__APPLE__)
   int __padding_; // padding to fake the `__f_` field above
 #    endif
 
diff --git a/libcxx/test/libcxx-03/numerics/rand/rand.device/abi.compile.pass.cpp b/libcxx/test/libcxx-03/numerics/rand/rand.device/abi.compile.pass.cpp
deleted file mode 100644
index c9555b174dfe6b..00000000000000
--- a/libcxx/test/libcxx-03/numerics/rand/rand.device/abi.compile.pass.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: no-random-device
-
-// Ensure layout of std::random_device is compatible.
-
-#include <random>
-
-#include "test_macros.h"
-
-#if defined(_LIBCPP_USING_DEV_RANDOM) ||                                                                               \
-    (!defined(_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT) && (defined(__APPLE__) || defined(__GLIBC__)))
-
-static_assert(sizeof(std::random_device) == sizeof(int), "");
-static_assert(TEST_ALIGNOF(std::random_device) == TEST_ALIGNOF(int), "");
-
-#else
-
-static_assert(sizeof(std::random_device) == 1, "");
-static_assert(TEST_ALIGNOF(std::random_device) == 1, "");
-
-#endif

>From ec519ab112695ecc4367c74734020b66d0e3225b Mon Sep 17 00:00:00 2001
From: Qiu Chaofan <qcf at ecnelises.com>
Date: Sat, 10 Oct 2026 17:47:28 +0800
Subject: [PATCH 3/3] fixup! [libc++] Use glibc random APIs for
 std::random_device on Linux

---
 .../libcxx/numerics/rand/rand.device/abi.compile.pass.cpp   | 5 ++---
 libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp     | 6 ++++--
 libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp     | 3 ++-
 libcxx/utils/libcxx/test/features/libcxx_macros.py          | 3 +++
 4 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp b/libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp
index c9555b174dfe6b..4d450149a9c597 100644
--- a/libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp
+++ b/libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: no-random-device
+// UNSUPPORTED: no-random-device, libcpp-abi-no-random-device-compatibility-layout
 
 // Ensure layout of std::random_device is compatible.
 
@@ -14,8 +14,7 @@
 
 #include "test_macros.h"
 
-#if defined(_LIBCPP_USING_DEV_RANDOM) ||                                                                               \
-    (!defined(_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT) && (defined(__APPLE__) || defined(__GLIBC__)))
+#if defined(_LIBCPP_USING_DEV_RANDOM) || defined(__APPLE__) || defined(__GLIBC__)
 
 static_assert(sizeof(std::random_device) == sizeof(int), "");
 static_assert(TEST_ALIGNOF(std::random_device) == TEST_ALIGNOF(int), "");
diff --git a/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp b/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp
index 6db61479e041f2..44790d4d04b91d 100644
--- a/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp
+++ b/libcxx/test/std/numerics/rand/rand.device/ctor.pass.cpp
@@ -11,6 +11,8 @@
 // XFAIL: target={{.+}}-apple-{{.+}} && using-built-library-before-llvm-14
 
 // UNSUPPORTED: no-random-device
+// ADDITIONAL_COMPILE_FLAGS(libcpp-using-arc4-random): -DTEST_USING_ARC4_RANDOM
+// ADDITIONAL_COMPILE_FLAGS(libcpp-using-dev-random): -DTEST_USING_DEV_RANDOM
 
 // <random>
 
@@ -62,13 +64,13 @@ int main(int, char**) {
   }
   // Check the validity of various tokens
   {
-#if defined(_LIBCPP_USING_ARC4_RANDOM)
+#if defined(TEST_USING_ARC4_RANDOM)
     check_random_device_valid("/dev/urandom");
     check_random_device_valid("/dev/random");
     check_random_device_valid("/dev/null");
     check_random_device_valid("/dev/nonexistent");
     check_random_device_valid("wrong file");
-#elif defined(_LIBCPP_USING_DEV_RANDOM)
+#elif defined(TEST_USING_DEV_RANDOM)
     check_random_device_valid("/dev/urandom");
     check_random_device_valid("/dev/random");
     check_random_device_valid("/dev/null");
diff --git a/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp b/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp
index 9c385b3b88ec72..14bab0af723ea1 100644
--- a/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp
+++ b/libcxx/test/std/numerics/rand/rand.device/eval.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // UNSUPPORTED: no-random-device
+// ADDITIONAL_COMPILE_FLAGS(libcpp-using-dev-random): -DTEST_USING_DEV_RANDOM
 
 // <random>
 
@@ -31,7 +32,7 @@ int main(int, char**)
 
     // When using the `/dev/urandom` implementation, make sure that we throw
     // an exception when we hit EOF while reading the custom-provided file.
-#if !defined(TEST_HAS_NO_EXCEPTIONS) && defined(_LIBCPP_USING_DEV_RANDOM)
+#if !defined(TEST_HAS_NO_EXCEPTIONS) && defined(TEST_USING_DEV_RANDOM)
     {
         std::random_device r("/dev/null");
         try {
diff --git a/libcxx/utils/libcxx/test/features/libcxx_macros.py b/libcxx/utils/libcxx/test/features/libcxx_macros.py
index 9ac22e07c549ce..0417940898c6af 100644
--- a/libcxx/utils/libcxx/test/features/libcxx_macros.py
+++ b/libcxx/utils/libcxx/test/features/libcxx_macros.py
@@ -36,6 +36,9 @@
     "_LIBCPP_PSTL_BACKEND_LIBDISPATCH": "libcpp-pstl-backend-libdispatch",
     "_LIBCPP_ABI_USE_SMALL_DEQUE_BLOCK_SIZE": "libcpp-abi-use-small-deque-block-size",
     "_LIBCPP_ABI_VECTORIZED_MERSENNE_TWISTER_ENGINE": "libcpp-abi-vectorized-mersenne-twister-engine",
+    "_LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT": "libcpp-abi-no-random-device-compatibility-layout",
+    "_LIBCPP_USING_ARC4_RANDOM": "libcpp-using-arc4-random",
+    "_LIBCPP_USING_DEV_RANDOM": "libcpp-using-dev-random",
 }
 for macro, feature in macros.items():
     features.append(



More information about the libcxx-commits mailing list