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
3636
3737// runtime routines use C calling conventions, but are in __cxxabiv1 namespace
3838namespace __cxxabiv1 {
39
40struct __cxa_exception;
41
3942extern "C" {
4043
4144// 2.4.2 Allocating the Exception Object
......@@ -43,11 +46,19 @@ extern _LIBCXXABI_FUNC_VIS void *
4346__cxa_allocate_exception(size_t thrown_size) throw();
4447extern _LIBCXXABI_FUNC_VIS void
4548__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
4753// 2.4.3 Throwing the Exception Object
4854extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void
4955__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
5060 void (_LIBCXXABI_DTOR_FUNC *dest)(void *));
61#endif
5162
5263// 2.5.3 Exception Handlers
5364extern _LIBCXXABI_FUNC_VIS void *
lib/libcxxabi/src/abort_message.h+11
......@@ -14,4 +14,15 @@
1414extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
1515abort_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
1726#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
740740 return 0;
741741}
742742
743} // extern "C"
743} // extern "C"
744744
745745} // __cxxabiv1
lib/libcxxabi/src/cxa_demangle.cpp+5-2
......@@ -10,14 +10,17 @@
1010// file does not yet support:
1111// - C++ modules TS
1212
13#include "abort_message.h"
14#define DEMANGLE_ASSERT(expr, msg) _LIBCXXABI_ASSERT(expr, msg)
15
1316#include "demangle/DemangleConfig.h"
1417#include "demangle/ItaniumDemangle.h"
1518#include "__cxxabi_config.h"
16#include <cassert>
1719#include <cctype>
1820#include <cstdio>
1921#include <cstdlib>
2022#include <cstring>
23#include <exception>
2124#include <functional>
2225#include <numeric>
2326#include <string_view>
......@@ -394,7 +397,7 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
394397 InternalStatus = demangle_invalid_mangled_name;
395398 else {
396399 OutputBuffer O(Buf, N);
397 assert(Parser.ForwardTemplateRefs.empty());
400 DEMANGLE_ASSERT(Parser.ForwardTemplateRefs.empty(), "");
398401 AST->print(O);
399402 O += '\0';
400403 if (N != nullptr)
lib/libcxxabi/src/cxa_exception.cpp+25-14
......@@ -206,6 +206,19 @@ void __cxa_free_exception(void *thrown_object) throw() {
206206 __aligned_free_with_fallback((void *)raw_buffer);
207207}
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
210223// This function shall allocate a __cxa_dependent_exception and
211224// 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
254267exception.
255268*/
256269void
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
257274__cxa_throw(void *thrown_object, std::type_info *tinfo, void (_LIBCXXABI_DTOR_FUNC *dest)(void *)) {
258 __cxa_eh_globals *globals = __cxa_get_globals();
259 __cxa_exception* exception_header = cxa_exception_from_thrown_object(thrown_object);
260
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
275#endif
276 __cxa_eh_globals* globals = __cxa_get_globals();
277 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
271282#if __has_feature(address_sanitizer)
272 // Inform the ASan runtime that now might be a good time to clean stuff up.
273 __asan_handle_no_return();
283 // Inform the ASan runtime that now might be a good time to clean stuff up.
284 __asan_handle_no_return();
274285#endif
275286
276287#ifdef __USING_SJLJ_EXCEPTIONS__
......@@ -771,6 +782,6 @@ __cxa_uncaught_exceptions() throw()
771782 return globals->uncaughtExceptions;
772783}
773784
774} // extern "C"
785} // extern "C"
775786
776787} // abi
lib/libcxxabi/src/cxa_exception.h+5
......@@ -43,7 +43,12 @@ struct _LIBCXXABI_HIDDEN __cxa_exception {
4343
4444 // Manage the exception object itself.
4545 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
4650 void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *);
51#endif
4752 std::unexpected_handler unexpectedHandler;
4853 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) {
4848 SelectedImplementation imp(raw_guard_object);
4949 imp.cxa_guard_abort();
5050}
51} // extern "C"
51} // extern "C"
5252
5353} // __cxxabiv1
lib/libcxxabi/src/cxa_noexception.cpp+1-1
......@@ -49,7 +49,7 @@ __cxa_uncaught_exception() throw() { return false; }
4949unsigned int
5050__cxa_uncaught_exceptions() throw() { return 0; }
5151
52} // extern "C"
52} // extern "C"
5353
5454// provide dummy implementations for the 'no exceptions' case.
5555uint64_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,
7070+------------------+--+-----+-----+------------------------+--------------------------+
7171| callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table |
7272+---------------------+-----------+---------------------------------------------------+
73#ifndef __USING_SJLJ_EXCEPTIONS__
73#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
7474+---------------------+-----------+------------------------------------------------+
7575| Beginning of Call Site Table The current ip lies within the |
7676| ... (start, length) range of one of these |
......@@ -84,7 +84,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
8484| +-------------+---------------------------------+------------------------------+ |
8585| ... |
8686+----------------------------------------------------------------------------------+
87#else // __USING_SJLJ_EXCEPTIONS__
87#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
8888+---------------------+-----------+------------------------------------------------+
8989| Beginning of Call Site Table The current ip is a 1-based index into |
9090| ... this table. Or it is -1 meaning no |
......@@ -97,7 +97,7 @@ extern "C" EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD,
9797| +-------------+---------------------------------+------------------------------+ |
9898| ... |
9999+----------------------------------------------------------------------------------+
100#endif // __USING_SJLJ_EXCEPTIONS__
100#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
101101+---------------------------------------------------------------------+
102102| Beginning of Action Table ttypeIndex == 0 : cleanup |
103103| ... ttypeIndex > 0 : catch |
......@@ -547,7 +547,7 @@ void
547547set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
548548 const scan_results& results)
549549{
550#if defined(__USING_SJLJ_EXCEPTIONS__)
550#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
551551#define __builtin_eh_return_data_regno(regno) regno
552552#elif defined(__ibmxl__)
553553// 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,
642642 // Get beginning current frame's code (as defined by the
643643 // emitted dwarf code)
644644 uintptr_t funcStart = _Unwind_GetRegionStart(context);
645#ifdef __USING_SJLJ_EXCEPTIONS__
645#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
646646 if (ip == uintptr_t(-1))
647647 {
648648 // no action
......@@ -652,18 +652,17 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
652652 else if (ip == 0)
653653 call_terminate(native_exception, unwind_exception);
654654 // ip is 1-based index into call site table
655#else // !__USING_SJLJ_EXCEPTIONS__
655#else // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
656656 uintptr_t ipOffset = ip - funcStart;
657#endif // !defined(_USING_SLJL_EXCEPTIONS__)
657#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
658658 const uint8_t* classInfo = NULL;
659659 // Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
660660 // dwarf emission
661661 // Parse LSDA header.
662662 uint8_t lpStartEncoding = *lsda++;
663 const uint8_t* lpStart =
664 (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
665 if (lpStart == 0)
666 lpStart = (const uint8_t*)funcStart;
663 const uint8_t* lpStart = lpStartEncoding == DW_EH_PE_omit
664 ? (const uint8_t*)funcStart
665 : (const uint8_t*)readEncodedPointer(&lsda, lpStartEncoding, base);
667666 uint8_t ttypeEncoding = *lsda++;
668667 if (ttypeEncoding != DW_EH_PE_omit)
669668 {
......@@ -676,8 +675,8 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
676675 // Walk call-site table looking for range that
677676 // includes current PC.
678677 uint8_t callSiteEncoding = *lsda++;
679#ifdef __USING_SJLJ_EXCEPTIONS__
680 (void)callSiteEncoding; // When using SjLj exceptions, callSiteEncoding is never used
678#if defined(__USING_SJLJ_EXCEPTIONS__) || defined(__USING_WASM_EXCEPTIONS__)
679 (void)callSiteEncoding; // When using SjLj/Wasm exceptions, callSiteEncoding is never used
681680#endif
682681 uint32_t callSiteTableLength = static_cast<uint32_t>(readULEB128(&lsda));
683682 const uint8_t* callSiteTableStart = lsda;
......@@ -687,7 +686,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
687686 while (callSitePtr < callSiteTableEnd)
688687 {
689688 // There is one entry per call site.
690#ifndef __USING_SJLJ_EXCEPTIONS__
689#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
691690 // The call sites are non-overlapping in [start, start+length)
692691 // The call sites are ordered in increasing value of start
693692 uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding);
......@@ -695,15 +694,15 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
695694 uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding);
696695 uintptr_t actionEntry = readULEB128(&callSitePtr);
697696 if ((start <= ipOffset) && (ipOffset < (start + length)))
698#else // __USING_SJLJ_EXCEPTIONS__
697#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
699698 // ip is 1-based index into this table
700699 uintptr_t landingPad = readULEB128(&callSitePtr);
701700 uintptr_t actionEntry = readULEB128(&callSitePtr);
702701 if (--ip == 0)
703#endif // __USING_SJLJ_EXCEPTIONS__
702#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
704703 {
705704 // Found the call site containing ip.
706#ifndef __USING_SJLJ_EXCEPTIONS__
705#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
707706 if (landingPad == 0)
708707 {
709708 // No handler here
......@@ -711,9 +710,9 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
711710 return;
712711 }
713712 landingPad = (uintptr_t)lpStart + landingPad;
714#else // __USING_SJLJ_EXCEPTIONS__
713#else // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
715714 ++landingPad;
716#endif // __USING_SJLJ_EXCEPTIONS__
715#endif // __USING_SJLJ_EXCEPTIONS__ || __USING_WASM_EXCEPTIONS__
717716 results.landingPad = landingPad;
718717 if (actionEntry == 0)
719718 {
......@@ -841,7 +840,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
841840 action += actionOffset;
842841 } // there is no break out of this loop, only return
843842 }
844#ifndef __USING_SJLJ_EXCEPTIONS__
843#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
845844 else if (ipOffset < start)
846845 {
847846 // There is no call site for this ip
......@@ -849,7 +848,7 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
849848 // Possible stack corruption.
850849 call_terminate(native_exception, unwind_exception);
851850 }
852#endif // !__USING_SJLJ_EXCEPTIONS__
851#endif // !__USING_SJLJ_EXCEPTIONS__ && !__USING_WASM_EXCEPTIONS__
853852 } // there might be some tricky cases which break out of this loop
854853
855854 // It is possible that no eh table entry specify how to handle
......@@ -906,7 +905,9 @@ _UA_CLEANUP_PHASE
906905*/
907906
908907#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__)
910911static _Unwind_Reason_Code __gxx_personality_imp
911912#else
912913_LIBCXXABI_FUNC_VIS _Unwind_Reason_Code
......@@ -973,6 +974,11 @@ __gxx_personality_v0
973974 exc->languageSpecificData = results.languageSpecificData;
974975 exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
975976 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
976982 }
977983 return _URC_HANDLER_FOUND;
978984 }
......@@ -1304,7 +1310,7 @@ _LIBCXXABI_FUNC_VIS _Unwind_Reason_Code __xlcxx_personality_v1(
13041310 __attribute__((__alias__("__gxx_personality_v0")));
13051311#endif
13061312
1307} // extern "C"
1313} // extern "C"
13081314
13091315} // __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,
416416}
417417
418418
419} // extern "C"
419} // extern "C"
420420
421421} // abi
lib/libcxxabi/src/demangle/DemangleConfig.h+6-1
......@@ -19,7 +19,7 @@
1919#include "../abort_message.h"
2020#endif
2121
22#include <ciso646>
22#include <version>
2323
2424#ifdef _MSC_VER
2525// snprintf is implemented in VS 2015
......@@ -99,6 +99,11 @@
9999#define DEMANGLE_FALLTHROUGH
100100#endif
101101
102#ifndef DEMANGLE_ASSERT
103#include <cassert>
104#define DEMANGLE_ASSERT(__expr, __msg) assert((__expr) && (__msg))
105#endif
106
102107#define DEMANGLE_NAMESPACE_BEGIN namespace { namespace itanium_demangle {
103108#define DEMANGLE_NAMESPACE_END } }
104109
lib/libcxxabi/src/demangle/ItaniumDemangle.h+538-103
......@@ -21,7 +21,6 @@
2121#include "Utility.h"
2222#include <__cxxabi_config.h>
2323#include <algorithm>
24#include <cassert>
2524#include <cctype>
2625#include <cstdio>
2726#include <cstdlib>
......@@ -61,13 +60,13 @@ template <class T, size_t N> class PODSmallVector {
6160 if (isInline()) {
6261 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));
6362 if (Tmp == nullptr)
64 std::terminate();
63 std::abort();
6564 std::copy(First, Last, Tmp);
6665 First = Tmp;
6766 } else {
6867 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));
6968 if (First == nullptr)
70 std::terminate();
69 std::abort();
7170 }
7271 Last = First + S;
7372 Cap = First + NewCap;
......@@ -129,12 +128,12 @@ public:
129128
130129 // NOLINTNEXTLINE(readability-identifier-naming)
131130 void pop_back() {
132 assert(Last != First && "Popping empty vector!");
131 DEMANGLE_ASSERT(Last != First, "Popping empty vector!");
133132 --Last;
134133 }
135134
136 void dropBack(size_t Index) {
137 assert(Index <= size() && "dropBack() can't expand!");
135 void shrinkToSize(size_t Index) {
136 DEMANGLE_ASSERT(Index <= size(), "shrinkToSize() can't expand!");
138137 Last = First + Index;
139138 }
140139
......@@ -144,11 +143,11 @@ public:
144143 bool empty() const { return First == Last; }
145144 size_t size() const { return static_cast<size_t>(Last - First); }
146145 T &back() {
147 assert(Last != First && "Calling back() on empty vector!");
146 DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!");
148147 return *(Last - 1);
149148 }
150149 T &operator[](size_t Index) {
151 assert(Index < size() && "Invalid access!");
150 DEMANGLE_ASSERT(Index < size(), "Invalid access!");
152151 return *(begin() + Index);
153152 }
154153 void clear() { Last = First; }
......@@ -534,6 +533,23 @@ public:
534533 }
535534};
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
537553struct AbiTagAttr : Node {
538554 Node *Base;
539555 std::string_view Tag;
......@@ -873,26 +889,53 @@ public:
873889 }
874890};
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
876918class FunctionEncoding final : public Node {
877919 const Node *Ret;
878920 const Node *Name;
879921 NodeArray Params;
880922 const Node *Attrs;
923 const Node *Requires;
881924 Qualifiers CVQuals;
882925 FunctionRefQual RefQual;
883926
884927public:
885928 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,
886 const Node *Attrs_, Qualifiers CVQuals_,
887 FunctionRefQual RefQual_)
929 const Node *Attrs_, const Node *Requires_,
930 Qualifiers CVQuals_, FunctionRefQual RefQual_)
888931 : Node(KFunctionEncoding,
889932 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,
890933 /*FunctionCache=*/Cache::Yes),
891934 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),
892 CVQuals(CVQuals_), RefQual(RefQual_) {}
935 Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}
893936
894937 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);
896939 }
897940
898941 Qualifiers getCVQuals() const { return CVQuals; }
......@@ -935,6 +978,11 @@ public:
935978
936979 if (Attrs != nullptr)
937980 Attrs->print(OB);
981
982 if (Requires != nullptr) {
983 OB += " requires ";
984 Requires->print(OB);
985 }
938986 }
939987};
940988
......@@ -1006,6 +1054,24 @@ struct NestedName : Node {
10061054 }
10071055};
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
10091075struct ModuleName : Node {
10101076 ModuleName *Parent;
10111077 Node *Name;
......@@ -1171,6 +1237,24 @@ public:
11711237 }
11721238};
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
11741258/// A template type parameter declaration, 'typename T'.
11751259class TypeTemplateParamDecl final : public Node {
11761260 Node *Name;
......@@ -1186,6 +1270,26 @@ public:
11861270 void printRight(OutputBuffer &OB) const override { Name->print(OB); }
11871271};
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
11891293/// A non-type template parameter declaration, 'int N'.
11901294class NonTypeTemplateParamDecl final : public Node {
11911295 Node *Name;
......@@ -1214,13 +1318,14 @@ public:
12141318class TemplateTemplateParamDecl final : public Node {
12151319 Node *Name;
12161320 NodeArray Params;
1321 Node *Requires;
12171322
12181323public:
1219 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_)
1324 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_)
12201325 : 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
12251330 void printLeft(OutputBuffer &OB) const override {
12261331 ScopedOverride<unsigned> LT(OB.GtIsGt, 0);
......@@ -1229,7 +1334,13 @@ public:
12291334 OB += "> typename ";
12301335 }
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 }
12331344};
12341345
12351346/// A template parameter pack declaration, 'typename ...T'.
......@@ -1326,7 +1437,7 @@ public:
13261437
13271438/// A variadic template argument. This node represents an occurrence of
13281439/// 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 the
1440/// one of its Elements is. The parser inserts a ParameterPack into the
13301441/// TemplateParams table if the <template-args> this pack belongs to apply to an
13311442/// <encoding>.
13321443class TemplateArgumentPack final : public Node {
......@@ -1392,11 +1503,13 @@ public:
13921503
13931504class TemplateArgs final : public Node {
13941505 NodeArray Params;
1506 Node *Requires;
13951507
13961508public:
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
14011514 NodeArray getParams() { return Params; }
14021515
......@@ -1405,6 +1518,7 @@ public:
14051518 OB += "<";
14061519 Params.printWithComma(OB);
14071520 OB += ">";
1521 // Don't print the requires clause to keep the output simple.
14081522 }
14091523};
14101524
......@@ -1589,7 +1703,7 @@ public:
15891703 std::string_view SV = ExpandedSpecialSubstitution::getBaseName();
15901704 if (isInstantiation()) {
15911705 // The instantiations are typedefs that drop the "basic_" prefix.
1592 assert(starts_with(SV, "basic_"));
1706 DEMANGLE_ASSERT(starts_with(SV, "basic_"), "");
15931707 SV.remove_prefix(sizeof("basic_") - 1);
15941708 }
15951709 return SV;
......@@ -1655,17 +1769,21 @@ public:
16551769
16561770class ClosureTypeName : public Node {
16571771 NodeArray TemplateParams;
1772 const Node *Requires1;
16581773 NodeArray Params;
1774 const Node *Requires2;
16591775 std::string_view Count;
16601776
16611777public:
1662 ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_,
1778 ClosureTypeName(NodeArray TemplateParams_, const Node *Requires1_,
1779 NodeArray Params_, const Node *Requires2_,
16631780 std::string_view Count_)
16641781 : Node(KClosureTypeName), TemplateParams(TemplateParams_),
1665 Params(Params_), Count(Count_) {}
1782 Requires1(Requires1_), Params(Params_), Requires2(Requires2_),
1783 Count(Count_) {}
16661784
16671785 template<typename Fn> void match(Fn F) const {
1668 F(TemplateParams, Params, Count);
1786 F(TemplateParams, Requires1, Params, Requires2, Count);
16691787 }
16701788
16711789 void printDeclarator(OutputBuffer &OB) const {
......@@ -1675,12 +1793,22 @@ public:
16751793 TemplateParams.printWithComma(OB);
16761794 OB += ">";
16771795 }
1796 if (Requires1 != nullptr) {
1797 OB += " requires ";
1798 Requires1->print(OB);
1799 OB += " ";
1800 }
16781801 OB.printOpen();
16791802 Params.printWithComma(OB);
16801803 OB.printClose();
1804 if (Requires2 != nullptr) {
1805 OB += " requires ";
1806 Requires2->print(OB);
1807 }
16811808 }
16821809
16831810 void printLeft(OutputBuffer &OB) const override {
1811 // FIXME: This demangling is not particularly readable.
16841812 OB += "\'lambda";
16851813 OB += Count;
16861814 OB += "\'";
......@@ -2309,6 +2437,95 @@ public:
23092437 }
23102438};
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
23122529template <class Float> struct FloatData;
23132530
23142531namespace float_literal_impl {
......@@ -2377,7 +2594,7 @@ void Node::visit(Fn F) const {
23772594 return F(static_cast<const X *>(this));
23782595#include "ItaniumNodes.def"
23792596 }
2380 assert(0 && "unknown mangling node kind");
2597 DEMANGLE_ASSERT(0, "unknown mangling node kind");
23812598}
23822599
23832600/// Determine the kind of a node from its type.
......@@ -2403,6 +2620,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24032620 // table.
24042621 PODSmallVector<Node *, 32> Subs;
24052622
2623 // A list of template argument values corresponding to a template parameter
2624 // list.
24062625 using TemplateParamList = PODSmallVector<Node *, 8>;
24072626
24082627 class ScopedTemplateParamList {
......@@ -2417,9 +2636,11 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24172636 Parser->TemplateParams.push_back(&Params);
24182637 }
24192638 ~ScopedTemplateParamList() {
2420 assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists);
2421 Parser->TemplateParams.dropBack(OldNumTemplateParamLists);
2639 DEMANGLE_ASSERT(Parser->TemplateParams.size() >= OldNumTemplateParamLists,
2640 "");
2641 Parser->TemplateParams.shrinkToSize(OldNumTemplateParamLists);
24222642 }
2643 TemplateParamList *params() { return &Params; }
24232644 };
24242645
24252646 // Template parameter table. Like the above, but referenced like "T42_".
......@@ -2434,12 +2655,31 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24342655 // parameter list, the corresponding parameter list pointer will be null.
24352656 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
24372676 // Set of unresolved forward <template-param> references. These can occur in a
24382677 // conversion operator's type, and are resolved in the enclosing <encoding>.
24392678 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
24402679
24412680 bool TryToParseTemplateArgs = true;
24422681 bool PermitForwardTemplateReferences = false;
2682 bool InConstraintExpr = false;
24432683 size_t ParsingLambdaParamsAtLevel = (size_t)-1;
24442684
24452685 unsigned NumSyntheticTemplateParameters[3] = {};
......@@ -2478,10 +2718,10 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
24782718 }
24792719
24802720 NodeArray popTrailingNodeArray(size_t FromPosition) {
2481 assert(FromPosition <= Names.size());
2721 DEMANGLE_ASSERT(FromPosition <= Names.size(), "");
24822722 NodeArray res =
24832723 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());
2484 Names.dropBack(FromPosition);
2724 Names.shrinkToSize(FromPosition);
24852725 return res;
24862726 }
24872727
......@@ -2519,11 +2759,16 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
25192759 bool parseSeqId(size_t *Out);
25202760 Node *parseSubstitution();
25212761 Node *parseTemplateParam();
2522 Node *parseTemplateParamDecl();
2762 Node *parseTemplateParamDecl(TemplateParamList *Params);
25232763 Node *parseTemplateArgs(bool TagTemplates = false);
25242764 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.
25272772 Node *parseExpr();
25282773 Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);
25292774 Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);
......@@ -2536,6 +2781,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
25362781 Node *parseFoldExpr();
25372782 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);
25382783 Node *parseSubobjectExpr();
2784 Node *parseConstraintExpr();
2785 Node *parseRequiresExpr();
25392786
25402787 /// Parse the <type> production.
25412788 Node *parseType();
......@@ -2547,7 +2794,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
25472794 Node *parseClassEnumType();
25482795 Node *parseQualifiedType();
25492796
2550 Node *parseEncoding();
2797 Node *parseEncoding(bool ParseParams = true);
25512798 bool parseCallOffset();
25522799 Node *parseSpecialName();
25532800
......@@ -2559,6 +2806,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
25592806 Qualifiers CVQualifiers = QualNone;
25602807 FunctionRefQual ReferenceQualifier = FrefQualNone;
25612808 size_t ForwardTemplateRefsBegin;
2809 bool HasExplicitObjectParameter = false;
25622810
25632811 NameState(AbstractManglingParser *Enclosing)
25642812 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
......@@ -2574,7 +2822,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
25742822 return true;
25752823 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];
25762824 }
2577 ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
2825 ForwardTemplateRefs.shrinkToSize(State.ForwardTemplateRefsBegin);
25782826 return false;
25792827 }
25802828
......@@ -2638,8 +2886,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
26382886 std::string_view getSymbol() const {
26392887 std::string_view Res = Name;
26402888 if (Kind < Unnameable) {
2641 assert(starts_with(Res, "operator") &&
2642 "operator name does not start with 'operator'");
2889 DEMANGLE_ASSERT(starts_with(Res, "operator"),
2890 "operator name does not start with 'operator'");
26432891 Res.remove_prefix(sizeof("operator") - 1);
26442892 if (starts_with(Res, ' '))
26452893 Res.remove_prefix(1);
......@@ -2663,7 +2911,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
26632911 Node *parseDestructorName();
26642912
26652913 /// Top-level entry point into the parser.
2666 Node *parse();
2914 Node *parse(bool ParseParams = true);
26672915};
26682916
26692917const char* parse_discriminator(const char* first, const char* last);
......@@ -2727,6 +2975,10 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
27272975 return make<LocalName>(Encoding, StringLitName);
27282976 }
27292977
2978 // The template parameters of the inner name are unrelated to those of the
2979 // enclosing context.
2980 SaveTemplateParams SaveTemplateParamsScope(this);
2981
27302982 if (consumeIf('d')) {
27312983 parseNumber(true);
27322984 if (!consumeIf('_'))
......@@ -2782,9 +3034,9 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
27823034 return Res;
27833035}
27843036
2785// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
3037// <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]
27863038// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
2787// ::= [<module-name>] L? <source-name> [<abi-tags>]
3039// ::= [<module-name>] F? L? <source-name> [<abi-tags>]
27883040// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
27893041// # structured binding declaration
27903042// ::= [<module-name>] L? DC <source-name>+ E
......@@ -2794,6 +3046,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
27943046 if (getDerived().parseModuleNameOpt(Module))
27953047 return nullptr;
27963048
3049 bool IsMemberLikeFriend = Scope && consumeIf('F');
3050
27973051 consumeIf('L');
27983052
27993053 Node *Result;
......@@ -2824,7 +3078,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
28243078 Result = make<ModuleEntity>(Module, Result);
28253079 if (Result != nullptr)
28263080 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)
28283084 Result = make<NestedName>(Scope, Result);
28293085
28303086 return Result;
......@@ -2856,7 +3112,8 @@ bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(
28563112//
28573113// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
28583114//
2859// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters
3115// <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]
3116// <parameter type>+ # or "v" if the lambda has no parameters
28603117template <typename Derived, typename Alloc>
28613118Node *
28623119AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
......@@ -2877,10 +3134,10 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
28773134 ScopedTemplateParamList LambdaTemplateParams(this);
28783135
28793136 size_t ParamsBegin = Names.size();
2880 while (look() == 'T' &&
2881 std::string_view("yptn").find(look(1)) != std::string_view::npos) {
2882 Node *T = parseTemplateParamDecl();
2883 if (!T)
3137 while (getDerived().isTemplateParamDecl()) {
3138 Node *T =
3139 getDerived().parseTemplateParamDecl(LambdaTemplateParams.params());
3140 if (T == nullptr)
28843141 return nullptr;
28853142 Names.push_back(T);
28863143 }
......@@ -2911,20 +3168,38 @@ AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {
29113168 if (TempParams.empty())
29123169 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")) {
29153179 do {
29163180 Node *P = getDerived().parseType();
29173181 if (P == nullptr)
29183182 return nullptr;
29193183 Names.push_back(P);
2920 } while (!consumeIf('E'));
3184 } while (look() != 'E' && look() != 'Q');
29213185 }
29223186 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
29243198 std::string_view Count = parseNumber();
29253199 if (!consumeIf('_'))
29263200 return nullptr;
2927 return make<ClosureTypeName>(TempParams, Params, Count);
3201 return make<ClosureTypeName>(TempParams, Requires1, Params, Requires2,
3202 Count);
29283203 }
29293204 if (consumeIf("Ub")) {
29303205 (void)parseNumber();
......@@ -3190,15 +3465,25 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
31903465 if (!consumeIf('N'))
31913466 return nullptr;
31923467
3193 Qualifiers CVTmp = parseCVQualifiers();
3194 if (State) State->CVQualifiers = CVTmp;
3468 // 'H' specifies that the encoding that follows
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')) {
3197 if (State) State->ReferenceQualifier = FrefQualRValue;
3198 } else if (consumeIf('R')) {
3199 if (State) State->ReferenceQualifier = FrefQualLValue;
3200 } else {
3201 if (State) State->ReferenceQualifier = FrefQualNone;
3475 if (consumeIf('O')) {
3476 if (State)
3477 State->ReferenceQualifier = FrefQualRValue;
3478 } else if (consumeIf('R')) {
3479 if (State)
3480 State->ReferenceQualifier = FrefQualLValue;
3481 } else {
3482 if (State)
3483 State->ReferenceQualifier = FrefQualNone;
3484 }
3485 } else if (State) {
3486 State->HasExplicitObjectParameter = true;
32023487 }
32033488
32043489 Node *SoFar = nullptr;
......@@ -3446,7 +3731,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {
34463731 }
34473732 }
34483733
3449 assert(SoFar != nullptr);
3734 DEMANGLE_ASSERT(SoFar != nullptr, "");
34503735
34513736 Node *Base = getDerived().parseBaseUnresolvedName();
34523737 if (Base == nullptr)
......@@ -3894,7 +4179,15 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
38944179 // Typically, <builtin-type>s are not considered substitution candidates,
38954180 // but the exception to that exception is vendor extended types (Itanium C++
38964181 // 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);
38984191 break;
38994192 }
39004193 case 'D':
......@@ -3961,6 +4254,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
39614254 case 'c':
39624255 First += 2;
39634256 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 }
39644268 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
39654269 case 'n':
39664270 First += 2;
......@@ -4512,6 +4816,75 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {
45124816 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);
45134817}
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
45154888// <expression> ::= <unary operator-name> <expression>
45164889// ::= <binary operator-name> <expression> <expression>
45174890// ::= <ternary operator-name> <expression> <expression> <expression>
......@@ -4748,6 +5121,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
47485121 return Ex;
47495122 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);
47505123 }
5124 if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))
5125 return parseRequiresExpr();
47515126 if (consumeIf("so"))
47525127 return parseSubobjectExpr();
47535128 if (consumeIf("sp")) {
......@@ -5026,29 +5401,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
50265401}
50275402
50285403// <encoding> ::= <function name> <bare-function-type>
5404// [`Q` <requires-clause expr>]
50295405// ::= <data name>
50305406// ::= <special-name>
50315407template <typename Derived, typename Alloc>
5032Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
5408Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {
50335409 // The template parameters of an encoding are unrelated to those of the
50345410 // enclosing context.
5035 class SaveTemplateParams {
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);
5411 SaveTemplateParams SaveTemplateParamsScope(this);
50525412
50535413 if (look() == 'G' || look() == 'T')
50545414 return getDerived().parseSpecialName();
......@@ -5071,6 +5431,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
50715431 if (IsEndOfEncoding())
50725432 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
50745444 Node *Attrs = nullptr;
50755445 if (consumeIf("Ua9enable_ifI")) {
50765446 size_t BeforeArgs = Names.size();
......@@ -5092,22 +5462,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
50925462 return nullptr;
50935463 }
50945464
5095 if (consumeIf('v'))
5096 return make<FunctionEncoding>(ReturnType, Name, NodeArray(),
5097 Attrs, NameInfo.CVQualifiers,
5098 NameInfo.ReferenceQualifier);
5465 NodeArray Params;
5466 if (!consumeIf('v')) {
5467 size_t ParamsBegin = Names.size();
5468 do {
5469 Node *Ty = getDerived().parseType();
5470 if (Ty == nullptr)
5471 return nullptr;
50995472
5100 size_t ParamsBegin = Names.size();
5101 do {
5102 Node *Ty = getDerived().parseType();
5103 if (Ty == nullptr)
5473 const bool IsFirstParam = ParamsBegin == Names.size();
5474 if (NameInfo.HasExplicitObjectParameter && IsFirstParam)
5475 Ty = make<ExplicitObjectParameter>(Ty);
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)
51045489 return nullptr;
5105 Names.push_back(Ty);
5106 } while (!IsEndOfEncoding());
5490 }
51075491
5108 return make<FunctionEncoding>(ReturnType, Name,
5109 popTrailingNodeArray(ParamsBegin),
5110 Attrs, NameInfo.CVQualifiers,
5492 return make<FunctionEncoding>(ReturnType, Name, Params, Attrs, Requires,
5493 NameInfo.CVQualifiers,
51115494 NameInfo.ReferenceQualifier);
51125495}
51135496
......@@ -5134,7 +5517,8 @@ template <>
51345517struct FloatData<long double>
51355518{
51365519#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__)
51385522 static const size_t mangled_size = 32;
51395523#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)
51405524 static const size_t mangled_size = 16;
......@@ -5268,6 +5652,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {
52685652// ::= TL <level-1> _ <parameter-2 non-negative number> _
52695653template <typename Derived, typename Alloc>
52705654Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
5655 const char *Begin = First;
52715656 if (!consumeIf('T'))
52725657 return nullptr;
52735658
......@@ -5289,6 +5674,14 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
52895674 return nullptr;
52905675 }
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
52925685 // If we're in a context where this <template-param> refers to a
52935686 // <template-arg> further ahead in the mangled name (currently just conversion
52945687 // operator types), then we should only look it up in the right context.
......@@ -5297,7 +5690,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
52975690 Node *ForwardRef = make<ForwardTemplateReference>(Index);
52985691 if (!ForwardRef)
52995692 return nullptr;
5300 assert(ForwardRef->getKind() == Node::KForwardTemplateReference);
5693 DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference,
5694 "");
53015695 ForwardTemplateRefs.push_back(
53025696 static_cast<ForwardTemplateReference *>(ForwardRef));
53035697 return ForwardRef;
......@@ -5326,11 +5720,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {
53265720// ::= Tt <template-param-decl>* E # template parameter
53275721// ::= Tp <template-param-decl> # parameter pack
53285722template <typename Derived, typename Alloc>
5329Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
5723Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(
5724 TemplateParamList *Params) {
53305725 auto InventTemplateParamName = [&](TemplateParamKind Kind) {
53315726 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;
53325727 Node *N = make<SyntheticTemplateParamName>(Kind, Index);
5333 if (N) TemplateParams.back()->push_back(N);
5728 if (N && Params)
5729 Params->push_back(N);
53345730 return N;
53355731 };
53365732
......@@ -5341,6 +5737,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
53415737 return make<TypeTemplateParamDecl>(Name);
53425738 }
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
53445750 if (consumeIf("Tn")) {
53455751 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);
53465752 if (!Name)
......@@ -5357,18 +5763,25 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
53575763 return nullptr;
53585764 size_t ParamsBegin = Names.size();
53595765 ScopedTemplateParamList TemplateTemplateParamParams(this);
5360 while (!consumeIf("E")) {
5361 Node *P = parseTemplateParamDecl();
5766 Node *Requires = nullptr;
5767 while (!consumeIf('E')) {
5768 Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params());
53625769 if (!P)
53635770 return nullptr;
53645771 Names.push_back(P);
5772 if (consumeIf('Q')) {
5773 Requires = getDerived().parseConstraintExpr();
5774 if (Requires == nullptr || !consumeIf('E'))
5775 return nullptr;
5776 break;
5777 }
53655778 }
5366 NodeArray Params = popTrailingNodeArray(ParamsBegin);
5367 return make<TemplateTemplateParamDecl>(Name, Params);
5779 NodeArray InnerParams = popTrailingNodeArray(ParamsBegin);
5780 return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);
53685781 }
53695782
53705783 if (consumeIf("Tp")) {
5371 Node *P = parseTemplateParamDecl();
5784 Node *P = parseTemplateParamDecl(Params);
53725785 if (!P)
53735786 return nullptr;
53745787 return make<TemplateParamPackDecl>(P);
......@@ -5382,6 +5795,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl() {
53825795// ::= <expr-primary> # simple expressions
53835796// ::= J <template-arg>* E # argument pack
53845797// ::= LZ <encoding> E # extension
5798// ::= <template-param-decl> <template-arg>
53855799template <typename Derived, typename Alloc>
53865800Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
53875801 switch (look()) {
......@@ -5416,6 +5830,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {
54165830 // ::= <expr-primary> # simple expressions
54175831 return getDerived().parseExprPrimary();
54185832 }
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 }
54195845 default:
54205846 return getDerived().parseType();
54215847 }
......@@ -5438,30 +5864,39 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
54385864 }
54395865
54405866 size_t ArgsBegin = Names.size();
5867 Node *Requires = nullptr;
54415868 while (!consumeIf('E')) {
54425869 if (TagTemplates) {
5443 auto OldParams = std::move(TemplateParams);
54445870 Node *Arg = getDerived().parseTemplateArg();
5445 TemplateParams = std::move(OldParams);
54465871 if (Arg == nullptr)
54475872 return nullptr;
54485873 Names.push_back(Arg);
54495874 Node *TableEntry = Arg;
5875 if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {
5876 TableEntry =
5877 static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();
5878 }
54505879 if (Arg->getKind() == Node::KTemplateArgumentPack) {
54515880 TableEntry = make<ParameterPack>(
54525881 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());
54535882 if (!TableEntry)
54545883 return nullptr;
54555884 }
5456 TemplateParams.back()->push_back(TableEntry);
5885 OuterTemplateParams.push_back(TableEntry);
54575886 } else {
54585887 Node *Arg = getDerived().parseTemplateArg();
54595888 if (Arg == nullptr)
54605889 return nullptr;
54615890 Names.push_back(Arg);
54625891 }
5892 if (consumeIf('Q')) {
5893 Requires = getDerived().parseConstraintExpr();
5894 if (!Requires || !consumeIf('E'))
5895 return nullptr;
5896 break;
5897 }
54635898 }
5464 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));
5899 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin), Requires);
54655900}
54665901
54675902// <mangled-name> ::= _Z <encoding>
......@@ -5470,9 +5905,9 @@ AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {
54705905// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+
54715906// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+
54725907template <typename Derived, typename Alloc>
5473Node *AbstractManglingParser<Derived, Alloc>::parse() {
5908Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {
54745909 if (consumeIf("_Z") || consumeIf("__Z")) {
5475 Node *Encoding = getDerived().parseEncoding();
5910 Node *Encoding = getDerived().parseEncoding(ParseParams);
54765911 if (Encoding == nullptr)
54775912 return nullptr;
54785913 if (look() == '.') {
......@@ -5486,7 +5921,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parse() {
54865921 }
54875922
54885923 if (consumeIf("___Z") || consumeIf("____Z")) {
5489 Node *Encoding = getDerived().parseEncoding();
5924 Node *Encoding = getDerived().parseEncoding(ParseParams);
54905925 if (Encoding == nullptr || !consumeIf("_block_invoke"))
54915926 return nullptr;
54925927 bool RequireNumber = consumeIf('_');
lib/libcxxabi/src/demangle/ItaniumNodes.def+9
......@@ -19,6 +19,7 @@ NODE(QualType)
1919NODE(ConversionOperatorType)
2020NODE(PostfixQualifiedType)
2121NODE(ElaboratedTypeSpefType)
22NODE(TransformedType)
2223NODE(NameType)
2324NODE(AbiTagAttr)
2425NODE(EnableIfAttr)
......@@ -36,6 +37,7 @@ NODE(SpecialName)
3637NODE(CtorVtableSpecialName)
3738NODE(QualifiedName)
3839NODE(NestedName)
40NODE(MemberLikeFriendName)
3941NODE(LocalName)
4042NODE(ModuleName)
4143NODE(ModuleEntity)
......@@ -44,7 +46,9 @@ NODE(PixelVectorType)
4446NODE(BinaryFPType)
4547NODE(BitIntType)
4648NODE(SyntheticTemplateParamName)
49NODE(TemplateParamQualifiedArg)
4750NODE(TypeTemplateParamDecl)
51NODE(ConstrainedTypeTemplateParamDecl)
4852NODE(NonTypeTemplateParamDecl)
4953NODE(TemplateTemplateParamDecl)
5054NODE(TemplateParamPackDecl)
......@@ -91,5 +95,10 @@ NODE(DoubleLiteral)
9195NODE(LongDoubleLiteral)
9296NODE(BracedExpr)
9397NODE(BracedRangeExpr)
98NODE(RequiresExpr)
99NODE(ExprRequirement)
100NODE(TypeRequirement)
101NODE(NestedRequirement)
102NODE(ExplicitObjectParameter)
94103
95104#undef NODE
lib/libcxxabi/src/demangle/Utility.h+3-5
......@@ -19,11 +19,9 @@
1919#include "DemangleConfig.h"
2020
2121#include <array>
22#include <cassert>
2322#include <cstdint>
2423#include <cstdlib>
2524#include <cstring>
26#include <exception>
2725#include <limits>
2826#include <string_view>
2927
......@@ -49,7 +47,7 @@ class OutputBuffer {
4947 BufferCapacity = Need;
5048 Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
5149 if (Buffer == nullptr)
52 std::terminate();
50 std::abort();
5351 }
5452 }
5553
......@@ -160,7 +158,7 @@ public:
160158 }
161159
162160 void insert(size_t Pos, const char *S, size_t N) {
163 assert(Pos <= CurrentPosition);
161 DEMANGLE_ASSERT(Pos <= CurrentPosition, "");
164162 if (N == 0)
165163 return;
166164 grow(N);
......@@ -173,7 +171,7 @@ public:
173171 void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
174172
175173 char back() const {
176 assert(CurrentPosition);
174 DEMANGLE_ASSERT(CurrentPosition, "");
177175 return Buffer[CurrentPosition - 1];
178176 }
179177
lib/libcxxabi/src/fallback_malloc.cpp+5-4
......@@ -7,6 +7,7 @@
77//===----------------------------------------------------------------------===//
88
99#include "fallback_malloc.h"
10#include "abort_message.h"
1011
1112#include <__threading_support>
1213#ifndef _LIBCXXABI_HAS_NO_THREADS
......@@ -16,7 +17,7 @@
1617#endif
1718
1819#include <__memory/aligned_alloc.h>
19#include <assert.h>
20#include <__assert>
2021#include <stdlib.h> // for malloc, calloc, free
2122#include <string.h> // for memset
2223
......@@ -142,7 +143,7 @@ void* fallback_malloc(size_t len) {
142143
143144 // Check the invariant that all heap_nodes pointers 'p' are aligned
144145 // 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
147148 // Calculate the number of extra padding elements needed in order
148149 // to split 'p' and create a properly aligned heap_node from the tail
......@@ -163,7 +164,7 @@ void* fallback_malloc(size_t len) {
163164 q->next_node = 0;
164165 q->len = static_cast<heap_size>(aligned_nelems);
165166 void* ptr = q + 1;
166 assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);
167 _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0, "");
167168 return ptr;
168169 }
169170
......@@ -176,7 +177,7 @@ void* fallback_malloc(size_t len) {
176177 prev->next_node = p->next_node;
177178 p->next_node = 0;
178179 void* ptr = p + 1;
179 assert(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0);
180 _LIBCXXABI_ASSERT(reinterpret_cast<size_t>(ptr) % RequiredAlignment == 0, "");
180181 return ptr;
181182 }
182183 }
lib/libcxxabi/src/private_typeinfo.cpp+333-187
......@@ -42,6 +42,7 @@
4242// is_equal() with use_strcmp=false so the string names are not compared.
4343
4444#include <cstdint>
45#include <cassert>
4546#include <string.h>
4647
4748#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
......@@ -75,6 +76,242 @@ static inline ptrdiff_t update_offset_to_base(const char* vtable,
7576namespace __cxxabiv1
7677{
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
78315// __shim_type_info
79316
80317__shim_type_info::~__shim_type_info()
......@@ -233,7 +470,8 @@ __class_type_info::can_catch(const __shim_type_info* thrown_type,
233470 if (thrown_class_type == 0)
234471 return false;
235472 // 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};
237475 info.number_of_dst_type = 1;
238476 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
239477 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,
248486#pragma clang diagnostic pop
249487#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
251505void
252506__class_type_info::process_found_base_class(__dynamic_cast_info* info,
253507 void* adjustedPtr,
254508 int path_below) const
255509{
256 if (info->dst_ptr_leading_to_static_ptr == 0)
257 {
258 // First time here
259 info->dst_ptr_leading_to_static_ptr = adjustedPtr;
260 info->path_dst_ptr_to_static_ptr = path_below;
261 info->number_to_static_ptr = 1;
262 }
263 else if (info->dst_ptr_leading_to_static_ptr == adjustedPtr)
264 {
265 // We've been here before. Update path to "most public"
266 if (info->path_dst_ptr_to_static_ptr == not_public_path)
267 info->path_dst_ptr_to_static_ptr = path_below;
268 }
269 else
270 {
271 // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
272 // to a static_type
273 info->number_to_static_ptr += 1;
274 info->path_dst_ptr_to_static_ptr = not_public_path;
275 info->search_done = true;
276 }
510 if (info->number_to_static_ptr == 0) {
511 // First time we found this base
512 info->dst_ptr_leading_to_static_ptr = adjustedPtr;
513 info->path_dst_ptr_to_static_ptr = path_below;
514 // stash the virtual base cookie.
515 info->dst_ptr_not_leading_to_static_ptr = info->vbase_cookie;
516 info->number_to_static_ptr = 1;
517 } else if (info->dst_ptr_not_leading_to_static_ptr == info->vbase_cookie &&
518 info->dst_ptr_leading_to_static_ptr == adjustedPtr) {
519 // We've been here before. Update path to "most public"
520 if (info->path_dst_ptr_to_static_ptr == not_public_path)
521 info->path_dst_ptr_to_static_ptr = path_below;
522 } else {
523 // We've detected an ambiguous cast from (thrown_class_type, adjustedPtr)
524 // to a static_type.
525 info->number_to_static_ptr += 1;
526 info->path_dst_ptr_to_static_ptr = not_public_path;
527 info->search_done = true;
528 }
277529}
278530
279531void
......@@ -301,16 +553,30 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
301553 void* adjustedPtr,
302554 int path_below) const
303555{
304 ptrdiff_t offset_to_base = 0;
305 if (adjustedPtr != nullptr)
306 {
307 offset_to_base = __offset_flags >> __offset_shift;
308 if (__offset_flags & __virtual_mask)
309 {
310 const char* vtable = *static_cast<const char*const*>(adjustedPtr);
311 offset_to_base = update_offset_to_base(vtable, offset_to_base);
312 }
556 bool is_virtual = __offset_flags & __virtual_mask;
557 ptrdiff_t offset_to_base = 0;
558 if (info->have_object) {
559 /* We have an object to inspect, we can look through its vtables to
560 find the layout. */
561 offset_to_base = __offset_flags >> __offset_shift;
562 if (is_virtual) {
563 const char* vtable = *static_cast<const char* const*>(adjustedPtr);
564 offset_to_base = update_offset_to_base(vtable, offset_to_base);
313565 }
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 }
314580 __base_type->has_unambiguous_public_base(
315581 info,
316582 static_cast<char*>(adjustedPtr) + offset_to_base,
......@@ -431,14 +697,22 @@ __pointer_type_info::can_catch(const __shim_type_info* thrown_type,
431697 dynamic_cast<const __class_type_info*>(thrown_pointer_type->__pointee);
432698 if (thrown_class_type == 0)
433699 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};
435703 info.number_of_dst_type = 1;
436704 thrown_class_type->has_unambiguous_public_base(&info, adjustedPtr, public_path);
437705 if (info.path_dst_ptr_to_static_ptr == public_path)
438706 {
439 if (adjustedPtr != NULL)
440 adjustedPtr = const_cast<void*>(info.dst_ptr_leading_to_static_ptr);
441 return true;
707 // In the case of a thrown null pointer, we have no object but we might
708 // well have computed the offset to where a public sub-object would be.
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;
442716 }
443717 return false;
444718}
......@@ -623,174 +897,46 @@ extern "C" _LIBCXXABI_FUNC_VIS void *
623897__dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
624898 const __class_type_info *dst_type,
625899 std::ptrdiff_t src2dst_offset) {
626 // Possible future optimization: Take advantage of src2dst_offset
627
628900 // Get (dynamic_ptr, dynamic_type) from static_ptr
629#if __has_feature(cxx_abi_relative_vtable)
630 // The vtable address will point to the first virtual function, which is 8
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
901 derived_object_info derived_info;
902 dyn_cast_get_derived_info(&derived_info, static_ptr);
649903
650904 // Initialize answer to nullptr. This will be changed from the search
651905 // results if a non-null answer is found. Regardless, this is what will
652906 // be returned.
653907 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
657909 // 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))
659911 {
660 // We're downcasting from src_type to the complete object's dynamic
661 // type. This is a really hot path that can be further optimized
662 // with the `src2dst_offset` hint.
663 // In such a case, dynamic_ptr already gives the casting result if the
664 // casting ever succeeds. All we have to do now is to check
665 // static_ptr points to a public base sub-object of dynamic_ptr.
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 }
912 dst_ptr = dyn_cast_to_derived(static_ptr,
913 derived_info.dynamic_ptr,
914 static_type,
915 dst_type,
916 derived_info.offset_to_derived,
917 src2dst_offset);
722918 }
723919 else
724920 {
725 if (src2dst_offset >= 0)
726 {
727 // Optimize toward downcasting: dst_type has one unique public
728 // static_type bases. Let's first try to do a downcast before
729 // falling back to the slow path. The downcast succeeds if there
730 // is at least one path regardless of visibility from
731 // dynamic_type to dst_type.
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 }
921 // Optimize toward downcasting: let's first try to do a downcast before
922 // falling back to the slow path.
923 dst_ptr = dyn_cast_try_downcast(static_ptr,
924 derived_info.dynamic_ptr,
925 dst_type,
926 derived_info.dynamic_type,
927 src2dst_offset);
746928
747929 if (!dst_ptr)
748930 {
749 // Not using giant short cut. Do the search
750 dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
751#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
752 // The following if should always be false because we should
753 // definitely find (static_ptr, static_type), either on a public
754 // or private path
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 }
931 dst_ptr = dyn_cast_slow(static_ptr,
932 derived_info.dynamic_ptr,
933 static_type,
934 dst_type,
935 derived_info.dynamic_type,
936 src2dst_offset);
792937 }
793938 }
939
794940 return const_cast<void*>(dst_ptr);
795941}
796942
......@@ -1075,7 +1221,7 @@ __vmi_class_type_info::search_below_dst(__dynamic_cast_info* info,
10751221 if (info->search_done)
10761222 break;
10771223 // 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 sure
1224 // then the only reason to continue the search is to make sure
10791225 // no other dst_type points to (static_ptr, static_type).
10801226 // If !diamond, then we don't need to search here.
10811227 // 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
110110 bool found_any_static_type;
111111 // Set whenever a search can be stopped
112112 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;
113120};
114121
115122// Has no base class
lib/libcxxabi/src/stdlib_new_delete.cpp+190-212
......@@ -7,7 +7,10 @@
77//===----------------------------------------------------------------------===//
88
99#include "__cxxabi_config.h"
10#include "abort_message.h"
11#include "include/overridable_function.h" // from libc++
1012#include <__memory/aligned_alloc.h>
13#include <cstddef>
1114#include <cstdlib>
1215#include <new>
1316
......@@ -25,241 +28,216 @@
2528# error libc++ and libc++abi seem to disagree on whether exceptions are enabled
2629#endif
2730
28// ------------------ BEGIN COPY ------------------
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
31inline void __throw_bad_alloc_shim() {
4832#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
49 throw std::bad_alloc();
33 throw std::bad_alloc();
5034#else
51 break;
35 abort_message("bad_alloc was thrown in -fno-exceptions mode");
5236#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);
8137}
8238
83_LIBCPP_WEAK
84void*
85operator new[](size_t size, const std::nothrow_t&) noexcept
86{
87 void* p = nullptr;
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}
39#define _LIBCPP_ASSERT_SHIM(expr, str) \
40 do { \
41 if (!expr) \
42 abort_message(str); \
43 } while (false)
10144
102_LIBCPP_WEAK
103void
104operator delete(void* ptr) noexcept
105{
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}
45// ------------------ BEGIN COPY ------------------
46// Implement all new and delete operators as weak definitions
47// in this shared library, so that they can be overridden by programs
48// that define non-weak copies of the functions.
12949
130_LIBCPP_WEAK
131void
132operator delete[] (void* ptr, const std::nothrow_t&) noexcept
133{
134 ::operator delete[](ptr);
50static void* operator_new_impl(std::size_t size) {
51 if (size == 0)
52 size = 1;
53 void* p;
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
13595}
13696
137_LIBCPP_WEAK
138void
139operator delete[] (void* ptr, size_t) noexcept
140{
141 ::operator delete[](ptr);
97_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC {
98 return ::operator new(size);
14299}
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_WEAK
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();
114 return operator_new_impl(size);
170115#else
171 break;
116 void* p = nullptr;
117 try {
118 p = ::operator new[](size);
119 } catch (...) {
120 }
121 return p;
172122#endif
173 }
174 }
175 return p;
176123}
177124
178_LIBCPP_WEAK
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}
125_LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); }
196126
197_LIBCPP_WEAK
198void*
199operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
200{
201 return ::operator new(size, alignment);
202}
127_LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); }
203128
204_LIBCPP_WEAK
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}
129_LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); }
229130
230_LIBCPP_WEAK
231void
232operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
233{
234 ::operator delete(ptr, alignment);
235}
131_LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); }
236132
237_LIBCPP_WEAK
238void
239operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept
240{
241 ::operator delete(ptr, alignment);
242}
133_LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); }
243134
244_LIBCPP_WEAK
245void
246operator delete[] (void* ptr, std::align_val_t alignment) noexcept
247{
248 ::operator delete(ptr, alignment);
249}
135_LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); }
250136
251_LIBCPP_WEAK
252void
253operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept
254{
255 ::operator delete[](ptr, alignment);
256}
137#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
257138
258_LIBCPP_WEAK
259void
260operator delete[] (void* ptr, size_t, std::align_val_t alignment) noexcept
261{
262 ::operator delete[](ptr, alignment);
139static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) {
140 if (size == 0)
141 size = 1;
142 if (static_cast<size_t>(alignment) < sizeof(void*))
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);
263241}
264242
265243#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION