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

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 1 07:29:24 PDT 2026


Author: A. Jiang
Date: 2026-07-01T22:29:19+08:00
New Revision: bb6868abb8dd6f8ef7130ed2c81cf538793547c6

URL: https://github.com/llvm/llvm-project/commit/bb6868abb8dd6f8ef7130ed2c81cf538793547c6
DIFF: https://github.com/llvm/llvm-project/commit/bb6868abb8dd6f8ef7130ed2c81cf538793547c6.diff

LOG: [libc++] Fix behavior for `get_temporary_buffer` with non-positive size (#206871)

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.

GCC generally warns on negative size due to `-Walloc-size-larger-than=`,
which is false positive due to incomplete control flow analysis. The
warning is coupled with optimizations, and this patch make tests
suppress it instead.

Added: 
    

Modified: 
    libcxx/include/__memory/temporary_buffer.h
    libcxx/test/std/utilities/memory/temporary.buffer/overaligned.pass.cpp
    libcxx/test/std/utilities/memory/temporary.buffer/temporary_buffer.pass.cpp

Removed: 
    


################################################################################
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*, ptr
diff _t>
 get_temporary_buffer(ptr
diff _t __n) _NOEXCEPT {
+  if (__n <= 0)
+    return pair<_Tp*, ptr
diff _t>();
+
   __unique_temporary_buffer<_Tp> __unique_buf = std::__allocate_unique_temporary_buffer<_Tp>(__n);
   pair<_Tp*, ptr
diff _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..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,9 +24,12 @@
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
+#include <limits>
 #include <memory>
 #include <utility>
 
+#include "test_macros.h"
+
 struct alignas(32) A {
     int field;
 };
@@ -38,5 +41,23 @@ 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::ptr
diff _t> ret = std::get_temporary_buffer<A>(0);
+      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<A*, std::ptr
diff _t> ret = std::get_temporary_buffer<A>(std::numeric_limits<std::ptr
diff _t>::min());
+      TEST_DIAGNOSTIC_POP
+      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..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,9 +21,12 @@
 
 #include <cassert>
 #include <cstddef>
+#include <limits>
 #include <memory>
 #include <utility>
 
+#include "test_macros.h"
+
 int main(int, char**)
 {
     std::pair<int*, std::ptr
diff _t> ip = std::get_temporary_buffer<int>(5);
@@ -31,5 +34,32 @@ 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::ptr
diff _t> ret = std::get_temporary_buffer<int>(0);
+      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::ptr
diff _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::ptr
diff _t> ret = std::get_temporary_buffer<int>(std::numeric_limits<std::ptr
diff _t>::min());
+      TEST_DIAGNOSTIC_POP
+      assert(ret.first == NULL);
+      assert(ret.second == 0);
+    }
+
   return 0;
 }


        


More information about the libcxx-commits mailing list