aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2025-01-21 20:01:24 +0300
committerthegeorg <thegeorg@yandex-team.com>2025-01-21 20:28:14 +0300
commit6b26b7fba89ee483b19cef1b1f9adfc50a0b882c (patch)
treea213b47c3532dddccec07dc0ac8e16a97da4843b /contrib/libs
parent10feea72534dc5f149c6f0282675e76da8102275 (diff)
downloadydb-6b26b7fba89ee483b19cef1b1f9adfc50a0b882c.tar.gz
Update contrib/libs/cxxsupp/libcxxabi to 18.1.8
commit_hash:782297dacb6df72c5c25e9298cf3ef6b2861b9f6
Diffstat (limited to 'contrib/libs')
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__exception/exception_ptr.h17
-rw-r--r--contrib/libs/cxxsupp/libcxx/include/__locale4
-rw-r--r--contrib/libs/cxxsupp/libcxx/patches/00-future-2024-05-22-wasm-eptr.patch58
-rw-r--r--contrib/libs/cxxsupp/libcxx/patches/23__locale.patch2
-rw-r--r--contrib/libs/cxxsupp/libcxx/patches/41-exception.patch10
-rw-r--r--contrib/libs/cxxsupp/libcxx/patches/72-abi-has-no-init_primary_exception.patch4
-rw-r--r--contrib/libs/cxxsupp/libcxxabi-parts/ya.make4
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py2
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix4
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/include/cxxabi.h16
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/patches/01-commit-e0e82fc-initial.patch351
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/patches/01-emscripten.patch226
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/patches/02-commit-fd92733-3.1.27.patch65
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/patches/03-commit-fbea9fc-3.1.31.patch19
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/abort_message.h11
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/cxa_demangle.cpp7
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp71
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h5
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/cxa_guard.cpp2
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/cxa_guard_impl.h16
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp46
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/cxa_vector.cpp2
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/demangle/DemangleConfig.h7
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumDemangle.h641
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumNodes.def9
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/demangle/README.txt2
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/demangle/Utility.h8
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/fallback_malloc.cpp9
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp520
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.h7
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp410
-rw-r--r--contrib/libs/cxxsupp/libcxxabi/ya.make5
32 files changed, 1519 insertions, 1041 deletions
diff --git a/contrib/libs/cxxsupp/libcxx/include/__exception/exception_ptr.h b/contrib/libs/cxxsupp/libcxx/include/__exception/exception_ptr.h
index 53df28de7f..08e34967fa 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__exception/exception_ptr.h
+++ b/contrib/libs/cxxsupp/libcxx/include/__exception/exception_ptr.h
@@ -36,11 +36,14 @@ struct __cxa_exception;
_LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(
void*,
std::type_info*,
- void(
# if defined(_WIN32)
- __thiscall
+ void(__thiscall*)(void*)) throw();
+# elif defined(__wasm__)
+ // In Wasm, a destructor returns its argument
+ void* (*)(void*)) throw();
+# else
+ void (*)(void*)) throw();
# endif
- *)(void*)) throw();
}
} // namespace __cxxabiv1
@@ -94,8 +97,16 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
using _Ep2 = __decay_t<_Ep>;
void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep));
+# ifdef __wasm__
+ // In Wasm, a destructor returns its argument
+ (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) -> void* {
+# else
(void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) {
+# endif
std::__destroy_at(static_cast<_Ep2*>(__p));
+# ifdef __wasm__
+ return __p;
+# endif
});
try {
diff --git a/contrib/libs/cxxsupp/libcxx/include/__locale b/contrib/libs/cxxsupp/libcxx/include/__locale
index 42b31f52b7..de7c2c61f5 100644
--- a/contrib/libs/cxxsupp/libcxx/include/__locale
+++ b/contrib/libs/cxxsupp/libcxx/include/__locale
@@ -344,12 +344,12 @@ public:
static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
# define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
-#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
+#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
# ifdef __APPLE__
typedef __uint32_t mask;
# elif defined(__FreeBSD__)
typedef unsigned long mask;
-# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__)
+# elif defined(__NetBSD__)
typedef unsigned short mask;
# endif
static const mask space = _CTYPE_S;
diff --git a/contrib/libs/cxxsupp/libcxx/patches/00-future-2024-05-22-wasm-eptr.patch b/contrib/libs/cxxsupp/libcxx/patches/00-future-2024-05-22-wasm-eptr.patch
new file mode 100644
index 0000000000..f426cdd5f2
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxx/patches/00-future-2024-05-22-wasm-eptr.patch
@@ -0,0 +1,58 @@
+diff --git a/include/__exception/exception_ptr.h b/include/__exception/exception_ptr.h
+index 53e2f71..73834b6 100644
+--- a/include/__exception/exception_ptr.h
++++ b/include/__exception/exception_ptr.h
+@@ -36,11 +36,14 @@ struct __cxa_exception;
+ _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(
+ void*,
+ std::type_info*,
+- void(
+ # if defined(_WIN32)
+- __thiscall
++ void(__thiscall*)(void*)) throw();
++# elif defined(__wasm__)
++ // In Wasm, a destructor returns its argument
++ void* (*)(void*)) throw();
++# else
++ void (*)(void*)) throw();
+ # endif
+- *)(void*)) throw();
+ }
+
+ } // namespace __cxxabiv1
+@@ -88,8 +91,16 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
+ using _Ep2 = __decay_t<_Ep>;
+
+ void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep));
++# ifdef __wasm__
++ // In Wasm, a destructor returns its argument
++ (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) -> void* {
++# else
+ (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) {
++# endif
+ std::__destroy_at(static_cast<_Ep2*>(__p));
++# ifdef __wasm__
++ return __p;
++# endif
+ });
+
+ try {
+diff --git a/include/__locale b/include/__locale
+index 2186db8..fa987cb 100644
+--- a/include/__locale
++++ b/include/__locale
+@@ -344,12 +344,12 @@ public:
+ static const mask __regex_word = 0x4000; // 0x8000 and 0x0100 and 0x00ff are used
+ # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_PRINT
+ # define _LIBCPP_CTYPE_MASK_IS_COMPOSITE_ALPHA
+-#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__)
++#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
+ # ifdef __APPLE__
+ typedef __uint32_t mask;
+ # elif defined(__FreeBSD__)
+ typedef unsigned long mask;
+-# elif defined(__EMSCRIPTEN__) || defined(__NetBSD__)
++# elif defined(__NetBSD__)
+ typedef unsigned short mask;
+ # endif
+ static const mask space = _CTYPE_S;
diff --git a/contrib/libs/cxxsupp/libcxx/patches/23__locale.patch b/contrib/libs/cxxsupp/libcxx/patches/23__locale.patch
index 5769dc3015..6739ec5e8d 100644
--- a/contrib/libs/cxxsupp/libcxx/patches/23__locale.patch
+++ b/contrib/libs/cxxsupp/libcxx/patches/23__locale.patch
@@ -1,5 +1,5 @@
diff --git a/include/__locale b/include/__locale
-index 2186db8..42b31f5 100644
+index fa987cb..de7c2c6 100644
--- a/include/__locale
+++ b/include/__locale
@@ -17,6 +17,7 @@
diff --git a/contrib/libs/cxxsupp/libcxx/patches/41-exception.patch b/contrib/libs/cxxsupp/libcxx/patches/41-exception.patch
index 172c087738..adb9debf11 100644
--- a/contrib/libs/cxxsupp/libcxx/patches/41-exception.patch
+++ b/contrib/libs/cxxsupp/libcxx/patches/41-exception.patch
@@ -1,8 +1,8 @@
diff --git a/include/__exception/exception_ptr.h b/include/__exception/exception_ptr.h
-index 53e2f71..b340ac0 100644
+index 73834b6..e641928 100644
--- a/include/__exception/exception_ptr.h
+++ b/include/__exception/exception_ptr.h
-@@ -49,8 +49,6 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(
+@@ -52,8 +52,6 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(
namespace std { // purposefully not using versioning namespace
@@ -11,7 +11,7 @@ index 53e2f71..b340ac0 100644
class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
void* __ptr_;
-@@ -77,10 +75,18 @@ public:
+@@ -80,10 +78,18 @@ public:
return !(__x == __y);
}
@@ -30,7 +30,7 @@ index 53e2f71..b340ac0 100644
template <class _Ep>
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
-@@ -114,34 +120,7 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
+@@ -125,34 +131,7 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
#else // _LIBCPP_ABI_MICROSOFT
@@ -66,7 +66,7 @@ index 53e2f71..b340ac0 100644
// This is a built-in template function which automagically extracts the required
// information.
-@@ -149,7 +128,7 @@ template <class _E>
+@@ -160,7 +139,7 @@ template <class _E>
void* __GetExceptionInfo(_E);
template <class _Ep>
diff --git a/contrib/libs/cxxsupp/libcxx/patches/72-abi-has-no-init_primary_exception.patch b/contrib/libs/cxxsupp/libcxx/patches/72-abi-has-no-init_primary_exception.patch
index e48292db7a..9564e46456 100644
--- a/contrib/libs/cxxsupp/libcxx/patches/72-abi-has-no-init_primary_exception.patch
+++ b/contrib/libs/cxxsupp/libcxx/patches/72-abi-has-no-init_primary_exception.patch
@@ -1,8 +1,8 @@
diff --git a/include/__exception/exception_ptr.h b/include/__exception/exception_ptr.h
-index b340ac0..53df28d 100644
+index e641928..08e3496 100644
--- a/include/__exception/exception_ptr.h
+++ b/include/__exception/exception_ptr.h
-@@ -90,7 +90,7 @@ public:
+@@ -93,7 +93,7 @@ public:
template <class _Ep>
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
# ifndef _LIBCPP_HAS_NO_EXCEPTIONS
diff --git a/contrib/libs/cxxsupp/libcxxabi-parts/ya.make b/contrib/libs/cxxsupp/libcxxabi-parts/ya.make
index ec57a006df..5425e9f654 100644
--- a/contrib/libs/cxxsupp/libcxxabi-parts/ya.make
+++ b/contrib/libs/cxxsupp/libcxxabi-parts/ya.make
@@ -6,9 +6,9 @@ LICENSE(
Apache-2.0 WITH LLVM-exception
)
-VERSION(17.0.6)
+VERSION(18.1.8)
-ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/llvmorg-17.0.6.tar.gz)
+ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/llvmorg-18.1.8.tar.gz)
ADDINCL(
contrib/libs/cxxsupp/libcxxabi/include
diff --git a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py
index c77e96a5b3..0e45bb48bf 100644
--- a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py
+++ b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/__init__.py
@@ -69,6 +69,7 @@ def post_install(self):
CFLAGS(
-D_LIBCPP_SAFE_STATIC=
-D_LIBCXXABI_DTOR_FUNC=
+ -D__USING_WASM_EXCEPTIONS__
)
ENDIF()
""",
@@ -96,6 +97,7 @@ libcxxabi = NixSourceProject(
],
disable_includes=[
"aix_state_tab_eh.inc",
+ "sys/futex.h",
],
post_install=post_install,
)
diff --git a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix
index 46d08274e3..0ff1b8277f 100644
--- a/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix
+++ b/contrib/libs/cxxsupp/libcxxabi/.yandex_meta/override.nix
@@ -1,11 +1,11 @@
pkgs: attrs: with pkgs; with attrs; rec {
- version = "17.0.6";
+ version = "18.1.8";
src = fetchFromGitHub {
owner = "llvm";
repo = "llvm-project";
rev = "llvmorg-${version}";
- hash = "sha256-8MEDLLhocshmxoEBRSKlJ/GzJ8nfuzQ8qn0X/vLA+ag=";
+ hash = "sha256-iiZKMRo/WxJaBXct9GdAcAT3cz9d9pnAcO1mmR6oPNE=";
};
patches = [];
diff --git a/contrib/libs/cxxsupp/libcxxabi/include/cxxabi.h b/contrib/libs/cxxsupp/libcxxabi/include/cxxabi.h
index 292bac3b32..211d4a5021 100644
--- a/contrib/libs/cxxsupp/libcxxabi/include/cxxabi.h
+++ b/contrib/libs/cxxsupp/libcxxabi/include/cxxabi.h
@@ -36,6 +36,9 @@ class type_info; // forward declaration
// runtime routines use C calling conventions, but are in __cxxabiv1 namespace
namespace __cxxabiv1 {
+
+struct __cxa_exception;
+
extern "C" {
// 2.4.2 Allocating the Exception Object
@@ -43,15 +46,22 @@ extern _LIBCXXABI_FUNC_VIS void *
__cxa_allocate_exception(size_t thrown_size) throw();
extern _LIBCXXABI_FUNC_VIS void
__cxa_free_exception(void *thrown_exception) throw();
+// This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt
+extern _LIBCXXABI_FUNC_VIS __cxa_exception*
+#ifdef __wasm__
+// In Wasm, a destructor returns its argument
+__cxa_init_primary_exception(void* object, std::type_info* tinfo, void*(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw();
+#else
+__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw();
+#endif
// 2.4.3 Throwing the Exception Object
-#ifdef __USING_WASM_EXCEPTIONS__
extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
__cxa_throw(void *thrown_exception, std::type_info *tinfo,
+#ifdef __USING_WASM_EXCEPTIONS__
+ // In Wasm, a destructor returns its argument
void *(_LIBCXXABI_DTOR_FUNC *dest)(void *));
#else
-extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
-__cxa_throw(void *thrown_exception, std::type_info *tinfo,
void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
#endif
diff --git a/contrib/libs/cxxsupp/libcxxabi/patches/01-commit-e0e82fc-initial.patch b/contrib/libs/cxxsupp/libcxxabi/patches/01-commit-e0e82fc-initial.patch
deleted file mode 100644
index aa2fe9e33d..0000000000
--- a/contrib/libs/cxxsupp/libcxxabi/patches/01-commit-e0e82fc-initial.patch
+++ /dev/null
@@ -1,351 +0,0 @@
-From e0e82fcf1ab23805ce90709320ae688e1ea8be57 Mon Sep 17 00:00:00 2001
-From: Sam Clegg <sbc@chromium.org>
-Date: Sat, 22 May 2021 06:39:33 -0700
-Subject: [PATCH] Rebase of changed from emscripten-libs-13.0.0 onto
- llvmorg-14.0.0
-
-diff --git a/include/cxxabi.h b/include/cxxabi.h
---- a/include/cxxabi.h
-+++ b/include/cxxabi.h
-@@ -39,3 +39,9 @@ namespace __cxxabiv1 {
-+#ifdef __USING_WASM_EXCEPTIONS__
-+extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
-+__cxa_throw(void *thrown_exception, std::type_info *tinfo,
-+ void *(_LIBCXXABI_DTOR_FUNC *dest)(void *));
-+#else
- extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
- __cxa_throw(void *thrown_exception, std::type_info *tinfo,
- void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
-+#endif
-diff --git a/src/abort_message.cpp b/src/abort_message.cpp
---- a/src/abort_message.cpp
-+++ b/src/abort_message.cpp
-@@ -33,12 +33,21 @@ void abort_message(const char* format, ...)
- // formatting into the variable-sized buffer fails.
- #if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL)
- {
-+#if defined(__EMSCRIPTEN__) && defined(NDEBUG)
-+ // Just trap in a non-debug build. These internal libcxxabi assertions are
-+ // very rare, and it's not worth linking in vfprintf stdio support or
-+ // even minimal logging for them, as we'll have a proper call stack, which
-+ // will show a call into "abort_message", and can help debugging. (In a
-+ // debug build that won't be inlined.)
-+ abort();
-+#else
- fprintf(stderr, "libc++abi: ");
- va_list list;
- va_start(list, format);
- vfprintf(stderr, format, list);
- va_end(list);
- fprintf(stderr, "\n");
-+#endif
- }
- #endif
-
-diff --git a/src/cxa_exception.cpp b/src/cxa_exception.cpp
---- a/src/cxa_exception.cpp
-+++ b/src/cxa_exception.cpp
-@@ -254,7 +264,13 @@ will call terminate, assuming that there was no handler for the
- exception.
- */
- void
--__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
-+#ifdef __USING_WASM_EXCEPTIONS__
-+// In wasm, destructors return their argument
-+__cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *))
-+#else
-+__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *))
-+#endif
-+{
- __cxa_eh_globals *globals = __cxa_get_globals();
- __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
-
-diff --git a/src/cxa_exception.h b/src/cxa_exception.h
---- a/src/cxa_exception.h
-+++ b/src/cxa_exception.h
-@@ -19,6 +19,25 @@
-
- namespace __cxxabiv1 {
-
-+#ifdef __USING_EMSCRIPTEN_EXCEPTIONS__
-+
-+struct _LIBCXXABI_HIDDEN __cxa_exception {
-+ size_t referenceCount;
-+ std::type_info *exceptionType;
-+ void (*exceptionDestructor)(void *);
-+ uint8_t caught;
-+ uint8_t rethrown;
-+ void *adjustedPtr;
-+ // Add padding to ensure that the size of __cxa_exception is a multiple of
-+ // the maximum useful alignment for the target machine. This ensures that
-+ // the thrown object that follows has that correct alignment.
-+ void *padding;
-+};
-+
-+static_assert(sizeof(__cxa_exception) % alignof(max_align_t) == 0, "__cxa_exception must have a size that is multipl of max alignment");
-+
-+#else
-+
- static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC++\0
- static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
- static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++
-@@ -43,7 +62,12 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
-
- // Manage the exception object itself.
- std::type_info *exceptionType;
-+#ifdef __USING_WASM_EXCEPTIONS__
-+ // In wasm, destructors return their argument
-+ void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
-+#else
- void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
-+#endif
- std::unexpected_handler unexpectedHandler;
- std::terminate_handler terminateHandler;
-
-@@ -159,6 +183,8 @@ extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast ();
- extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception ();
- extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception);
-
-+#endif // !__USING_EMSCRIPTEN_EXCEPTIONS__
-+
- } // namespace __cxxabiv1
-
- #endif // _CXA_EXCEPTION_H
-diff --git a/src/cxa_handlers.cpp b/src/cxa_handlers.cpp
---- a/src/cxa_handlers.cpp
-+++ b/src/cxa_handlers.cpp
-@@ -73,7 +73,7 @@ __attribute__((noreturn))
- void
- terminate() noexcept
- {
--#ifndef _LIBCXXABI_NO_EXCEPTIONS
-+#if !defined(_LIBCXXABI_NO_EXCEPTIONS) && !defined(__USING_EMSCRIPTEN_EXCEPTIONS__)
- // If there might be an uncaught exception
- using namespace __cxxabiv1;
- __cxa_eh_globals* globals = __cxa_get_globals_fast();
-diff --git a/src/cxa_personality.cpp b/src/cxa_personality.cpp
---- a/src/cxa_personality.cpp
-+++ b/src/cxa_personality.cpp
-@@ -41,6 +41,8 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
- _Unwind_Personality_Fn);
- #endif
-
-+#define __USING_SJLJ_OR_WASM_EXCEPTIONS__ (__USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__)
-+
- /*
- Exception Header Layout:
-
-@@ -70,7 +72,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
- +------------------+--+-----+-----+------------------------+--------------------------+
- | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
- +---------------------+-----------+---------------------------------------------------+
--#ifndef __USING_SJLJ_EXCEPTIONS__
-+#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
- +---------------------+-----------+------------------------------------------------+
- | Beginning of Call Site Table The current ip lies within the |
- | ... (start, length) range of one of these |
-@@ -84,7 +86,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
- | +-------------+---------------------------------+------------------------------+ |
- | ... |
- +----------------------------------------------------------------------------------+
--#else // __USING_SJLJ_EXCEPTIONS__
-+#else // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
- +---------------------+-----------+------------------------------------------------+
- | Beginning of Call Site Table The current ip is a 1-based index into |
- | ... this table. Or it is -1 meaning no |
-@@ -97,7 +99,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
- | +-------------+---------------------------------+------------------------------+ |
- | ... |
- +----------------------------------------------------------------------------------+
--#endif // __USING_SJLJ_EXCEPTIONS__
-+#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
- +---------------------------------------------------------------------+
- | Beginning of Action Table ttypeIndex == 0 : cleanup |
- | ... ttypeIndex > 0 : catch |
-@@ -547,7 +549,7 @@ void
- set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
- const scan_results& results)
- {
--#if defined(__USING_SJLJ_EXCEPTIONS__)
-+#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
- #define __builtin_eh_return_data_regno(regno) regno
- #elif defined(__ibmxl__)
- // IBM xlclang++ compiler does not support __builtin_eh_return_data_regno.
-@@ -642,7 +644,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
- // Get beginning current frame's code (as defined by the
- // emitted dwarf code)
- uintptr_t funcStart = _Unwind_GetRegionStart(context);
--#ifdef __USING_SJLJ_EXCEPTIONS__
-+#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
- if (ip == uintptr_t(-1))
- {
- // no action
-@@ -652,9 +654,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
- else if (ip == 0)
- call_terminate(native_exception, unwind_exception);
- // ip is 1-based index into call site table
--#else // !__USING_SJLJ_EXCEPTIONS__
-+#else // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
- uintptr_t ipOffset = ip - funcStart;
--#endif // !defined(_USING_SLJL_EXCEPTIONS__)
-+#endif // !defined(__USING_SJLJ_OR_WASM_EXCEPTIONS__)
- const uint8_t* classInfo = NULL;
- // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
- // dwarf emission
-@@ -676,7 +678,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
- // Walk call-site table looking for range that
- // includes current PC.
- uint8_t callSiteEncoding = *lsda++;
--#ifdef __USING_SJLJ_EXCEPTIONS__
-+#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
- (void)callSiteEncoding; // When using SjLj exceptions, callSiteEncoding is never used
- #endif
- uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
-@@ -687,7 +689,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
- while (callSitePtr < callSiteTableEnd)
- {
- // There is one entry per call site.
--#ifndef __USING_SJLJ_EXCEPTIONS__
-+#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
- // The call sites are non-overlapping in [start, start+length)
- // The call sites are ordered in increasing value of start
- uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
-@@ -695,15 +697,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
- uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
- uintptr_t actionEntry = readULEB128(&callSitePtr);
- if ((start <= ipOffset) && (ipOffset < (start + length)))
--#else // __USING_SJLJ_EXCEPTIONS__
-+#else // __USING_SJLJ_OR_WASM_EXCEPTIONS__
- // ip is 1-based index into this table
- uintptr_t landingPad = readULEB128(&callSitePtr);
- uintptr_t actionEntry = readULEB128(&callSitePtr);
- if (--ip == 0)
--#endif // __USING_SJLJ_EXCEPTIONS__
-+#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
- {
- // Found the call site containing ip.
--#ifndef __USING_SJLJ_EXCEPTIONS__
-+#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
- if (landingPad == 0)
- {
- // No handler here
-@@ -711,9 +713,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
- return;
- }
- landingPad = (uintptr_t)lpStart + landingPad;
--#else // __USING_SJLJ_EXCEPTIONS__
-+#else // __USING_SJLJ_OR_WASM_EXCEPTIONS__
- ++landingPad;
--#endif // __USING_SJLJ_EXCEPTIONS__
-+#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
- results.landingPad = landingPad;
- if (actionEntry == 0)
- {
-@@ -841,7 +843,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
- action += actionOffset;
- } // there is no break out of this loop, only return
- }
--#ifndef __USING_SJLJ_EXCEPTIONS__
-+#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
- else if (ipOffset < start)
- {
- // There is no call site for this ip
-@@ -849,7 +851,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
- // Possible stack corruption.
- call_terminate(native_exception, unwind_exception);
- }
--#endif // !__USING_SJLJ_EXCEPTIONS__
-+#endif // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
- } // there might be some tricky cases which break out of this loop
-
- // It is possible that no eh table entry specify how to handle
-@@ -906,7 +908,9 @@ _UA_CLEANUP_PHASE
- */
-
- #if !defined(_LIBCXXABI_ARM_EHABI)
--#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
-+#ifdef __USING_WASM_EXCEPTIONS__
-+_Unwind_Reason_Code __gxx_personality_wasm0
-+#elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
- static _Unwind_Reason_Code __gxx_personality_imp
- #else
- _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
-diff --git a/src/cxa_thread_atexit.cpp b/src/cxa_thread_atexit.cpp
---- a/src/cxa_thread_atexit.cpp
-+++ b/src/cxa_thread_atexit.cpp
-@@ -112,9 +112,14 @@ extern "C" {
- #ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
- return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
- #else
-+#ifndef __EMSCRIPTEN__
-+ // Emscripten doesn't fully support weak undefined symbols yet
-+ // https://github.com/emscripten-core/emscripten/issues/12819
- if (__cxa_thread_atexit_impl) {
- return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
-- } else {
-+ } else
-+#endif
-+ {
- // Initialize the dtors std::__libcpp_tls_key (uses __cxa_guard_*() for
- // one-time initialization and __cxa_atexit() for destruction)
- static DtorsManager manager;
-diff --git a/src/private_typeinfo.cpp b/src/private_typeinfo.cpp
---- a/src/private_typeinfo.cpp
-+++ b/src/private_typeinfo.cpp
-@@ -1323,4 +1323,35 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
- use_strcmp);
- }
-
-+// XXX EMSCRIPTEN
-+
-+#ifndef __USING_WASM_EXCEPTIONS__
-+
-+// These functions are used by the emscripten-style exception handling
-+// mechanism.
-+// Note that they need to be included even in the `-noexcept` build of
-+// libc++abi to support the case where some parts of a project are built
-+// with exception catching enabled, but at link time exception catching
-+// is disabled. In this case dependencies to these functions (and the JS
-+// functions which call them) will still exist in the final build.
-+extern "C" {
-+
-+int __cxa_can_catch(__shim_type_info* catchType, __shim_type_info* excpType, void **thrown) {
-+ //std::type_info *t1 = static_cast<std::type_info*>(catchType);
-+ //std::type_info *t2 = static_cast<std::type_info*>(excpType);
-+ //printf("can %s catch %s (%p)?\n", t1->name(), t2->name(), thrown);
-+
-+ void *temp = *thrown;
-+ int ret = catchType->can_catch(excpType, temp);
-+ if (ret) *thrown = temp; // apply changes only if we are catching
-+ return ret;
-+}
-+
-+int __cxa_is_pointer_type(__shim_type_info* type) {
-+ return !!dynamic_cast<__pointer_type_info*>(type);
-+}
-+
-+}
-+#endif // __USING_EMSCRIPTEN_EXCEPTIONS__
-+
- } // __cxxabiv1
-diff --git a/src/stdlib_new_delete.cpp b/src/stdlib_new_delete.cpp
---- a/src/stdlib_new_delete.cpp
-+++ b/src/stdlib_new_delete.cpp
-@@ -37,9 +37,17 @@ operator new(std::size_t size) _THROW_BAD_ALLOC
- else
- #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- throw std::bad_alloc();
-+#ifdef __EMSCRIPTEN__
-+ // Abort here so that when exceptions are disabled, we do not just
-+ // return 0 when malloc returns 0.
-+ // We could also do this with set_new_handler, but that adds a
-+ // global constructor and a table entry, overhead that we can avoid
-+ // by doing it this way.
-+ abort();
- #else
- break;
- #endif
-+#endif
- }
- return p;
- }
diff --git a/contrib/libs/cxxsupp/libcxxabi/patches/01-emscripten.patch b/contrib/libs/cxxsupp/libcxxabi/patches/01-emscripten.patch
new file mode 100644
index 0000000000..11ab3d48ad
--- /dev/null
+++ b/contrib/libs/cxxsupp/libcxxabi/patches/01-emscripten.patch
@@ -0,0 +1,226 @@
+--- contrib/libs/cxxsupp/libcxxabi/include/cxxabi.h (index)
++++ contrib/libs/cxxsupp/libcxxabi/include/cxxabi.h (working tree)
+@@ -48,7 +48,12 @@ extern _LIBCXXABI_FUNC_VIS void
+ __cxa_free_exception(void *thrown_exception) throw();
+ // This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt
+ extern _LIBCXXABI_FUNC_VIS __cxa_exception*
++#ifdef __wasm__
++// In Wasm, a destructor returns its argument
++__cxa_init_primary_exception(void* object, std::type_info* tinfo, void*(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw();
++#else
+ __cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw();
++#endif
+
+ // 2.4.3 Throwing the Exception Object
+ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
+--- contrib/libs/cxxsupp/libcxxabi/src/abort_message.cpp (index)
++++ contrib/libs/cxxsupp/libcxxabi/src/abort_message.cpp (working tree)
+@@ -33,12 +33,21 @@ void abort_message(const char* format, ...)
+ // formatting into the variable-sized buffer fails.
+ #if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL)
+ {
++#if defined(__EMSCRIPTEN__) && defined(NDEBUG)
++ // Just trap in a non-debug build. These internal libcxxabi assertions are
++ // very rare, and it's not worth linking in vfprintf stdio support or
++ // even minimal logging for them, as we'll have a proper call stack, which
++ // will show a call into "abort_message", and can help debugging. (In a
++ // debug build that won't be inlined.)
++ abort();
++#else
+ fprintf(stderr, "libc++abi: ");
+ va_list list;
+ va_start(list, format);
+ vfprintf(stderr, format, list);
+ va_end(list);
+ fprintf(stderr, "\n");
++#endif
+ }
+ #endif
+
+--- contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp (index)
++++ contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp (working tree)
+@@ -207,7 +207,12 @@ void __cxa_free_exception(void *thrown_object) throw() {
+ }
+
+ __cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
++#ifdef __USING_WASM_EXCEPTIONS__
++// In Wasm, a destructor returns its argument
++ void *(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() {
++#else
+ void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() {
++#endif
+ __cxa_exception* exception_header = cxa_exception_from_thrown_object(object);
+ exception_header->referenceCount = 0;
+ exception_header->unexpectedHandler = std::get_unexpected();
+@@ -266,6 +271,13 @@ handler, _Unwind_RaiseException may return. In that case, __cxa_throw
+ will call terminate, assuming that there was no handler for the
+ exception.
+ */
++
++#if defined(__EMSCRIPTEN__) && defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
++extern "C" {
++void __throw_exception_with_stack_trace(_Unwind_Exception*);
++} // extern "C"
++#endif
++
+ void
+ #ifdef __USING_WASM_EXCEPTIONS__
+ // In Wasm, a destructor returns its argument
+@@ -286,6 +298,10 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FU
+
+ #ifdef __USING_SJLJ_EXCEPTIONS__
+ _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
++#elif defined(__EMSCRIPTEN__) && defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
++ // In debug mode, call a JS library function to use WebAssembly.Exception JS
++ // API, which enables us to include stack traces
++ __throw_exception_with_stack_trace(&exception_header->unwindHeader);
+ #else
+ _Unwind_RaiseException(&exception_header->unwindHeader);
+ #endif
+@@ -635,6 +651,10 @@ void __cxa_rethrow() {
+ }
+ #ifdef __USING_SJLJ_EXCEPTIONS__
+ _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
++#elif defined(__EMSCRIPTEN__) && defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
++ // In debug mode, call a JS library function to use WebAssembly.Exception JS
++ // API, which enables us to include stack traces
++ __throw_exception_with_stack_trace(&exception_header->unwindHeader);
+ #else
+ _Unwind_RaiseException(&exception_header->unwindHeader);
+ #endif
+@@ -760,6 +780,11 @@ __cxa_rethrow_primary_exception(void* thrown_object)
+ dep_exception_header->unwindHeader.exception_cleanup = dependent_exception_cleanup;
+ #ifdef __USING_SJLJ_EXCEPTIONS__
+ _Unwind_SjLj_RaiseException(&dep_exception_header->unwindHeader);
++#elif defined(__EMSCRIPTEN__) && defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
++ // In debug mode, call a JS library function to use
++ // WebAssembly.Exception JS API, which enables us to include stack
++ // traces
++ __throw_exception_with_stack_trace(&exception_header->unwindHeader);
+ #else
+ _Unwind_RaiseException(&dep_exception_header->unwindHeader);
+ #endif
+--- contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h (index)
++++ contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h (working tree)
+@@ -19,6 +19,26 @@
+
+ namespace __cxxabiv1 {
+
++#ifdef __USING_EMSCRIPTEN_EXCEPTIONS__
++
++struct _LIBCXXABI_HIDDEN __cxa_exception {
++ size_t referenceCount;
++ std::type_info *exceptionType;
++ // In wasm, destructors return 'this' as in ARM
++ void* (*exceptionDestructor)(void *);
++ uint8_t caught;
++ uint8_t rethrown;
++ void *adjustedPtr;
++ // Add padding to ensure that the size of __cxa_exception is a multiple of
++ // the maximum useful alignment for the target machine. This ensures that
++ // the thrown object that follows has that correct alignment.
++ void *padding;
++};
++
++static_assert(sizeof(__cxa_exception) % alignof(max_align_t) == 0, "__cxa_exception must have a size that is multipl of max alignment");
++
++#else
++
+ static const uint64_t kOurExceptionClass = 0x434C4E47432B2B00; // CLNGC++\0
+ static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
+ static const uint64_t get_vendor_and_language = 0xFFFFFFFFFFFFFF00; // mask for CLNGC++
+@@ -164,6 +184,8 @@ extern "C" _LIBCXXABI_FUNC_VIS __cxa_eh_globals * __cxa_get_globals_fast ();
+ extern "C" _LIBCXXABI_FUNC_VIS void * __cxa_allocate_dependent_exception ();
+ extern "C" _LIBCXXABI_FUNC_VIS void __cxa_free_dependent_exception (void * dependent_exception);
+
++#endif // !__USING_EMSCRIPTEN_EXCEPTIONS__
++
+ } // namespace __cxxabiv1
+
+ #endif // _CXA_EXCEPTION_H
+--- contrib/libs/cxxsupp/libcxxabi/src/cxa_handlers.cpp (index)
++++ contrib/libs/cxxsupp/libcxxabi/src/cxa_handlers.cpp (working tree)
+@@ -73,7 +73,7 @@ __attribute__((noreturn))
+ void
+ terminate() noexcept
+ {
+-#ifndef _LIBCXXABI_NO_EXCEPTIONS
++#if !defined(_LIBCXXABI_NO_EXCEPTIONS) && !defined(__USING_EMSCRIPTEN_EXCEPTIONS__)
+ // If there might be an uncaught exception
+ using namespace __cxxabiv1;
+ __cxa_eh_globals* globals = __cxa_get_globals_fast();
+--- contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp (index)
++++ contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp (working tree)
+@@ -663,6 +663,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
+ const uint8_t* lpStart = lpStartEncoding == DW_EH_PE_omit
+ ? (const uint8_t*)funcStart
+ : (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
++ (void)(lpStart); // Unused when using SjLj/Wasm exceptions
+ uint8_t ttypeEncoding = *lsda++;
+ if (ttypeEncoding != DW_EH_PE_omit)
+ {
+@@ -676,7 +677,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
+ // includes current PC.
+ uint8_t callSiteEncoding = *lsda++;
+ #if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
+- (void)callSiteEncoding; // When using SjLj/Wasm exceptions, callSiteEncoding is never used
++ (void)callSiteEncoding; // Unused when using SjLj/Wasm exceptions
+ #endif
+ uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
+ const uint8_t* callSiteTableStart = lsda;
+--- contrib/libs/cxxsupp/libcxxabi/src/cxa_thread_atexit.cpp (index)
++++ contrib/libs/cxxsupp/libcxxabi/src/cxa_thread_atexit.cpp (working tree)
+@@ -112,9 +112,14 @@ extern "C" {
+ #ifdef HAVE___CXA_THREAD_ATEXIT_IMPL
+ return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
+ #else
++#ifndef __EMSCRIPTEN__
++ // Emscripten doesn't implement __cxa_thread_atexit_impl, so we can simply
++ // avoid this check.
+ if (__cxa_thread_atexit_impl) {
+ return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
+- } else {
++ } else
++#endif
++ {
+ // Initialize the dtors std::__libcpp_tls_key (uses __cxa_guard_*() for
+ // one-time initialization and __cxa_atexit() for destruction)
+ static DtorsManager manager;
+--- contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp (index)
++++ contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp (working tree)
+@@ -1531,4 +1531,35 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
+ use_strcmp);
+ }
+
++// XXX EMSCRIPTEN
++
++#ifndef __USING_WASM_EXCEPTIONS__
++
++// These functions are used by the emscripten-style exception handling
++// mechanism.
++// Note that they need to be included even in the `-noexcept` build of
++// libc++abi to support the case where some parts of a project are built
++// with exception catching enabled, but at link time exception catching
++// is disabled. In this case dependencies to these functions (and the JS
++// functions which call them) will still exist in the final build.
++extern "C" {
++
++int __cxa_can_catch(__shim_type_info* catchType, __shim_type_info* excpType, void **thrown) {
++ //std::type_info *t1 = static_cast<std::type_info*>(catchType);
++ //std::type_info *t2 = static_cast<std::type_info*>(excpType);
++ //printf("can %s catch %s (%p)?\n", t1->name(), t2->name(), thrown);
++
++ void *temp = *thrown;
++ int ret = catchType->can_catch(excpType, temp);
++ if (ret) *thrown = temp; // apply changes only if we are catching
++ return ret;
++}
++
++int __cxa_is_pointer_type(__shim_type_info* type) {
++ return !!dynamic_cast<__pointer_type_info*>(type);
++}
++
++}
++#endif // __USING_EMSCRIPTEN_EXCEPTIONS__
++
+ } // __cxxabiv1
diff --git a/contrib/libs/cxxsupp/libcxxabi/patches/02-commit-fd92733-3.1.27.patch b/contrib/libs/cxxsupp/libcxxabi/patches/02-commit-fd92733-3.1.27.patch
deleted file mode 100644
index f4c7b96bf5..0000000000
--- a/contrib/libs/cxxsupp/libcxxabi/patches/02-commit-fd92733-3.1.27.patch
+++ /dev/null
@@ -1,65 +0,0 @@
-From fd92733b4753ad0efdb916a5aca3742b555c9de0 Mon Sep 17 00:00:00 2001
-From: Sam Clegg <sbc@chromium.org>
-Date: Tue, 6 Dec 2022 17:01:34 -0800
-Subject: [PATCH] Patches from emscripten 3.1.27
-
-diff --git a/src/cxa_exception.cpp b/src/cxa_exception.cpp
---- a/src/cxa_exception.cpp
-+++ b/src/cxa_exception.cpp
-@@ -263,6 +263,13 @@ handler, _Unwind_RaiseException may return. In that case, __cxa_throw
- will call terminate, assuming that there was no handler for the
- exception.
- */
-+
-+#if defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
-+extern "C" {
-+void __throw_exception_with_stack_trace(_Unwind_Exception*);
-+} // extern "C"
-+#endif
-+
- void
- #ifdef __USING_WASM_EXCEPTIONS__
- // In wasm, destructors return their argument
-@@ -289,11 +296,27 @@ __cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FU
- __asan_handle_no_return();
- #endif
-
-+#ifdef __EMSCRIPTEN__
- #ifdef __USING_SJLJ_EXCEPTIONS__
- _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
-+#elif __USING_WASM_EXCEPTIONS__
-+#ifdef NDEBUG
-+ _Unwind_RaiseException(&exception_header->unwindHeader);
-+#else
-+ // In debug mode, call a JS library function to use WebAssembly.Exception JS
-+ // API, which enables us to include stack traces
-+ __throw_exception_with_stack_trace(&exception_header->unwindHeader);
-+#endif
- #else
- _Unwind_RaiseException(&exception_header->unwindHeader);
- #endif
-+#else // !__EMSCRIPTEN__
-+#ifdef __USING_SJLJ_EXCEPTIONS__
-+ _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
-+#else
-+ _Unwind_RaiseException(&exception_header->unwindHeader);
-+#endif
-+#endif
- // This only happens when there is no handler, or some unexpected unwinding
- // error happens.
- failed_throw(exception_header);
-diff --git a/src/cxa_personality.cpp b/src/cxa_personality.cpp
---- a/src/cxa_personality.cpp
-+++ b/src/cxa_personality.cpp
-@@ -977,6 +977,11 @@ __gxx_personality_v0
- exc->languageSpecificData = results.languageSpecificData;
- exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
- exc->adjustedPtr = results.adjustedPtr;
-+#ifdef __USING_WASM_EXCEPTIONS__
-+ // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
-+ // results here.
-+ set_registers(unwind_exception, context, results);
-+#endif
- }
- return _URC_HANDLER_FOUND;
- }
diff --git a/contrib/libs/cxxsupp/libcxxabi/patches/03-commit-fbea9fc-3.1.31.patch b/contrib/libs/cxxsupp/libcxxabi/patches/03-commit-fbea9fc-3.1.31.patch
deleted file mode 100644
index 1a896e52e5..0000000000
--- a/contrib/libs/cxxsupp/libcxxabi/patches/03-commit-fbea9fc-3.1.31.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-From fbea9fc86eba9a35958b0154b1b08dbc4744fa09 Mon Sep 17 00:00:00 2001
-From: Sam Clegg <sbc@chromium.org>
-Date: Fri, 27 Jan 2023 09:02:49 -0800
-Subject: [PATCH] Patches from emscripten 3.1.31
-
-diff --git a/src/cxa_thread_atexit.cpp b/src/cxa_thread_atexit.cpp
---- a/src/cxa_thread_atexit.cpp
-+++ b/src/cxa_thread_atexit.cpp
-@@ -113,8 +113,8 @@ extern "C" {
- return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
- #else
- #ifndef __EMSCRIPTEN__
-- // Emscripten doesn't fully support weak undefined symbols yet
-- // https://github.com/emscripten-core/emscripten/issues/12819
-+ // Emscripten doesn't implement __cxa_thread_atexit_impl, so we can simply
-+ // avoid this check.
- if (__cxa_thread_atexit_impl) {
- return __cxa_thread_atexit_impl(dtor, obj, dso_symbol);
- } else
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/abort_message.h b/contrib/libs/cxxsupp/libcxxabi/src/abort_message.h
index f1d5c12e25..9764177780 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/abort_message.h
+++ b/contrib/libs/cxxsupp/libcxxabi/src/abort_message.h
@@ -14,4 +14,15 @@
extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
abort_message(const char *format, ...) __attribute__((format(printf, 1, 2)));
+#ifndef _LIBCXXABI_ASSERT
+# define _LIBCXXABI_ASSERT(expr, msg) \
+ do { \
+ if (!(expr)) { \
+ char const* __msg = (msg); \
+ ::abort_message("%s:%d: %s", __FILE__, __LINE__, __msg); \
+ } \
+ } while (false)
+
#endif
+
+#endif // __ABORT_MESSAGE_H_
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_demangle.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_demangle.cpp
index 03085cb590..bece33a007 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_demangle.cpp
+++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_demangle.cpp
@@ -10,14 +10,17 @@
// file does not yet support:
// - C++ modules TS
+#include "abort_message.h"
+#define DEMANGLE_ASSERT(expr, msg) _LIBCXXABI_ASSERT(expr, msg)
+
#include "demangle/DemangleConfig.h"
#include "demangle/ItaniumDemangle.h"
#include "__cxxabi_config.h"
-#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
+#include <exception>
#include <functional>
#include <numeric>
#include <string_view>
@@ -394,7 +397,7 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
InternalStatus = demangle_invalid_mangled_name;
else {
OutputBuffer O(Buf, N);
- assert(Parser.ForwardTemplateRefs.empty());
+ DEMANGLE_ASSERT(Parser.ForwardTemplateRefs.empty(), "");
AST->print(O);
O += '\0';
if (N != nullptr)
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp
index 19c333d9c0..4a792e0851 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp
+++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.cpp
@@ -206,6 +206,24 @@ void __cxa_free_exception(void *thrown_object) throw() {
__aligned_free_with_fallback((void *)raw_buffer);
}
+__cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
+#ifdef __USING_WASM_EXCEPTIONS__
+// In Wasm, a destructor returns its argument
+ void *(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() {
+#else
+ void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() {
+#endif
+ __cxa_exception* exception_header = cxa_exception_from_thrown_object(object);
+ exception_header->referenceCount = 0;
+ exception_header->unexpectedHandler = std::get_unexpected();
+ exception_header->terminateHandler = std::get_terminate();
+ exception_header->exceptionType = tinfo;
+ exception_header->exceptionDestructor = dest;
+ setOurExceptionClass(&exception_header->unwindHeader);
+ exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;
+
+ return exception_header;
+}
// This function shall allocate a __cxa_dependent_exception and
// return a pointer to it. (Really to the object, not past its' end).
@@ -254,7 +272,7 @@ will call terminate, assuming that there was no handler for the
exception.
*/
-#if defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
+#if defined(__EMSCRIPTEN__) && defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
extern "C" {
void __throw_exception_with_stack_trace(_Unwind_Exception*);
} // extern "C"
@@ -262,51 +280,31 @@ void __throw_exception_with_stack_trace(_Unwind_Exception*);
void
#ifdef __USING_WASM_EXCEPTIONS__
-// In wasm, destructors return their argument
-__cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *))
+// In Wasm, a destructor returns its argument
+__cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
#else
-__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *))
+__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
#endif
-{
- __cxa_eh_globals *globals = __cxa_get_globals();
- __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
-
- exception_header->unexpectedHandler = std::get_unexpected();
- exception_header->terminateHandler = std::get_terminate();
- exception_header->exceptionType = tinfo;
- exception_header->exceptionDestructor = dest;
- setOurExceptionClass(&exception_header->unwindHeader);
- exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
- globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
+ __cxa_eh_globals* globals = __cxa_get_globals();
+ globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
- exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;
+ __cxa_exception* exception_header = __cxa_init_primary_exception(thrown_object, tinfo, dest);
+ exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
#if __has_feature(address_sanitizer)
- // Inform the ASan runtime that now might be a good time to clean stuff up.
- __asan_handle_no_return();
+ // Inform the ASan runtime that now might be a good time to clean stuff up.
+ __asan_handle_no_return();
#endif
-#ifdef __EMSCRIPTEN__
#ifdef __USING_SJLJ_EXCEPTIONS__
_Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
-#elif __USING_WASM_EXCEPTIONS__
-#ifdef NDEBUG
- _Unwind_RaiseException(&exception_header->unwindHeader);
-#else
+#elif defined(__EMSCRIPTEN__) && defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
// In debug mode, call a JS library function to use WebAssembly.Exception JS
// API, which enables us to include stack traces
__throw_exception_with_stack_trace(&exception_header->unwindHeader);
-#endif
#else
_Unwind_RaiseException(&exception_header->unwindHeader);
#endif
-#else // !__EMSCRIPTEN__
-#ifdef __USING_SJLJ_EXCEPTIONS__
- _Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
-#else
- _Unwind_RaiseException(&exception_header->unwindHeader);
-#endif
-#endif
// This only happens when there is no handler, or some unexpected unwinding
// error happens.
failed_throw(exception_header);
@@ -653,6 +651,10 @@ void __cxa_rethrow() {
}
#ifdef __USING_SJLJ_EXCEPTIONS__
_Unwind_SjLj_RaiseException(&exception_header->unwindHeader);
+#elif defined(__EMSCRIPTEN__) && defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
+ // In debug mode, call a JS library function to use WebAssembly.Exception JS
+ // API, which enables us to include stack traces
+ __throw_exception_with_stack_trace(&exception_header->unwindHeader);
#else
_Unwind_RaiseException(&exception_header->unwindHeader);
#endif
@@ -778,6 +780,11 @@ __cxa_rethrow_primary_exception(void* thrown_object)
dep_exception_header->unwindHeader.exception_cleanup = dependent_exception_cleanup;
#ifdef __USING_SJLJ_EXCEPTIONS__
_Unwind_SjLj_RaiseException(&dep_exception_header->unwindHeader);
+#elif defined(__EMSCRIPTEN__) && defined(__USING_WASM_EXCEPTIONS__) && !defined(NDEBUG)
+ // In debug mode, call a JS library function to use
+ // WebAssembly.Exception JS API, which enables us to include stack
+ // traces
+ __throw_exception_with_stack_trace(&exception_header->unwindHeader);
#else
_Unwind_RaiseException(&dep_exception_header->unwindHeader);
#endif
@@ -800,6 +807,6 @@ __cxa_uncaught_exceptions() throw()
return globals->uncaughtExceptions;
}
-} // extern "C"
+} // extern "C"
} // abi
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h b/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h
index dd20ba1e88..098e0bf95a 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h
+++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_exception.h
@@ -24,7 +24,8 @@ namespace __cxxabiv1 {
struct _LIBCXXABI_HIDDEN __cxa_exception {
size_t referenceCount;
std::type_info *exceptionType;
- void (*exceptionDestructor)(void *);
+ // In wasm, destructors return 'this' as in ARM
+ void* (*exceptionDestructor)(void *);
uint8_t caught;
uint8_t rethrown;
void *adjustedPtr;
@@ -63,7 +64,7 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
// Manage the exception object itself.
std::type_info *exceptionType;
#ifdef __USING_WASM_EXCEPTIONS__
- // In wasm, destructors return their argument
+ // In Wasm, a destructor returns its argument
void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
#else
void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_guard.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_guard.cpp
index fc1fa90511..514fa962e3 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_guard.cpp
+++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_guard.cpp
@@ -48,6 +48,6 @@ _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *raw_guard_object) {
SelectedImplementation imp(raw_guard_object);
imp.cxa_guard_abort();
}
-} // extern "C"
+} // extern "C"
} // __cxxabiv1
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_guard_impl.h b/contrib/libs/cxxsupp/libcxxabi/src/cxa_guard_impl.h
index 7b140d3c36..fb3e9eed8f 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_guard_impl.h
+++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_guard_impl.h
@@ -47,6 +47,9 @@
#include "__cxxabi_config.h"
#include "include/atomic_support.h" // from libc++
#if defined(__has_include)
+# if __has_include(<sys/futex.h>)
+# error #include <sys/futex.h>
+# endif
# if __has_include(<sys/syscall.h>)
# include <sys/syscall.h>
# endif
@@ -411,7 +414,18 @@ private:
// Futex Implementation
//===----------------------------------------------------------------------===//
-#if defined(SYS_futex)
+#if defined(__OpenBSD__)
+void PlatformFutexWait(int* addr, int expect) {
+ constexpr int WAIT = 0;
+ futex(reinterpret_cast<volatile uint32_t*>(addr), WAIT, expect, NULL, NULL);
+ __tsan_acquire(addr);
+}
+void PlatformFutexWake(int* addr) {
+ constexpr int WAKE = 1;
+ __tsan_release(addr);
+ futex(reinterpret_cast<volatile uint32_t*>(addr), WAKE, INT_MAX, NULL, NULL);
+}
+#elif defined(SYS_futex)
void PlatformFutexWait(int* addr, int expect) {
constexpr int WAIT = 0;
syscall(SYS_futex, addr, WAIT, expect, 0);
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp
index 1a969265f0..501bc75a8c 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp
+++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_personality.cpp
@@ -41,8 +41,6 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
_Unwind_Personality_Fn);
#endif
-#define __USING_SJLJ_OR_WASM_EXCEPTIONS__ (__USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__)
-
/*
Exception Header Layout:
@@ -72,7 +70,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
+------------------+--+-----+-----+------------------------+--------------------------+
| callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
+---------------------+-----------+---------------------------------------------------+
-#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
+---------------------+-----------+------------------------------------------------+
| Beginning of Call Site Table The current ip lies within the |
| ... (start, length) range of one of these |
@@ -86,7 +84,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
| +-------------+---------------------------------+------------------------------+ |
| ... |
+----------------------------------------------------------------------------------+
-#else // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
+#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
+---------------------+-----------+------------------------------------------------+
| Beginning of Call Site Table The current ip is a 1-based index into |
| ... this table. Or it is -1 meaning no |
@@ -99,7 +97,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
| +-------------+---------------------------------+------------------------------+ |
| ... |
+----------------------------------------------------------------------------------+
-#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
+---------------------------------------------------------------------+
| Beginning of Action Table ttypeIndex == 0 : cleanup |
| ... ttypeIndex > 0 : catch |
@@ -549,7 +547,7 @@ void
set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
const scan_results& results)
{
-#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
#define __builtin_eh_return_data_regno(regno) regno
#elif defined(__ibmxl__)
// IBM xlclang++ compiler does not support __builtin_eh_return_data_regno.
@@ -644,7 +642,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
// Get beginning current frame's code (as defined by the
// emitted dwarf code)
uintptr_t funcStart = _Unwind_GetRegionStart(context);
-#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
if (ip == uintptr_t(-1))
{
// no action
@@ -654,18 +652,18 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
else if (ip == 0)
call_terminate(native_exception, unwind_exception);
// ip is 1-based index into call site table
-#else // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
+#else // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
uintptr_t ipOffset = ip - funcStart;
-#endif // !defined(__USING_SJLJ_OR_WASM_EXCEPTIONS__)
+#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
const uint8_t* classInfo = NULL;
// Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
// dwarf emission
// Parse LSDA header.
uint8_t lpStartEncoding = *lsda++;
- const uint8_t* lpStart =
- (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
- if (lpStart == 0)
- lpStart = (const uint8_t*)funcStart;
+ const uint8_t* lpStart = lpStartEncoding == DW_EH_PE_omit
+ ? (const uint8_t*)funcStart
+ : (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
+ (void)(lpStart); // Unused when using SjLj/Wasm exceptions
uint8_t ttypeEncoding = *lsda++;
if (ttypeEncoding != DW_EH_PE_omit)
{
@@ -678,8 +676,8 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
// Walk call-site table looking for range that
// includes current PC.
uint8_t callSiteEncoding = *lsda++;
-#ifdef __USING_SJLJ_OR_WASM_EXCEPTIONS__
- (void)callSiteEncoding; // When using SjLj exceptions, callSiteEncoding is never used
+#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
+ (void)callSiteEncoding; // Unused when using SjLj/Wasm exceptions
#endif
uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
const uint8_t* callSiteTableStart = lsda;
@@ -689,7 +687,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
while (callSitePtr < callSiteTableEnd)
{
// There is one entry per call site.
-#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
// The call sites are non-overlapping in [start, start+length)
// The call sites are ordered in increasing value of start
uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
@@ -697,15 +695,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
uintptr_t actionEntry = readULEB128(&callSitePtr);
if ((start <= ipOffset) && (ipOffset < (start + length)))
-#else // __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
// ip is 1-based index into this table
uintptr_t landingPad = readULEB128(&callSitePtr);
uintptr_t actionEntry = readULEB128(&callSitePtr);
if (--ip == 0)
-#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
{
// Found the call site containing ip.
-#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
if (landingPad == 0)
{
// No handler here
@@ -713,9 +711,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
return;
}
landingPad = (uintptr_t)lpStart + landingPad;
-#else // __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
++landingPad;
-#endif // __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
results.landingPad = landingPad;
if (actionEntry == 0)
{
@@ -843,7 +841,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
action += actionOffset;
} // there is no break out of this loop, only return
}
-#ifndef __USING_SJLJ_OR_WASM_EXCEPTIONS__
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
else if (ipOffset < start)
{
// There is no call site for this ip
@@ -851,7 +849,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
// Possible stack corruption.
call_terminate(native_exception, unwind_exception);
}
-#endif // !__USING_SJLJ_OR_WASM_EXCEPTIONS__
+#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
} // there might be some tricky cases which break out of this loop
// It is possible that no eh table entry specify how to handle
@@ -1313,7 +1311,7 @@ _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(
__attribute__((__alias__("__gxx_personality_v0")));
#endif
-} // extern "C"
+} // extern "C"
} // __cxxabiv1
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/cxa_vector.cpp b/contrib/libs/cxxsupp/libcxxabi/src/cxa_vector.cpp
index 099f9f0c1e..17d942a6e6 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/cxa_vector.cpp
+++ b/contrib/libs/cxxsupp/libcxxabi/src/cxa_vector.cpp
@@ -416,6 +416,6 @@ __cxa_vec_delete3(void *array_address, size_t element_size, size_t padding_size,
}
-} // extern "C"
+} // extern "C"
} // abi
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/demangle/DemangleConfig.h b/contrib/libs/cxxsupp/libcxxabi/src/demangle/DemangleConfig.h
index d5e11432d9..d67d89bdb0 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/demangle/DemangleConfig.h
+++ b/contrib/libs/cxxsupp/libcxxabi/src/demangle/DemangleConfig.h
@@ -19,7 +19,7 @@
#include "../abort_message.h"
#endif
-#include <ciso646>
+#include <version>
#ifdef _MSC_VER
// snprintf is implemented in VS 2015
@@ -99,6 +99,11 @@
#define DEMANGLE_FALLTHROUGH
#endif
+#ifndef DEMANGLE_ASSERT
+#include <cassert>
+#define DEMANGLE_ASSERT(__expr, __msg) assert((__expr) && (__msg))
+#endif
+
#define DEMANGLE_NAMESPACE_BEGIN namespace { namespace itanium_demangle {
#define DEMANGLE_NAMESPACE_END } }
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumDemangle.h b/contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumDemangle.h
index 5427278597..03282ac68c 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -21,7 +21,6 @@
#include "Utility.h"
#include <__cxxabi_config.h>
#include <algorithm>
-#include <cassert>
#include <cctype>
#include <cstdio>
#include <cstdlib>
@@ -61,13 +60,13 @@ template <class T, size_t N> class PODSmallVector {
if (isInline()) {
auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
if (Tmp == nullptr)
- std::terminate();
+ std::abort();
std::copy(First, Last, Tmp);
First = Tmp;
} else {
First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
if (First == nullptr)
- std::terminate();
+ std::abort();
}
Last = First + S;
Cap = First + NewCap;
@@ -129,12 +128,12 @@ public:
// NOLINTNEXTLINE(readability-identifier-naming)
void pop_back() {
- assert(Last != First && "Popping empty vector!");
+ DEMANGLE_ASSERT(Last != First, "Popping empty vector!");
--Last;
}
- void dropBack(size_t Index) {
- assert(Index <= size() && "dropBack() can't expand!");
+ void shrinkToSize(size_t Index) {
+ DEMANGLE_ASSERT(Index <= size(), "shrinkToSize() can't expand!");
Last = First + Index;
}
@@ -144,11 +143,11 @@ public:
bool empty() const { return First == Last; }
size_t size() const { return static_cast<size_t>(Last - First); }
T &back() {
- assert(Last != First && "Calling back() on empty vector!");
+ DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!");
return *(Last - 1);
}
T &operator[](size_t Index) {
- assert(Index < size() && "Invalid access!");
+ DEMANGLE_ASSERT(Index < size(), "Invalid access!");
return *(begin() + Index);
}
void clear() { Last = First; }
@@ -534,6 +533,23 @@ public:
}
};
+class TransformedType : public Node {
+ std::string_view Transform;
+ Node *BaseType;
+public:
+ TransformedType(std::string_view Transform_, Node *BaseType_)
+ : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
+
+ template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
+
+ void printLeft(OutputBuffer &OB) const override {
+ OB += Transform;
+ OB += '(';
+ BaseType->print(OB);
+ OB += ')';
+ }
+};
+
struct AbiTagAttr : Node {
Node *Base;
std::string_view Tag;
@@ -873,26 +889,53 @@ public:
}
};
+/// Represents the explicitly named object parameter.
+/// E.g.,
+/// \code{.cpp}
+/// struct Foo {
+/// void bar(this Foo && self);
+/// };
+/// \endcode
+class ExplicitObjectParameter final : public Node {
+ Node *Base;
+
+public:
+ ExplicitObjectParameter(Node *Base_)
+ : Node(KExplicitObjectParameter), Base(Base_) {
+ DEMANGLE_ASSERT(
+ Base != nullptr,
+ "Creating an ExplicitObjectParameter without a valid Base Node.");
+ }
+
+ template <typename Fn> void match(Fn F) const { F(Base); }
+
+ void printLeft(OutputBuffer &OB) const override {
+ OB += "this ";
+ Base->print(OB);
+ }
+};
+
class FunctionEncoding final : public Node {
const Node *Ret;
const Node *Name;
NodeArray Params;
const Node *Attrs;
+ const Node *Requires;
Qualifiers CVQuals;
FunctionRefQual RefQual;
public:
FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
- const Node *Attrs_, Qualifiers CVQuals_,
- FunctionRefQual RefQual_)
+ const Node *Attrs_, const Node *Requires_,
+ Qualifiers CVQuals_, FunctionRefQual RefQual_)
: Node(KFunctionEncoding,
/*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
/*FunctionCache=*/Cache::Yes),
Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
- CVQuals(CVQuals_), RefQual(RefQual_) {}
+ Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}
template<typename Fn> void match(Fn F) const {
- F(Ret, Name, Params, Attrs, CVQuals, RefQual);
+ F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual);
}
Qualifiers getCVQuals() const { return CVQuals; }
@@ -935,6 +978,11 @@ public:
if (Attrs != nullptr)
Attrs->print(OB);
+
+ if (Requires != nullptr) {
+ OB += " requires ";
+ Requires->print(OB);
+ }
}
};
@@ -1006,6 +1054,24 @@ struct NestedName : Node {
}
};
+struct MemberLikeFriendName : Node {
+ Node *Qual;
+ Node *Name;
+
+ MemberLikeFriendName(Node *Qual_, Node *Name_)
+ : Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {}
+
+ template<typename Fn> void match(Fn F) const { F(Qual, Name); }
+
+ std::string_view getBaseName() const override { return Name->getBaseName(); }
+
+ void printLeft(OutputBuffer &OB) const override {
+ Qual->print(OB);
+ OB += "::friend ";
+ Name->print(OB);
+ }
+};
+
struct ModuleName : Node {
ModuleName *Parent;
Node *Name;
@@ -1171,6 +1237,24 @@ public:
}
};
+class TemplateParamQualifiedArg final : public Node {
+ Node *Param;
+ Node *Arg;
+
+public:
+ TemplateParamQualifiedArg(Node *Param_, Node *Arg_)
+ : Node(KTemplateParamQualifiedArg), Param(Param_), Arg(Arg_) {}
+
+ template <typename Fn> void match(Fn F) const { F(Param, Arg); }
+
+ Node *getArg() { return Arg; }
+
+ void printLeft(OutputBuffer &OB) const override {
+ // Don't print Param to keep the output consistent.
+ Arg->print(OB);
+ }
+};
+
/// A template type parameter declaration, 'typename T'.
class TypeTemplateParamDecl final : public Node {
Node *Name;
@@ -1186,6 +1270,26 @@ public:
void printRight(OutputBuffer &OB) const override { Name->print(OB); }
};
+/// A constrained template type parameter declaration, 'C<U> T'.
+class ConstrainedTypeTemplateParamDecl final : public Node {
+ Node *Constraint;
+ Node *Name;
+
+public:
+ ConstrainedTypeTemplateParamDecl(Node *Constraint_, Node *Name_)
+ : Node(KConstrainedTypeTemplateParamDecl, Cache::Yes),
+ Constraint(Constraint_), Name(Name_) {}
+
+ template<typename Fn> void match(Fn F) const { F(Constraint, Name); }
+
+ void printLeft(OutputBuffer &OB) const override {
+ Constraint->print(OB);
+ OB += " ";
+ }
+
+ void printRight(OutputBuffer &OB) const override { Name->print(OB); }
+};
+
/// A non-type template parameter declaration, 'int N'.
class NonTypeTemplateParamDecl final : public Node {
Node *Name;
@@ -1214,13 +1318,14 @@ public:
class TemplateTemplateParamDecl final : public Node {
Node *Name;
NodeArray Params;
+ Node *Requires;
public:
- TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
+ TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_)
: Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
- Params(Params_) {}
+ Params(Params_), Requires(Requires_) {}
- template<typename Fn> void match(Fn F) const { F(Name, Params); }
+ template <typename Fn> void match(Fn F) const { F(Name, Params, Requires); }
void printLeft(OutputBuffer &OB) const override {
ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
@@ -1229,7 +1334,13 @@ public:
OB += "> typename ";
}
- void printRight(OutputBuffer &OB) const override { Name->print(OB); }
+ void printRight(OutputBuffer &OB) const override {
+ Name->print(OB);
+ if (Requires != nullptr) {
+ OB += " requires ";
+ Requires->print(OB);
+ }
+ }
};
/// A template parameter pack declaration, 'typename ...T'.
@@ -1326,7 +1437,7 @@ public:
/// A variadic template argument. This node represents an occurrence of
/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
-/// one of it's Elements is. The parser inserts a ParameterPack into the
+/// one of its Elements is. The parser inserts a ParameterPack into the
/// TemplateParams table if the <template-args> this pack belongs to apply to an
/// <encoding>.
class TemplateArgumentPack final : public Node {
@@ -1392,11 +1503,13 @@ public:
class TemplateArgs final : public Node {
NodeArray Params;
+ Node *Requires;
public:
- TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}
+ TemplateArgs(NodeArray Params_, Node *Requires_)
+ : Node(KTemplateArgs), Params(Params_), Requires(Requires_) {}
- template<typename Fn> void match(Fn F) const { F(Params); }
+ template<typename Fn> void match(Fn F) const { F(Params, Requires); }
NodeArray getParams() { return Params; }
@@ -1405,6 +1518,7 @@ public:
OB += "<";
Params.printWithComma(OB);
OB += ">";
+ // Don't print the requires clause to keep the output simple.
}
};
@@ -1589,7 +1703,7 @@ public:
std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
if (isInstantiation()) {
// The instantiations are typedefs that drop the "basic_" prefix.
- assert(starts_with(SV, "basic_"));
+ DEMANGLE_ASSERT(starts_with(SV, "basic_"), "");
SV.remove_prefix(sizeof("basic_") - 1);
}
return SV;
@@ -1655,17 +1769,21 @@ public:
class ClosureTypeName : public Node {
NodeArray TemplateParams;
+ const Node *Requires1;
NodeArray Params;
+ const Node *Requires2;
std::string_view Count;
public:
- ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
+ ClosureTypeName(NodeArray TemplateParams_, const Node *Requires1_,
+ NodeArray Params_, const Node *Requires2_,
std::string_view Count_)
: Node(KClosureTypeName), TemplateParams(TemplateParams_),
- Params(Params_), Count(Count_) {}
+ Requires1(Requires1_), Params(Params_), Requires2(Requires2_),
+ Count(Count_) {}
template<typename Fn> void match(Fn F) const {
- F(TemplateParams, Params, Count);
+ F(TemplateParams, Requires1, Params, Requires2, Count);
}
void printDeclarator(OutputBuffer &OB) const {
@@ -1675,12 +1793,22 @@ public:
TemplateParams.printWithComma(OB);
OB += ">";
}
+ if (Requires1 != nullptr) {
+ OB += " requires ";
+ Requires1->print(OB);
+ OB += " ";
+ }
OB.printOpen();
Params.printWithComma(OB);
OB.printClose();
+ if (Requires2 != nullptr) {
+ OB += " requires ";
+ Requires2->print(OB);
+ }
}
void printLeft(OutputBuffer &OB) const override {
+ // FIXME: This demangling is not particularly readable.
OB += "\'lambda";
OB += Count;
OB += "\'";
@@ -2309,6 +2437,95 @@ public:
}
};
+class RequiresExpr : public Node {
+ NodeArray Parameters;
+ NodeArray Requirements;
+public:
+ RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)
+ : Node(KRequiresExpr), Parameters(Parameters_),
+ Requirements(Requirements_) {}
+
+ template<typename Fn> void match(Fn F) const { F(Parameters, Requirements); }
+
+ void printLeft(OutputBuffer &OB) const override {
+ OB += "requires";
+ if (!Parameters.empty()) {
+ OB += ' ';
+ OB.printOpen();
+ Parameters.printWithComma(OB);
+ OB.printClose();
+ }
+ OB += ' ';
+ OB.printOpen('{');
+ for (const Node *Req : Requirements) {
+ Req->print(OB);
+ }
+ OB += ' ';
+ OB.printClose('}');
+ }
+};
+
+class ExprRequirement : public Node {
+ const Node *Expr;
+ bool IsNoexcept;
+ const Node *TypeConstraint;
+public:
+ ExprRequirement(const Node *Expr_, bool IsNoexcept_,
+ const Node *TypeConstraint_)
+ : Node(KExprRequirement), Expr(Expr_), IsNoexcept(IsNoexcept_),
+ TypeConstraint(TypeConstraint_) {}
+
+ template <typename Fn> void match(Fn F) const {
+ F(Expr, IsNoexcept, TypeConstraint);
+ }
+
+ void printLeft(OutputBuffer &OB) const override {
+ OB += " ";
+ if (IsNoexcept || TypeConstraint)
+ OB.printOpen('{');
+ Expr->print(OB);
+ if (IsNoexcept || TypeConstraint)
+ OB.printClose('}');
+ if (IsNoexcept)
+ OB += " noexcept";
+ if (TypeConstraint) {
+ OB += " -> ";
+ TypeConstraint->print(OB);
+ }
+ OB += ';';
+ }
+};
+
+class TypeRequirement : public Node {
+ const Node *Type;
+public:
+ TypeRequirement(const Node *Type_)
+ : Node(KTypeRequirement), Type(Type_) {}
+
+ template <typename Fn> void match(Fn F) const { F(Type); }
+
+ void printLeft(OutputBuffer &OB) const override {
+ OB += " typename ";
+ Type->print(OB);
+ OB += ';';
+ }
+};
+
+class NestedRequirement : public Node {
+ const Node *Constraint;
+public:
+ NestedRequirement(const Node *Constraint_)
+ : Node(KNestedRequirement), Constraint(Constraint_) {}
+
+ template <typename Fn> void match(Fn F) const { F(Constraint); }
+
+ void printLeft(OutputBuffer &OB) const override {
+ OB += " requires ";
+ Constraint->print(OB);
+ OB += ';';
+ }
+};
+
template <class Float> struct FloatData;
namespace float_literal_impl {
@@ -2377,7 +2594,7 @@ void Node::visit(Fn F) const {
return F(static_cast<const X *>(this));
#include "ItaniumNodes.def"
}
- assert(0 && "unknown mangling node kind");
+ DEMANGLE_ASSERT(0, "unknown mangling node kind");
}
/// Determine the kind of a node from its type.
@@ -2403,6 +2620,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
// table.
PODSmallVector<Node *, 32> Subs;
+ // A list of template argument values corresponding to a template parameter
+ // list.
using TemplateParamList = PODSmallVector<Node *, 8>;
class ScopedTemplateParamList {
@@ -2417,9 +2636,11 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Parser->TemplateParams.push_back(&Params);
}
~ScopedTemplateParamList() {
- assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
- Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
+ DEMANGLE_ASSERT(Parser->TemplateParams.size() >= OldNumTemplateParamLists,
+ "");
+ Parser->TemplateParams.shrinkToSize(OldNumTemplateParamLists);
}
+ TemplateParamList *params() { return &Params; }
};
// Template parameter table. Like the above, but referenced like "T42_".
@@ -2434,12 +2655,31 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
// parameter list, the corresponding parameter list pointer will be null.
PODSmallVector<TemplateParamList *, 4> TemplateParams;
+ class SaveTemplateParams {
+ AbstractManglingParser *Parser;
+ decltype(TemplateParams) OldParams;
+ decltype(OuterTemplateParams) OldOuterParams;
+
+ public:
+ SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
+ OldParams = std::move(Parser->TemplateParams);
+ OldOuterParams = std::move(Parser->OuterTemplateParams);
+ Parser->TemplateParams.clear();
+ Parser->OuterTemplateParams.clear();
+ }
+ ~SaveTemplateParams() {
+ Parser->TemplateParams = std::move(OldParams);
+ Parser->OuterTemplateParams = std::move(OldOuterParams);
+ }
+ };
+
// Set of unresolved forward <template-param> references. These can occur in a
// conversion operator's type, and are resolved in the enclosing <encoding>.
PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
bool TryToParseTemplateArgs = true;
bool PermitForwardTemplateReferences = false;
+ bool InConstraintExpr = false;
size_t ParsingLambdaParamsAtLevel = (size_t)-1;
unsigned NumSyntheticTemplateParameters[3] = {};
@@ -2478,10 +2718,10 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
}
NodeArray popTrailingNodeArray(size_t FromPosition) {
- assert(FromPosition <= Names.size());
+ DEMANGLE_ASSERT(FromPosition <= Names.size(), "");
NodeArray res =
makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
- Names.dropBack(FromPosition);
+ Names.shrinkToSize(FromPosition);
return res;
}
@@ -2519,11 +2759,16 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
bool parseSeqId(size_t *Out);
Node *parseSubstitution();
Node *parseTemplateParam();
- Node *parseTemplateParamDecl();
+ Node *parseTemplateParamDecl(TemplateParamList *Params);
Node *parseTemplateArgs(bool TagTemplates = false);
Node *parseTemplateArg();
- /// Parse the <expr> production.
+ bool isTemplateParamDecl() {
+ return look() == 'T' &&
+ std::string_view("yptnk").find(look(1)) != std::string_view::npos;
+ }
+
+ /// Parse the <expression> production.
Node *parseExpr();
Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);
Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);
@@ -2536,6 +2781,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseFoldExpr();
Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
Node *parseSubobjectExpr();
+ Node *parseConstraintExpr();
+ Node *parseRequiresExpr();
/// Parse the <type> production.
Node *parseType();
@@ -2547,7 +2794,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseClassEnumType();
Node *parseQualifiedType();
- Node *parseEncoding();
+ Node *parseEncoding(bool ParseParams = true);
bool parseCallOffset();
Node *parseSpecialName();
@@ -2559,6 +2806,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Qualifiers CVQualifiers = QualNone;
FunctionRefQual ReferenceQualifier = FrefQualNone;
size_t ForwardTemplateRefsBegin;
+ bool HasExplicitObjectParameter = false;
NameState(AbstractManglingParser *Enclosing)
: ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
@@ -2574,7 +2822,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
return true;
ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
}
- ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
+ ForwardTemplateRefs.shrinkToSize(State.ForwardTemplateRefsBegin);
return false;
}
@@ -2638,8 +2886,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
std::string_view getSymbol() const {
std::string_view Res = Name;
if (Kind < Unnameable) {
- assert(starts_with(Res, "operator") &&
- "operator name does not start with 'operator'");
+ DEMANGLE_ASSERT(starts_with(Res, "operator"),
+ "operator name does not start with 'operator'");
Res.remove_prefix(sizeof("operator") - 1);
if (starts_with(Res, ' '))
Res.remove_prefix(1);
@@ -2663,7 +2911,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseDestructorName();
/// Top-level entry point into the parser.
- Node *parse();
+ Node *parse(bool ParseParams = true);
};
const char* parse_discriminator(const char* first, const char* last);
@@ -2727,6 +2975,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
return make<LocalName>(Encoding, StringLitName);
}
+ // The template parameters of the inner name are unrelated to those of the
+ // enclosing context.
+ SaveTemplateParams SaveTemplateParamsScope(this);
+
if (consumeIf('d')) {
parseNumber(true);
if (!consumeIf('_'))
@@ -2782,9 +3034,9 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
return Res;
}
-// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
+// <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]
// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
-// ::= [<module-name>] L? <source-name> [<abi-tags>]
+// ::= [<module-name>] F? L? <source-name> [<abi-tags>]
// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
// # structured binding declaration
// ::= [<module-name>] L? DC <source-name>+ E
@@ -2794,6 +3046,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
if (getDerived().parseModuleNameOpt(Module))
return nullptr;
+ bool IsMemberLikeFriend = Scope && consumeIf('F');
+
consumeIf('L');
Node *Result;
@@ -2824,7 +3078,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
Result = make<ModuleEntity>(Module, Result);
if (Result != nullptr)
Result = getDerived().parseAbiTags(Result);
- if (Result != nullptr && Scope != nullptr)
+ if (Result != nullptr && IsMemberLikeFriend)
+ Result = make<MemberLikeFriendName>(Scope, Result);
+ else if (Result != nullptr && Scope != nullptr)
Result = make<NestedName>(Scope, Result);
return Result;
@@ -2856,7 +3112,8 @@ bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
//
// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
//
-// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
+// <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]
+// <parameter type>+ # or "v" if the lambda has no parameters
template <typename Derived, typename Alloc>
Node *
AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
@@ -2877,10 +3134,10 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
ScopedTemplateParamList LambdaTemplateParams(this);
size_t ParamsBegin = Names.size();
- while (look() == 'T' &&
- std::string_view("yptn").find(look(1)) != std::string_view::npos) {
- Node *T = parseTemplateParamDecl();
- if (!T)
+ while (getDerived().isTemplateParamDecl()) {
+ Node *T =
+ getDerived().parseTemplateParamDecl(LambdaTemplateParams.params());
+ if (T == nullptr)
return nullptr;
Names.push_back(T);
}
@@ -2911,20 +3168,38 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
if (TempParams.empty())
TemplateParams.pop_back();
- if (!consumeIf("vE")) {
+ Node *Requires1 = nullptr;
+ if (consumeIf('Q')) {
+ Requires1 = getDerived().parseConstraintExpr();
+ if (Requires1 == nullptr)
+ return nullptr;
+ }
+
+ if (!consumeIf("v")) {
do {
Node *P = getDerived().parseType();
if (P == nullptr)
return nullptr;
Names.push_back(P);
- } while (!consumeIf('E'));
+ } while (look() != 'E' && look() != 'Q');
}
NodeArray Params = popTrailingNodeArray(ParamsBegin);
+ Node *Requires2 = nullptr;
+ if (consumeIf('Q')) {
+ Requires2 = getDerived().parseConstraintExpr();
+ if (Requires2 == nullptr)
+ return nullptr;
+ }
+
+ if (!consumeIf('E'))
+ return nullptr;
+
std::string_view Count = parseNumber();
if (!consumeIf('_'))
return nullptr;
- return make<ClosureTypeName>(TempParams, Params, Count);
+ return make<ClosureTypeName>(TempParams, Requires1, Params, Requires2,
+ Count);
}
if (consumeIf("Ub")) {
(void)parseNumber();
@@ -3190,15 +3465,25 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
if (!consumeIf('N'))
return nullptr;
- Qualifiers CVTmp = parseCVQualifiers();
- if (State) State->CVQualifiers = CVTmp;
+ // 'H' specifies that the encoding that follows
+ // has an explicit object parameter.
+ if (!consumeIf('H')) {
+ Qualifiers CVTmp = parseCVQualifiers();
+ if (State)
+ State->CVQualifiers = CVTmp;
- if (consumeIf('O')) {
- if (State) State->ReferenceQualifier = FrefQualRValue;
- } else if (consumeIf('R')) {
- if (State) State->ReferenceQualifier = FrefQualLValue;
- } else {
- if (State) State->ReferenceQualifier = FrefQualNone;
+ if (consumeIf('O')) {
+ if (State)
+ State->ReferenceQualifier = FrefQualRValue;
+ } else if (consumeIf('R')) {
+ if (State)
+ State->ReferenceQualifier = FrefQualLValue;
+ } else {
+ if (State)
+ State->ReferenceQualifier = FrefQualNone;
+ }
+ } else if (State) {
+ State->HasExplicitObjectParameter = true;
}
Node *SoFar = nullptr;
@@ -3446,7 +3731,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
}
}
- assert(SoFar != nullptr);
+ DEMANGLE_ASSERT(SoFar != nullptr, "");
Node *Base = getDerived().parseBaseUnresolvedName();
if (Base == nullptr)
@@ -3894,7 +4179,15 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
// Typically, <builtin-type>s are not considered substitution candidates,
// but the exception to that exception is vendor extended types (Itanium C++
// ABI 5.9.1).
- Result = make<NameType>(Res);
+ if (consumeIf('I')) {
+ Node *BaseType = parseType();
+ if (BaseType == nullptr)
+ return nullptr;
+ if (!consumeIf('E'))
+ return nullptr;
+ Result = make<TransformedType>(Res, BaseType);
+ } else
+ Result = make<NameType>(Res);
break;
}
case 'D':
@@ -3961,6 +4254,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
case 'c':
First += 2;
return make<NameType>("decltype(auto)");
+ // ::= Dk <type-constraint> # constrained auto
+ // ::= DK <type-constraint> # constrained decltype(auto)
+ case 'k':
+ case 'K': {
+ std::string_view Kind = look(1) == 'k' ? " auto" : " decltype(auto)";
+ First += 2;
+ Node *Constraint = getDerived().parseName();
+ if (!Constraint)
+ return nullptr;
+ return make<PostfixQualifiedType>(Constraint, Kind);
+ }
// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
case 'n':
First += 2;
@@ -4512,6 +4816,75 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
}
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {
+ // Within this expression, all enclosing template parameter lists are in
+ // scope.
+ ScopedOverride<bool> SaveInConstraintExpr(InConstraintExpr, true);
+ return getDerived().parseExpr();
+}
+
+template <typename Derived, typename Alloc>
+Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() {
+ NodeArray Params;
+ if (consumeIf("rQ")) {
+ // <expression> ::= rQ <bare-function-type> _ <requirement>+ E
+ size_t ParamsBegin = Names.size();
+ while (!consumeIf('_')) {
+ Node *Type = getDerived().parseType();
+ if (Type == nullptr)
+ return nullptr;
+ Names.push_back(Type);
+ }
+ Params = popTrailingNodeArray(ParamsBegin);
+ } else if (!consumeIf("rq")) {
+ // <expression> ::= rq <requirement>+ E
+ return nullptr;
+ }
+
+ size_t ReqsBegin = Names.size();
+ do {
+ Node *Constraint = nullptr;
+ if (consumeIf('X')) {
+ // <requirement> ::= X <expression> [N] [R <type-constraint>]
+ Node *Expr = getDerived().parseExpr();
+ if (Expr == nullptr)
+ return nullptr;
+ bool Noexcept = consumeIf('N');
+ Node *TypeReq = nullptr;
+ if (consumeIf('R')) {
+ TypeReq = getDerived().parseName();
+ if (TypeReq == nullptr)
+ return nullptr;
+ }
+ Constraint = make<ExprRequirement>(Expr, Noexcept, TypeReq);
+ } else if (consumeIf('T')) {
+ // <requirement> ::= T <type>
+ Node *Type = getDerived().parseType();
+ if (Type == nullptr)
+ return nullptr;
+ Constraint = make<TypeRequirement>(Type);
+ } else if (consumeIf('Q')) {
+ // <requirement> ::= Q <constraint-expression>
+ //
+ // FIXME: We use <expression> instead of <constraint-expression>. Either
+ // the requires expression is already inside a constraint expression, in
+ // which case it makes no difference, or we're in a requires-expression
+ // that might be partially-substituted, where the language behavior is
+ // not yet settled and clang mangles after substitution.
+ Node *NestedReq = getDerived().parseExpr();
+ if (NestedReq == nullptr)
+ return nullptr;
+ Constraint = make<NestedRequirement>(NestedReq);
+ }
+ if (Constraint == nullptr)
+ return nullptr;
+ Names.push_back(Constraint);
+ } while (!consumeIf('E'));
+
+ return make<RequiresExpr>(Params, popTrailingNodeArray(ReqsBegin));
+}
+
// <expression> ::= <unary operator-name> <expression>
// ::= <binary operator-name> <expression> <expression>
// ::= <ternary operator-name> <expression> <expression> <expression>
@@ -4748,6 +5121,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
return Ex;
return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
}
+ if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))
+ return parseRequiresExpr();
if (consumeIf("so"))
return parseSubobjectExpr();
if (consumeIf("sp")) {
@@ -5026,29 +5401,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
}
// <encoding> ::= <function name> <bare-function-type>
+// [`Q` <requires-clause expr>]
// ::= <data name>
// ::= <special-name>
template <typename Derived, typename Alloc>
-Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
+Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {
// The template parameters of an encoding are unrelated to those of the
// enclosing context.
- class SaveTemplateParams {
- AbstractManglingParser *Parser;
- decltype(TemplateParams) OldParams;
- decltype(OuterTemplateParams) OldOuterParams;
-
- public:
- SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
- OldParams = std::move(Parser->TemplateParams);
- OldOuterParams = std::move(Parser->OuterTemplateParams);
- Parser->TemplateParams.clear();
- Parser->OuterTemplateParams.clear();
- }
- ~SaveTemplateParams() {
- Parser->TemplateParams = std::move(OldParams);
- Parser->OuterTemplateParams = std::move(OldOuterParams);
- }
- } SaveTemplateParams(this);
+ SaveTemplateParams SaveTemplateParamsScope(this);
if (look() == 'G' || look() == 'T')
return getDerived().parseSpecialName();
@@ -5071,6 +5431,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
if (IsEndOfEncoding())
return Name;
+ // ParseParams may be false at the top level only, when called from parse().
+ // For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
+ // false when demangling 3fooILZ3BarEET_f but is always true when demangling
+ // 3Bar.
+ if (!ParseParams) {
+ while (consume())
+ ;
+ return Name;
+ }
+
Node *Attrs = nullptr;
if (consumeIf("Ua9enable_ifI")) {
size_t BeforeArgs = Names.size();
@@ -5092,22 +5462,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
return nullptr;
}
- if (consumeIf('v'))
- return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
- Attrs, NameInfo.CVQualifiers,
- NameInfo.ReferenceQualifier);
+ NodeArray Params;
+ if (!consumeIf('v')) {
+ size_t ParamsBegin = Names.size();
+ do {
+ Node *Ty = getDerived().parseType();
+ if (Ty == nullptr)
+ return nullptr;
- size_t ParamsBegin = Names.size();
- do {
- Node *Ty = getDerived().parseType();
- if (Ty == nullptr)
+ const bool IsFirstParam = ParamsBegin == Names.size();
+ if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
+ Ty = make<ExplicitObjectParameter>(Ty);
+
+ if (Ty == nullptr)
+ return nullptr;
+
+ Names.push_back(Ty);
+ } while (!IsEndOfEncoding() && look() != 'Q');
+ Params = popTrailingNodeArray(ParamsBegin);
+ }
+
+ Node *Requires = nullptr;
+ if (consumeIf('Q')) {
+ Requires = getDerived().parseConstraintExpr();
+ if (!Requires)
return nullptr;
- Names.push_back(Ty);
- } while (!IsEndOfEncoding());
+ }
- return make<FunctionEncoding>(ReturnType, Name,
- popTrailingNodeArray(ParamsBegin),
- Attrs, NameInfo.CVQualifiers,
+ return make<FunctionEncoding>(ReturnType, Name, Params, Attrs, Requires,
+ NameInfo.CVQualifiers,
NameInfo.ReferenceQualifier);
}
@@ -5134,7 +5517,8 @@ template <>
struct FloatData<long double>
{
#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
- defined(__wasm__) || defined(__riscv) || defined(__loongarch__)
+ defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
+ defined(__ve__)
static const size_t mangled_size = 32;
#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
static const size_t mangled_size = 16;
@@ -5268,6 +5652,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
// ::= TL <level-1> _ <parameter-2 non-negative number> _
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
+ const char *Begin = First;
if (!consumeIf('T'))
return nullptr;
@@ -5289,6 +5674,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
return nullptr;
}
+ // We don't track enclosing template parameter levels well enough to reliably
+ // substitute them all within a <constraint-expression>, so print the
+ // parameter numbering instead for now.
+ // TODO: Track all enclosing template parameters and substitute them here.
+ if (InConstraintExpr) {
+ return make<NameType>(std::string_view(Begin, First - 1 - Begin));
+ }
+
// If we're in a context where this <template-param> refers to a
// <template-arg> further ahead in the mangled name (currently just conversion
// operator types), then we should only look it up in the right context.
@@ -5297,7 +5690,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
Node *ForwardRef = make<ForwardTemplateReference>(Index);
if (!ForwardRef)
return nullptr;
- assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
+ DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference,
+ "");
ForwardTemplateRefs.push_back(
static_cast<ForwardTemplateReference *>(ForwardRef));
return ForwardRef;
@@ -5326,11 +5720,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
// ::= Tt <template-param-decl>* E # template parameter
// ::= Tp <template-param-decl> # parameter pack
template <typename Derived, typename Alloc>
-Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
+Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(
+ TemplateParamList *Params) {
auto InventTemplateParamName = [&](TemplateParamKind Kind) {
unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
Node *N = make<SyntheticTemplateParamName>(Kind, Index);
- if (N) TemplateParams.back()->push_back(N);
+ if (N && Params)
+ Params->push_back(N);
return N;
};
@@ -5341,6 +5737,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
return make<TypeTemplateParamDecl>(Name);
}
+ if (consumeIf("Tk")) {
+ Node *Constraint = getDerived().parseName();
+ if (!Constraint)
+ return nullptr;
+ Node *Name = InventTemplateParamName(TemplateParamKind::Type);
+ if (!Name)
+ return nullptr;
+ return make<ConstrainedTypeTemplateParamDecl>(Constraint, Name);
+ }
+
if (consumeIf("Tn")) {
Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
if (!Name)
@@ -5357,18 +5763,25 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
return nullptr;
size_t ParamsBegin = Names.size();
ScopedTemplateParamList TemplateTemplateParamParams(this);
- while (!consumeIf("E")) {
- Node *P = parseTemplateParamDecl();
+ Node *Requires = nullptr;
+ while (!consumeIf('E')) {
+ Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params());
if (!P)
return nullptr;
Names.push_back(P);
+ if (consumeIf('Q')) {
+ Requires = getDerived().parseConstraintExpr();
+ if (Requires == nullptr || !consumeIf('E'))
+ return nullptr;
+ break;
+ }
}
- NodeArray Params = popTrailingNodeArray(ParamsBegin);
- return make<TemplateTemplateParamDecl>(Name, Params);
+ NodeArray InnerParams = popTrailingNodeArray(ParamsBegin);
+ return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);
}
if (consumeIf("Tp")) {
- Node *P = parseTemplateParamDecl();
+ Node *P = parseTemplateParamDecl(Params);
if (!P)
return nullptr;
return make<TemplateParamPackDecl>(P);
@@ -5382,6 +5795,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
// ::= <expr-primary> # simple expressions
// ::= J <template-arg>* E # argument pack
// ::= LZ <encoding> E # extension
+// ::= <template-param-decl> <template-arg>
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
switch (look()) {
@@ -5416,6 +5830,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
// ::= <expr-primary> # simple expressions
return getDerived().parseExprPrimary();
}
+ case 'T': {
+ // Either <template-param> or a <template-param-decl> <template-arg>.
+ if (!getDerived().isTemplateParamDecl())
+ return getDerived().parseType();
+ Node *Param = getDerived().parseTemplateParamDecl(nullptr);
+ if (!Param)
+ return nullptr;
+ Node *Arg = getDerived().parseTemplateArg();
+ if (!Arg)
+ return nullptr;
+ return make<TemplateParamQualifiedArg>(Param, Arg);
+ }
default:
return getDerived().parseType();
}
@@ -5438,30 +5864,39 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
}
size_t ArgsBegin = Names.size();
+ Node *Requires = nullptr;
while (!consumeIf('E')) {
if (TagTemplates) {
- auto OldParams = std::move(TemplateParams);
Node *Arg = getDerived().parseTemplateArg();
- TemplateParams = std::move(OldParams);
if (Arg == nullptr)
return nullptr;
Names.push_back(Arg);
Node *TableEntry = Arg;
+ if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {
+ TableEntry =
+ static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();
+ }
if (Arg->getKind() == Node::KTemplateArgumentPack) {
TableEntry = make<ParameterPack>(
static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
if (!TableEntry)
return nullptr;
}
- TemplateParams.back()->push_back(TableEntry);
+ OuterTemplateParams.push_back(TableEntry);
} else {
Node *Arg = getDerived().parseTemplateArg();
if (Arg == nullptr)
return nullptr;
Names.push_back(Arg);
}
+ if (consumeIf('Q')) {
+ Requires = getDerived().parseConstraintExpr();
+ if (!Requires || !consumeIf('E'))
+ return nullptr;
+ break;
+ }
}
- return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
+ return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin), Requires);
}
// <mangled-name> ::= _Z <encoding>
@@ -5470,9 +5905,9 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
template <typename Derived, typename Alloc>
-Node *AbstractManglingParser<Derived, Alloc>::parse() {
+Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
if (consumeIf("_Z") || consumeIf("__Z")) {
- Node *Encoding = getDerived().parseEncoding();
+ Node *Encoding = getDerived().parseEncoding(ParseParams);
if (Encoding == nullptr)
return nullptr;
if (look() == '.') {
@@ -5486,7 +5921,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {
}
if (consumeIf("___Z") || consumeIf("____Z")) {
- Node *Encoding = getDerived().parseEncoding();
+ Node *Encoding = getDerived().parseEncoding(ParseParams);
if (Encoding == nullptr || !consumeIf("_block_invoke"))
return nullptr;
bool RequireNumber = consumeIf('_');
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumNodes.def b/contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumNodes.def
index f615cb9fad..18f5d52b47 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumNodes.def
+++ b/contrib/libs/cxxsupp/libcxxabi/src/demangle/ItaniumNodes.def
@@ -19,6 +19,7 @@ NODE(QualType)
NODE(ConversionOperatorType)
NODE(PostfixQualifiedType)
NODE(ElaboratedTypeSpefType)
+NODE(TransformedType)
NODE(NameType)
NODE(AbiTagAttr)
NODE(EnableIfAttr)
@@ -36,6 +37,7 @@ NODE(SpecialName)
NODE(CtorVtableSpecialName)
NODE(QualifiedName)
NODE(NestedName)
+NODE(MemberLikeFriendName)
NODE(LocalName)
NODE(ModuleName)
NODE(ModuleEntity)
@@ -44,7 +46,9 @@ NODE(PixelVectorType)
NODE(BinaryFPType)
NODE(BitIntType)
NODE(SyntheticTemplateParamName)
+NODE(TemplateParamQualifiedArg)
NODE(TypeTemplateParamDecl)
+NODE(ConstrainedTypeTemplateParamDecl)
NODE(NonTypeTemplateParamDecl)
NODE(TemplateTemplateParamDecl)
NODE(TemplateParamPackDecl)
@@ -91,5 +95,10 @@ NODE(DoubleLiteral)
NODE(LongDoubleLiteral)
NODE(BracedExpr)
NODE(BracedRangeExpr)
+NODE(RequiresExpr)
+NODE(ExprRequirement)
+NODE(TypeRequirement)
+NODE(NestedRequirement)
+NODE(ExplicitObjectParameter)
#undef NODE
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/demangle/README.txt b/contrib/libs/cxxsupp/libcxxabi/src/demangle/README.txt
index 76470f61f9..d38f6abbb0 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/demangle/README.txt
+++ b/contrib/libs/cxxsupp/libcxxabi/src/demangle/README.txt
@@ -34,7 +34,7 @@ differences, we want to keep the "core" generic demangling library
identical between both copies to simplify development and testing.
If you're working on the generic library, then do the work first in
-libcxxabi, then run the cp-to-llvm.sh script in src/demangle. This
+libcxxabi, then run libcxxabi/src/demangle/cp-to-llvm.sh. This
script takes as an optional argument the path to llvm, and copies the
changes you made to libcxxabi over. Note that this script just
blindly overwrites all changes to the generic library in llvm, so be
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/demangle/Utility.h b/contrib/libs/cxxsupp/libcxxabi/src/demangle/Utility.h
index 8370633ace..f1fad35d60 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/demangle/Utility.h
+++ b/contrib/libs/cxxsupp/libcxxabi/src/demangle/Utility.h
@@ -19,11 +19,9 @@
#include "DemangleConfig.h"
#include <array>
-#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <cstring>
-#include <exception>
#include <limits>
#include <string_view>
@@ -49,7 +47,7 @@ class OutputBuffer {
BufferCapacity = Need;
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
if (Buffer == nullptr)
- std::terminate();
+ std::abort();
}
}
@@ -160,7 +158,7 @@ public:
}
void insert(size_t Pos, const char *S, size_t N) {
- assert(Pos <= CurrentPosition);
+ DEMANGLE_ASSERT(Pos <= CurrentPosition, "");
if (N == 0)
return;
grow(N);
@@ -173,7 +171,7 @@ public:
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
char back() const {
- assert(CurrentPosition);
+ DEMANGLE_ASSERT(CurrentPosition, "");
return Buffer[CurrentPosition - 1];
}
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/fallback_malloc.cpp b/contrib/libs/cxxsupp/libcxxabi/src/fallback_malloc.cpp
index 11e79740ff..76bd2e9bcd 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/fallback_malloc.cpp
+++ b/contrib/libs/cxxsupp/libcxxabi/src/fallback_malloc.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "fallback_malloc.h"
+#include "abort_message.h"
#include <__thread/support.h>
#ifndef _LIBCXXABI_HAS_NO_THREADS
@@ -16,7 +17,7 @@
#endif
#include <__memory/aligned_alloc.h>
-#include <assert.h>
+#include <__assert>
#include <stdlib.h> // for malloc, calloc, free
#include <string.h> // for memset
@@ -142,7 +143,7 @@ void* fallback_malloc(size_t len) {
// Check the invariant that all heap_nodes pointers 'p' are aligned
// so that 'p + 1' has an alignment of at least RequiredAlignment
- assert(reinterpret_cast<size_t>(p + 1) % RequiredAlignment == 0);
+ _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(p + 1) % RequiredAlignment == 0, "");
// Calculate the number of extra padding elements needed in order
// to split 'p' and create a properly aligned heap_node from the tail
@@ -163,7 +164,7 @@ void* fallback_malloc(size_t len) {
q->next_node = 0;
q->len = static_cast<heap_size>(aligned_nelems);
void* ptr = q + 1;
- assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);
+ _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0, "");
return ptr;
}
@@ -176,7 +177,7 @@ void* fallback_malloc(size_t len) {
prev->next_node = p->next_node;
p->next_node = 0;
void* ptr = p + 1;
- assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);
+ _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0, "");
return ptr;
}
}
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp b/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp
index 85232a494a..88fa7b5d65 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp
+++ b/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.cpp
@@ -42,6 +42,7 @@
// is_equal() with use_strcmp=false so the string names are not compared.
#include <cstdint>
+#include <cassert>
#include <string.h>
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
@@ -75,6 +76,242 @@ static inline ptrdiff_t update_offset_to_base(const char* vtable,
namespace __cxxabiv1
{
+namespace {
+
+struct derived_object_info {
+ const void* dynamic_ptr;
+ const __class_type_info* dynamic_type;
+ std::ptrdiff_t offset_to_derived;
+};
+
+/// A helper function that gets (dynamic_ptr, dynamic_type, offset_to_derived) from static_ptr.
+void dyn_cast_get_derived_info(derived_object_info* info, const void* static_ptr)
+{
+#if __has_feature(cxx_abi_relative_vtable)
+ // The vtable address will point to the first virtual function, which is 8
+ // bytes after the start of the vtable (4 for the offset from top + 4 for
+ // the typeinfo component).
+ const int32_t* vtable =
+ *reinterpret_cast<const int32_t* const*>(static_ptr);
+ info->offset_to_derived = static_cast<std::ptrdiff_t>(vtable[-2]);
+ info->dynamic_ptr = static_cast<const char*>(static_ptr) + info->offset_to_derived;
+
+ // The typeinfo component is now a relative offset to a proxy.
+ int32_t offset_to_ti_proxy = vtable[-1];
+ const uint8_t* ptr_to_ti_proxy =
+ reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
+ info->dynamic_type = *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
+#else
+ void **vtable = *static_cast<void ** const *>(static_ptr);
+ info->offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
+ info->dynamic_ptr = static_cast<const char*>(static_ptr) + info->offset_to_derived;
+ info->dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
+#endif
+}
+
+/// A helper function for __dynamic_cast that casts a base sub-object pointer
+/// to the object's dynamic type.
+///
+/// This function returns the casting result directly. No further processing
+/// required.
+///
+/// Specifically, this function can only be called if the following pre-
+/// condition holds:
+/// * The dynamic type of the object pointed to by `static_ptr` is exactly
+/// the same as `dst_type`.
+const void* dyn_cast_to_derived(const void* static_ptr,
+ const void* dynamic_ptr,
+ const __class_type_info* static_type,
+ const __class_type_info* dst_type,
+ std::ptrdiff_t offset_to_derived,
+ std::ptrdiff_t src2dst_offset)
+{
+ // We're downcasting from src_type to the complete object's dynamic type.
+ // This is a really hot path that can be further optimized with the
+ // `src2dst_offset` hint.
+ // In such a case, dynamic_ptr already gives the casting result if the
+ // casting ever succeeds. All we have to do now is to check static_ptr
+ // points to a public base sub-object of dynamic_ptr.
+
+ if (src2dst_offset >= 0)
+ {
+ // The static type is a unique public non-virtual base type of
+ // dst_type at offset `src2dst_offset` from the origin of dst.
+ // Note that there might be other non-public static_type bases. The
+ // hint only guarantees that the public base is non-virtual and
+ // unique. So we have to check whether static_ptr points to that
+ // unique public base sub-object.
+ if (offset_to_derived != -src2dst_offset)
+ return nullptr;
+ return dynamic_ptr;
+ }
+
+ if (src2dst_offset == -2)
+ {
+ // static_type is not a public base of dst_type.
+ return nullptr;
+ }
+
+ // If src2dst_offset == -3, then:
+ // src_type is a multiple public base type but never a virtual
+ // base type. We can't conclude that static_ptr points to those
+ // public base sub-objects because there might be other non-
+ // public static_type bases. The search is inevitable.
+
+ // Fallback to the slow path to check that static_type is a public
+ // base type of dynamic_type.
+ // Using giant short cut. Add that information to info.
+ __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, // number_of_dst_type
+ false, false, false, true, nullptr};
+ // Do the search
+ dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ // The following if should always be false because we should
+ // definitely find (static_ptr, static_type), either on a public
+ // or private path
+ if (info.path_dst_ptr_to_static_ptr == unknown)
+ {
+ // We get here only if there is some kind of visibility problem
+ // in client code.
+ static_assert(std::atomic<size_t>::is_always_lock_free, "");
+ static std::atomic<size_t> error_count(0);
+ size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
+ if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
+ syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
+ "should have public visibility. At least one of them is hidden. %s"
+ ", %s.\n", static_type->name(), dst_type->name());
+ // Redo the search comparing type_info's using strcmp
+ info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, false, false, false, true, nullptr};
+ info.number_of_dst_type = 1;
+ dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
+ }
+#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ // Query the search.
+ if (info.path_dst_ptr_to_static_ptr != public_path)
+ return nullptr;
+
+ return dynamic_ptr;
+}
+
+/// A helper function for __dynamic_cast that tries to perform a downcast
+/// before giving up and falling back to the slow path.
+const void* dyn_cast_try_downcast(const void* static_ptr,
+ const void* dynamic_ptr,
+ const __class_type_info* dst_type,
+ const __class_type_info* dynamic_type,
+ std::ptrdiff_t src2dst_offset)
+{
+ if (src2dst_offset < 0)
+ {
+ // We can only optimize the case if the static type is a unique public
+ // base of dst_type. Give up.
+ return nullptr;
+ }
+
+ // Pretend there is a dst_type object that leads to static_ptr. Later we
+ // will check whether this imagined dst_type object exists. If it exists
+ // then it will be the casting result.
+ const void* dst_ptr_to_static = reinterpret_cast<const char*>(static_ptr) - src2dst_offset;
+
+ if (reinterpret_cast<std::intptr_t>(dst_ptr_to_static) < reinterpret_cast<std::intptr_t>(dynamic_ptr))
+ {
+ // The imagined dst_type object does not exist. Bail-out quickly.
+ return nullptr;
+ }
+
+ // Try to search a path from dynamic_type to dst_type.
+ __dynamic_cast_info dynamic_to_dst_info = {dynamic_type,
+ dst_ptr_to_static,
+ dst_type,
+ src2dst_offset,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1, // number_of_dst_type
+ false,
+ false,
+ false,
+ true,
+ nullptr};
+ dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
+ if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
+ // We have found at least one path from dynamic_ptr to dst_ptr. The
+ // downcast can succeed.
+ return dst_ptr_to_static;
+ }
+
+ return nullptr;
+}
+
+const void* dyn_cast_slow(const void* static_ptr,
+ const void* dynamic_ptr,
+ const __class_type_info* static_type,
+ const __class_type_info* dst_type,
+ const __class_type_info* dynamic_type,
+ std::ptrdiff_t src2dst_offset)
+{
+ // Not using giant short cut. Do the search
+
+ // Initialize info struct for this search.
+ __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, false, false, false, true, nullptr};
+
+ dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
+#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ // The following if should always be false because we should
+ // definitely find (static_ptr, static_type), either on a public
+ // or private path
+ if (info.path_dst_ptr_to_static_ptr == unknown &&
+ info.path_dynamic_ptr_to_static_ptr == unknown)
+ {
+ static_assert(std::atomic<size_t>::is_always_lock_free, "");
+ static std::atomic<size_t> error_count(0);
+ size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
+ if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
+ syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
+ "has hidden visibility or is defined in more than one translation "
+ "unit. They should all have public visibility. "
+ "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
+ dst_type->name());
+ // Redo the search comparing type_info's using strcmp
+ info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, false, false, false, true, nullptr};
+ dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
+ }
+#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
+ // Query the search.
+ switch (info.number_to_static_ptr)
+ {
+ case 0:
+ if (info.number_to_dst_ptr == 1 &&
+ info.path_dynamic_ptr_to_static_ptr == public_path &&
+ info.path_dynamic_ptr_to_dst_ptr == public_path)
+ return info.dst_ptr_not_leading_to_static_ptr;
+ break;
+ case 1:
+ if (info.path_dst_ptr_to_static_ptr == public_path ||
+ (
+ info.number_to_dst_ptr == 0 &&
+ info.path_dynamic_ptr_to_static_ptr == public_path &&
+ info.path_dynamic_ptr_to_dst_ptr == public_path
+ )
+ )
+ return info.dst_ptr_leading_to_static_ptr;
+ break;
+ }
+
+ return nullptr;
+}
+
+} // namespace
+
// __shim_type_info
__shim_type_info::~__shim_type_info()
@@ -233,7 +470,8 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type,
if (thrown_class_type == 0)
return false;
// bullet 2
- __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
+ assert(adjustedPtr && "catching a class without an object?");
+ __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true, nullptr};
info.number_of_dst_type = 1;
thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
if (info.path_dst_ptr_to_static_ptr == public_path)
@@ -248,32 +486,46 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type,
#pragma clang diagnostic pop
#endif
+// When we have an object to inspect - we just pass the pointer to the sub-
+// object that matched the static_type we just checked. If that is different
+// from any previously recorded pointer to that object type, then we have
+// an ambiguous case.
+
+// When we have no object to inspect, we need to account for virtual bases
+// explicitly.
+// info->vbase_cookie is a pointer to the name of the innermost virtual base
+// type, or nullptr if there is no virtual base on the path so far.
+// adjustedPtr points to the subobject we just found.
+// If vbase_cookie != any previously recorded (including the case of nullptr
+// representing an already-found static sub-object) then we have an ambiguous
+// case. Assuming that the vbase_cookie values agree; if then we have a
+// different offset (adjustedPtr) from any previously recorded, this indicates
+// an ambiguous case within the virtual base.
+
void
__class_type_info::process_found_base_class(__dynamic_cast_info* info,
void* adjustedPtr,
int path_below) const
{
- if (info->dst_ptr_leading_to_static_ptr == 0)
- {
- // First time here
- info->dst_ptr_leading_to_static_ptr = adjustedPtr;
- info->path_dst_ptr_to_static_ptr = path_below;
- info->number_to_static_ptr = 1;
- }
- else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
- {
- // We've been here before. Update path to "most public"
- if (info->path_dst_ptr_to_static_ptr == not_public_path)
- info->path_dst_ptr_to_static_ptr = path_below;
- }
- else
- {
- // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
- // to a static_type
- info->number_to_static_ptr += 1;
- info->path_dst_ptr_to_static_ptr = not_public_path;
- info->search_done = true;
- }
+ if (info->number_to_static_ptr == 0) {
+ // First time we found this base
+ info->dst_ptr_leading_to_static_ptr = adjustedPtr;
+ info->path_dst_ptr_to_static_ptr = path_below;
+ // stash the virtual base cookie.
+ info->dst_ptr_not_leading_to_static_ptr = info->vbase_cookie;
+ info->number_to_static_ptr = 1;
+ } else if (info->dst_ptr_not_leading_to_static_ptr == info->vbase_cookie &&
+ info->dst_ptr_leading_to_static_ptr == adjustedPtr) {
+ // We've been here before. Update path to "most public"
+ if (info->path_dst_ptr_to_static_ptr == not_public_path)
+ info->path_dst_ptr_to_static_ptr = path_below;
+ } else {
+ // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
+ // to a static_type.
+ info->number_to_static_ptr += 1;
+ info->path_dst_ptr_to_static_ptr = not_public_path;
+ info->search_done = true;
+ }
}
void
@@ -301,16 +553,30 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
void* adjustedPtr,
int path_below) const
{
- ptrdiff_t offset_to_base = 0;
- if (adjustedPtr != nullptr)
- {
- offset_to_base = __offset_flags >> __offset_shift;
- if (__offset_flags & __virtual_mask)
- {
- const char* vtable = *static_cast<const char*const*>(adjustedPtr);
- offset_to_base = update_offset_to_base(vtable, offset_to_base);
- }
+ bool is_virtual = __offset_flags & __virtual_mask;
+ ptrdiff_t offset_to_base = 0;
+ if (info->have_object) {
+ /* We have an object to inspect, we can look through its vtables to
+ find the layout. */
+ offset_to_base = __offset_flags >> __offset_shift;
+ if (is_virtual) {
+ const char* vtable = *static_cast<const char* const*>(adjustedPtr);
+ offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
+ } else if (!is_virtual) {
+ /* We have no object; however, for non-virtual bases, (since we do not
+ need to inspect any content) we can pretend to have an object based
+ at '0'. */
+ offset_to_base = __offset_flags >> __offset_shift;
+ } else {
+ /* No object to inspect, and the next base is virtual.
+ We cannot indirect through the vtable to find the actual object offset.
+ So, update vbase_cookie to the new innermost virtual base using the
+ pointer to the typeinfo name as a key. */
+ info->vbase_cookie = static_cast<const void*>(__base_type->name());
+ // .. and reset the pointer.
+ adjustedPtr = nullptr;
+ }
__base_type->has_unambiguous_public_base(
info,
static_cast<char*>(adjustedPtr) + offset_to_base,
@@ -431,14 +697,22 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type,
dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
if (thrown_class_type == 0)
return false;
- __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
+ bool have_object = adjustedPtr != nullptr;
+ __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ have_object, nullptr};
info.number_of_dst_type = 1;
thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
if (info.path_dst_ptr_to_static_ptr == public_path)
{
- if (adjustedPtr != NULL)
- adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
- return true;
+ // In the case of a thrown null pointer, we have no object but we might
+ // well have computed the offset to where a public sub-object would be.
+ // However, we do not want to return that offset to the user; we still
+ // want them to catch a null ptr.
+ if (have_object)
+ adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
+ else
+ adjustedPtr = nullptr;
+ return true;
}
return false;
}
@@ -623,174 +897,46 @@ extern "C" _LIBCXXABI_FUNC_VIS void *
__dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
const __class_type_info *dst_type,
std::ptrdiff_t src2dst_offset) {
- // Possible future optimization: Take advantage of src2dst_offset
-
// Get (dynamic_ptr, dynamic_type) from static_ptr
-#if __has_feature(cxx_abi_relative_vtable)
- // The vtable address will point to the first virtual function, which is 8
- // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component).
- const int32_t* vtable =
- *reinterpret_cast<const int32_t* const*>(static_ptr);
- int32_t offset_to_derived = vtable[-2];
- const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
-
- // The typeinfo component is now a relative offset to a proxy.
- int32_t offset_to_ti_proxy = vtable[-1];
- const uint8_t* ptr_to_ti_proxy =
- reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
- const __class_type_info* dynamic_type =
- *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
-#else
- void **vtable = *static_cast<void ** const *>(static_ptr);
- ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
- const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
- const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
-#endif
+ derived_object_info derived_info;
+ dyn_cast_get_derived_info(&derived_info, static_ptr);
// Initialize answer to nullptr. This will be changed from the search
// results if a non-null answer is found. Regardless, this is what will
// be returned.
const void* dst_ptr = 0;
- // Initialize info struct for this search.
- __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
// Find out if we can use a giant short cut in the search
- if (is_equal(dynamic_type, dst_type, false))
+ if (is_equal(derived_info.dynamic_type, dst_type, false))
{
- // We're downcasting from src_type to the complete object's dynamic
- // type. This is a really hot path that can be further optimized
- // with the `src2dst_offset` hint.
- // In such a case, dynamic_ptr already gives the casting result if the
- // casting ever succeeds. All we have to do now is to check
- // static_ptr points to a public base sub-object of dynamic_ptr.
-
- if (src2dst_offset >= 0)
- {
- // The static type is a unique public non-virtual base type of
- // dst_type at offset `src2dst_offset` from the origin of dst.
- // Note that there might be other non-public static_type bases. The
- // hint only guarantees that the public base is non-virtual and
- // unique. So we have to check whether static_ptr points to that
- // unique public base sub-object.
- if (offset_to_derived == -src2dst_offset)
- dst_ptr = dynamic_ptr;
- }
- else if (src2dst_offset == -2)
- {
- // static_type is not a public base of dst_type.
- dst_ptr = nullptr;
- }
- else
- {
- // If src2dst_offset == -3, then:
- // src_type is a multiple public base type but never a virtual
- // base type. We can't conclude that static_ptr points to those
- // public base sub-objects because there might be other non-
- // public static_type bases. The search is inevitable.
-
- // Fallback to the slow path to check that static_type is a public
- // base type of dynamic_type.
- // Using giant short cut. Add that information to info.
- info.number_of_dst_type = 1;
- // Do the search
- dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
-#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
- // The following if should always be false because we should
- // definitely find (static_ptr, static_type), either on a public
- // or private path
- if (info.path_dst_ptr_to_static_ptr == unknown)
- {
- // We get here only if there is some kind of visibility problem
- // in client code.
- static_assert(std::atomic<size_t>::is_always_lock_free, "");
- static std::atomic<size_t> error_count(0);
- size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
- if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
- syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
- "should have public visibility. At least one of them is hidden. %s"
- ", %s.\n", static_type->name(), dynamic_type->name());
- // Redo the search comparing type_info's using strcmp
- info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
- info.number_of_dst_type = 1;
- dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
- }
-#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
- // Query the search.
- if (info.path_dst_ptr_to_static_ptr == public_path)
- dst_ptr = dynamic_ptr;
- }
+ dst_ptr = dyn_cast_to_derived(static_ptr,
+ derived_info.dynamic_ptr,
+ static_type,
+ dst_type,
+ derived_info.offset_to_derived,
+ src2dst_offset);
}
else
{
- if (src2dst_offset >= 0)
- {
- // Optimize toward downcasting: dst_type has one unique public
- // static_type bases. Let's first try to do a downcast before
- // falling back to the slow path. The downcast succeeds if there
- // is at least one path regardless of visibility from
- // dynamic_type to dst_type.
- const void* dst_ptr_to_static = reinterpret_cast<const char*>(static_ptr) - src2dst_offset;
- if (reinterpret_cast<std::intptr_t>(dst_ptr_to_static) >= reinterpret_cast<std::intptr_t>(dynamic_ptr))
- {
- // Try to search a path from dynamic_type to dst_type.
- __dynamic_cast_info dynamic_to_dst_info = {dynamic_type, dst_ptr_to_static, dst_type, src2dst_offset};
- dynamic_to_dst_info.number_of_dst_type = 1;
- dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
- if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
- // We have found at least one path from dynamic_ptr to
- // dst_ptr. The downcast can succeed.
- dst_ptr = dst_ptr_to_static;
- }
- }
- }
+ // Optimize toward downcasting: let's first try to do a downcast before
+ // falling back to the slow path.
+ dst_ptr = dyn_cast_try_downcast(static_ptr,
+ derived_info.dynamic_ptr,
+ dst_type,
+ derived_info.dynamic_type,
+ src2dst_offset);
if (!dst_ptr)
{
- // Not using giant short cut. Do the search
- dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
-#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
- // The following if should always be false because we should
- // definitely find (static_ptr, static_type), either on a public
- // or private path
- if (info.path_dst_ptr_to_static_ptr == unknown &&
- info.path_dynamic_ptr_to_static_ptr == unknown)
- {
- static_assert(std::atomic<size_t>::is_always_lock_free, "");
- static std::atomic<size_t> error_count(0);
- size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
- if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
- syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
- "has hidden visibility or is defined in more than one translation "
- "unit. They should all have public visibility. "
- "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
- dst_type->name());
- // Redo the search comparing type_info's using strcmp
- info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
- dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
- }
-#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
- // Query the search.
- switch (info.number_to_static_ptr)
- {
- case 0:
- if (info.number_to_dst_ptr == 1 &&
- info.path_dynamic_ptr_to_static_ptr == public_path &&
- info.path_dynamic_ptr_to_dst_ptr == public_path)
- dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
- break;
- case 1:
- if (info.path_dst_ptr_to_static_ptr == public_path ||
- (
- info.number_to_dst_ptr == 0 &&
- info.path_dynamic_ptr_to_static_ptr == public_path &&
- info.path_dynamic_ptr_to_dst_ptr == public_path
- )
- )
- dst_ptr = info.dst_ptr_leading_to_static_ptr;
- break;
- }
+ dst_ptr = dyn_cast_slow(static_ptr,
+ derived_info.dynamic_ptr,
+ static_type,
+ dst_type,
+ derived_info.dynamic_type,
+ src2dst_offset);
}
}
+
return const_cast<void*>(dst_ptr);
}
@@ -1075,7 +1221,7 @@ __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
if (info->search_done)
break;
// If we just found a dst_type with a public path to (static_ptr, static_type),
- // then the only reason to continue the search is to make sure sure
+ // then the only reason to continue the search is to make sure
// no other dst_type points to (static_ptr, static_type).
// If !diamond, then we don't need to search here.
// if we just found a dst_type with a private path to (static_ptr, static_type),
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.h b/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.h
index 622e09cc24..328a02edef 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.h
+++ b/contrib/libs/cxxsupp/libcxxabi/src/private_typeinfo.h
@@ -110,6 +110,13 @@ struct _LIBCXXABI_HIDDEN __dynamic_cast_info
bool found_any_static_type;
// Set whenever a search can be stopped
bool search_done;
+
+ // Data that modifies the search mechanism.
+
+ // There is no object (seen when we throw a null pointer to object).
+ bool have_object;
+ // Virtual base
+ const void* vbase_cookie;
};
// Has no base class
diff --git a/contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp b/contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp
index 25cfb2b824..b802559d47 100644
--- a/contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp
+++ b/contrib/libs/cxxsupp/libcxxabi/src/stdlib_new_delete.cpp
@@ -7,7 +7,10 @@
//===----------------------------------------------------------------------===//
#include "__cxxabi_config.h"
+#include "abort_message.h"
+#include "include/overridable_function.h" // from libc++
#include <__memory/aligned_alloc.h>
+#include <cstddef>
#include <cstdlib>
#include <new>
@@ -25,249 +28,216 @@
# error libc++ and libc++abi seem to disagree on whether exceptions are enabled
#endif
-// ------------------ BEGIN COPY ------------------
-// Implement all new and delete operators as weak definitions
-// in this shared library, so that they can be overridden by programs
-// that define non-weak copies of the functions.
-
-_LIBCPP_WEAK
-void *
-operator new(std::size_t size) _THROW_BAD_ALLOC
-{
- if (size == 0)
- size = 1;
- void* p;
- while ((p = std::malloc(size)) == nullptr)
- {
- // If malloc fails and there is a new_handler,
- // call it to try free up memory.
- std::new_handler nh = std::get_new_handler();
- if (nh)
- nh();
- else
+inline void __throw_bad_alloc_shim() {
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- throw std::bad_alloc();
-#ifdef __EMSCRIPTEN__
- // Abort here so that when exceptions are disabled, we do not just
- // return 0 when malloc returns 0.
- // We could also do this with set_new_handler, but that adds a
- // global constructor and a table entry, overhead that we can avoid
- // by doing it this way.
- abort();
+ throw std::bad_alloc();
#else
- break;
-#endif
+ abort_message("bad_alloc was thrown in -fno-exceptions mode");
#endif
- }
- return p;
-}
-
-_LIBCPP_WEAK
-void*
-operator new(size_t size, const std::nothrow_t&) noexcept
-{
- void* p = nullptr;
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- try
- {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- p = ::operator new(size);
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- }
- catch (...)
- {
- }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- return p;
-}
-
-_LIBCPP_WEAK
-void*
-operator new[](size_t size) _THROW_BAD_ALLOC
-{
- return ::operator new(size);
-}
-
-_LIBCPP_WEAK
-void*
-operator new[](size_t size, const std::nothrow_t&) noexcept
-{
- void* p = nullptr;
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- try
- {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- p = ::operator new[](size);
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- }
- catch (...)
- {
- }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- return p;
}
-_LIBCPP_WEAK
-void
-operator delete(void* ptr) noexcept
-{
- std::free(ptr);
-}
+#define _LIBCPP_ASSERT_SHIM(expr, str) \
+ do { \
+ if (!expr) \
+ abort_message(str); \
+ } while (false)
-_LIBCPP_WEAK
-void
-operator delete(void* ptr, const std::nothrow_t&) noexcept
-{
- ::operator delete(ptr);
-}
-
-_LIBCPP_WEAK
-void
-operator delete(void* ptr, size_t) noexcept
-{
- ::operator delete(ptr);
-}
-
-_LIBCPP_WEAK
-void
-operator delete[] (void* ptr) noexcept
-{
- ::operator delete(ptr);
-}
+// ------------------ BEGIN COPY ------------------
+// Implement all new and delete operators as weak definitions
+// in this shared library, so that they can be overridden by programs
+// that define non-weak copies of the functions.
-_LIBCPP_WEAK
-void
-operator delete[] (void* ptr, const std::nothrow_t&) noexcept
-{
- ::operator delete[](ptr);
+static void* operator_new_impl(std::size_t size) {
+ if (size == 0)
+ size = 1;
+ void* p;
+ while ((p = std::malloc(size)) == nullptr) {
+ // If malloc fails and there is a new_handler,
+ // call it to try free up memory.
+ std::new_handler nh = std::get_new_handler();
+ if (nh)
+ nh();
+ else
+ break;
+ }
+ return p;
+}
+
+_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
+ void* p = operator_new_impl(size);
+ if (p == nullptr)
+ __throw_bad_alloc_shim();
+ return p;
+}
+
+_LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
+#ifdef _LIBCPP_HAS_NO_EXCEPTIONS
+# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
+ _LIBCPP_ASSERT_SHIM(
+ !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)),
+ "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
+ "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
+ "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
+ "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its "
+ "contract (since it should return nullptr upon failure). Please make sure you override "
+ "`operator new(size_t, nothrow_t)` as well.");
+# endif
+
+ return operator_new_impl(size);
+#else
+ void* p = nullptr;
+ try {
+ p = ::operator new(size);
+ } catch (...) {
+ }
+ return p;
+#endif
}
-_LIBCPP_WEAK
-void
-operator delete[] (void* ptr, size_t) noexcept
-{
- ::operator delete[](ptr);
+_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
+ return ::operator new(size);
}
-#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
+_LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
+#ifdef _LIBCPP_HAS_NO_EXCEPTIONS
+# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
+ _LIBCPP_ASSERT_SHIM(
+ !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])),
+ "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
+ "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
+ "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
+ "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "
+ "contract (since it should return nullptr upon failure). Please make sure you override "
+ "`operator new[](size_t, nothrow_t)` as well.");
+# endif
-_LIBCPP_WEAK
-void *
-operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
-{
- if (size == 0)
- size = 1;
- if (static_cast<size_t>(alignment) < sizeof(void*))
- alignment = std::align_val_t(sizeof(void*));
-
- // Try allocating memory. If allocation fails and there is a new_handler,
- // call it to try free up memory, and try again until it succeeds, or until
- // the new_handler decides to terminate.
- //
- // If allocation fails and there is no new_handler, we throw bad_alloc
- // (or return nullptr if exceptions are disabled).
- void* p;
- while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr)
- {
- std::new_handler nh = std::get_new_handler();
- if (nh)
- nh();
- else {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- throw std::bad_alloc();
+ return operator_new_impl(size);
#else
- break;
+ void* p = nullptr;
+ try {
+ p = ::operator new[](size);
+ } catch (...) {
+ }
+ return p;
#endif
- }
- }
- return p;
-}
-
-_LIBCPP_WEAK
-void*
-operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
-{
- void* p = nullptr;
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- try
- {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- p = ::operator new(size, alignment);
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- }
- catch (...)
- {
- }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- return p;
}
-_LIBCPP_WEAK
-void*
-operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
-{
- return ::operator new(size, alignment);
-}
+_LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
-_LIBCPP_WEAK
-void*
-operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
-{
- void* p = nullptr;
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- try
- {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- p = ::operator new[](size, alignment);
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
- }
- catch (...)
- {
- }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
- return p;
-}
+_LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }
-_LIBCPP_WEAK
-void
-operator delete(void* ptr, std::align_val_t) noexcept
-{
- std::__libcpp_aligned_free(ptr);
-}
+_LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }
-_LIBCPP_WEAK
-void
-operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
-{
- ::operator delete(ptr, alignment);
-}
+_LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }
-_LIBCPP_WEAK
-void
-operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept
-{
- ::operator delete(ptr, alignment);
-}
+_LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }
-_LIBCPP_WEAK
-void
-operator delete[] (void* ptr, std::align_val_t alignment) noexcept
-{
- ::operator delete(ptr, alignment);
-}
+_LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
-_LIBCPP_WEAK
-void
-operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
-{
- ::operator delete[](ptr, alignment);
-}
+#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
-_LIBCPP_WEAK
-void
-operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept
-{
- ::operator delete[](ptr, alignment);
+static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {
+ if (size == 0)
+ size = 1;
+ if (static_cast<size_t>(alignment) < sizeof(void*))
+ alignment = std::align_val_t(sizeof(void*));
+
+ // Try allocating memory. If allocation fails and there is a new_handler,
+ // call it to try free up memory, and try again until it succeeds, or until
+ // the new_handler decides to terminate.
+ void* p;
+ while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {
+ std::new_handler nh = std::get_new_handler();
+ if (nh)
+ nh();
+ else
+ break;
+ }
+ return p;
+}
+
+_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
+operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
+ void* p = operator_new_aligned_impl(size, alignment);
+ if (p == nullptr)
+ __throw_bad_alloc_shim();
+ return p;
+}
+
+_LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
+# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
+# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
+ _LIBCPP_ASSERT_SHIM(
+ !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)),
+ "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
+ "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
+ "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
+ "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "
+ "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "
+ "`operator new(size_t, align_val_t, nothrow_t)` as well.");
+# endif
+
+ return operator_new_aligned_impl(size, alignment);
+# else
+ void* p = nullptr;
+ try {
+ p = ::operator new(size, alignment);
+ } catch (...) {
+ }
+ return p;
+# endif
+}
+
+_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
+operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
+ return ::operator new(size, alignment);
+}
+
+_LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
+# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
+# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
+ _LIBCPP_ASSERT_SHIM(
+ !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])),
+ "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
+ "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
+ "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "
+ "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, "
+ "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "
+ "override "
+ "`operator new[](size_t, align_val_t, nothrow_t)` as well.");
+# endif
+
+ return operator_new_aligned_impl(size, alignment);
+# else
+ void* p = nullptr;
+ try {
+ p = ::operator new[](size, alignment);
+ } catch (...) {
+ }
+ return p;
+# endif
+}
+
+_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }
+
+_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
+ ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept {
+ ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept {
+ ::operator delete(ptr, alignment);
+}
+
+_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
+ ::operator delete[](ptr, alignment);
+}
+
+_LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept {
+ ::operator delete[](ptr, alignment);
}
#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION
diff --git a/contrib/libs/cxxsupp/libcxxabi/ya.make b/contrib/libs/cxxsupp/libcxxabi/ya.make
index a96ac77959..ea3a68d892 100644
--- a/contrib/libs/cxxsupp/libcxxabi/ya.make
+++ b/contrib/libs/cxxsupp/libcxxabi/ya.make
@@ -11,9 +11,9 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(17.0.6)
+VERSION(18.1.8)
-ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/llvmorg-17.0.6.tar.gz)
+ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/llvmorg-18.1.8.tar.gz)
PEERDIR(
contrib/libs/libunwind
@@ -74,6 +74,7 @@ ELSEIF (OS_EMSCRIPTEN AND ARCH_WASM32)
CFLAGS(
-D_LIBCPP_SAFE_STATIC=
-D_LIBCXXABI_DTOR_FUNC=
+ -D__USING_WASM_EXCEPTIONS__
)
ENDIF()