[compiler-rt] [sanitizer_common] Add operator new chain-handling framework (PR #201151)

David Justo via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 13 11:55:44 PDT 2026


================
@@ -0,0 +1,140 @@
+//===-- sanitizer_new_handler.h ---------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is shared between run-time libraries of sanitizers.
+//
+// It provides the operator new chain-handling framework required by
+// [new.delete.single]/3+/4: a std::get_new_handler() loop plus the
+// throwing / nothrow exhaustion policies that compose with it. Each
+// sanitizer's operator new wrapper supplies two small lambdas:
+//
+//   * Alloc        — invokes the sanitizer's internal allocator, returning
+//                    nullptr on OOM (never aborting on OOM). Non-OOM
+//                    failure modes (e.g. invalid alignment) are the
+//                    caller's responsibility to detect and report before
+//                    invoking the framework — those conditions are UB/API
+//                    misuse, not allocation failures, and should die with
+//                    the caller's specific diagnostic rather than be
+//                    routed through the std::get_new_handler() chain.
+//
+//   * OnExhausted  — invokes the sanitizer's "abort with diagnostic"
+//                    handler (e.g. asan's ReportOutOfMemory + Die()).
+//                    Required to never return (enforced by UNREACHABLE()
+//                    annotations in this common infrastructure).
+//===----------------------------------------------------------------------===//
+#ifndef SANITIZER_NEW_HANDLER_H
+#define SANITIZER_NEW_HANDLER_H
+
+#include "sanitizer_allocator.h"
+#include "sanitizer_internal_defs.h"
+#include "sanitizer_platform.h"
+
+#if !SANITIZER_WINDOWS && defined(__cpp_exceptions)
+#  include <new>
+#else
+// Builds without exception support can't include <new>: on Windows the
+// sanitizer runtimes are built without exceptions; elsewhere this TU may
+// have been compiled with -fno-exceptions (e.g. with
+// -DCOMPILER_RT_ASAN_ENABLE_EXCEPTIONS=OFF). Forward-declare just enough
+// of std for the loop; the real std::get_new_handler is supplied by the
+// C++ runtime the sanitizer links against (vcruntime / msvcprt /
+// mingw libstdc++ / libstdc++ / libc++) — it doesn't need to come from
+// <new>.
+namespace std {
+struct nothrow_t {};
+enum class align_val_t : __sanitizer::usize {};
+using new_handler = void (*)();
+new_handler get_new_handler() noexcept;
+}  // namespace std
+#endif  // !SANITIZER_WINDOWS && defined(__cpp_exceptions)
+
+namespace __sanitizer {
+
+// Runs std::get_new_handler() per [new.delete.single]/3+/4 until the
+// allocation succeeds or the chain is exhausted. Returns the allocated
+// pointer on success, nullptr if the handler chain is exhausted.
+//
+// NOTE: A handler that throws, propagates out of this function.
+//       Callers that need to convert exceptions to a nullptr return
+//       (e.g. NewImplNothrow below) must wrap the call in try/catch
+//       themselves.
+template <typename Alloc>
+void* RunNewHandlerChain(Alloc alloc) {
+  for (;;) {
+    void* res = alloc();
+    if (LIKELY(res != nullptr))
+      return res;
+    std::new_handler handler = std::get_new_handler();
+    if (!handler)
+      return nullptr;
+    handler();
+  }
+}
+
+// NORETURN wrapper that promotes the OnExhausted callable's
+// morally-noreturn contract into a real noreturn function signature
+// the compiler can see at every call site.
----------------
davidmrdavid wrote:

I think this is well-understood by the name of the macro. I'd remove this.

```suggestion
```

https://github.com/llvm/llvm-project/pull/201151


More information about the llvm-commits mailing list