[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
Thu Sep 10 02:45:36 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] [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 a7b9e8731d555..ee3b7ef7c60a4 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 e98aea7be8531..2383840a27f57 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 46c7c4440e7b9..7bcc2ea2ceafa 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 f898c072b023e..9a79aaefed354 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 f28e5fca140e5..28e53d746a32d 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 0000000000000..c9555b174dfe6
--- /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 0000000000000..c9555b174dfe6
--- /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



More information about the libcxx-commits mailing list