[libcxx-commits] [libcxx] [libc++] Fix behavior for `get_temporary_buffer` with non-positive size (PR #206871)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 1 01:46:09 PDT 2026


https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/206871

>From 92bae65367bbcc5caa6601e70e37715d1bec9e5b Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Wed, 1 Jul 2026 10:12:44 +0800
Subject: [PATCH 1/4] [libc++] Fix behavior for `get_temporary_buffer` with
 non-positive size

Per C++17 [depr.temporary.buffer]/4, `get_temporary_buffer` is required
to return `{nullptr, 0}` when the size argument is zero or negative.
libc++ used to correctly handle this, but the refactoring in
94e7c0b051c79fd56205f115771980f2e7812306 got this wrong.
---
 libcxx/include/__memory/temporary_buffer.h         |  3 +++
 .../memory/temporary.buffer/overaligned.pass.cpp   | 14 ++++++++++++++
 .../temporary.buffer/temporary_buffer.pass.cpp     | 14 ++++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/libcxx/include/__memory/temporary_buffer.h b/libcxx/include/__memory/temporary_buffer.h
index d18717f52d1cd..3c572e43db641 100644
--- a/libcxx/include/__memory/temporary_buffer.h
+++ b/libcxx/include/__memory/temporary_buffer.h
@@ -26,6 +26,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _Tp>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _LIBCPP_DEPRECATED_IN_CXX17 pair<_Tp*, ptrdiff_t>
 get_temporary_buffer(ptrdiff_t __n) _NOEXCEPT {
+  if (__n <= 0)
+    return pair<_Tp*, ptrdiff_t>();
+
   __unique_temporary_buffer<_Tp> __unique_buf = std::__allocate_unique_temporary_buffer<_Tp>(__n);
   pair<_Tp*, ptrdiff_t> __result(__unique_buf.get(), __unique_buf.get_deleter().__count_);
   __unique_buf.release();
diff --git a/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp b/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
index 3fa9355270866..678e4e3d342fb 100644
--- a/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
+++ b/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
@@ -38,5 +38,19 @@ int main(int, char**)
     assert(reinterpret_cast<std::uintptr_t>(ip.first) % alignof(A) == 0);
     std::return_temporary_buffer(ip.first);
 
+    // C++17 [depr.temporary.buffer]/4
+    // Returns: If n <= 0 or if no storage could be obtained,
+    // returns a pair P such that P.first is a null pointer value and P.second == 0;
+    {
+      std::pair<A*, std::ptrdiff_t> ret = std::get_temporary_buffer<A>(0);
+      assert(ret.first == NULL);
+      assert(ret.second == 0);
+    }
+    {
+      std::pair<A*, std::ptrdiff_t> ret = std::get_temporary_buffer<A>(-5);
+      assert(ret.first == NULL);
+      assert(ret.second == 0);
+    }
+
   return 0;
 }
diff --git a/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp b/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
index 39a4767d874e3..50ca6b21ae46c 100644
--- a/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
+++ b/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
@@ -31,5 +31,19 @@ int main(int, char**)
     assert(ip.second == 5);
     std::return_temporary_buffer(ip.first);
 
+    // C++17 [depr.temporary.buffer]/4
+    // Returns: If n <= 0 or if no storage could be obtained,
+    // returns a pair P such that P.first is a null pointer value and P.second == 0;
+    {
+      std::pair<int*, std::ptrdiff_t> ret = std::get_temporary_buffer<int>(0);
+      assert(ret.first == NULL);
+      assert(ret.second == 0);
+    }
+    {
+      std::pair<int*, std::ptrdiff_t> ret = std::get_temporary_buffer<int>(-5);
+      assert(ret.first == NULL);
+      assert(ret.second == 0);
+    }
+
   return 0;
 }

>From 90d750fbdc0f9a9fcb01c7b5cfa3ed36d99cd163 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Wed, 1 Jul 2026 13:35:25 +0800
Subject: [PATCH 2/4] `-Wno-alloc-size-larger-than`

---
 .../utilities/memory/temporary.buffer/overaligned.pass.cpp   | 5 +++++
 .../memory/temporary.buffer/temporary_buffer.pass.cpp        | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp b/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
index 678e4e3d342fb..0f119ae90b82e 100644
--- a/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
+++ b/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
@@ -27,6 +27,11 @@
 #include <memory>
 #include <utility>
 
+#include "test_macros.h"
+
+// This warning is coupled with completeness of control flow analysis which is affected by optimizations.
+TEST_GCC_DIAGNOSTIC_IGNORED("-Wno-alloc-size-larger-than")
+
 struct alignas(32) A {
     int field;
 };
diff --git a/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp b/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
index 50ca6b21ae46c..729cb14b9c5e9 100644
--- a/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
+++ b/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
@@ -24,6 +24,11 @@
 #include <memory>
 #include <utility>
 
