[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
Sun Oct 11 20:00:10 PDT 2026
https://github.com/ecnelises updated https://github.com/llvm/llvm-project/pull/222567
>From cc7b530405468a9588e941b833fd05a2de288fc4 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/__random/random_device.h | 8 +++---
.../rand/rand.device/abi.compile.pass.cpp | 27 +++++++++++++++++++
.../numerics/rand/rand.device/ctor.pass.cpp | 6 +++--
.../numerics/rand/rand.device/eval.pass.cpp | 3 ++-
.../libcxx/test/features/libcxx_macros.py | 4 +++
7 files changed, 53 insertions(+), 7 deletions(-)
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 04f02ab66a773..fc528a15f3fe2 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -72,6 +72,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 ade43d42dc283..8a3b18255ce14 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/__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/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..4d450149a9c59
--- /dev/null
+++ b/libcxx/test/libcxx/numerics/rand/rand.device/abi.compile.pass.cpp
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, libcpp-abi-no-random-device-compatibility-layout
+
+// Ensure layout of std::random_device is compatible.
+
+#include <random>
+
+#include "test_macros.h"
+
+#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), "");
+
+#else
+
+static_assert(sizeof(std::random_device) == 1, "");
+static_assert(TEST_ALIGNOF(std::random_device) == 1, "");
+
+#endif
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 6db61479e041f..44790d4d04b91 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 9c385b3b88ec7..14bab0af723ea 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 33d569e75e6bc..0417940898c6a 100644
--- a/libcxx/utils/libcxx/test/features/libcxx_macros.py
+++ b/libcxx/utils/libcxx/test/features/libcxx_macros.py
@@ -35,6 +35,10 @@
"_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING": "libcpp-abi-no-compressed-pair-padding",
"_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