[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