authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-04-26 14:41:45-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-08 19:37:29-07:00
logbc6ebc6f2597fda1f98842c6f545751fef2a5334
tree7fe57a76daad5c2ea3c0f429c04d8ef861baaf32
parent6295415da72eb17b263494a070fdf957e89460fb

libcxxabi: update to LLVM 18

release/18.x branch, commit 78b99c73ee4b96fe9ce0e294d4632326afb2db42

18 files changed, 1181 insertions(+), 555 deletions(-)

lib/libcxxabi/include/cxxabi.h+11
...@@ -36,6 +36,9 @@ class type_info; // forward declaration...@@ -36,6 +36,9 @@ class type_info; // forward declaration
3636
37// runtime routines use C calling conventions, but are in __cxxabiv1 namespace37// runtime routines use C calling conventions, but are in __cxxabiv1 namespace
38namespace __cxxabiv1 {38namespace __cxxabiv1 {
39
40struct __cxa_exception;
41
39extern "C" {42extern "C" {
4043
41// 2.4.2 Allocating the Exception Object44// 2.4.2 Allocating the Exception Object
...@@ -43,11 +46,19 @@ extern _LIBCXXABI_FUNC_VIS void *...@@ -43,11 +46,19 @@ extern _LIBCXXABI_FUNC_VIS void *
43__cxa_allocate_exception(size_t thrown_size) throw();46__cxa_allocate_exception(size_t thrown_size) throw();
44extern _LIBCXXABI_FUNC_VIS void47extern _LIBCXXABI_FUNC_VIS void
45__cxa_free_exception(void *thrown_exception) throw();48__cxa_free_exception(void *thrown_exception) throw();
49// This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt
50extern _LIBCXXABI_FUNC_VIS __cxa_exception*
51__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw();
4652
47// 2.4.3 Throwing the Exception Object53// 2.4.3 Throwing the Exception Object
48extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void54extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
49__cxa_throw(void *thrown_exception, std::type_info *tinfo,55__cxa_throw(void *thrown_exception, std::type_info *tinfo,
56#ifdef __USING_WASM_EXCEPTIONS__
57 // In Wasm, a destructor returns its argument
58 void *(_LIBCXXABI_DTOR_FUNC *dest)(void *));
59#else
50 void (_LIBCXXABI_DTOR_FUNC *dest)(void *));60 void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
61#endif
5162
52// 2.5.3 Exception Handlers63// 2.5.3 Exception Handlers
53extern _LIBCXXABI_FUNC_VIS void *64extern _LIBCXXABI_FUNC_VIS void *
lib/libcxxabi/src/abort_message.h+11
...@@ -14,4 +14,15 @@...@@ -14,4 +14,15 @@
14extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void14extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
15abort_message(const char *format, ...) __attribute__((format(printf, 1, 2)));15abort_message(const char *format, ...) __attribute__((format(printf, 1, 2)));
1616
17#ifndef _LIBCXXABI_ASSERT
18# define _LIBCXXABI_ASSERT(expr, msg) \
19 do { \
20 if (!(expr)) { \
21 char const* __msg = (msg); \
22 ::abort_message("%s:%d: %s", __FILE__, __LINE__, __msg); \
23 } \
24 } while (false)
25
17#endif26#endif
27
28#endif // __ABORT_MESSAGE_H_
lib/libcxxabi/src/aix_state_tab_eh.inc+1-1
...@@ -740,6 +740,6 @@ __catchThrownException(void (*cdfunc)(void), // function which may fail...@@ -740,6 +740,6 @@ __catchThrownException(void (*cdfunc)(void), // function which may fail
740 return 0;740 return 0;
741}741}
742742
743} // extern "C"743} // extern "C"
744744
745} // __cxxabiv1745} // __cxxabiv1
lib/libcxxabi/src/cxa_demangle.cpp+5-2
...@@ -10,14 +10,17 @@...@@ -10,14 +10,17 @@
10// file does not yet support:10// file does not yet support:
11// - C++ modules TS11// - C++ modules TS
1212
13#include "abort_message.h"
14#define DEMANGLE_ASSERT(expr, msg) _LIBCXXABI_ASSERT(expr, msg)
15
13#include "demangle/DemangleConfig.h"16#include "demangle/DemangleConfig.h"
14#include "demangle/ItaniumDemangle.h"17#include "demangle/ItaniumDemangle.h"
15#include "__cxxabi_config.h"18#include "__cxxabi_config.h"
16#include <cassert>
17#include <cctype>19#include <cctype>
18#include <cstdio>20#include <cstdio>
19#include <cstdlib>21#include <cstdlib>
20#include <cstring>22#include <cstring>
23#include <exception>
21#include <functional>24#include <functional>
22#include <numeric>25#include <numeric>
23#include <string_view>26#include <string_view>
...@@ -394,7 +397,7 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {...@@ -394,7 +397,7 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
394 InternalStatus = demangle_invalid_mangled_name;397 InternalStatus = demangle_invalid_mangled_name;
395 else {398 else {
396 OutputBuffer O(Buf, N);399 OutputBuffer O(Buf, N);
397 assert(Parser.ForwardTemplateRefs.empty());400 DEMANGLE_ASSERT(Parser.ForwardTemplateRefs.empty(), "");
398 AST->print(O);401 AST->print(O);
399 O += '\0';402 O += '\0';
400 if (N != nullptr)403 if (N != nullptr)
lib/libcxxabi/src/cxa_exception.cpp+25-14
...@@ -206,6 +206,19 @@ void __cxa_free_exception(void *thrown_object) throw() {...@@ -206,6 +206,19 @@ void __cxa_free_exception(void *thrown_object) throw() {
206 __aligned_free_with_fallback((void *)raw_buffer);206 __aligned_free_with_fallback((void *)raw_buffer);
207}207}
208208
209__cxa_exception* __cxa_init_primary_exception(void* object, std::type_info* tinfo,
210 void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw() {
211 __cxa_exception* exception_header = cxa_exception_from_thrown_object(object);
212 exception_header->referenceCount = 0;
213 exception_header->unexpectedHandler = std::get_unexpected();
214 exception_header->terminateHandler = std::get_terminate();
215 exception_header->exceptionType = tinfo;
216 exception_header->exceptionDestructor = dest;
217 setOurExceptionClass(&exception_header->unwindHeader);
218 exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;
219
220 return exception_header;
221}
209222
210// This function shall allocate a __cxa_dependent_exception and223// This function shall allocate a __cxa_dependent_exception and
211// return a pointer to it. (Really to the object, not past its' end).224// return a pointer to it. (Really to the object, not past its' end).
...@@ -254,23 +267,21 @@ will call terminate, assuming that there was no handler for the...@@ -254,23 +267,21 @@ will call terminate, assuming that there was no handler for the
254exception.267exception.
255*/268*/
256void269void
270#ifdef __USING_WASM_EXCEPTIONS__
271// In Wasm, a destructor returns its argument
272__cxa_throw(void *thrown_object, std::type_info *tinfo, void *(_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
273#else
257__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *)) {274__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
258 __cxa_eh_globals *globals = __cxa_get_globals();275#endif
259 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);276 __cxa_eh_globals* globals = __cxa_get_globals();
260277 globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
261 exception_header->unexpectedHandler = std::get_unexpected();
262 exception_header->terminateHandler = std::get_terminate();
263 exception_header->exceptionType = tinfo;
264 exception_header->exceptionDestructor = dest;
265 setOurExceptionClass(&exception_header->unwindHeader);
266 exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
267 globals->uncaughtExceptions += 1; // Not atomically, since globals are thread-local
268278
269 exception_header->unwindHeader.exception_cleanup = exception_cleanup_func;279 __cxa_exception* exception_header = __cxa_init_primary_exception(thrown_object, tinfo, dest);
280 exception_header->referenceCount = 1; // This is a newly allocated exception, no need for thread safety.
270281
271#if __has_feature(address_sanitizer)282#if __has_feature(address_sanitizer)
272 // Inform the ASan runtime that now might be a good time to clean stuff up.283 // Inform the ASan runtime that now might be a good time to clean stuff up.
273 __asan_handle_no_return();284 __asan_handle_no_return();
274#endif285#endif
275286
276#ifdef __USING_SJLJ_EXCEPTIONS__287#ifdef __USING_SJLJ_EXCEPTIONS__
...@@ -771,6 +782,6 @@ __cxa_uncaught_exceptions() throw()...@@ -771,6 +782,6 @@ __cxa_uncaught_exceptions() throw()
771 return globals->uncaughtExceptions;782 return globals->uncaughtExceptions;
772}783}
773784
774} // extern "C"785} // extern "C"
775786
776} // abi787} // abi
lib/libcxxabi/src/cxa_exception.h+5
...@@ -43,7 +43,12 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {...@@ -43,7 +43,12 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
4343
44 // Manage the exception object itself.44 // Manage the exception object itself.
45 std::type_info *exceptionType;45 std::type_info *exceptionType;
46#ifdef __USING_WASM_EXCEPTIONS__
47 // In Wasm, a destructor returns its argument
48 void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
49#else
46 void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);50 void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
51#endif
47 std::unexpected_handler unexpectedHandler;52 std::unexpected_handler unexpectedHandler;
48 std::terminate_handler terminateHandler;53 std::terminate_handler terminateHandler;
4954
lib/libcxxabi/src/cxa_guard.cpp+1-1
...@@ -48,6 +48,6 @@ _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *raw_guard_object) {...@@ -48,6 +48,6 @@ _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(guard_type *raw_guard_object) {
48 SelectedImplementation imp(raw_guard_object);48 SelectedImplementation imp(raw_guard_object);
49 imp.cxa_guard_abort();49 imp.cxa_guard_abort();
50}50}
51} // extern "C"51} // extern "C"
5252
53} // __cxxabiv153} // __cxxabiv1
lib/libcxxabi/src/cxa_noexception.cpp+1-1
...@@ -49,7 +49,7 @@ __cxa_uncaught_exception() throw() { return false; }...@@ -49,7 +49,7 @@ __cxa_uncaught_exception() throw() { return false; }
49unsigned int49unsigned int
50__cxa_uncaught_exceptions() throw() { return 0; }50__cxa_uncaught_exceptions() throw() { return 0; }
5151
52} // extern "C"52} // extern "C"
5353
54// provide dummy implementations for the 'no exceptions' case.54// provide dummy implementations for the 'no exceptions' case.
55uint64_t __getExceptionClass (const _Unwind_Exception*) { return 0; }55uint64_t __getExceptionClass (const _Unwind_Exception*) { return 0; }
lib/libcxxabi/src/cxa_personality.cpp+29-23
...@@ -70,7 +70,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,...@@ -70,7 +70,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
70+------------------+--+-----+-----+------------------------+--------------------------+70+------------------+--+-----+-----+------------------------+--------------------------+
71| callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |71| callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
72+---------------------+-----------+---------------------------------------------------+72+---------------------+-----------+---------------------------------------------------+
73#ifndef __USING_SJLJ_EXCEPTIONS__73#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
74+---------------------+-----------+------------------------------------------------+74+---------------------+-----------+------------------------------------------------+
75| Beginning of Call Site Table The current ip lies within the |75| Beginning of Call Site Table The current ip lies within the |
76| ... (start, length) range of one of these |76| ... (start, length) range of one of these |
...@@ -84,7 +84,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,...@@ -84,7 +84,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
84| +-------------+---------------------------------+------------------------------+ |84| +-------------+---------------------------------+------------------------------+ |
85| ... |85| ... |
86+----------------------------------------------------------------------------------+86+----------------------------------------------------------------------------------+
87#else // __USING_SJLJ_EXCEPTIONS__87#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
88+---------------------+-----------+------------------------------------------------+88+---------------------+-----------+------------------------------------------------+
89| Beginning of Call Site Table The current ip is a 1-based index into |89| Beginning of Call Site Table The current ip is a 1-based index into |
90| ... this table. Or it is -1 meaning no |90| ... this table. Or it is -1 meaning no |
...@@ -97,7 +97,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,...@@ -97,7 +97,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
97| +-------------+---------------------------------+------------------------------+ |97| +-------------+---------------------------------+------------------------------+ |
98| ... |98| ... |
99+----------------------------------------------------------------------------------+99+----------------------------------------------------------------------------------+
100#endif // __USING_SJLJ_EXCEPTIONS__100#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
101+---------------------------------------------------------------------+101+---------------------------------------------------------------------+
102| Beginning of Action Table ttypeIndex == 0 : cleanup |102| Beginning of Action Table ttypeIndex == 0 : cleanup |
103| ... ttypeIndex > 0 : catch |103| ... ttypeIndex > 0 : catch |
...@@ -547,7 +547,7 @@ void...@@ -547,7 +547,7 @@ void
547set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,547set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
548 const scan_results& results)548 const scan_results& results)
549{549{
550#if defined(__USING_SJLJ_EXCEPTIONS__)550#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
551#define __builtin_eh_return_data_regno(regno) regno551#define __builtin_eh_return_data_regno(regno) regno
552#elif defined(__ibmxl__)552#elif defined(__ibmxl__)
553// IBM xlclang++ compiler does not support __builtin_eh_return_data_regno.553// IBM xlclang++ compiler does not support __builtin_eh_return_data_regno.
...@@ -642,7 +642,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -642,7 +642,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
642 // Get beginning current frame's code (as defined by the642 // Get beginning current frame's code (as defined by the
643 // emitted dwarf code)643 // emitted dwarf code)
644 uintptr_t funcStart = _Unwind_GetRegionStart(context);644 uintptr_t funcStart = _Unwind_GetRegionStart(context);
645#ifdef __USING_SJLJ_EXCEPTIONS__645#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
646 if (ip == uintptr_t(-1))646 if (ip == uintptr_t(-1))
647 {647 {
648 // no action648 // no action
...@@ -652,18 +652,17 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -652,18 +652,17 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
652 else if (ip == 0)652 else if (ip == 0)
653 call_terminate(native_exception, unwind_exception);653 call_terminate(native_exception, unwind_exception);
654 // ip is 1-based index into call site table654 // ip is 1-based index into call site table
655#else // !__USING_SJLJ_EXCEPTIONS__655#else // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
656 uintptr_t ipOffset = ip - funcStart;656 uintptr_t ipOffset = ip - funcStart;
657#endif // !defined(_USING_SLJL_EXCEPTIONS__)657#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
658 const uint8_t* classInfo = NULL;658 const uint8_t* classInfo = NULL;
659 // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding659 // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
660 // dwarf emission660 // dwarf emission
661 // Parse LSDA header.661 // Parse LSDA header.
662 uint8_t lpStartEncoding = *lsda++;662 uint8_t lpStartEncoding = *lsda++;
663 const uint8_t* lpStart =663 const uint8_t* lpStart = lpStartEncoding == DW_EH_PE_omit
664 (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);664 ? (const uint8_t*)funcStart
665 if (lpStart == 0)665 : (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
666 lpStart = (const uint8_t*)funcStart;
667 uint8_t ttypeEncoding = *lsda++;666 uint8_t ttypeEncoding = *lsda++;
668 if (ttypeEncoding != DW_EH_PE_omit)667 if (ttypeEncoding != DW_EH_PE_omit)
669 {668 {
...@@ -676,8 +675,8 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -676,8 +675,8 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
676 // Walk call-site table looking for range that675 // Walk call-site table looking for range that
677 // includes current PC.676 // includes current PC.
678 uint8_t callSiteEncoding = *lsda++;677 uint8_t callSiteEncoding = *lsda++;
679#ifdef __USING_SJLJ_EXCEPTIONS__678#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
680 (void)callSiteEncoding; // When using SjLj exceptions, callSiteEncoding is never used679 (void)callSiteEncoding; // When using SjLj/Wasm exceptions, callSiteEncoding is never used
681#endif680#endif
682 uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));681 uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
683 const uint8_t* callSiteTableStart = lsda;682 const uint8_t* callSiteTableStart = lsda;
...@@ -687,7 +686,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -687,7 +686,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
687 while (callSitePtr < callSiteTableEnd)686 while (callSitePtr < callSiteTableEnd)
688 {687 {
689 // There is one entry per call site.688 // There is one entry per call site.
690#ifndef __USING_SJLJ_EXCEPTIONS__689#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
691 // The call sites are non-overlapping in [start, start+length)690 // The call sites are non-overlapping in [start, start+length)
692 // The call sites are ordered in increasing value of start691 // The call sites are ordered in increasing value of start
693 uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);692 uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
...@@ -695,15 +694,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -695,15 +694,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
695 uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);694 uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
696 uintptr_t actionEntry = readULEB128(&callSitePtr);695 uintptr_t actionEntry = readULEB128(&callSitePtr);
697 if ((start <= ipOffset) && (ipOffset < (start + length)))696 if ((start <= ipOffset) && (ipOffset < (start + length)))
698#else // __USING_SJLJ_EXCEPTIONS__697#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
699 // ip is 1-based index into this table698 // ip is 1-based index into this table
700 uintptr_t landingPad = readULEB128(&callSitePtr);699 uintptr_t landingPad = readULEB128(&callSitePtr);
701 uintptr_t actionEntry = readULEB128(&callSitePtr);700 uintptr_t actionEntry = readULEB128(&callSitePtr);
702 if (--ip == 0)701 if (--ip == 0)
703#endif // __USING_SJLJ_EXCEPTIONS__702#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
704 {703 {
705 // Found the call site containing ip.704 // Found the call site containing ip.
706#ifndef __USING_SJLJ_EXCEPTIONS__705#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
707 if (landingPad == 0)706 if (landingPad == 0)
708 {707 {
709 // No handler here708 // No handler here
...@@ -711,9 +710,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -711,9 +710,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
711 return;710 return;
712 }711 }
713 landingPad = (uintptr_t)lpStart + landingPad;712 landingPad = (uintptr_t)lpStart + landingPad;
714#else // __USING_SJLJ_EXCEPTIONS__713#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
715 ++landingPad;714 ++landingPad;
716#endif // __USING_SJLJ_EXCEPTIONS__715#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
717 results.landingPad = landingPad;716 results.landingPad = landingPad;
718 if (actionEntry == 0)717 if (actionEntry == 0)
719 {718 {
...@@ -841,7 +840,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -841,7 +840,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
841 action += actionOffset;840 action += actionOffset;
842 } // there is no break out of this loop, only return841 } // there is no break out of this loop, only return
843 }842 }
844#ifndef __USING_SJLJ_EXCEPTIONS__843#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
845 else if (ipOffset < start)844 else if (ipOffset < start)
846 {845 {
847 // There is no call site for this ip846 // There is no call site for this ip
...@@ -849,7 +848,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,...@@ -849,7 +848,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
849 // Possible stack corruption.848 // Possible stack corruption.
850 call_terminate(native_exception, unwind_exception);849 call_terminate(native_exception, unwind_exception);
851 }850 }
852#endif // !__USING_SJLJ_EXCEPTIONS__851#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
853 } // there might be some tricky cases which break out of this loop852 } // there might be some tricky cases which break out of this loop
854853
855 // It is possible that no eh table entry specify how to handle854 // It is possible that no eh table entry specify how to handle
...@@ -906,7 +905,9 @@ _UA_CLEANUP_PHASE...@@ -906,7 +905,9 @@ _UA_CLEANUP_PHASE
906*/905*/
907906
908#if !defined(_LIBCXXABI_ARM_EHABI)907#if !defined(_LIBCXXABI_ARM_EHABI)
909#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)908#ifdef __USING_WASM_EXCEPTIONS__
909_Unwind_Reason_Code __gxx_personality_wasm0
910#elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
910static _Unwind_Reason_Code __gxx_personality_imp911static _Unwind_Reason_Code __gxx_personality_imp
911#else912#else
912_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code913_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
...@@ -973,6 +974,11 @@ __gxx_personality_v0...@@ -973,6 +974,11 @@ __gxx_personality_v0
973 exc->languageSpecificData = results.languageSpecificData;974 exc->languageSpecificData = results.languageSpecificData;
974 exc->catchTemp = reinterpret_cast<void*>(results.landingPad);975 exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
975 exc->adjustedPtr = results.adjustedPtr;976 exc->adjustedPtr = results.adjustedPtr;
977#ifdef __USING_WASM_EXCEPTIONS__
978 // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
979 // results here.
980 set_registers(unwind_exception, context, results);
981#endif
976 }982 }
977 return _URC_HANDLER_FOUND;983 return _URC_HANDLER_FOUND;
978 }984 }
...@@ -1304,7 +1310,7 @@ _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(...@@ -1304,7 +1310,7 @@ _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(
1304 __attribute__((__alias__("__gxx_personality_v0")));1310 __attribute__((__alias__("__gxx_personality_v0")));
1305#endif1311#endif
13061312
1307} // extern "C"1313} // extern "C"
13081314
1309} // __cxxabiv11315} // __cxxabiv1
13101316
lib/libcxxabi/src/cxa_vector.cpp+1-1
...@@ -416,6 +416,6 @@ __cxa_vec_delete3(void *array_address, size_t element_size, size_t padding_size,...@@ -416,6 +416,6 @@ __cxa_vec_delete3(void *array_address, size_t element_size, size_t padding_size,
416}416}
417417
418418
419} // extern "C"419} // extern "C"
420420
421} // abi421} // abi
lib/libcxxabi/src/demangle/DemangleConfig.h+6-1
...@@ -19,7 +19,7 @@...@@ -19,7 +19,7 @@
19#include "../abort_message.h"19#include "../abort_message.h"
20#endif20#endif
2121
22#include <ciso646>22#include <version>
2323
24#ifdef _MSC_VER24#ifdef _MSC_VER
25// snprintf is implemented in VS 201525// snprintf is implemented in VS 2015
...@@ -99,6 +99,11 @@...@@ -99,6 +99,11 @@
99#define DEMANGLE_FALLTHROUGH99#define DEMANGLE_FALLTHROUGH
100#endif100#endif
101101
102#ifndef DEMANGLE_ASSERT
103#include <cassert>
104#define DEMANGLE_ASSERT(__expr, __msg) assert((__expr) && (__msg))
105#endif
106
102#define DEMANGLE_NAMESPACE_BEGIN namespace { namespace itanium_demangle {107#define DEMANGLE_NAMESPACE_BEGIN namespace { namespace itanium_demangle {
103#define DEMANGLE_NAMESPACE_END } }108#define DEMANGLE_NAMESPACE_END } }
104109
lib/libcxxabi/src/demangle/ItaniumDemangle.h+538-103
...@@ -21,7 +21,6 @@...@@ -21,7 +21,6 @@
21#include "Utility.h"21#include "Utility.h"
22#include <__cxxabi_config.h>22#include <__cxxabi_config.h>
23#include <algorithm>23#include <algorithm>
24#include <cassert>
25#include <cctype>24#include <cctype>
26#include <cstdio>25#include <cstdio>
27#include <cstdlib>26#include <cstdlib>
...@@ -61,13 +60,13 @@ template <class T, size_t N> class PODSmallVector {...@@ -61,13 +60,13 @@ template <class T, size_t N> class PODSmallVector {
61 if (isInline()) {60 if (isInline()) {
62 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));61 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
63 if (Tmp == nullptr)62 if (Tmp == nullptr)
64 std::terminate();63 std::abort();
65 std::copy(First, Last, Tmp);64 std::copy(First, Last, Tmp);
66 First = Tmp;65 First = Tmp;
67 } else {66 } else {
68 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));67 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
69 if (First == nullptr)68 if (First == nullptr)
70 std::terminate();69 std::abort();
71 }70 }
72 Last = First + S;71 Last = First + S;
73 Cap = First + NewCap;72 Cap = First + NewCap;
...@@ -129,12 +128,12 @@ public:...@@ -129,12 +128,12 @@ public:
129128
130 // NOLINTNEXTLINE(readability-identifier-naming)129 // NOLINTNEXTLINE(readability-identifier-naming)
131 void pop_back() {130 void pop_back() {
132 assert(Last != First && "Popping empty vector!");131 DEMANGLE_ASSERT(Last != First, "Popping empty vector!");
133 --Last;132 --Last;
134 }133 }
135134
136 void dropBack(size_t Index) {135 void shrinkToSize(size_t Index) {
137 assert(Index <= size() && "dropBack() can't expand!");136 DEMANGLE_ASSERT(Index <= size(), "shrinkToSize() can't expand!");
138 Last = First + Index;137 Last = First + Index;
139 }138 }
140139
...@@ -144,11 +143,11 @@ public:...@@ -144,11 +143,11 @@ public:
144 bool empty() const { return First == Last; }143 bool empty() const { return First == Last; }
145 size_t size() const { return static_cast<size_t>(Last - First); }144 size_t size() const { return static_cast<size_t>(Last - First); }
146 T &back() {145 T &back() {
147 assert(Last != First && "Calling back() on empty vector!");146 DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!");
148 return *(Last - 1);147 return *(Last - 1);
149 }148 }
150 T &operator[](size_t Index) {149 T &operator[](size_t Index) {
151 assert(Index < size() && "Invalid access!");150 DEMANGLE_ASSERT(Index < size(), "Invalid access!");
152 return *(begin() + Index);151 return *(begin() + Index);
153 }152 }
154 void clear() { Last = First; }153 void clear() { Last = First; }
...@@ -534,6 +533,23 @@ public:...@@ -534,6 +533,23 @@ public:
534 }533 }
535};534};
536535
536class TransformedType : public Node {
537 std::string_view Transform;
538 Node *BaseType;
539public:
540 TransformedType(std::string_view Transform_, Node *BaseType_)
541 : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}
542
543 template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }
544
545 void printLeft(OutputBuffer &OB) const override {
546 OB += Transform;
547 OB += '(';
548 BaseType->print(OB);
549 OB += ')';
550 }
551};
552
537struct AbiTagAttr : Node {553struct AbiTagAttr : Node {
538 Node *Base;554 Node *Base;
539 std::string_view Tag;555 std::string_view Tag;
...@@ -873,26 +889,53 @@ public:...@@ -873,26 +889,53 @@ public:
873 }889 }
874};890};
875891
892/// Represents the explicitly named object parameter.
893/// E.g.,
894/// \code{.cpp}
895/// struct Foo {
896/// void bar(this Foo && self);
897/// };
898/// \endcode
899class ExplicitObjectParameter final : public Node {
900 Node *Base;
901
902public:
903 ExplicitObjectParameter(Node *Base_)
904 : Node(KExplicitObjectParameter), Base(Base_) {
905 DEMANGLE_ASSERT(
906 Base != nullptr,
907 "Creating an ExplicitObjectParameter without a valid Base Node.");
908 }
909
910 template <typename Fn> void match(Fn F) const { F(Base); }
911
912 void printLeft(OutputBuffer &OB) const override {
913 OB += "this ";
914 Base->print(OB);
915 }
916};
917
876class FunctionEncoding final : public Node {918class FunctionEncoding final : public Node {
877 const Node *Ret;919 const Node *Ret;
878 const Node *Name;920 const Node *Name;
879 NodeArray Params;921 NodeArray Params;
880 const Node *Attrs;922 const Node *Attrs;
923 const Node *Requires;
881 Qualifiers CVQuals;924 Qualifiers CVQuals;
882 FunctionRefQual RefQual;925 FunctionRefQual RefQual;
883926
884public:927public:
885 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,928 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
886 const Node *Attrs_, Qualifiers CVQuals_,929 const Node *Attrs_, const Node *Requires_,
887 FunctionRefQual RefQual_)930 Qualifiers CVQuals_, FunctionRefQual RefQual_)
888 : Node(KFunctionEncoding,931 : Node(KFunctionEncoding,
889 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,932 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
890 /*FunctionCache=*/Cache::Yes),933 /*FunctionCache=*/Cache::Yes),
891 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),934 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
892 CVQuals(CVQuals_), RefQual(RefQual_) {}935 Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}
893936
894 template<typename Fn> void match(Fn F) const {937 template<typename Fn> void match(Fn F) const {
895 F(Ret, Name, Params, Attrs, CVQuals, RefQual);938 F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual);
896 }939 }
897940
898 Qualifiers getCVQuals() const { return CVQuals; }941 Qualifiers getCVQuals() const { return CVQuals; }
...@@ -935,6 +978,11 @@ public:...@@ -935,6 +978,11 @@ public:
935978
936 if (Attrs != nullptr)979 if (Attrs != nullptr)
937 Attrs->print(OB);980 Attrs->print(OB);
981
982 if (Requires != nullptr) {
983 OB += " requires ";
984 Requires->print(OB);
985 }
938 }986 }
939};987};
940988
...@@ -1006,6 +1054,24 @@ struct NestedName : Node {...@@ -1006,6 +1054,24 @@ struct NestedName : Node {
1006 }1054 }
1007};1055};
10081056
1057struct MemberLikeFriendName : Node {
1058 Node *Qual;
1059 Node *Name;
1060
1061 MemberLikeFriendName(Node *Qual_, Node *Name_)
1062 : Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {}
1063
1064 template<typename Fn> void match(Fn F) const { F(Qual, Name); }
1065
1066 std::string_view getBaseName() const override { return Name->getBaseName(); }
1067
1068 void printLeft(OutputBuffer &OB) const override {
1069 Qual->print(OB);
1070 OB += "::friend ";
1071 Name->print(OB);
1072 }
1073};
1074
1009struct ModuleName : Node {1075struct ModuleName : Node {
1010 ModuleName *Parent;1076 ModuleName *Parent;
1011 Node *Name;1077 Node *Name;
...@@ -1171,6 +1237,24 @@ public:...@@ -1171,6 +1237,24 @@ public:
1171 }1237 }
1172};1238};
11731239
1240class TemplateParamQualifiedArg final : public Node {
1241 Node *Param;
1242 Node *Arg;
1243
1244public:
1245 TemplateParamQualifiedArg(Node *Param_, Node *Arg_)
1246 : Node(KTemplateParamQualifiedArg), Param(Param_), Arg(Arg_) {}
1247
1248 template <typename Fn> void match(Fn F) const { F(Param, Arg); }
1249
1250 Node *getArg() { return Arg; }
1251
1252 void printLeft(OutputBuffer &OB) const override {
1253 // Don't print Param to keep the output consistent.
1254 Arg->print(OB);
1255 }
1256};
1257
1174/// A template type parameter declaration, 'typename T'.1258/// A template type parameter declaration, 'typename T'.
1175class TypeTemplateParamDecl final : public Node {1259class TypeTemplateParamDecl final : public Node {
1176 Node *Name;1260 Node *Name;
...@@ -1186,6 +1270,26 @@ public:...@@ -1186,6 +1270,26 @@ public:
1186 void printRight(OutputBuffer &OB) const override { Name->print(OB); }1270 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
1187};1271};
11881272
1273/// A constrained template type parameter declaration, 'C<U> T'.
1274class ConstrainedTypeTemplateParamDecl final : public Node {
1275 Node *Constraint;
1276 Node *Name;
1277
1278public:
1279 ConstrainedTypeTemplateParamDecl(Node *Constraint_, Node *Name_)
1280 : Node(KConstrainedTypeTemplateParamDecl, Cache::Yes),
1281 Constraint(Constraint_), Name(Name_) {}
1282
1283 template<typename Fn> void match(Fn F) const { F(Constraint, Name); }
1284
1285 void printLeft(OutputBuffer &OB) const override {
1286 Constraint->print(OB);
1287 OB += " ";
1288 }
1289
1290 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
1291};
1292
1189/// A non-type template parameter declaration, 'int N'.1293/// A non-type template parameter declaration, 'int N'.
1190class NonTypeTemplateParamDecl final : public Node {1294class NonTypeTemplateParamDecl final : public Node {
1191 Node *Name;1295 Node *Name;
...@@ -1214,13 +1318,14 @@ public:...@@ -1214,13 +1318,14 @@ public:
1214class TemplateTemplateParamDecl final : public Node {1318class TemplateTemplateParamDecl final : public Node {
1215 Node *Name;1319 Node *Name;
1216 NodeArray Params;1320 NodeArray Params;
1321 Node *Requires;
12171322
1218public:1323public:
1219 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)1324 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_)
1220 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),1325 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),
1221 Params(Params_) {}1326 Params(Params_), Requires(Requires_) {}
12221327
1223 template<typename Fn> void match(Fn F) const { F(Name, Params); }1328 template <typename Fn> void match(Fn F) const { F(Name, Params, Requires); }
12241329
1225 void printLeft(OutputBuffer &OB) const override {1330 void printLeft(OutputBuffer &OB) const override {
1226 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);1331 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
...@@ -1229,7 +1334,13 @@ public:...@@ -1229,7 +1334,13 @@ public:
1229 OB += "> typename ";1334 OB += "> typename ";
1230 }1335 }
12311336
1232 void printRight(OutputBuffer &OB) const override { Name->print(OB); }1337 void printRight(OutputBuffer &OB) const override {
1338 Name->print(OB);
1339 if (Requires != nullptr) {
1340 OB += " requires ";
1341 Requires->print(OB);
1342 }
1343 }
1233};1344};
12341345
1235/// A template parameter pack declaration, 'typename ...T'.1346/// A template parameter pack declaration, 'typename ...T'.
...@@ -1326,7 +1437,7 @@ public:...@@ -1326,7 +1437,7 @@ public:
13261437
1327/// A variadic template argument. This node represents an occurrence of1438/// A variadic template argument. This node represents an occurrence of
1328/// J<something>E in some <template-args>. It isn't itself unexpanded, unless1439/// J<something>E in some <template-args>. It isn't itself unexpanded, unless
1329/// one of it's Elements is. The parser inserts a ParameterPack into the1440/// one of its Elements is. The parser inserts a ParameterPack into the
1330/// TemplateParams table if the <template-args> this pack belongs to apply to an1441/// TemplateParams table if the <template-args> this pack belongs to apply to an
1331/// <encoding>.1442/// <encoding>.
1332class TemplateArgumentPack final : public Node {1443class TemplateArgumentPack final : public Node {
...@@ -1392,11 +1503,13 @@ public:...@@ -1392,11 +1503,13 @@ public:
13921503
1393class TemplateArgs final : public Node {1504class TemplateArgs final : public Node {
1394 NodeArray Params;1505 NodeArray Params;
1506 Node *Requires;
13951507
1396public:1508public:
1397 TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}1509 TemplateArgs(NodeArray Params_, Node *Requires_)
1510 : Node(KTemplateArgs), Params(Params_), Requires(Requires_) {}
13981511
1399 template<typename Fn> void match(Fn F) const { F(Params); }1512 template<typename Fn> void match(Fn F) const { F(Params, Requires); }
14001513
1401 NodeArray getParams() { return Params; }1514 NodeArray getParams() { return Params; }
14021515
...@@ -1405,6 +1518,7 @@ public:...@@ -1405,6 +1518,7 @@ public:
1405 OB += "<";1518 OB += "<";
1406 Params.printWithComma(OB);1519 Params.printWithComma(OB);
1407 OB += ">";1520 OB += ">";
1521 // Don't print the requires clause to keep the output simple.
1408 }1522 }
1409};1523};
14101524
...@@ -1589,7 +1703,7 @@ public:...@@ -1589,7 +1703,7 @@ public:
1589 std::string_view SV = ExpandedSpecialSubstitution::getBaseName();1703 std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
1590 if (isInstantiation()) {1704 if (isInstantiation()) {
1591 // The instantiations are typedefs that drop the "basic_" prefix.1705 // The instantiations are typedefs that drop the "basic_" prefix.
1592 assert(starts_with(SV, "basic_"));1706 DEMANGLE_ASSERT(starts_with(SV, "basic_"), "");
1593 SV.remove_prefix(sizeof("basic_") - 1);1707 SV.remove_prefix(sizeof("basic_") - 1);
1594 }1708 }
1595 return SV;1709 return SV;
...@@ -1655,17 +1769,21 @@ public:...@@ -1655,17 +1769,21 @@ public:
16551769
1656class ClosureTypeName : public Node {1770class ClosureTypeName : public Node {
1657 NodeArray TemplateParams;1771 NodeArray TemplateParams;
1772 const Node *Requires1;
1658 NodeArray Params;1773 NodeArray Params;
1774 const Node *Requires2;
1659 std::string_view Count;1775 std::string_view Count;
16601776
1661public:1777public:
1662 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,1778 ClosureTypeName(NodeArray TemplateParams_, const Node *Requires1_,
1779 NodeArray Params_, const Node *Requires2_,
1663 std::string_view Count_)1780 std::string_view Count_)
1664 : Node(KClosureTypeName), TemplateParams(TemplateParams_),1781 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1665 Params(Params_), Count(Count_) {}1782 Requires1(Requires1_), Params(Params_), Requires2(Requires2_),
1783 Count(Count_) {}
16661784
1667 template<typename Fn> void match(Fn F) const {1785 template<typename Fn> void match(Fn F) const {
1668 F(TemplateParams, Params, Count);1786 F(TemplateParams, Requires1, Params, Requires2, Count);
1669 }1787 }
16701788
1671 void printDeclarator(OutputBuffer &OB) const {1789 void printDeclarator(OutputBuffer &OB) const {
...@@ -1675,12 +1793,22 @@ public:...@@ -1675,12 +1793,22 @@ public:
1675 TemplateParams.printWithComma(OB);1793 TemplateParams.printWithComma(OB);
1676 OB += ">";1794 OB += ">";
1677 }1795 }
1796 if (Requires1 != nullptr) {
1797 OB += " requires ";
1798 Requires1->print(OB);
1799 OB += " ";
1800 }
1678 OB.printOpen();1801 OB.printOpen();
1679 Params.printWithComma(OB);1802 Params.printWithComma(OB);
1680 OB.printClose();1803 OB.printClose();
1804 if (Requires2 != nullptr) {
1805 OB += " requires ";
1806 Requires2->print(OB);
1807 }
1681 }1808 }
16821809
1683 void printLeft(OutputBuffer &OB) const override {1810 void printLeft(OutputBuffer &OB) const override {
1811 // FIXME: This demangling is not particularly readable.
1684 OB += "\'lambda";1812 OB += "\'lambda";
1685 OB += Count;1813 OB += Count;
1686 OB += "\'";1814 OB += "\'";
...@@ -2309,6 +2437,95 @@ public:...@@ -2309,6 +2437,95 @@ public:
2309 }2437 }
2310};2438};
23112439
2440class RequiresExpr : public Node {
2441 NodeArray Parameters;
2442 NodeArray Requirements;
2443public:
2444 RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)
2445 : Node(KRequiresExpr), Parameters(Parameters_),
2446 Requirements(Requirements_) {}
2447
2448 template<typename Fn> void match(Fn F) const { F(Parameters, Requirements); }
2449
2450 void printLeft(OutputBuffer &OB) const override {
2451 OB += "requires";
2452 if (!Parameters.empty()) {
2453 OB += ' ';
2454 OB.printOpen();
2455 Parameters.printWithComma(OB);
2456 OB.printClose();
2457 }
2458 OB += ' ';
2459 OB.printOpen('{');
2460 for (const Node *Req : Requirements) {
2461 Req->print(OB);
2462 }
2463 OB += ' ';
2464 OB.printClose('}');
2465 }
2466};
2467
2468class ExprRequirement : public Node {
2469 const Node *Expr;
2470 bool IsNoexcept;
2471 const Node *TypeConstraint;
2472public:
2473 ExprRequirement(const Node *Expr_, bool IsNoexcept_,
2474 const Node *TypeConstraint_)
2475 : Node(KExprRequirement), Expr(Expr_), IsNoexcept(IsNoexcept_),
2476 TypeConstraint(TypeConstraint_) {}
2477
2478 template <typename Fn> void match(Fn F) const {
2479 F(Expr, IsNoexcept, TypeConstraint);
2480 }
2481
2482 void printLeft(OutputBuffer &OB) const override {
2483 OB += " ";
2484 if (IsNoexcept || TypeConstraint)
2485 OB.printOpen('{');
2486 Expr->print(OB);
2487 if (IsNoexcept || TypeConstraint)
2488 OB.printClose('}');
2489 if (IsNoexcept)
2490 OB += " noexcept";
2491 if (TypeConstraint) {
2492 OB += " -> ";
2493 TypeConstraint->print(OB);
2494 }
2495 OB += ';';
2496 }
2497};
2498
2499class TypeRequirement : public Node {
2500 const Node *Type;
2501public:
2502 TypeRequirement(const Node *Type_)
2503 : Node(KTypeRequirement), Type(Type_) {}
2504
2505 template <typename Fn> void match(Fn F) const { F(Type); }
2506
2507 void printLeft(OutputBuffer &OB) const override {
2508 OB += " typename ";
2509 Type->print(OB);
2510 OB += ';';
2511 }
2512};
2513
2514class NestedRequirement : public Node {
2515 const Node *Constraint;
2516public:
2517 NestedRequirement(const Node *Constraint_)
2518 : Node(KNestedRequirement), Constraint(Constraint_) {}
2519
2520 template <typename Fn> void match(Fn F) const { F(Constraint); }
2521
2522 void printLeft(OutputBuffer &OB) const override {
2523 OB += " requires ";
2524 Constraint->print(OB);
2525 OB += ';';
2526 }
2527};
2528
2312template <class Float> struct FloatData;2529template <class Float> struct FloatData;
23132530
2314namespace float_literal_impl {2531namespace float_literal_impl {
...@@ -2377,7 +2594,7 @@ void Node::visit(Fn F) const {...@@ -2377,7 +2594,7 @@ void Node::visit(Fn F) const {
2377 return F(static_cast<const X *>(this));2594 return F(static_cast<const X *>(this));
2378#include "ItaniumNodes.def"2595#include "ItaniumNodes.def"
2379 }2596 }
2380 assert(0 && "unknown mangling node kind");2597 DEMANGLE_ASSERT(0, "unknown mangling node kind");
2381}2598}
23822599
2383/// Determine the kind of a node from its type.2600/// Determine the kind of a node from its type.
...@@ -2403,6 +2620,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2403,6 +2620,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2403 // table.2620 // table.
2404 PODSmallVector<Node *, 32> Subs;2621 PODSmallVector<Node *, 32> Subs;
24052622
2623 // A list of template argument values corresponding to a template parameter
2624 // list.
2406 using TemplateParamList = PODSmallVector<Node *, 8>;2625 using TemplateParamList = PODSmallVector<Node *, 8>;
24072626
2408 class ScopedTemplateParamList {2627 class ScopedTemplateParamList {
...@@ -2417,9 +2636,11 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2417,9 +2636,11 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2417 Parser->TemplateParams.push_back(&Params);2636 Parser->TemplateParams.push_back(&Params);
2418 }2637 }
2419 ~ScopedTemplateParamList() {2638 ~ScopedTemplateParamList() {
2420 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);2639 DEMANGLE_ASSERT(Parser->TemplateParams.size() >= OldNumTemplateParamLists,
2421 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);2640 "");
2641 Parser->TemplateParams.shrinkToSize(OldNumTemplateParamLists);
2422 }2642 }
2643 TemplateParamList *params() { return &Params; }
2423 };2644 };
24242645
2425 // Template parameter table. Like the above, but referenced like "T42_".2646 // Template parameter table. Like the above, but referenced like "T42_".
...@@ -2434,12 +2655,31 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2434,12 +2655,31 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2434 // parameter list, the corresponding parameter list pointer will be null.2655 // parameter list, the corresponding parameter list pointer will be null.
2435 PODSmallVector<TemplateParamList *, 4> TemplateParams;2656 PODSmallVector<TemplateParamList *, 4> TemplateParams;
24362657
2658 class SaveTemplateParams {
2659 AbstractManglingParser *Parser;
2660 decltype(TemplateParams) OldParams;
2661 decltype(OuterTemplateParams) OldOuterParams;
2662
2663 public:
2664 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
2665 OldParams = std::move(Parser->TemplateParams);
2666 OldOuterParams = std::move(Parser->OuterTemplateParams);
2667 Parser->TemplateParams.clear();
2668 Parser->OuterTemplateParams.clear();
2669 }
2670 ~SaveTemplateParams() {
2671 Parser->TemplateParams = std::move(OldParams);
2672 Parser->OuterTemplateParams = std::move(OldOuterParams);
2673 }
2674 };
2675
2437 // Set of unresolved forward <template-param> references. These can occur in a2676 // Set of unresolved forward <template-param> references. These can occur in a
2438 // conversion operator's type, and are resolved in the enclosing <encoding>.2677 // conversion operator's type, and are resolved in the enclosing <encoding>.
2439 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;2678 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
24402679
2441 bool TryToParseTemplateArgs = true;2680 bool TryToParseTemplateArgs = true;
2442 bool PermitForwardTemplateReferences = false;2681 bool PermitForwardTemplateReferences = false;
2682 bool InConstraintExpr = false;
2443 size_t ParsingLambdaParamsAtLevel = (size_t)-1;2683 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
24442684
2445 unsigned NumSyntheticTemplateParameters[3] = {};2685 unsigned NumSyntheticTemplateParameters[3] = {};
...@@ -2478,10 +2718,10 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2478,10 +2718,10 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2478 }2718 }
24792719
2480 NodeArray popTrailingNodeArray(size_t FromPosition) {2720 NodeArray popTrailingNodeArray(size_t FromPosition) {
2481 assert(FromPosition <= Names.size());2721 DEMANGLE_ASSERT(FromPosition <= Names.size(), "");
2482 NodeArray res =2722 NodeArray res =
2483 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());2723 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2484 Names.dropBack(FromPosition);2724 Names.shrinkToSize(FromPosition);
2485 return res;2725 return res;
2486 }2726 }
24872727
...@@ -2519,11 +2759,16 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2519,11 +2759,16 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2519 bool parseSeqId(size_t *Out);2759 bool parseSeqId(size_t *Out);
2520 Node *parseSubstitution();2760 Node *parseSubstitution();
2521 Node *parseTemplateParam();2761 Node *parseTemplateParam();
2522 Node *parseTemplateParamDecl();2762 Node *parseTemplateParamDecl(TemplateParamList *Params);
2523 Node *parseTemplateArgs(bool TagTemplates = false);2763 Node *parseTemplateArgs(bool TagTemplates = false);
2524 Node *parseTemplateArg();2764 Node *parseTemplateArg();
25252765
2526 /// Parse the <expr> production.2766 bool isTemplateParamDecl() {
2767 return look() == 'T' &&
2768 std::string_view("yptnk").find(look(1)) != std::string_view::npos;
2769 }
2770
2771 /// Parse the <expression> production.
2527 Node *parseExpr();2772 Node *parseExpr();
2528 Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);2773 Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);
2529 Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);2774 Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);
...@@ -2536,6 +2781,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2536,6 +2781,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2536 Node *parseFoldExpr();2781 Node *parseFoldExpr();
2537 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);2782 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
2538 Node *parseSubobjectExpr();2783 Node *parseSubobjectExpr();
2784 Node *parseConstraintExpr();
2785 Node *parseRequiresExpr();
25392786
2540 /// Parse the <type> production.2787 /// Parse the <type> production.
2541 Node *parseType();2788 Node *parseType();
...@@ -2547,7 +2794,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2547,7 +2794,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2547 Node *parseClassEnumType();2794 Node *parseClassEnumType();
2548 Node *parseQualifiedType();2795 Node *parseQualifiedType();
25492796
2550 Node *parseEncoding();2797 Node *parseEncoding(bool ParseParams = true);
2551 bool parseCallOffset();2798 bool parseCallOffset();
2552 Node *parseSpecialName();2799 Node *parseSpecialName();
25532800
...@@ -2559,6 +2806,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2559,6 +2806,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2559 Qualifiers CVQualifiers = QualNone;2806 Qualifiers CVQualifiers = QualNone;
2560 FunctionRefQual ReferenceQualifier = FrefQualNone;2807 FunctionRefQual ReferenceQualifier = FrefQualNone;
2561 size_t ForwardTemplateRefsBegin;2808 size_t ForwardTemplateRefsBegin;
2809 bool HasExplicitObjectParameter = false;
25622810
2563 NameState(AbstractManglingParser *Enclosing)2811 NameState(AbstractManglingParser *Enclosing)
2564 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}2812 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
...@@ -2574,7 +2822,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2574,7 +2822,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2574 return true;2822 return true;
2575 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];2823 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
2576 }2824 }
2577 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);2825 ForwardTemplateRefs.shrinkToSize(State.ForwardTemplateRefsBegin);
2578 return false;2826 return false;
2579 }2827 }
25802828
...@@ -2638,8 +2886,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2638,8 +2886,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2638 std::string_view getSymbol() const {2886 std::string_view getSymbol() const {
2639 std::string_view Res = Name;2887 std::string_view Res = Name;
2640 if (Kind < Unnameable) {2888 if (Kind < Unnameable) {
2641 assert(starts_with(Res, "operator") &&2889 DEMANGLE_ASSERT(starts_with(Res, "operator"),
2642 "operator name does not start with 'operator'");2890 "operator name does not start with 'operator'");
2643 Res.remove_prefix(sizeof("operator") - 1);2891 Res.remove_prefix(sizeof("operator") - 1);
2644 if (starts_with(Res, ' '))2892 if (starts_with(Res, ' '))
2645 Res.remove_prefix(1);2893 Res.remove_prefix(1);
...@@ -2663,7 +2911,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {...@@ -2663,7 +2911,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
2663 Node *parseDestructorName();2911 Node *parseDestructorName();
26642912
2665 /// Top-level entry point into the parser.2913 /// Top-level entry point into the parser.
2666 Node *parse();2914 Node *parse(bool ParseParams = true);
2667};2915};
26682916
2669const char* parse_discriminator(const char* first, const char* last);2917const char* parse_discriminator(const char* first, const char* last);
...@@ -2727,6 +2975,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {...@@ -2727,6 +2975,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
2727 return make<LocalName>(Encoding, StringLitName);2975 return make<LocalName>(Encoding, StringLitName);
2728 }2976 }
27292977
2978 // The template parameters of the inner name are unrelated to those of the
2979 // enclosing context.
2980 SaveTemplateParams SaveTemplateParamsScope(this);
2981
2730 if (consumeIf('d')) {2982 if (consumeIf('d')) {
2731 parseNumber(true);2983 parseNumber(true);
2732 if (!consumeIf('_'))2984 if (!consumeIf('_'))
...@@ -2782,9 +3034,9 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,...@@ -2782,9 +3034,9 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
2782 return Res;3034 return Res;
2783}3035}
27843036
2785// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]3037// <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]
2786// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]3038// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2787// ::= [<module-name>] L? <source-name> [<abi-tags>]3039// ::= [<module-name>] F? L? <source-name> [<abi-tags>]
2788// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]3040// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
2789// # structured binding declaration3041// # structured binding declaration
2790// ::= [<module-name>] L? DC <source-name>+ E3042// ::= [<module-name>] L? DC <source-name>+ E
...@@ -2794,6 +3046,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(...@@ -2794,6 +3046,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2794 if (getDerived().parseModuleNameOpt(Module))3046 if (getDerived().parseModuleNameOpt(Module))
2795 return nullptr;3047 return nullptr;
27963048
3049 bool IsMemberLikeFriend = Scope && consumeIf('F');
3050
2797 consumeIf('L');3051 consumeIf('L');
27983052
2799 Node *Result;3053 Node *Result;
...@@ -2824,7 +3078,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(...@@ -2824,7 +3078,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
2824 Result = make<ModuleEntity>(Module, Result);3078 Result = make<ModuleEntity>(Module, Result);
2825 if (Result != nullptr)3079 if (Result != nullptr)
2826 Result = getDerived().parseAbiTags(Result);3080 Result = getDerived().parseAbiTags(Result);
2827 if (Result != nullptr && Scope != nullptr)3081 if (Result != nullptr && IsMemberLikeFriend)
3082 Result = make<MemberLikeFriendName>(Scope, Result);
3083 else if (Result != nullptr && Scope != nullptr)
2828 Result = make<NestedName>(Scope, Result);3084 Result = make<NestedName>(Scope, Result);
28293085
2830 return Result;3086 return Result;
...@@ -2856,7 +3112,8 @@ bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(...@@ -2856,7 +3112,8 @@ bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
2856//3112//
2857// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _3113// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
2858//3114//
2859// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters3115// <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]
3116// <parameter type>+ # or "v" if the lambda has no parameters
2860template <typename Derived, typename Alloc>3117template <typename Derived, typename Alloc>
2861Node *3118Node *
2862AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {3119AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
...@@ -2877,10 +3134,10 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {...@@ -2877,10 +3134,10 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2877 ScopedTemplateParamList LambdaTemplateParams(this);3134 ScopedTemplateParamList LambdaTemplateParams(this);
28783135
2879 size_t ParamsBegin = Names.size();3136 size_t ParamsBegin = Names.size();
2880 while (look() == 'T' &&3137 while (getDerived().isTemplateParamDecl()) {
2881 std::string_view("yptn").find(look(1)) != std::string_view::npos) {3138 Node *T =
2882 Node *T = parseTemplateParamDecl();3139 getDerived().parseTemplateParamDecl(LambdaTemplateParams.params());
2883 if (!T)3140 if (T == nullptr)
2884 return nullptr;3141 return nullptr;
2885 Names.push_back(T);3142 Names.push_back(T);
2886 }3143 }
...@@ -2911,20 +3168,38 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {...@@ -2911,20 +3168,38 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
2911 if (TempParams.empty())3168 if (TempParams.empty())
2912 TemplateParams.pop_back();3169 TemplateParams.pop_back();
29133170
2914 if (!consumeIf("vE")) {3171 Node *Requires1 = nullptr;
3172 if (consumeIf('Q')) {
3173 Requires1 = getDerived().parseConstraintExpr();
3174 if (Requires1 == nullptr)
3175 return nullptr;
3176 }
3177
3178 if (!consumeIf("v")) {
2915 do {3179 do {
2916 Node *P = getDerived().parseType();3180 Node *P = getDerived().parseType();
2917 if (P == nullptr)3181 if (P == nullptr)
2918 return nullptr;3182 return nullptr;
2919 Names.push_back(P);3183 Names.push_back(P);
2920 } while (!consumeIf('E'));3184 } while (look() != 'E' && look() != 'Q');
2921 }3185 }
2922 NodeArray Params = popTrailingNodeArray(ParamsBegin);3186 NodeArray Params = popTrailingNodeArray(ParamsBegin);
29233187
3188 Node *Requires2 = nullptr;
3189 if (consumeIf('Q')) {
3190 Requires2 = getDerived().parseConstraintExpr();
3191 if (Requires2 == nullptr)
3192 return nullptr;
3193 }
3194
3195 if (!consumeIf('E'))
3196 return nullptr;
3197
2924 std::string_view Count = parseNumber();3198 std::string_view Count = parseNumber();
2925 if (!consumeIf('_'))3199 if (!consumeIf('_'))
2926 return nullptr;3200 return nullptr;
2927 return make<ClosureTypeName>(TempParams, Params, Count);3201 return make<ClosureTypeName>(TempParams, Requires1, Params, Requires2,
3202 Count);
2928 }3203 }
2929 if (consumeIf("Ub")) {3204 if (consumeIf("Ub")) {
2930 (void)parseNumber();3205 (void)parseNumber();
...@@ -3190,15 +3465,25 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {...@@ -3190,15 +3465,25 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
3190 if (!consumeIf('N'))3465 if (!consumeIf('N'))
3191 return nullptr;3466 return nullptr;
31923467
3193 Qualifiers CVTmp = parseCVQualifiers();3468 // 'H' specifies that the encoding that follows
3194 if (State) State->CVQualifiers = CVTmp;3469 // has an explicit object parameter.
3470 if (!consumeIf('H')) {
3471 Qualifiers CVTmp = parseCVQualifiers();
3472 if (State)
3473 State->CVQualifiers = CVTmp;
31953474
3196 if (consumeIf('O')) {3475 if (consumeIf('O')) {
3197 if (State) State->ReferenceQualifier = FrefQualRValue;3476 if (State)
3198 } else if (consumeIf('R')) {3477 State->ReferenceQualifier = FrefQualRValue;
3199 if (State) State->ReferenceQualifier = FrefQualLValue;3478 } else if (consumeIf('R')) {
3200 } else {3479 if (State)
3201 if (State) State->ReferenceQualifier = FrefQualNone;3480 State->ReferenceQualifier = FrefQualLValue;
3481 } else {
3482 if (State)
3483 State->ReferenceQualifier = FrefQualNone;
3484 }
3485 } else if (State) {
3486 State->HasExplicitObjectParameter = true;
3202 }3487 }
32033488
3204 Node *SoFar = nullptr;3489 Node *SoFar = nullptr;
...@@ -3446,7 +3731,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {...@@ -3446,7 +3731,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
3446 }3731 }
3447 }3732 }
34483733
3449 assert(SoFar != nullptr);3734 DEMANGLE_ASSERT(SoFar != nullptr, "");
34503735
3451 Node *Base = getDerived().parseBaseUnresolvedName();3736 Node *Base = getDerived().parseBaseUnresolvedName();
3452 if (Base == nullptr)3737 if (Base == nullptr)
...@@ -3894,7 +4179,15 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -3894,7 +4179,15 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
3894 // Typically, <builtin-type>s are not considered substitution candidates,4179 // Typically, <builtin-type>s are not considered substitution candidates,
3895 // but the exception to that exception is vendor extended types (Itanium C++4180 // but the exception to that exception is vendor extended types (Itanium C++
3896 // ABI 5.9.1).4181 // ABI 5.9.1).
3897 Result = make<NameType>(Res);4182 if (consumeIf('I')) {
4183 Node *BaseType = parseType();
4184 if (BaseType == nullptr)
4185 return nullptr;
4186 if (!consumeIf('E'))
4187 return nullptr;
4188 Result = make<TransformedType>(Res, BaseType);
4189 } else
4190 Result = make<NameType>(Res);
3898 break;4191 break;
3899 }4192 }
3900 case 'D':4193 case 'D':
...@@ -3961,6 +4254,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {...@@ -3961,6 +4254,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
3961 case 'c':4254 case 'c':
3962 First += 2;4255 First += 2;
3963 return make<NameType>("decltype(auto)");4256 return make<NameType>("decltype(auto)");
4257 // ::= Dk <type-constraint> # constrained auto
4258 // ::= DK <type-constraint> # constrained decltype(auto)
4259 case 'k':
4260 case 'K': {
4261 std::string_view Kind = look(1) == 'k' ? " auto" : " decltype(auto)";
4262 First += 2;
4263 Node *Constraint = getDerived().parseName();
4264 if (!Constraint)
4265 return nullptr;
4266 return make<PostfixQualifiedType>(Constraint, Kind);
4267 }
3964 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))4268 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
3965 case 'n':4269 case 'n':
3966 First += 2;4270 First += 2;
...@@ -4512,6 +4816,75 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {...@@ -4512,6 +4816,75 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
4512 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);4816 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
4513}4817}
45144818
4819template <typename Derived, typename Alloc>
4820Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {
4821 // Within this expression, all enclosing template parameter lists are in
4822 // scope.
4823 ScopedOverride<bool> SaveInConstraintExpr(InConstraintExpr, true);
4824 return getDerived().parseExpr();
4825}
4826
4827template <typename Derived, typename Alloc>
4828Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() {
4829 NodeArray Params;
4830 if (consumeIf("rQ")) {
4831 // <expression> ::= rQ <bare-function-type> _ <requirement>+ E
4832 size_t ParamsBegin = Names.size();
4833 while (!consumeIf('_')) {
4834 Node *Type = getDerived().parseType();
4835 if (Type == nullptr)
4836 return nullptr;
4837 Names.push_back(Type);
4838 }
4839 Params = popTrailingNodeArray(ParamsBegin);
4840 } else if (!consumeIf("rq")) {
4841 // <expression> ::= rq <requirement>+ E
4842 return nullptr;
4843 }
4844
4845 size_t ReqsBegin = Names.size();
4846 do {
4847 Node *Constraint = nullptr;
4848 if (consumeIf('X')) {
4849 // <requirement> ::= X <expression> [N] [R <type-constraint>]
4850 Node *Expr = getDerived().parseExpr();
4851 if (Expr == nullptr)
4852 return nullptr;
4853 bool Noexcept = consumeIf('N');
4854 Node *TypeReq = nullptr;
4855 if (consumeIf('R')) {
4856 TypeReq = getDerived().parseName();
4857 if (TypeReq == nullptr)
4858 return nullptr;
4859 }
4860 Constraint = make<ExprRequirement>(Expr, Noexcept, TypeReq);
4861 } else if (consumeIf('T')) {
4862 // <requirement> ::= T <type>
4863 Node *Type = getDerived().parseType();
4864 if (Type == nullptr)
4865 return nullptr;
4866 Constraint = make<TypeRequirement>(Type);
4867 } else if (consumeIf('Q')) {
4868 // <requirement> ::= Q <constraint-expression>
4869 //
4870 // FIXME: We use <expression> instead of <constraint-expression>. Either
4871 // the requires expression is already inside a constraint expression, in
4872 // which case it makes no difference, or we're in a requires-expression
4873 // that might be partially-substituted, where the language behavior is
4874 // not yet settled and clang mangles after substitution.
4875 Node *NestedReq = getDerived().parseExpr();
4876 if (NestedReq == nullptr)
4877 return nullptr;
4878 Constraint = make<NestedRequirement>(NestedReq);
4879 }
4880 if (Constraint == nullptr)
4881 return nullptr;
4882 Names.push_back(Constraint);
4883 } while (!consumeIf('E'));
4884
4885 return make<RequiresExpr>(Params, popTrailingNodeArray(ReqsBegin));
4886}
4887
4515// <expression> ::= <unary operator-name> <expression>4888// <expression> ::= <unary operator-name> <expression>
4516// ::= <binary operator-name> <expression> <expression>4889// ::= <binary operator-name> <expression> <expression>
4517// ::= <ternary operator-name> <expression> <expression> <expression>4890// ::= <ternary operator-name> <expression> <expression> <expression>
...@@ -4748,6 +5121,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {...@@ -4748,6 +5121,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
4748 return Ex;5121 return Ex;
4749 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);5122 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
4750 }5123 }
5124 if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))
5125 return parseRequiresExpr();
4751 if (consumeIf("so"))5126 if (consumeIf("so"))
4752 return parseSubobjectExpr();5127 return parseSubobjectExpr();
4753 if (consumeIf("sp")) {5128 if (consumeIf("sp")) {
...@@ -5026,29 +5401,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {...@@ -5026,29 +5401,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
5026}5401}
50275402
5028// <encoding> ::= <function name> <bare-function-type>5403// <encoding> ::= <function name> <bare-function-type>
5404// [`Q` <requires-clause expr>]
5029// ::= <data name>5405// ::= <data name>
5030// ::= <special-name>5406// ::= <special-name>
5031template <typename Derived, typename Alloc>5407template <typename Derived, typename Alloc>
5032Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {5408Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {
5033 // The template parameters of an encoding are unrelated to those of the5409 // The template parameters of an encoding are unrelated to those of the
5034 // enclosing context.5410 // enclosing context.
5035 class SaveTemplateParams {5411 SaveTemplateParams SaveTemplateParamsScope(this);
5036 AbstractManglingParser *Parser;
5037 decltype(TemplateParams) OldParams;
5038 decltype(OuterTemplateParams) OldOuterParams;
5039
5040 public:
5041 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {
5042 OldParams = std::move(Parser->TemplateParams);
5043 OldOuterParams = std::move(Parser->OuterTemplateParams);
5044 Parser->TemplateParams.clear();
5045 Parser->OuterTemplateParams.clear();
5046 }
5047 ~SaveTemplateParams() {
5048 Parser->TemplateParams = std::move(OldParams);
5049 Parser->OuterTemplateParams = std::move(OldOuterParams);
5050 }
5051 } SaveTemplateParams(this);
50525412
5053 if (look() == 'G' || look() == 'T')5413 if (look() == 'G' || look() == 'T')
5054 return getDerived().parseSpecialName();5414 return getDerived().parseSpecialName();
...@@ -5071,6 +5431,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {...@@ -5071,6 +5431,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
5071 if (IsEndOfEncoding())5431 if (IsEndOfEncoding())
5072 return Name;5432 return Name;
50735433
5434 // ParseParams may be false at the top level only, when called from parse().
5435 // For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be
5436 // false when demangling 3fooILZ3BarEET_f but is always true when demangling
5437 // 3Bar.
5438 if (!ParseParams) {
5439 while (consume())
5440 ;
5441 return Name;
5442 }
5443
5074 Node *Attrs = nullptr;5444 Node *Attrs = nullptr;
5075 if (consumeIf("Ua9enable_ifI")) {5445 if (consumeIf("Ua9enable_ifI")) {
5076 size_t BeforeArgs = Names.size();5446 size_t BeforeArgs = Names.size();
...@@ -5092,22 +5462,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {...@@ -5092,22 +5462,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
5092 return nullptr;5462 return nullptr;
5093 }5463 }
50945464
5095 if (consumeIf('v'))5465 NodeArray Params;
5096 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),5466 if (!consumeIf('v')) {
5097 Attrs, NameInfo.CVQualifiers,5467 size_t ParamsBegin = Names.size();
5098 NameInfo.ReferenceQualifier);5468 do {
5469 Node *Ty = getDerived().parseType();
5470 if (Ty == nullptr)
5471 return nullptr;
50995472
5100 size_t ParamsBegin = Names.size();5473 const bool IsFirstParam = ParamsBegin == Names.size();
5101 do {5474 if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
5102 Node *Ty = getDerived().parseType();5475 Ty = make<ExplicitObjectParameter>(Ty);
5103 if (Ty == nullptr)5476
5477 if (Ty == nullptr)
5478 return nullptr;
5479
5480 Names.push_back(Ty);
5481 } while (!IsEndOfEncoding() && look() != 'Q');
5482 Params = popTrailingNodeArray(ParamsBegin);
5483 }
5484
5485 Node *Requires = nullptr;
5486 if (consumeIf('Q')) {
5487 Requires = getDerived().parseConstraintExpr();
5488 if (!Requires)
5104 return nullptr;5489 return nullptr;
5105 Names.push_back(Ty);5490 }
5106 } while (!IsEndOfEncoding());
51075491
5108 return make<FunctionEncoding>(ReturnType, Name,5492 return make<FunctionEncoding>(ReturnType, Name, Params, Attrs, Requires,
5109 popTrailingNodeArray(ParamsBegin),5493 NameInfo.CVQualifiers,
5110 Attrs, NameInfo.CVQualifiers,
5111 NameInfo.ReferenceQualifier);5494 NameInfo.ReferenceQualifier);
5112}5495}
51135496
...@@ -5134,7 +5517,8 @@ template <>...@@ -5134,7 +5517,8 @@ template <>
5134struct FloatData<long double>5517struct FloatData<long double>
5135{5518{
5136#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \5519#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \
5137 defined(__wasm__) || defined(__riscv) || defined(__loongarch__)5520 defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \
5521 defined(__ve__)
5138 static const size_t mangled_size = 32;5522 static const size_t mangled_size = 32;
5139#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)5523#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
5140 static const size_t mangled_size = 16;5524 static const size_t mangled_size = 16;
...@@ -5268,6 +5652,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {...@@ -5268,6 +5652,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
5268// ::= TL <level-1> _ <parameter-2 non-negative number> _5652// ::= TL <level-1> _ <parameter-2 non-negative number> _
5269template <typename Derived, typename Alloc>5653template <typename Derived, typename Alloc>
5270Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {5654Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
5655 const char *Begin = First;
5271 if (!consumeIf('T'))5656 if (!consumeIf('T'))
5272 return nullptr;5657 return nullptr;
52735658
...@@ -5289,6 +5674,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {...@@ -5289,6 +5674,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
5289 return nullptr;5674 return nullptr;
5290 }5675 }
52915676
5677 // We don't track enclosing template parameter levels well enough to reliably
5678 // substitute them all within a <constraint-expression>, so print the
5679 // parameter numbering instead for now.
5680 // TODO: Track all enclosing template parameters and substitute them here.
5681 if (InConstraintExpr) {
5682 return make<NameType>(std::string_view(Begin, First - 1 - Begin));
5683 }
5684
5292 // If we're in a context where this <template-param> refers to a5685 // If we're in a context where this <template-param> refers to a
5293 // <template-arg> further ahead in the mangled name (currently just conversion5686 // <template-arg> further ahead in the mangled name (currently just conversion
5294 // operator types), then we should only look it up in the right context.5687 // operator types), then we should only look it up in the right context.
...@@ -5297,7 +5690,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {...@@ -5297,7 +5690,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
5297 Node *ForwardRef = make<ForwardTemplateReference>(Index);5690 Node *ForwardRef = make<ForwardTemplateReference>(Index);
5298 if (!ForwardRef)5691 if (!ForwardRef)
5299 return nullptr;5692 return nullptr;
5300 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);5693 DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference,
5694 "");
5301 ForwardTemplateRefs.push_back(5695 ForwardTemplateRefs.push_back(
5302 static_cast<ForwardTemplateReference *>(ForwardRef));5696 static_cast<ForwardTemplateReference *>(ForwardRef));
5303 return ForwardRef;5697 return ForwardRef;
...@@ -5326,11 +5720,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {...@@ -5326,11 +5720,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
5326// ::= Tt <template-param-decl>* E # template parameter5720// ::= Tt <template-param-decl>* E # template parameter
5327// ::= Tp <template-param-decl> # parameter pack5721// ::= Tp <template-param-decl> # parameter pack
5328template <typename Derived, typename Alloc>5722template <typename Derived, typename Alloc>
5329Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {5723Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(
5724 TemplateParamList *Params) {
5330 auto InventTemplateParamName = [&](TemplateParamKind Kind) {5725 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
5331 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;5726 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
5332 Node *N = make<SyntheticTemplateParamName>(Kind, Index);5727 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5333 if (N) TemplateParams.back()->push_back(N);5728 if (N && Params)
5729 Params->push_back(N);
5334 return N;5730 return N;
5335 };5731 };
53365732
...@@ -5341,6 +5737,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {...@@ -5341,6 +5737,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5341 return make<TypeTemplateParamDecl>(Name);5737 return make<TypeTemplateParamDecl>(Name);
5342 }5738 }
53435739
5740 if (consumeIf("Tk")) {
5741 Node *Constraint = getDerived().parseName();
5742 if (!Constraint)
5743 return nullptr;
5744 Node *Name = InventTemplateParamName(TemplateParamKind::Type);
5745 if (!Name)
5746 return nullptr;
5747 return make<ConstrainedTypeTemplateParamDecl>(Constraint, Name);
5748 }
5749
5344 if (consumeIf("Tn")) {5750 if (consumeIf("Tn")) {
5345 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);5751 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
5346 if (!Name)5752 if (!Name)
...@@ -5357,18 +5763,25 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {...@@ -5357,18 +5763,25 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5357 return nullptr;5763 return nullptr;
5358 size_t ParamsBegin = Names.size();5764 size_t ParamsBegin = Names.size();
5359 ScopedTemplateParamList TemplateTemplateParamParams(this);5765 ScopedTemplateParamList TemplateTemplateParamParams(this);
5360 while (!consumeIf("E")) {5766 Node *Requires = nullptr;
5361 Node *P = parseTemplateParamDecl();5767 while (!consumeIf('E')) {
5768 Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params());
5362 if (!P)5769 if (!P)
5363 return nullptr;5770 return nullptr;
5364 Names.push_back(P);5771 Names.push_back(P);
5772 if (consumeIf('Q')) {
5773 Requires = getDerived().parseConstraintExpr();
5774 if (Requires == nullptr || !consumeIf('E'))
5775 return nullptr;
5776 break;
5777 }
5365 }5778 }
5366 NodeArray Params = popTrailingNodeArray(ParamsBegin);5779 NodeArray InnerParams = popTrailingNodeArray(ParamsBegin);
5367 return make<TemplateTemplateParamDecl>(Name, Params);5780 return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);
5368 }5781 }
53695782
5370 if (consumeIf("Tp")) {5783 if (consumeIf("Tp")) {
5371 Node *P = parseTemplateParamDecl();5784 Node *P = parseTemplateParamDecl(Params);
5372 if (!P)5785 if (!P)
5373 return nullptr;5786 return nullptr;
5374 return make<TemplateParamPackDecl>(P);5787 return make<TemplateParamPackDecl>(P);
...@@ -5382,6 +5795,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {...@@ -5382,6 +5795,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5382// ::= <expr-primary> # simple expressions5795// ::= <expr-primary> # simple expressions
5383// ::= J <template-arg>* E # argument pack5796// ::= J <template-arg>* E # argument pack
5384// ::= LZ <encoding> E # extension5797// ::= LZ <encoding> E # extension
5798// ::= <template-param-decl> <template-arg>
5385template <typename Derived, typename Alloc>5799template <typename Derived, typename Alloc>
5386Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {5800Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
5387 switch (look()) {5801 switch (look()) {
...@@ -5416,6 +5830,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {...@@ -5416,6 +5830,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
5416 // ::= <expr-primary> # simple expressions5830 // ::= <expr-primary> # simple expressions
5417 return getDerived().parseExprPrimary();5831 return getDerived().parseExprPrimary();
5418 }5832 }
5833 case 'T': {
5834 // Either <template-param> or a <template-param-decl> <template-arg>.
5835 if (!getDerived().isTemplateParamDecl())
5836 return getDerived().parseType();
5837 Node *Param = getDerived().parseTemplateParamDecl(nullptr);
5838 if (!Param)
5839 return nullptr;
5840 Node *Arg = getDerived().parseTemplateArg();
5841 if (!Arg)
5842 return nullptr;
5843 return make<TemplateParamQualifiedArg>(Param, Arg);
5844 }
5419 default:5845 default:
5420 return getDerived().parseType();5846 return getDerived().parseType();
5421 }5847 }
...@@ -5438,30 +5864,39 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {...@@ -5438,30 +5864,39 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
5438 }5864 }
54395865
5440 size_t ArgsBegin = Names.size();5866 size_t ArgsBegin = Names.size();
5867 Node *Requires = nullptr;
5441 while (!consumeIf('E')) {5868 while (!consumeIf('E')) {
5442 if (TagTemplates) {5869 if (TagTemplates) {
5443 auto OldParams = std::move(TemplateParams);
5444 Node *Arg = getDerived().parseTemplateArg();5870 Node *Arg = getDerived().parseTemplateArg();
5445 TemplateParams = std::move(OldParams);
5446 if (Arg == nullptr)5871 if (Arg == nullptr)
5447 return nullptr;5872 return nullptr;
5448 Names.push_back(Arg);5873 Names.push_back(Arg);
5449 Node *TableEntry = Arg;5874 Node *TableEntry = Arg;
5875 if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {
5876 TableEntry =
5877 static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();
5878 }
5450 if (Arg->getKind() == Node::KTemplateArgumentPack) {5879 if (Arg->getKind() == Node::KTemplateArgumentPack) {
5451 TableEntry = make<ParameterPack>(5880 TableEntry = make<ParameterPack>(
5452 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());5881 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
5453 if (!TableEntry)5882 if (!TableEntry)
5454 return nullptr;5883 return nullptr;
5455 }5884 }
5456 TemplateParams.back()->push_back(TableEntry);5885 OuterTemplateParams.push_back(TableEntry);
5457 } else {5886 } else {
5458 Node *Arg = getDerived().parseTemplateArg();5887 Node *Arg = getDerived().parseTemplateArg();
5459 if (Arg == nullptr)5888 if (Arg == nullptr)
5460 return nullptr;5889 return nullptr;
5461 Names.push_back(Arg);5890 Names.push_back(Arg);
5462 }5891 }
5892 if (consumeIf('Q')) {
5893 Requires = getDerived().parseConstraintExpr();
5894 if (!Requires || !consumeIf('E'))
5895 return nullptr;
5896 break;
5897 }
5463 }5898 }
5464 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));5899 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin), Requires);
5465}5900}
54665901
5467// <mangled-name> ::= _Z <encoding>5902// <mangled-name> ::= _Z <encoding>
...@@ -5470,9 +5905,9 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {...@@ -5470,9 +5905,9 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
5470// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+5905// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
5471// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+5906// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
5472template <typename Derived, typename Alloc>5907template <typename Derived, typename Alloc>
5473Node *AbstractManglingParser<Derived, Alloc>::parse() {5908Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
5474 if (consumeIf("_Z") || consumeIf("__Z")) {5909 if (consumeIf("_Z") || consumeIf("__Z")) {
5475 Node *Encoding = getDerived().parseEncoding();5910 Node *Encoding = getDerived().parseEncoding(ParseParams);
5476 if (Encoding == nullptr)5911 if (Encoding == nullptr)
5477 return nullptr;5912 return nullptr;
5478 if (look() == '.') {5913 if (look() == '.') {
...@@ -5486,7 +5921,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {...@@ -5486,7 +5921,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {
5486 }5921 }
54875922
5488 if (consumeIf("___Z") || consumeIf("____Z")) {5923 if (consumeIf("___Z") || consumeIf("____Z")) {
5489 Node *Encoding = getDerived().parseEncoding();5924 Node *Encoding = getDerived().parseEncoding(ParseParams);
5490 if (Encoding == nullptr || !consumeIf("_block_invoke"))5925 if (Encoding == nullptr || !consumeIf("_block_invoke"))
5491 return nullptr;5926 return nullptr;
5492 bool RequireNumber = consumeIf('_');5927 bool RequireNumber = consumeIf('_');
lib/libcxxabi/src/demangle/ItaniumNodes.def+9
...@@ -19,6 +19,7 @@ NODE(QualType)...@@ -19,6 +19,7 @@ NODE(QualType)
19NODE(ConversionOperatorType)19NODE(ConversionOperatorType)
20NODE(PostfixQualifiedType)20NODE(PostfixQualifiedType)
21NODE(ElaboratedTypeSpefType)21NODE(ElaboratedTypeSpefType)
22NODE(TransformedType)
22NODE(NameType)23NODE(NameType)
23NODE(AbiTagAttr)24NODE(AbiTagAttr)
24NODE(EnableIfAttr)25NODE(EnableIfAttr)
...@@ -36,6 +37,7 @@ NODE(SpecialName)...@@ -36,6 +37,7 @@ NODE(SpecialName)
36NODE(CtorVtableSpecialName)37NODE(CtorVtableSpecialName)
37NODE(QualifiedName)38NODE(QualifiedName)
38NODE(NestedName)39NODE(NestedName)
40NODE(MemberLikeFriendName)
39NODE(LocalName)41NODE(LocalName)
40NODE(ModuleName)42NODE(ModuleName)
41NODE(ModuleEntity)43NODE(ModuleEntity)
...@@ -44,7 +46,9 @@ NODE(PixelVectorType)...@@ -44,7 +46,9 @@ NODE(PixelVectorType)
44NODE(BinaryFPType)46NODE(BinaryFPType)
45NODE(BitIntType)47NODE(BitIntType)
46NODE(SyntheticTemplateParamName)48NODE(SyntheticTemplateParamName)
49NODE(TemplateParamQualifiedArg)
47NODE(TypeTemplateParamDecl)50NODE(TypeTemplateParamDecl)
51NODE(ConstrainedTypeTemplateParamDecl)
48NODE(NonTypeTemplateParamDecl)52NODE(NonTypeTemplateParamDecl)
49NODE(TemplateTemplateParamDecl)53NODE(TemplateTemplateParamDecl)
50NODE(TemplateParamPackDecl)54NODE(TemplateParamPackDecl)
...@@ -91,5 +95,10 @@ NODE(DoubleLiteral)...@@ -91,5 +95,10 @@ NODE(DoubleLiteral)
91NODE(LongDoubleLiteral)95NODE(LongDoubleLiteral)
92NODE(BracedExpr)96NODE(BracedExpr)
93NODE(BracedRangeExpr)97NODE(BracedRangeExpr)
98NODE(RequiresExpr)
99NODE(ExprRequirement)
100NODE(TypeRequirement)
101NODE(NestedRequirement)
102NODE(ExplicitObjectParameter)
94103
95#undef NODE104#undef NODE
lib/libcxxabi/src/demangle/Utility.h+3-5
...@@ -19,11 +19,9 @@...@@ -19,11 +19,9 @@
19#include "DemangleConfig.h"19#include "DemangleConfig.h"
2020
21#include <array>21#include <array>
22#include <cassert>
23#include <cstdint>22#include <cstdint>
24#include <cstdlib>23#include <cstdlib>
25#include <cstring>24#include <cstring>
26#include <exception>
27#include <limits>25#include <limits>
28#include <string_view>26#include <string_view>
2927
...@@ -49,7 +47,7 @@ class OutputBuffer {...@@ -49,7 +47,7 @@ class OutputBuffer {
49 BufferCapacity = Need;47 BufferCapacity = Need;
50 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));48 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
51 if (Buffer == nullptr)49 if (Buffer == nullptr)
52 std::terminate();50 std::abort();
53 }51 }
54 }52 }
5553
...@@ -160,7 +158,7 @@ public:...@@ -160,7 +158,7 @@ public:
160 }158 }
161159
162 void insert(size_t Pos, const char *S, size_t N) {160 void insert(size_t Pos, const char *S, size_t N) {
163 assert(Pos <= CurrentPosition);161 DEMANGLE_ASSERT(Pos <= CurrentPosition, "");
164 if (N == 0)162 if (N == 0)
165 return;163 return;
166 grow(N);164 grow(N);
...@@ -173,7 +171,7 @@ public:...@@ -173,7 +171,7 @@ public:
173 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }171 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
174172
175 char back() const {173 char back() const {
176 assert(CurrentPosition);174 DEMANGLE_ASSERT(CurrentPosition, "");
177 return Buffer[CurrentPosition - 1];175 return Buffer[CurrentPosition - 1];
178 }176 }
179177
lib/libcxxabi/src/fallback_malloc.cpp+5-4
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
88
9#include "fallback_malloc.h"9#include "fallback_malloc.h"
10#include "abort_message.h"
1011
11#include <__threading_support>12#include <__threading_support>
12#ifndef _LIBCXXABI_HAS_NO_THREADS13#ifndef _LIBCXXABI_HAS_NO_THREADS
...@@ -16,7 +17,7 @@...@@ -16,7 +17,7 @@
16#endif17#endif
1718
18#include <__memory/aligned_alloc.h>19#include <__memory/aligned_alloc.h>
19#include <assert.h>20#include <__assert>
20#include <stdlib.h> // for malloc, calloc, free21#include <stdlib.h> // for malloc, calloc, free
21#include <string.h> // for memset22#include <string.h> // for memset
2223
...@@ -142,7 +143,7 @@ void* fallback_malloc(size_t len) {...@@ -142,7 +143,7 @@ void* fallback_malloc(size_t len) {
142143
143 // Check the invariant that all heap_nodes pointers 'p' are aligned144 // Check the invariant that all heap_nodes pointers 'p' are aligned
144 // so that 'p + 1' has an alignment of at least RequiredAlignment145 // so that 'p + 1' has an alignment of at least RequiredAlignment
145 assert(reinterpret_cast<size_t>(p + 1) % RequiredAlignment == 0);146 _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(p + 1) % RequiredAlignment == 0, "");
146147
147 // Calculate the number of extra padding elements needed in order148 // Calculate the number of extra padding elements needed in order
148 // to split 'p' and create a properly aligned heap_node from the tail149 // to split 'p' and create a properly aligned heap_node from the tail
...@@ -163,7 +164,7 @@ void* fallback_malloc(size_t len) {...@@ -163,7 +164,7 @@ void* fallback_malloc(size_t len) {
163 q->next_node = 0;164 q->next_node = 0;
164 q->len = static_cast<heap_size>(aligned_nelems);165 q->len = static_cast<heap_size>(aligned_nelems);
165 void* ptr = q + 1;166 void* ptr = q + 1;
166 assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);167 _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0, "");
167 return ptr;168 return ptr;
168 }169 }
169170
...@@ -176,7 +177,7 @@ void* fallback_malloc(size_t len) {...@@ -176,7 +177,7 @@ void* fallback_malloc(size_t len) {
176 prev->next_node = p->next_node;177 prev->next_node = p->next_node;
177 p->next_node = 0;178 p->next_node = 0;
178 void* ptr = p + 1;179 void* ptr = p + 1;
179 assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);180 _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0, "");
180 return ptr;181 return ptr;
181 }182 }
182 }183 }
lib/libcxxabi/src/private_typeinfo.cpp+333-187
...@@ -42,6 +42,7 @@...@@ -42,6 +42,7 @@
42// is_equal() with use_strcmp=false so the string names are not compared.42// is_equal() with use_strcmp=false so the string names are not compared.
4343
44#include <cstdint>44#include <cstdint>
45#include <cassert>
45#include <string.h>46#include <string.h>
4647
47#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST48#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
...@@ -75,6 +76,242 @@ static inline ptrdiff_t update_offset_to_base(const char* vtable,...@@ -75,6 +76,242 @@ static inline ptrdiff_t update_offset_to_base(const char* vtable,
75namespace __cxxabiv176namespace __cxxabiv1
76{77{
7778
79namespace {
80
81struct derived_object_info {
82 const void* dynamic_ptr;
83 const __class_type_info* dynamic_type;
84 std::ptrdiff_t offset_to_derived;
85};
86
87/// A helper function that gets (dynamic_ptr, dynamic_type, offset_to_derived) from static_ptr.
88void dyn_cast_get_derived_info(derived_object_info* info, const void* static_ptr)
89{
90#if __has_feature(cxx_abi_relative_vtable)
91 // The vtable address will point to the first virtual function, which is 8
92 // bytes after the start of the vtable (4 for the offset from top + 4 for
93 // the typeinfo component).
94 const int32_t* vtable =
95 *reinterpret_cast<const int32_t* const*>(static_ptr);
96 info->offset_to_derived = static_cast<std::ptrdiff_t>(vtable[-2]);
97 info->dynamic_ptr = static_cast<const char*>(static_ptr) + info->offset_to_derived;
98
99 // The typeinfo component is now a relative offset to a proxy.
100 int32_t offset_to_ti_proxy = vtable[-1];
101 const uint8_t* ptr_to_ti_proxy =
102 reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
103 info->dynamic_type = *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
104#else
105 void **vtable = *static_cast<void ** const *>(static_ptr);
106 info->offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
107 info->dynamic_ptr = static_cast<const char*>(static_ptr) + info->offset_to_derived;
108 info->dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
109#endif
110}
111
112/// A helper function for __dynamic_cast that casts a base sub-object pointer
113/// to the object's dynamic type.
114///
115/// This function returns the casting result directly. No further processing
116/// required.
117///
118/// Specifically, this function can only be called if the following pre-
119/// condition holds:
120/// * The dynamic type of the object pointed to by `static_ptr` is exactly
121/// the same as `dst_type`.
122const void* dyn_cast_to_derived(const void* static_ptr,
123 const void* dynamic_ptr,
124 const __class_type_info* static_type,
125 const __class_type_info* dst_type,
126 std::ptrdiff_t offset_to_derived,
127 std::ptrdiff_t src2dst_offset)
128{
129 // We're downcasting from src_type to the complete object's dynamic type.
130 // This is a really hot path that can be further optimized with the
131 // `src2dst_offset` hint.
132 // In such a case, dynamic_ptr already gives the casting result if the
133 // casting ever succeeds. All we have to do now is to check static_ptr
134 // points to a public base sub-object of dynamic_ptr.
135
136 if (src2dst_offset >= 0)
137 {
138 // The static type is a unique public non-virtual base type of
139 // dst_type at offset `src2dst_offset` from the origin of dst.
140 // Note that there might be other non-public static_type bases. The
141 // hint only guarantees that the public base is non-virtual and
142 // unique. So we have to check whether static_ptr points to that
143 // unique public base sub-object.
144 if (offset_to_derived != -src2dst_offset)
145 return nullptr;
146 return dynamic_ptr;
147 }
148
149 if (src2dst_offset == -2)
150 {
151 // static_type is not a public base of dst_type.
152 return nullptr;
153 }
154
155 // If src2dst_offset == -3, then:
156 // src_type is a multiple public base type but never a virtual
157 // base type. We can't conclude that static_ptr points to those
158 // public base sub-objects because there might be other non-
159 // public static_type bases. The search is inevitable.
160
161 // Fallback to the slow path to check that static_type is a public
162 // base type of dynamic_type.
163 // Using giant short cut. Add that information to info.
164 __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0, 0, 0,
165 1, // number_of_dst_type
166 false, false, false, true, nullptr};
167 // Do the search
168 dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
169#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
170 // The following if should always be false because we should
171 // definitely find (static_ptr, static_type), either on a public
172 // or private path
173 if (info.path_dst_ptr_to_static_ptr == unknown)
174 {
175 // We get here only if there is some kind of visibility problem
176 // in client code.
177 static_assert(std::atomic<size_t>::is_always_lock_free, "");
178 static std::atomic<size_t> error_count(0);
179 size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
180 if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
181 syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
182 "should have public visibility. At least one of them is hidden. %s"
183 ", %s.\n", static_type->name(), dst_type->name());
184 // Redo the search comparing type_info's using strcmp
185 info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
186 0, 0, 0, false, false, false, true, nullptr};
187 info.number_of_dst_type = 1;
188 dst_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
189 }
190#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
191 // Query the search.
192 if (info.path_dst_ptr_to_static_ptr != public_path)
193 return nullptr;
194
195 return dynamic_ptr;
196}
197
198/// A helper function for __dynamic_cast that tries to perform a downcast
199/// before giving up and falling back to the slow path.
200const void* dyn_cast_try_downcast(const void* static_ptr,
201 const void* dynamic_ptr,
202 const __class_type_info* dst_type,
203 const __class_type_info* dynamic_type,
204 std::ptrdiff_t src2dst_offset)
205{
206 if (src2dst_offset < 0)
207 {
208 // We can only optimize the case if the static type is a unique public
209 // base of dst_type. Give up.
210 return nullptr;
211 }
212
213 // Pretend there is a dst_type object that leads to static_ptr. Later we
214 // will check whether this imagined dst_type object exists. If it exists
215 // then it will be the casting result.
216 const void* dst_ptr_to_static = reinterpret_cast<const char*>(static_ptr) - src2dst_offset;
217
218 if (reinterpret_cast<std::intptr_t>(dst_ptr_to_static) < reinterpret_cast<std::intptr_t>(dynamic_ptr))
219 {
220 // The imagined dst_type object does not exist. Bail-out quickly.
221 return nullptr;
222 }
223
224 // Try to search a path from dynamic_type to dst_type.
225 __dynamic_cast_info dynamic_to_dst_info = {dynamic_type,
226 dst_ptr_to_static,
227 dst_type,
228 src2dst_offset,
229 0,
230 0,
231 0,
232 0,
233 0,
234 0,
235 0,
236 0,
237 1, // number_of_dst_type
238 false,
239 false,
240 false,
241 true,
242 nullptr};
243 dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
244 if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
245 // We have found at least one path from dynamic_ptr to dst_ptr. The
246 // downcast can succeed.
247 return dst_ptr_to_static;
248 }
249
250 return nullptr;
251}
252
253const void* dyn_cast_slow(const void* static_ptr,
254 const void* dynamic_ptr,
255 const __class_type_info* static_type,
256 const __class_type_info* dst_type,
257 const __class_type_info* dynamic_type,
258 std::ptrdiff_t src2dst_offset)
259{
260 // Not using giant short cut. Do the search
261
262 // Initialize info struct for this search.
263 __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
264 0, 0, 0, false, false, false, true, nullptr};
265
266 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
267#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
268 // The following if should always be false because we should
269 // definitely find (static_ptr, static_type), either on a public
270 // or private path
271 if (info.path_dst_ptr_to_static_ptr == unknown &&
272 info.path_dynamic_ptr_to_static_ptr == unknown)
273 {
274 static_assert(std::atomic<size_t>::is_always_lock_free, "");
275 static std::atomic<size_t> error_count(0);
276 size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
277 if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
278 syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
279 "has hidden visibility or is defined in more than one translation "
280 "unit. They should all have public visibility. "
281 "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
282 dst_type->name());
283 // Redo the search comparing type_info's using strcmp
284 info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0,
285 0, 0, 0, false, false, false, true, nullptr};
286 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
287 }
288#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
289 // Query the search.
290 switch (info.number_to_static_ptr)
291 {
292 case 0:
293 if (info.number_to_dst_ptr == 1 &&
294 info.path_dynamic_ptr_to_static_ptr == public_path &&
295 info.path_dynamic_ptr_to_dst_ptr == public_path)
296 return info.dst_ptr_not_leading_to_static_ptr;
297 break;
298 case 1:
299 if (info.path_dst_ptr_to_static_ptr == public_path ||
300 (
301 info.number_to_dst_ptr == 0 &&
302 info.path_dynamic_ptr_to_static_ptr == public_path &&
303 info.path_dynamic_ptr_to_dst_ptr == public_path
304 )
305 )
306 return info.dst_ptr_leading_to_static_ptr;
307 break;
308 }
309
310 return nullptr;
311}
312
313} // namespace
314
78// __shim_type_info315// __shim_type_info
79316
80__shim_type_info::~__shim_type_info()317__shim_type_info::~__shim_type_info()
...@@ -233,7 +470,8 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type,...@@ -233,7 +470,8 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type,
233 if (thrown_class_type == 0)470 if (thrown_class_type == 0)
234 return false;471 return false;
235 // bullet 2472 // bullet 2
236 __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};473 assert(adjustedPtr && "catching a class without an object?");
474 __dynamic_cast_info info = {thrown_class_type, 0, this, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true, nullptr};
237 info.number_of_dst_type = 1;475 info.number_of_dst_type = 1;
238 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);476 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
239 if (info.path_dst_ptr_to_static_ptr == public_path)477 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,...@@ -248,32 +486,46 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type,
248#pragma clang diagnostic pop486#pragma clang diagnostic pop
249#endif487#endif
250488
489// When we have an object to inspect - we just pass the pointer to the sub-
490// object that matched the static_type we just checked. If that is different
491// from any previously recorded pointer to that object type, then we have
492// an ambiguous case.
493
494// When we have no object to inspect, we need to account for virtual bases
495// explicitly.
496// info->vbase_cookie is a pointer to the name of the innermost virtual base
497// type, or nullptr if there is no virtual base on the path so far.
498// adjustedPtr points to the subobject we just found.
499// If vbase_cookie != any previously recorded (including the case of nullptr
500// representing an already-found static sub-object) then we have an ambiguous
501// case. Assuming that the vbase_cookie values agree; if then we have a
502// different offset (adjustedPtr) from any previously recorded, this indicates
503// an ambiguous case within the virtual base.
504
251void505void
252__class_type_info::process_found_base_class(__dynamic_cast_info* info,506__class_type_info::process_found_base_class(__dynamic_cast_info* info,
253 void* adjustedPtr,507 void* adjustedPtr,
254 int path_below) const508 int path_below) const
255{509{
256 if (info->dst_ptr_leading_to_static_ptr == 0)510 if (info->number_to_static_ptr == 0) {
257 {511 // First time we found this base
258 // First time here512 info->dst_ptr_leading_to_static_ptr = adjustedPtr;
259 info->dst_ptr_leading_to_static_ptr = adjustedPtr;513 info->path_dst_ptr_to_static_ptr = path_below;
260 info->path_dst_ptr_to_static_ptr = path_below;514 // stash the virtual base cookie.
261 info->number_to_static_ptr = 1;515 info->dst_ptr_not_leading_to_static_ptr = info->vbase_cookie;
262 }516 info->number_to_static_ptr = 1;
263 else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)517 } else if (info->dst_ptr_not_leading_to_static_ptr == info->vbase_cookie &&
264 {518 info->dst_ptr_leading_to_static_ptr == adjustedPtr) {
265 // We've been here before. Update path to "most public"519 // We've been here before. Update path to "most public"
266 if (info->path_dst_ptr_to_static_ptr == not_public_path)520 if (info->path_dst_ptr_to_static_ptr == not_public_path)
267 info->path_dst_ptr_to_static_ptr = path_below;521 info->path_dst_ptr_to_static_ptr = path_below;
268 }522 } else {
269 else523 // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
270 {524 // to a static_type.
271 // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)525 info->number_to_static_ptr += 1;
272 // to a static_type526 info->path_dst_ptr_to_static_ptr = not_public_path;
273 info->number_to_static_ptr += 1;527 info->search_done = true;
274 info->path_dst_ptr_to_static_ptr = not_public_path;528 }
275 info->search_done = true;
276 }
277}529}
278530
279void531void
...@@ -301,16 +553,30 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,...@@ -301,16 +553,30 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
301 void* adjustedPtr,553 void* adjustedPtr,
302 int path_below) const554 int path_below) const
303{555{
304 ptrdiff_t offset_to_base = 0;556 bool is_virtual = __offset_flags & __virtual_mask;
305 if (adjustedPtr != nullptr)557 ptrdiff_t offset_to_base = 0;
306 {558 if (info->have_object) {
307 offset_to_base = __offset_flags >> __offset_shift;559 /* We have an object to inspect, we can look through its vtables to
308 if (__offset_flags & __virtual_mask)560 find the layout. */
309 {561 offset_to_base = __offset_flags >> __offset_shift;
310 const char* vtable = *static_cast<const char*const*>(adjustedPtr);562 if (is_virtual) {
311 offset_to_base = update_offset_to_base(vtable, offset_to_base);563 const char* vtable = *static_cast<const char* const*>(adjustedPtr);
312 }564 offset_to_base = update_offset_to_base(vtable, offset_to_base);
313 }565 }
566 } else if (!is_virtual) {
567 /* We have no object; however, for non-virtual bases, (since we do not
568 need to inspect any content) we can pretend to have an object based
569 at '0'. */
570 offset_to_base = __offset_flags >> __offset_shift;
571 } else {
572 /* No object to inspect, and the next base is virtual.
573 We cannot indirect through the vtable to find the actual object offset.
574 So, update vbase_cookie to the new innermost virtual base using the
575 pointer to the typeinfo name as a key. */
576 info->vbase_cookie = static_cast<const void*>(__base_type->name());
577 // .. and reset the pointer.
578 adjustedPtr = nullptr;
579 }
314 __base_type->has_unambiguous_public_base(580 __base_type->has_unambiguous_public_base(
315 info,581 info,
316 static_cast<char*>(adjustedPtr) + offset_to_base,582 static_cast<char*>(adjustedPtr) + offset_to_base,
...@@ -431,14 +697,22 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type,...@@ -431,14 +697,22 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type,
431 dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);697 dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
432 if (thrown_class_type == 0)698 if (thrown_class_type == 0)
433 return false;699 return false;
434 __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};700 bool have_object = adjustedPtr != nullptr;
701 __dynamic_cast_info info = {thrown_class_type, 0, catch_class_type, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
702 have_object, nullptr};
435 info.number_of_dst_type = 1;703 info.number_of_dst_type = 1;
436 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);704 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
437 if (info.path_dst_ptr_to_static_ptr == public_path)705 if (info.path_dst_ptr_to_static_ptr == public_path)
438 {706 {
439 if (adjustedPtr != NULL)707 // In the case of a thrown null pointer, we have no object but we might
440 adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);708 // well have computed the offset to where a public sub-object would be.
441 return true;709 // However, we do not want to return that offset to the user; we still
710 // want them to catch a null ptr.
711 if (have_object)
712 adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
713 else
714 adjustedPtr = nullptr;
715 return true;
442 }716 }
443 return false;717 return false;
444}718}
...@@ -623,174 +897,46 @@ extern "C" _LIBCXXABI_FUNC_VIS void *...@@ -623,174 +897,46 @@ extern "C" _LIBCXXABI_FUNC_VIS void *
623__dynamic_cast(const void *static_ptr, const __class_type_info *static_type,897__dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
624 const __class_type_info *dst_type,898 const __class_type_info *dst_type,
625 std::ptrdiff_t src2dst_offset) {899 std::ptrdiff_t src2dst_offset) {
626 // Possible future optimization: Take advantage of src2dst_offset
627
628 // Get (dynamic_ptr, dynamic_type) from static_ptr900 // Get (dynamic_ptr, dynamic_type) from static_ptr
629#if __has_feature(cxx_abi_relative_vtable)901 derived_object_info derived_info;
630 // The vtable address will point to the first virtual function, which is 8902 dyn_cast_get_derived_info(&derived_info, static_ptr);
631 // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component).
632 const int32_t* vtable =
633 *reinterpret_cast<const int32_t* const*>(static_ptr);
634 int32_t offset_to_derived = vtable[-2];
635 const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
636
637 // The typeinfo component is now a relative offset to a proxy.
638 int32_t offset_to_ti_proxy = vtable[-1];
639 const uint8_t* ptr_to_ti_proxy =
640 reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy;
641 const __class_type_info* dynamic_type =
642 *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
643#else
644 void **vtable = *static_cast<void ** const *>(static_ptr);
645 ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
646 const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived;
647 const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
648#endif
649903
650 // Initialize answer to nullptr. This will be changed from the search904 // Initialize answer to nullptr. This will be changed from the search
651 // results if a non-null answer is found. Regardless, this is what will905 // results if a non-null answer is found. Regardless, this is what will
652 // be returned.906 // be returned.
653 const void* dst_ptr = 0;907 const void* dst_ptr = 0;
654 // Initialize info struct for this search.
655 __dynamic_cast_info info = {dst_type, static_ptr, static_type, src2dst_offset, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
656908
657 // Find out if we can use a giant short cut in the search909 // Find out if we can use a giant short cut in the search
658 if (is_equal(dynamic_type, dst_type, false))910 if (is_equal(derived_info.dynamic_type, dst_type, false))
659 {911 {
660 // We're downcasting from src_type to the complete object's dynamic912 dst_ptr = dyn_cast_to_derived(static_ptr,
661 // type. This is a really hot path that can be further optimized913 derived_info.dynamic_ptr,
662 // with the `src2dst_offset` hint.914 static_type,
663 // In such a case, dynamic_ptr already gives the casting result if the915 dst_type,
664 // casting ever succeeds. All we have to do now is to check916 derived_info.offset_to_derived,
665 // static_ptr points to a public base sub-object of dynamic_ptr.917 src2dst_offset);
666
667 if (src2dst_offset >= 0)
668 {
669 // The static type is a unique public non-virtual base type of
670 // dst_type at offset `src2dst_offset` from the origin of dst.
671 // Note that there might be other non-public static_type bases. The
672 // hint only guarantees that the public base is non-virtual and
673 // unique. So we have to check whether static_ptr points to that
674 // unique public base sub-object.
675 if (offset_to_derived == -src2dst_offset)
676 dst_ptr = dynamic_ptr;
677 }
678 else if (src2dst_offset == -2)
679 {
680 // static_type is not a public base of dst_type.
681 dst_ptr = nullptr;
682 }
683 else
684 {
685 // If src2dst_offset == -3, then:
686 // src_type is a multiple public base type but never a virtual
687 // base type. We can't conclude that static_ptr points to those
688 // public base sub-objects because there might be other non-
689 // public static_type bases. The search is inevitable.
690
691 // Fallback to the slow path to check that static_type is a public
692 // base type of dynamic_type.
693 // Using giant short cut. Add that information to info.
694 info.number_of_dst_type = 1;
695 // Do the search
696 dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
697#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
698 // The following if should always be false because we should
699 // definitely find (static_ptr, static_type), either on a public
700 // or private path
701 if (info.path_dst_ptr_to_static_ptr == unknown)
702 {
703 // We get here only if there is some kind of visibility problem
704 // in client code.
705 static_assert(std::atomic<size_t>::is_always_lock_free, "");
706 static std::atomic<size_t> error_count(0);
707 size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
708 if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
709 syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
710 "should have public visibility. At least one of them is hidden. %s"
711 ", %s.\n", static_type->name(), dynamic_type->name());
712 // Redo the search comparing type_info's using strcmp
713 info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
714 info.number_of_dst_type = 1;
715 dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
716 }
717#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
718 // Query the search.
719 if (info.path_dst_ptr_to_static_ptr == public_path)
720 dst_ptr = dynamic_ptr;
721 }
722 }918 }
723 else919 else
724 {920 {
725 if (src2dst_offset >= 0)921 // Optimize toward downcasting: let's first try to do a downcast before
726 {922 // falling back to the slow path.
727 // Optimize toward downcasting: dst_type has one unique public923 dst_ptr = dyn_cast_try_downcast(static_ptr,
728 // static_type bases. Let's first try to do a downcast before924 derived_info.dynamic_ptr,
729 // falling back to the slow path. The downcast succeeds if there925 dst_type,
730 // is at least one path regardless of visibility from926 derived_info.dynamic_type,
731 // dynamic_type to dst_type.927 src2dst_offset);
732 const void* dst_ptr_to_static = reinterpret_cast<const char*>(static_ptr) - src2dst_offset;
733 if (reinterpret_cast<std::intptr_t>(dst_ptr_to_static) >= reinterpret_cast<std::intptr_t>(dynamic_ptr))
734 {
735 // Try to search a path from dynamic_type to dst_type.
736 __dynamic_cast_info dynamic_to_dst_info = {dynamic_type, dst_ptr_to_static, dst_type, src2dst_offset};
737 dynamic_to_dst_info.number_of_dst_type = 1;
738 dynamic_type->search_above_dst(&dynamic_to_dst_info, dynamic_ptr, dynamic_ptr, public_path, false);
739 if (dynamic_to_dst_info.path_dst_ptr_to_static_ptr != unknown) {
740 // We have found at least one path from dynamic_ptr to
741 // dst_ptr. The downcast can succeed.
742 dst_ptr = dst_ptr_to_static;
743 }
744 }
745 }
746928
747 if (!dst_ptr)929 if (!dst_ptr)
748 {930 {
749 // Not using giant short cut. Do the search931 dst_ptr = dyn_cast_slow(static_ptr,
750 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);932 derived_info.dynamic_ptr,
751#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST933 static_type,
752 // The following if should always be false because we should934 dst_type,
753 // definitely find (static_ptr, static_type), either on a public935 derived_info.dynamic_type,
754 // or private path936 src2dst_offset);
755 if (info.path_dst_ptr_to_static_ptr == unknown &&
756 info.path_dynamic_ptr_to_static_ptr == unknown)
757 {
758 static_assert(std::atomic<size_t>::is_always_lock_free, "");
759 static std::atomic<size_t> error_count(0);
760 size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
761 if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
762 syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
763 "has hidden visibility or is defined in more than one translation "
764 "unit. They should all have public visibility. "
765 "%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
766 dst_type->name());
767 // Redo the search comparing type_info's using strcmp
768 info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
769 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
770 }
771#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
772 // Query the search.
773 switch (info.number_to_static_ptr)
774 {
775 case 0:
776 if (info.number_to_dst_ptr == 1 &&
777 info.path_dynamic_ptr_to_static_ptr == public_path &&
778 info.path_dynamic_ptr_to_dst_ptr == public_path)
779 dst_ptr = info.dst_ptr_not_leading_to_static_ptr;
780 break;
781 case 1:
782 if (info.path_dst_ptr_to_static_ptr == public_path ||
783 (
784 info.number_to_dst_ptr == 0 &&
785 info.path_dynamic_ptr_to_static_ptr == public_path &&
786 info.path_dynamic_ptr_to_dst_ptr == public_path
787 )
788 )
789 dst_ptr = info.dst_ptr_leading_to_static_ptr;
790 break;
791 }
792 }937 }
793 }938 }
939
794 return const_cast<void*>(dst_ptr);940 return const_cast<void*>(dst_ptr);
795}941}
796942
...@@ -1075,7 +1221,7 @@ __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,...@@ -1075,7 +1221,7 @@ __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
1075 if (info->search_done)1221 if (info->search_done)
1076 break;1222 break;
1077 // If we just found a dst_type with a public path to (static_ptr, static_type),1223 // If we just found a dst_type with a public path to (static_ptr, static_type),
1078 // then the only reason to continue the search is to make sure sure1224 // then the only reason to continue the search is to make sure
1079 // no other dst_type points to (static_ptr, static_type).1225 // no other dst_type points to (static_ptr, static_type).
1080 // If !diamond, then we don't need to search here.1226 // If !diamond, then we don't need to search here.
1081 // if we just found a dst_type with a private path to (static_ptr, static_type),1227 // if we just found a dst_type with a private path to (static_ptr, static_type),
lib/libcxxabi/src/private_typeinfo.h+7
...@@ -110,6 +110,13 @@ struct _LIBCXXABI_HIDDEN __dynamic_cast_info...@@ -110,6 +110,13 @@ struct _LIBCXXABI_HIDDEN __dynamic_cast_info
110 bool found_any_static_type;110 bool found_any_static_type;
111 // Set whenever a search can be stopped111 // Set whenever a search can be stopped
112 bool search_done;112 bool search_done;
113
114 // Data that modifies the search mechanism.
115
116 // There is no object (seen when we throw a null pointer to object).
117 bool have_object;
118 // Virtual base
119 const void* vbase_cookie;
113};120};
114121
115// Has no base class122// Has no base class
lib/libcxxabi/src/stdlib_new_delete.cpp+190-212
...@@ -7,7 +7,10 @@...@@ -7,7 +7,10 @@
7//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
88
9#include "__cxxabi_config.h"9#include "__cxxabi_config.h"
10#include "abort_message.h"
11#include "include/overridable_function.h" // from libc++
10#include <__memory/aligned_alloc.h>12#include <__memory/aligned_alloc.h>
13#include <cstddef>
11#include <cstdlib>14#include <cstdlib>
12#include <new>15#include <new>
1316
...@@ -25,241 +28,216 @@...@@ -25,241 +28,216 @@
25# error libc++ and libc++abi seem to disagree on whether exceptions are enabled28# error libc++ and libc++abi seem to disagree on whether exceptions are enabled
26#endif29#endif
2730
28// ------------------ BEGIN COPY ------------------31inline void __throw_bad_alloc_shim() {
29// Implement all new and delete operators as weak definitions
30// in this shared library, so that they can be overridden by programs
31// that define non-weak copies of the functions.
32
33_LIBCPP_WEAK
34void *
35operator new(std::size_t size) _THROW_BAD_ALLOC
36{
37 if (size == 0)
38 size = 1;
39 void* p;
40 while ((p = std::malloc(size)) == nullptr)
41 {
42 // If malloc fails and there is a new_handler,
43 // call it to try free up memory.
44 std::new_handler nh = std::get_new_handler();
45 if (nh)
46 nh();
47 else
48#ifndef _LIBCPP_HAS_NO_EXCEPTIONS32#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
49 throw std::bad_alloc();33 throw std::bad_alloc();
50#else34#else
51 break;35 abort_message("bad_alloc was thrown in -fno-exceptions mode");
52#endif36#endif
53 }
54 return p;
55}
56
57_LIBCPP_WEAK
58void*
59operator new(size_t size, const std::nothrow_t&) noexcept
60{
61 void* p = nullptr;
62#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
63 try
64 {
65#endif // _LIBCPP_HAS_NO_EXCEPTIONS
66 p = ::operator new(size);
67#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
68 }
69 catch (...)
70 {
71 }
72#endif // _LIBCPP_HAS_NO_EXCEPTIONS
73 return p;
74}
75
76_LIBCPP_WEAK
77void*
78operator new[](size_t size) _THROW_BAD_ALLOC
79{
80 return ::operator new(size);
81}37}
8238
83_LIBCPP_WEAK39#define _LIBCPP_ASSERT_SHIM(expr, str) \
84void*40 do { \
85operator new[](size_t size, const std::nothrow_t&) noexcept41 if (!expr) \
86{42 abort_message(str); \
87 void* p = nullptr;43 } while (false)
88#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
89 try
90 {
91#endif // _LIBCPP_HAS_NO_EXCEPTIONS
92 p = ::operator new[](size);
93#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
94 }
95 catch (...)
96 {
97 }
98#endif // _LIBCPP_HAS_NO_EXCEPTIONS
99 return p;
100}
10144
102_LIBCPP_WEAK45// ------------------ BEGIN COPY ------------------
103void46// Implement all new and delete operators as weak definitions
104operator delete(void* ptr) noexcept47// in this shared library, so that they can be overridden by programs
105{48// that define non-weak copies of the functions.
106 std::free(ptr);
107}
108
109_LIBCPP_WEAK
110void
111operator delete(void* ptr, const std::nothrow_t&) noexcept
112{
113 ::operator delete(ptr);
114}
115
116_LIBCPP_WEAK
117void
118operator delete(void* ptr, size_t) noexcept
119{
120 ::operator delete(ptr);
121}
122
123_LIBCPP_WEAK
124void
125operator delete[] (void* ptr) noexcept
126{
127 ::operator delete(ptr);
128}
12949
130_LIBCPP_WEAK50static void* operator_new_impl(std::size_t size) {
131void51 if (size == 0)
132operator delete[] (void* ptr, const std::nothrow_t&) noexcept52 size = 1;
133{53 void* p;
134 ::operator delete[](ptr);54 while ((p = std::malloc(size)) == nullptr) {
55 // If malloc fails and there is a new_handler,
56 // call it to try free up memory.
57 std::new_handler nh = std::get_new_handler();
58 if (nh)
59 nh();
60 else
61 break;
62 }
63 return p;
64}
65
66_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC {
67 void* p = operator_new_impl(size);
68 if (p == nullptr)
69 __throw_bad_alloc_shim();
70 return p;
71}
72
73_LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept {
74#ifdef _LIBCPP_HAS_NO_EXCEPTIONS
75# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
76 _LIBCPP_ASSERT_SHIM(
77 !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)),
78 "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, "
79 "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because "
80 "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case "
81 "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its "
82 "contract (since it should return nullptr upon failure). Please make sure you override "
83 "`operator new(size_t, nothrow_t)` as well.");
84# endif
85
86 return operator_new_impl(size);
87#else
88 void* p = nullptr;
89 try {
90 p = ::operator new(size);
91 } catch (...) {
92 }
93 return p;
94#endif
135}95}
13696
137_LIBCPP_WEAK97_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
138void98 return ::operator new(size);
139operator delete[] (void* ptr, size_t) noexcept
140{
141 ::operator delete[](ptr);
142}99}
143100
144#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)101_LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept {
102#ifdef _LIBCPP_HAS_NO_EXCEPTIONS
103# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
104 _LIBCPP_ASSERT_SHIM(
105 !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])),
106 "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, "
107 "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because "
108 "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case "
109 "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its "
110 "contract (since it should return nullptr upon failure). Please make sure you override "
111 "`operator new[](size_t, nothrow_t)` as well.");
112# endif
145113
146_LIBCPP_WEAK114 return operator_new_impl(size);
147void *
148operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
149{
150 if (size == 0)
151 size = 1;
152 if (static_cast<size_t>(alignment) < sizeof(void*))
153 alignment = std::align_val_t(sizeof(void*));
154
155 // Try allocating memory. If allocation fails and there is a new_handler,
156 // call it to try free up memory, and try again until it succeeds, or until
157 // the new_handler decides to terminate.
158 //
159 // If allocation fails and there is no new_handler, we throw bad_alloc
160 // (or return nullptr if exceptions are disabled).
161 void* p;
162 while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr)
163 {
164 std::new_handler nh = std::get_new_handler();
165 if (nh)
166 nh();
167 else {
168#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
169 throw std::bad_alloc();
170#else115#else
171 break;116 void* p = nullptr;
117 try {
118 p = ::operator new[](size);
119 } catch (...) {
120 }
121 return p;
172#endif122#endif
173 }
174 }
175 return p;
176}123}
177124
178_LIBCPP_WEAK125_LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
179void*
180operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
181{
182 void* p = nullptr;
183#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
184 try
185 {
186#endif // _LIBCPP_HAS_NO_EXCEPTIONS
187 p = ::operator new(size, alignment);
188#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
189 }
190 catch (...)
191 {
192 }
193#endif // _LIBCPP_HAS_NO_EXCEPTIONS
194 return p;
195}
196126
197_LIBCPP_WEAK127_LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }
198void*
199operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
200{
201 return ::operator new(size, alignment);
202}
203128
204_LIBCPP_WEAK129_LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }
205void*
206operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept
207{
208 void* p = nullptr;
209#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
210 try
211 {
212#endif // _LIBCPP_HAS_NO_EXCEPTIONS
213 p = ::operator new[](size, alignment);
214#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
215 }
216 catch (...)
217 {
218 }
219#endif // _LIBCPP_HAS_NO_EXCEPTIONS
220 return p;
221}
222
223_LIBCPP_WEAK
224void
225operator delete(void* ptr, std::align_val_t) noexcept
226{
227 std::__libcpp_aligned_free(ptr);
228}
229130
230_LIBCPP_WEAK131_LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }
231void
232operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
233{
234 ::operator delete(ptr, alignment);
235}
236132
237_LIBCPP_WEAK133_LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }
238void
239operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept
240{
241 ::operator delete(ptr, alignment);
242}
243134
244_LIBCPP_WEAK135_LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
245void
246operator delete[] (void* ptr, std::align_val_t alignment) noexcept
247{
248 ::operator delete(ptr, alignment);
249}
250136
251_LIBCPP_WEAK137#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
252void
253operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
254{
255 ::operator delete[](ptr, alignment);
256}
257138
258_LIBCPP_WEAK139static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {
259void140 if (size == 0)
260operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept141 size = 1;
261{142 if (static_cast<size_t>(alignment) < sizeof(void*))
262 ::operator delete[](ptr, alignment);143 alignment = std::align_val_t(sizeof(void*));
144
145 // Try allocating memory. If allocation fails and there is a new_handler,
146 // call it to try free up memory, and try again until it succeeds, or until
147 // the new_handler decides to terminate.
148 void* p;
149 while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) {
150 std::new_handler nh = std::get_new_handler();
151 if (nh)
152 nh();
153 else
154 break;
155 }
156 return p;
157}
158
159_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
160operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
161 void* p = operator_new_aligned_impl(size, alignment);
162 if (p == nullptr)
163 __throw_bad_alloc_shim();
164 return p;
165}
166
167_LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
168# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
169# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
170 _LIBCPP_ASSERT_SHIM(
171 !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)),
172 "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, "
173 "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
174 "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will "
175 "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` "
176 "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override "
177 "`operator new(size_t, align_val_t, nothrow_t)` as well.");
178# endif
179
180 return operator_new_aligned_impl(size, alignment);
181# else
182 void* p = nullptr;
183 try {
184 p = ::operator new(size, alignment);
185 } catch (...) {
186 }
187 return p;
188# endif
189}
190
191_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void*
192operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC {
193 return ::operator new(size, alignment);
194}
195
196_LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept {
197# ifdef _LIBCPP_HAS_NO_EXCEPTIONS
198# if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION
199 _LIBCPP_ASSERT_SHIM(
200 !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])),
201 "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, "
202 "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because "
203 "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will "
204 "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, "
205 "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you "
206 "override "
207 "`operator new[](size_t, align_val_t, nothrow_t)` as well.");
208# endif
209
210 return operator_new_aligned_impl(size, alignment);
211# else
212 void* p = nullptr;
213 try {
214 p = ::operator new[](size, alignment);
215 } catch (...) {
216 }
217 return p;
218# endif
219}
220
221_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); }
222
223_LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
224 ::operator delete(ptr, alignment);
225}
226
227_LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept {
228 ::operator delete(ptr, alignment);
229}
230
231_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept {
232 ::operator delete(ptr, alignment);
233}
234
235_LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept {
236 ::operator delete[](ptr, alignment);
237}
238
239_LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept {
240 ::operator delete[](ptr, alignment);
263}241}
264242
265#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION243#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION