[libc-commits] [libc] [llvm] [libc] Move nullptr_t definition to cstddef/nullptr_t.h (PR #236712)
via libc-commits
libc-commits at lists.llvm.org
Thu Oct 29 03:23:15 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-libc
Author: Pavel Labath (labath)
<details>
<summary>Changes</summary>
cpp::nullptr_t was previously defined in type_traits/is_null_pointer.h, which is an odd place for it. In standard C++, nullptr_t is defined in <cstddef>. However, putting it directly into the umbrella cstddef.h pulls in byte, which depends on type_traits.h for enable_if_t and is_integral_v, creating an include cycle if type_traits wants to use nullptr_t.
To solve this, I've placed nullptr_t into a granular src/__support/CPP/cstddef/nullptr_t.h header (following the precedent of headers in utility/ and libc++'s __cstddef/nullptr_t.h).
With this change:
- cstddef.h re-exports nullptr_t from cstddef/nullptr_t.h.
- is_null_pointer.h includes cstddef/nullptr_t.h and uses cpp::nullptr_t without circular dependencies.
- unique_ptr.h, LibcTest.h, and tests include cstddef/nullptr_t.h directly and use nullptr_t in place of decltype(nullptr).
- added CMake target libc.src.__support.CPP.nullptr_t.
- added nullptr_t construction tests in unique_ptr_test.
Assisted-by: Gemini
---
Full diff: https://github.com/llvm/llvm-project/pull/236712.diff
13 Files Affected:
- (modified) libc/src/__support/CPP/CMakeLists.txt (+11)
- (modified) libc/src/__support/CPP/cstddef.h (+1)
- (added) libc/src/__support/CPP/cstddef/nullptr_t.h (+22)
- (modified) libc/src/__support/CPP/type_traits/is_null_pointer.h (+1-1)
- (modified) libc/src/__support/CPP/unique_ptr.h (+3-2)
- (modified) libc/test/UnitTest/CMakeLists.txt (+1)
- (modified) libc/test/UnitTest/LibcTest.h (+1)
- (modified) libc/test/src/__support/CPP/CMakeLists.txt (+2)
- (modified) libc/test/src/__support/CPP/functional_test.cpp (+4-2)
- (modified) libc/test/src/__support/CPP/unique_ptr_test.cpp (+15)
- (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+10)
- (modified) utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel (+1)
- (modified) utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel (+1)
``````````diff
diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt
index 97898e2744f7b0..6c911333f01079 100644
--- a/libc/src/__support/CPP/CMakeLists.txt
+++ b/libc/src/__support/CPP/CMakeLists.txt
@@ -29,11 +29,20 @@ add_header_library(
bitset.h
)
+add_header_library(
+ nullptr_t
+ HDRS
+ cstddef/nullptr_t.h
+ DEPENDS
+ libc.src.__support.macros.config
+)
+
add_header_library(
cstddef
HDRS
cstddef.h
DEPENDS
+ .nullptr_t
.type_traits
)
@@ -186,6 +195,7 @@ add_header_library(
type_traits/type_identity.h
type_traits/void_t.h
DEPENDS
+ .nullptr_t
libc.include.llvm-libc-macros.stdfix_macros
libc.src.__support.macros.attributes
libc.src.__support.macros.properties.types
@@ -229,6 +239,7 @@ add_header_library(
unique_ptr.h
DEPENDS
.new
+ .nullptr_t
.type_traits
.utility
libc.hdr.types.size_t
diff --git a/libc/src/__support/CPP/cstddef.h b/libc/src/__support/CPP/cstddef.h
index 1507789cb1b10c..4b0b4a25790d08 100644
--- a/libc/src/__support/CPP/cstddef.h
+++ b/libc/src/__support/CPP/cstddef.h
@@ -9,6 +9,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_CSTDDEF_H
#define LLVM_LIBC_SRC___SUPPORT_CPP_CSTDDEF_H
+#include "src/__support/CPP/cstddef/nullptr_t.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
#include "type_traits.h" // For enable_if_t, is_integral_v.
diff --git a/libc/src/__support/CPP/cstddef/nullptr_t.h b/libc/src/__support/CPP/cstddef/nullptr_t.h
new file mode 100644
index 00000000000000..6cf39070d00356
--- /dev/null
+++ b/libc/src/__support/CPP/cstddef/nullptr_t.h
@@ -0,0 +1,22 @@
+//===-- nullptr_t type ------------------------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_CSTDDEF_NULLPTR_T_H
+#define LLVM_LIBC_SRC___SUPPORT_CPP_CSTDDEF_NULLPTR_T_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+namespace cpp {
+
+using nullptr_t = decltype(nullptr);
+
+} // namespace cpp
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_CPP_CSTDDEF_NULLPTR_T_H
diff --git a/libc/src/__support/CPP/type_traits/is_null_pointer.h b/libc/src/__support/CPP/type_traits/is_null_pointer.h
index acf341311be06e..87a94192f01b22 100644
--- a/libc/src/__support/CPP/type_traits/is_null_pointer.h
+++ b/libc/src/__support/CPP/type_traits/is_null_pointer.h
@@ -8,6 +8,7 @@
#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_NULL_POINTER_H
#define LLVM_LIBC_SRC___SUPPORT_CPP_TYPE_TRAITS_IS_NULL_POINTER_H
+#include "src/__support/CPP/cstddef/nullptr_t.h"
#include "src/__support/CPP/type_traits/is_same.h"
#include "src/__support/CPP/type_traits/remove_cv.h"
#include "src/__support/macros/attributes.h"
@@ -17,7 +18,6 @@ namespace LIBC_NAMESPACE_DECL {
namespace cpp {
// is_null_pointer
-using nullptr_t = decltype(nullptr);
template <class T>
struct is_null_pointer : cpp::is_same<cpp::nullptr_t, cpp::remove_cv_t<T>> {};
template <class T>
diff --git a/libc/src/__support/CPP/unique_ptr.h b/libc/src/__support/CPP/unique_ptr.h
index a8cf11d2ae8a72..6a98d4223b368e 100644
--- a/libc/src/__support/CPP/unique_ptr.h
+++ b/libc/src/__support/CPP/unique_ptr.h
@@ -15,6 +15,7 @@
#define LLVM_LIBC_SRC___SUPPORT_CPP_UNIQUE_PTR_H
#include "hdr/types/size_t.h"
+#include "src/__support/CPP/cstddef/nullptr_t.h"
#include "src/__support/CPP/new.h"
#include "src/__support/CPP/type_traits.h"
#include "src/__support/CPP/utility.h"
@@ -66,7 +67,7 @@ class LIBC_TRIVIAL_ABI unique_ptr {
using pointer = T *;
LIBC_INLINE constexpr unique_ptr() = default;
- LIBC_INLINE constexpr unique_ptr(decltype(nullptr)) : ptr(nullptr) {}
+ LIBC_INLINE constexpr unique_ptr(nullptr_t) : ptr(nullptr) {}
LIBC_INLINE constexpr explicit unique_ptr(pointer p) : ptr(p) {}
LIBC_INLINE constexpr unique_ptr(pointer p, const deleter_type &d)
@@ -156,7 +157,7 @@ class LIBC_TRIVIAL_ABI unique_ptr<T[], Deleter> {
using pointer = T *;
LIBC_INLINE constexpr unique_ptr() = default;
- LIBC_INLINE constexpr unique_ptr(decltype(nullptr)) : ptr(nullptr) {}
+ LIBC_INLINE constexpr unique_ptr(nullptr_t) : ptr(nullptr) {}
LIBC_INLINE constexpr explicit unique_ptr(pointer p) : ptr(p) {}
LIBC_INLINE constexpr unique_ptr(pointer p, const deleter_type &d)
diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt
index de82c2f1362d65..2622e74a8ec78f 100644
--- a/libc/test/UnitTest/CMakeLists.txt
+++ b/libc/test/UnitTest/CMakeLists.txt
@@ -103,6 +103,7 @@ add_unittest_framework_library(
libc.src.__support.big_int
libc.src.__support.c_string
libc.src.__support.CPP.functional
+ libc.src.__support.CPP.nullptr_t
libc.src.__support.CPP.string
libc.src.__support.CPP.string_view
libc.src.__support.CPP.type_traits
diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h
index 56ed7f3383c053..3feecb262f4988 100644
--- a/libc/test/UnitTest/LibcTest.h
+++ b/libc/test/UnitTest/LibcTest.h
@@ -24,6 +24,7 @@
// This file can only include headers from src/__support/ or test/UnitTest. No
// other headers should be included.
+#include "src/__support/CPP/cstddef/nullptr_t.h"
#include "src/__support/CPP/functional.h"
#include "src/__support/CPP/string.h"
#include "src/__support/CPP/string_view.h"
diff --git a/libc/test/src/__support/CPP/CMakeLists.txt b/libc/test/src/__support/CPP/CMakeLists.txt
index ffb1ab6f9d61df..5116f559e71c0a 100644
--- a/libc/test/src/__support/CPP/CMakeLists.txt
+++ b/libc/test/src/__support/CPP/CMakeLists.txt
@@ -72,6 +72,7 @@ add_libc_test(
functional_test.cpp
DEPENDS
libc.src.__support.CPP.functional
+ libc.src.__support.CPP.nullptr_t
libc.src.__support.CPP.type_traits
)
@@ -174,6 +175,7 @@ add_libc_test(
unique_ptr_test.cpp
DEPENDS
libc.hdr.signal_macros
+ libc.src.__support.CPP.nullptr_t
libc.src.__support.CPP.unique_ptr
libc.src.__support.CPP.utility
)
diff --git a/libc/test/src/__support/CPP/functional_test.cpp b/libc/test/src/__support/CPP/functional_test.cpp
index db427f7e6901d2..5c803d2bf07b9c 100644
--- a/libc/test/src/__support/CPP/functional_test.cpp
+++ b/libc/test/src/__support/CPP/functional_test.cpp
@@ -11,6 +11,7 @@
///
//===----------------------------------------------------------------------===//
+#include "src/__support/CPP/cstddef/nullptr_t.h"
#include "src/__support/CPP/functional.h"
#include "src/__support/CPP/type_traits.h"
#include "test/UnitTest/Test.h"
@@ -18,6 +19,7 @@
using LIBC_NAMESPACE::cpp::function_ref;
using LIBC_NAMESPACE::cpp::is_assignable_v;
using LIBC_NAMESPACE::cpp::is_constructible_v;
+using LIBC_NAMESPACE::cpp::nullptr_t;
static int forty_two() { return 42; }
static int seven() { return 7; }
@@ -43,7 +45,7 @@ using IntIntFn = function_ref<int(int)>;
// Like std::function_ref, there is no empty state.
static_assert(!is_constructible_v<IntFn>);
-static_assert(!is_constructible_v<IntFn, decltype(nullptr)>);
+static_assert(!is_constructible_v<IntFn, nullptr_t>);
static_assert(!is_constructible_v<bool, IntFn>);
// Callables with incompatible signatures are rejected.
@@ -61,7 +63,7 @@ static_assert(is_assignable_v<IntFn &, int (&)()>);
static_assert(is_constructible_v<IntFn, Functor>);
static_assert(!is_assignable_v<IntFn &, Functor>);
static_assert(!is_assignable_v<IntFn &, Functor &>);
-static_assert(!is_assignable_v<IntFn &, decltype(nullptr)>);
+static_assert(!is_assignable_v<IntFn &, nullptr_t>);
TEST(LlvmLibcFunctionRefTest, Lambda) {
int offset = 10;
diff --git a/libc/test/src/__support/CPP/unique_ptr_test.cpp b/libc/test/src/__support/CPP/unique_ptr_test.cpp
index 56bdd77eb1e7ac..7e26a8e3449b3a 100644
--- a/libc/test/src/__support/CPP/unique_ptr_test.cpp
+++ b/libc/test/src/__support/CPP/unique_ptr_test.cpp
@@ -12,12 +12,14 @@
//===----------------------------------------------------------------------===//
#include "hdr/signal_macros.h"
+#include "src/__support/CPP/cstddef/nullptr_t.h"
#include "src/__support/CPP/unique_ptr.h"
#include "src/__support/CPP/utility.h"
#include "src/__support/alloc-checker.h"
#include "test/UnitTest/Test.h"
using LIBC_NAMESPACE::AllocChecker;
+using LIBC_NAMESPACE::cpp::nullptr_t;
using LIBC_NAMESPACE::cpp::unique_ptr;
struct DestructTracker {
@@ -48,6 +50,19 @@ TEST(LlvmLibcUniquePtrTest, Nullptr) {
unique_ptr<int> ptr(nullptr);
ASSERT_FALSE(static_cast<bool>(ptr));
ASSERT_EQ(ptr.get(), nullptr);
+
+ constexpr nullptr_t null{};
+ unique_ptr<int> ptr2(null);
+ ASSERT_FALSE(static_cast<bool>(ptr2));
+ ASSERT_EQ(ptr2.get(), nullptr);
+
+ unique_ptr<int[]> arr(nullptr);
+ ASSERT_FALSE(static_cast<bool>(arr));
+ ASSERT_EQ(arr.get(), nullptr);
+
+ unique_ptr<int[]> arr2(null);
+ ASSERT_FALSE(static_cast<bool>(arr2));
+ ASSERT_EQ(arr2.get(), nullptr);
}
// Test move construction transferring ownership.
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index f468f19e65edba..c97ba47c41c273 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -1784,10 +1784,19 @@ libc_support_library(
],
)
+libc_support_library(
+ name = "__support_cpp_nullptr_t",
+ hdrs = ["src/__support/CPP/cstddef/nullptr_t.h"],
+ deps = [
+ ":__support_macros_config",
+ ],
+)
+
libc_support_library(
name = "__support_cpp_cstddef",
hdrs = ["src/__support/CPP/cstddef.h"],
deps = [
+ ":__support_cpp_nullptr_t",
":__support_cpp_type_traits",
":__support_macros_attributes",
":__support_macros_config",
@@ -1965,6 +1974,7 @@ libc_support_library(
"src/__support/CPP/utility/forward.h",
],
deps = [
+ ":__support_cpp_nullptr_t",
":__support_macros_attributes",
":__support_macros_config",
":__support_macros_properties_compiler",
diff --git a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
index 70c48473105a6b..bc926453af3fc6 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
@@ -55,6 +55,7 @@ libc_test_library(
"//libc:__support_cpp_bitset",
"//libc:__support_cpp_functional",
"//libc:__support_cpp_limits",
+ "//libc:__support_cpp_nullptr_t",
"//libc:__support_cpp_scope",
"//libc:__support_cpp_span",
"//libc:__support_cpp_string",
diff --git a/utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel
index 56a64bf0c3c918..139e9412218bec 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/src/__support/CPP/BUILD.bazel
@@ -43,6 +43,7 @@ libc_test(
srcs = ["functional_test.cpp"],
deps = [
"//libc:__support_cpp_functional",
+ "//libc:__support_cpp_nullptr_t",
"//libc:__support_cpp_type_traits",
],
)
``````````
</details>
https://github.com/llvm/llvm-project/pull/236712
More information about the libc-commits
mailing list