+#include "test_macros.h"
+
+// This warning is coupled with completeness of control flow analysis which is affected by optimizations.
+TEST_GCC_DIAGNOSTIC_IGNORED("-Wno-alloc-size-larger-than")
+
 int main(int, char**)
 {
     std::pair<int*, std::ptrdiff_t> ip = std::get_temporary_buffer<int>(5);

>From 3590c72e1e0cb065b9297b2060c73344869f6f41 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Wed, 1 Jul 2026 15:40:16 +0800
Subject: [PATCH 3/4] Locally suppress the warning

---
 .../utilities/memory/temporary.buffer/overaligned.pass.cpp | 7 ++++---
 .../memory/temporary.buffer/temporary_buffer.pass.cpp      | 7 ++++---
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp b/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
index 0f119ae90b82e..2b4b6586f5563 100644
--- a/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
+++ b/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
@@ -29,9 +29,6 @@
 
 #include "test_macros.h"
 
-// This warning is coupled with completeness of control flow analysis which is affected by optimizations.
-TEST_GCC_DIAGNOSTIC_IGNORED("-Wno-alloc-size-larger-than")
-
 struct alignas(32) A {
     int field;
 };
@@ -52,7 +49,11 @@ int main(int, char**)
       assert(ret.second == 0);
     }
     {
+      TEST_DIAGNOSTIC_PUSH
+      // This warning is coupled with completeness of control flow analysis which is affected by optimizations.
+      TEST_GCC_DIAGNOSTIC_IGNORED("-Wno-alloc-size-larger-than")
       std::pair<A*, std::ptrdiff_t> ret = std::get_temporary_buffer<A>(-5);
+      TEST_DIAGNOSTIC_POP
       assert(ret.first == NULL);
       assert(ret.second == 0);
     }
diff --git a/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp b/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
index 729cb14b9c5e9..6935e8a9d83d5 100644
--- a/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
+++ b/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
@@ -26,9 +26,6 @@
 
 #include "test_macros.h"
 
-// This warning is coupled with completeness of control flow analysis which is affected by optimizations.
-TEST_GCC_DIAGNOSTIC_IGNORED("-Wno-alloc-size-larger-than")
-
 int main(int, char**)
 {
     std::pair<int*, std::ptrdiff_t> ip = std::get_temporary_buffer<int>(5);
@@ -45,7 +42,11 @@ int main(int, char**)
       assert(ret.second == 0);
     }
     {
+      TEST_DIAGNOSTIC_PUSH
+      // This warning is coupled with completeness of control flow analysis which is affected by optimizations.
+      TEST_GCC_DIAGNOSTIC_IGNORED("-Wno-alloc-size-larger-than")
       std::pair<int*, std::ptrdiff_t> ret = std::get_temporary_buffer<int>(-5);
+      TEST_DIAGNOSTIC_POP
       assert(ret.first == NULL);
       assert(ret.second == 0);
     }

>From c95c07613f6cebd619601ad85fc4d209cb8bfe4e Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Wed, 1 Jul 2026 16:45:46 +0800
Subject: [PATCH 4/4] Tweak the suppressing style and add test cases

---
 .../memory/temporary.buffer/overaligned.pass.cpp     |  5 +++--
 .../temporary.buffer/temporary_buffer.pass.cpp       | 12 +++++++++++-
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp b/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
index 2b4b6586f5563..c55e488af53b1 100644
--- a/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
+++ b/libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
@@ -24,6 +24,7 @@
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
+#include <limits>
 #include <memory>
 #include <utility>
 
@@ -51,8 +52,8 @@ int main(int, char**)
     {
       TEST_DIAGNOSTIC_PUSH
       // This warning is coupled with completeness of control flow analysis which is affected by optimizations.
-      TEST_GCC_DIAGNOSTIC_IGNORED("-Wno-alloc-size-larger-than")
-      std::pair<A*, std::ptrdiff_t> ret = std::get_temporary_buffer<A>(-5);
+      TEST_GCC_DIAGNOSTIC_IGNORED("-Walloc-size-larger-than=")
+      std::pair<A*, std::ptrdiff_t> ret = std::get_temporary_buffer<A>(std::numeric_limits<std::ptrdiff_t>::min());
       TEST_DIAGNOSTIC_POP
       assert(ret.first == NULL);
       assert(ret.second == 0);
diff --git a/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp b/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
index 6935e8a9d83d5..9bd49edbb0d02 100644
--- a/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
+++ b/libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp
@@ -21,6 +21,7 @@
 
 #include <cassert>
 #include <cstddef>
+#include <limits>
 #include <memory>
 #include <utility>
 
@@ -44,12 +45,21 @@ int main(int, char**)
     {
       TEST_DIAGNOSTIC_PUSH
       // This warning is coupled with completeness of control flow analysis which is affected by optimizations.
-      TEST_GCC_DIAGNOSTIC_IGNORED("-Wno-alloc-size-larger-than")
+      TEST_GCC_DIAGNOSTIC_IGNORED("-Walloc-size-larger-than=")
       std::pair<int*, std::ptrdiff_t> ret = std::get_temporary_buffer<int>(-5);
       TEST_DIAGNOSTIC_POP
       assert(ret.first == NULL);
       assert(ret.second == 0);
     }
+    {
+      TEST_DIAGNOSTIC_PUSH
+      // This warning is coupled with completeness of control flow analysis which is affected by optimizations.
+      TEST_GCC_DIAGNOSTIC_IGNORED("-Walloc-size-larger-than=")
+      std::pair<int*, std::ptrdiff_t> ret = std::get_temporary_buffer<int>(std::numeric_limits<std::ptrdiff_t>::min());
+      TEST_DIAGNOSTIC_POP
+      assert(ret.first == NULL);
+      assert(ret.second == 0);
+    }
 
   return 0;
 }



More information about the libcxx-commits mailing list