[compiler-rt] [asan] Build the asan_new_delete.cpp C++ slice with -frtti (PR #213077)
Justin T. Gibbs via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 12:03:18 PDT 2026
https://github.com/scsiguy updated https://github.com/llvm/llvm-project/pull/213077
>From 1de8daeca6b45d148ff162d72f398a4493f5228c Mon Sep 17 00:00:00 2001
From: Justin Gibbs <gibbs at meta.com>
Date: Thu, 30 Jul 2026 09:41:45 -0600
Subject: [PATCH] [asan] Build the asan_new_delete.cpp C++ slice with -frtti
In preparation for asan's operator new throwing `std::bad_alloc` on OOM,
compile the C++ slice (asan_new_delete.cpp, the only asan TU that throws)
with -frtti instead of the -fno-rtti inherited from ASAN_CFLAGS.
Throwing `std::bad_alloc` needs the type_info for std::bad_alloc. Under
-fno-rtti clang cannot reference the C++ ABI library's canonical
_ZTISt9bad_alloc and instead emits a private, hidden per-image copy of
it. On Mach-O that copy does not coalesce with the definition in
libc++abi, so the type_info the runtime throws with differs from the one
the user's `catch (const std::bad_alloc&)` matches against, and the
program terminates. On ELF the copy is weak with default visibility, so
the linker coalesces every copy to one and the addresses match, but that
coalescing is not guaranteed (e.g. `-Bsymbolic` defeats it).
Building this one TU with -frtti makes clang reference the external
canonical type_info, so the runtime's throw and the user's catch agree
on every platform. The change lives inside the existing exceptions
carve-out, so it only takes effect when the throwing path is compiled
in, and it adds no new library dependency (the exception throw already
requires the C++ ABI library).
---
compiler-rt/cmake/Modules/CompilerRTUtils.cmake | 4 ++++
compiler-rt/lib/asan/CMakeLists.txt | 13 +++++++++++++
2 files changed, 17 insertions(+)
diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
index b1c46ea5bfadb..54c0b6b87af63 100644
--- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
+++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
@@ -41,6 +41,10 @@ macro(append_string_if condition value)
endif()
endmacro()
+macro(remove_rtti_flags list)
+ list(REMOVE_ITEM ${list} -frtti -fno-rtti /GR /GR-)
+endmacro()
+
macro(append_rtti_flag polarity list)
if(${polarity})
append_list_if(COMPILER_RT_HAS_FRTTI_FLAG -frtti ${list})
diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 2a8809d88c70c..c5b1426812cfa 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -188,6 +188,19 @@ if(COMPILER_RT_ASAN_ENABLE_EXCEPTIONS AND COMPILER_RT_HAS_FEXCEPTIONS_FLAG)
list(APPEND ASAN_CXX_CFLAGS -fexceptions)
list(REMOVE_ITEM ASAN_DYNAMIC_CXX_CFLAGS -fno-exceptions)
list(APPEND ASAN_DYNAMIC_CXX_CFLAGS -fexceptions)
+ # The throwing version of operator new throws standard exceptions such as
+ # std::bad_alloc. Under -fno-rtti, clang emits a private type_info for
+ # these exceptions that a `catch` statement in a user's program, referencing
+ # type_info provided by the C++ standard library linked into the program,
+ # can't match on Mach-O.
+ # See this example of the behavior:
+ # https://stackoverflow.com/questions/21737201/problems-throwing-and-catching-exceptions-on-os-x-with-fno-rtti
+ # To avoid this, when available, enable RTTI for all potentially throwing TUs
+ # (ASAN_CXX_SOURCES).
+ remove_rtti_flags(ASAN_CXX_CFLAGS)
+ append_rtti_flag(ON ASAN_CXX_CFLAGS)
+ remove_rtti_flags(ASAN_DYNAMIC_CXX_CFLAGS)
+ append_rtti_flag(ON ASAN_DYNAMIC_CXX_CFLAGS)
if(TARGET cxx-headers OR HAVE_LIBCXX)
list(APPEND ASAN_CXX_CFLAGS ${COMPILER_RT_CXX_CFLAGS})
list(APPEND ASAN_DYNAMIC_CXX_CFLAGS ${COMPILER_RT_CXX_CFLAGS})
More information about the llvm-commits
mailing list