diff --git a/lib/libcxxabi/include/__cxxabi_config.h b/lib/libcxxabi/include/__cxxabi_config.h index e8aa37e6d5..759445dac9 100644 --- a/lib/libcxxabi/include/__cxxabi_config.h +++ b/lib/libcxxabi/include/__cxxabi_config.h @@ -103,4 +103,10 @@ #define _LIBCXXABI_DTOR_FUNC #endif +#if __cplusplus < 201103L +# define _LIBCXXABI_NOEXCEPT throw() +#else +# define _LIBCXXABI_NOEXCEPT noexcept +#endif + #endif // ____CXXABI_CONFIG_H diff --git a/lib/libcxxabi/include/cxxabi.h b/lib/libcxxabi/include/cxxabi.h index 8d1b5c9b55..9ea93680f6 100644 --- a/lib/libcxxabi/include/cxxabi.h +++ b/lib/libcxxabi/include/cxxabi.h @@ -43,16 +43,16 @@ extern "C" { // 2.4.2 Allocating the Exception Object extern _LIBCXXABI_FUNC_VIS void * -__cxa_allocate_exception(size_t thrown_size) throw(); +__cxa_allocate_exception(size_t thrown_size) _LIBCXXABI_NOEXCEPT; extern _LIBCXXABI_FUNC_VIS void -__cxa_free_exception(void *thrown_exception) throw(); +__cxa_free_exception(void *thrown_exception) _LIBCXXABI_NOEXCEPT; // This function is an LLVM extension, which mirrors the same extension in libsupc++ and libcxxrt extern _LIBCXXABI_FUNC_VIS __cxa_exception* #ifdef __wasm__ // In Wasm, a destructor returns its argument -__cxa_init_primary_exception(void* object, std::type_info* tinfo, void*(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw(); +__cxa_init_primary_exception(void* object, std::type_info* tinfo, void*(_LIBCXXABI_DTOR_FUNC* dest)(void*)) _LIBCXXABI_NOEXCEPT; #else -__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) throw(); +__cxa_init_primary_exception(void* object, std::type_info* tinfo, void(_LIBCXXABI_DTOR_FUNC* dest)(void*)) _LIBCXXABI_NOEXCEPT; #endif // 2.4.3 Throwing the Exception Object @@ -66,13 +66,13 @@ __cxa_throw(void *thrown_exception, std::type_info *tinfo, // 2.5.3 Exception Handlers extern _LIBCXXABI_FUNC_VIS void * -__cxa_get_exception_ptr(void *exceptionObject) throw(); +__cxa_get_exception_ptr(void *exceptionObject) _LIBCXXABI_NOEXCEPT; extern _LIBCXXABI_FUNC_VIS void * -__cxa_begin_catch(void *exceptionObject) throw(); +__cxa_begin_catch(void *exceptionObject) _LIBCXXABI_NOEXCEPT; extern _LIBCXXABI_FUNC_VIS void __cxa_end_catch(); #if defined(_LIBCXXABI_ARM_EHABI) extern _LIBCXXABI_FUNC_VIS bool -__cxa_begin_cleanup(void *exceptionObject) throw(); +__cxa_begin_cleanup(void *exceptionObject) _LIBCXXABI_NOEXCEPT; extern _LIBCXXABI_FUNC_VIS void __cxa_end_cleanup(); #endif extern _LIBCXXABI_FUNC_VIS std::type_info *__cxa_current_exception_type(); @@ -80,7 +80,7 @@ extern _LIBCXXABI_FUNC_VIS std::type_info *__cxa_current_exception_type(); // GNU extension // Calls `terminate` with the current exception being caught. This function is used by GCC when a `noexcept` function // throws an exception inside a try/catch block and doesn't catch it. -extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_call_terminate(void*) throw(); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_call_terminate(void*) _LIBCXXABI_NOEXCEPT; // 2.5.4 Rethrowing Exceptions extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_rethrow(); @@ -168,23 +168,23 @@ extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name, // Apple additions to support C++ 0x exception_ptr class // These are primitives to wrap a smart pointer around an exception object -extern _LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() throw(); +extern _LIBCXXABI_FUNC_VIS void *__cxa_current_primary_exception() _LIBCXXABI_NOEXCEPT; extern _LIBCXXABI_FUNC_VIS void __cxa_rethrow_primary_exception(void *primary_exception); extern _LIBCXXABI_FUNC_VIS void -__cxa_increment_exception_refcount(void *primary_exception) throw(); +__cxa_increment_exception_refcount(void *primary_exception) _LIBCXXABI_NOEXCEPT; extern _LIBCXXABI_FUNC_VIS void -__cxa_decrement_exception_refcount(void *primary_exception) throw(); +__cxa_decrement_exception_refcount(void *primary_exception) _LIBCXXABI_NOEXCEPT; // Apple extension to support std::uncaught_exception() -extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() throw(); -extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() throw(); +extern _LIBCXXABI_FUNC_VIS bool __cxa_uncaught_exception() _LIBCXXABI_NOEXCEPT; +extern _LIBCXXABI_FUNC_VIS unsigned int __cxa_uncaught_exceptions() _LIBCXXABI_NOEXCEPT; #if defined(__linux__) || defined(__Fuchsia__) // Linux and Fuchsia TLS support. Not yet an official part of the Itanium ABI. // https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables extern _LIBCXXABI_FUNC_VIS int __cxa_thread_atexit(void (*)(void *), void *, - void *) throw(); + void *) _LIBCXXABI_NOEXCEPT; #endif } // extern "C" diff --git a/lib/libcxxabi/src/abort_message.cpp b/lib/libcxxabi/src/abort_message.cpp index 859a5031b9..d51d9d87d3 100644 --- a/lib/libcxxabi/src/abort_message.cpp +++ b/lib/libcxxabi/src/abort_message.cpp @@ -12,13 +12,8 @@ #include "abort_message.h" #ifdef __BIONIC__ -# include -# if __ANDROID_API__ >= 21 -# include - extern "C" void android_set_abort_message(const char* msg); -# else -# include -# endif // __ANDROID_API__ >= 21 +# include +extern "C" void android_set_abort_message(const char* msg); #endif // __BIONIC__ #if defined(__APPLE__) && __has_include() @@ -26,7 +21,7 @@ # define _LIBCXXABI_USE_CRASHREPORTER_CLIENT #endif -void abort_message(const char* format, ...) +void __abort_message(const char* format, ...) { // Write message to stderr. We do this before formatting into a // variable-size buffer so that we still get some information if @@ -59,7 +54,6 @@ void abort_message(const char* format, ...) vasprintf(&buffer, format, list); va_end(list); -# if __ANDROID_API__ >= 21 // Show error in tombstone. android_set_abort_message(buffer); @@ -67,12 +61,6 @@ void abort_message(const char* format, ...) openlog("libc++abi", 0, 0); syslog(LOG_CRIT, "%s", buffer); closelog(); -# else - // The good error reporting wasn't available in Android until L. Since we're - // about to abort anyway, just call __assert2, which will log _somewhere_ - // (tombstone and/or logcat) in older releases. - __assert2(__FILE__, __LINE__, __func__, buffer); -# endif // __ANDROID_API__ >= 21 #endif // __BIONIC__ abort(); diff --git a/lib/libcxxabi/src/abort_message.h b/lib/libcxxabi/src/abort_message.h index 2cd09db1fb..85d6ba36e2 100644 --- a/lib/libcxxabi/src/abort_message.h +++ b/lib/libcxxabi/src/abort_message.h @@ -12,7 +12,7 @@ #include "cxxabi.h" extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void -abort_message(const char *format, ...) __attribute__((format(printf, 1, 2))); +__abort_message(const char *format, ...) __attribute__((format(printf, 1, 2))); #ifndef _LIBCXXABI_ASSERT // zig patch: respect NDEBUG. Otherwise the file path makes it into the binary, @@ -24,7 +24,7 @@ abort_message(const char *format, ...) __attribute__((format(printf, 1, 2))); do { \ if (!(expr)) { \ char const* __msg = (msg); \ - ::abort_message("%s:%d: %s", __FILE__, __LINE__, __msg); \ + ::__abort_message("%s:%d: %s", __FILE__, __LINE__, __msg); \ } \ } while (false) diff --git a/lib/libcxxabi/src/cxa_default_handlers.cpp b/lib/libcxxabi/src/cxa_default_handlers.cpp index 7bcfca069f..b029982ea8 100644 --- a/lib/libcxxabi/src/cxa_default_handlers.cpp +++ b/lib/libcxxabi/src/cxa_default_handlers.cpp @@ -10,8 +10,7 @@ //===----------------------------------------------------------------------===// #include -#include -#include +#include #include "abort_message.h" #include "cxxabi.h" #include "cxa_handlers.h" @@ -23,17 +22,7 @@ static constinit const char* cause = "uncaught"; -#ifndef _LIBCXXABI_NO_EXCEPTIONS -// Demangle the given string, or return the string as-is in case of an error. -static std::unique_ptr demangle(char const* str) -{ -#if !defined(LIBCXXABI_NON_DEMANGLING_TERMINATE) - if (const char* result = __cxxabiv1::__cxa_demangle(str, nullptr, nullptr, nullptr)) - return {result, [](char const* p) { std::free(const_cast(p)); }}; -#endif - return {str, [](char const*) { /* nothing to free */ }}; -} - +# ifndef _LIBCXXABI_NO_EXCEPTIONS __attribute__((noreturn)) static void demangling_terminate_handler() { @@ -42,18 +31,18 @@ static void demangling_terminate_handler() // If there is no uncaught exception, just note that we're terminating if (!globals) - abort_message("terminating"); + __abort_message("terminating"); __cxa_exception* exception_header = globals->caughtExceptions; if (!exception_header) - abort_message("terminating"); + __abort_message("terminating"); _Unwind_Exception* unwind_exception = reinterpret_cast<_Unwind_Exception*>(exception_header + 1) - 1; // If we're terminating due to a foreign exception if (!__isOurExceptionClass(unwind_exception)) - abort_message("terminating due to %s foreign exception", cause); + __abort_message("terminating due to %s foreign exception", cause); void* thrown_object = __getExceptionClass(unwind_exception) == kOurDependentExceptionClass ? @@ -61,7 +50,17 @@ static void demangling_terminate_handler() exception_header + 1; const __shim_type_info* thrown_type = static_cast(exception_header->exceptionType); - auto name = demangle(thrown_type->name()); + + auto name = [str = thrown_type->name()] { +# ifndef LIBCXXABI_NON_DEMANGLING_TERMINATE + if (const char* result = __cxxabiv1::__cxa_demangle(str, nullptr, nullptr, nullptr)) + // We're about to abort(), this memory can never be freed; so it's fine + // to just return a raw pointer + return result; +# endif + return str; + }(); + // If the uncaught exception can be caught with std::exception& const __shim_type_info* catch_type = static_cast(&typeid(std::exception)); @@ -69,19 +68,19 @@ static void demangling_terminate_handler() { // Include the what() message from the exception const std::exception* e = static_cast(thrown_object); - abort_message("terminating due to %s exception of type %s: %s", cause, name.get(), e->what()); + __abort_message("terminating due to %s exception of type %s: %s", cause, name, e->what()); } else { // Else just note that we're terminating due to an exception - abort_message("terminating due to %s exception of type %s", cause, name.get()); + __abort_message("terminating due to %s exception of type %s", cause, name); } } #else // !_LIBCXXABI_NO_EXCEPTIONS __attribute__((noreturn)) static void demangling_terminate_handler() { - abort_message("terminating"); + __abort_message("terminating"); } #endif // !_LIBCXXABI_NO_EXCEPTIONS diff --git a/lib/libcxxabi/src/cxa_demangle.cpp b/lib/libcxxabi/src/cxa_demangle.cpp index bece33a007..4756d83436 100644 --- a/lib/libcxxabi/src/cxa_demangle.cpp +++ b/lib/libcxxabi/src/cxa_demangle.cpp @@ -28,10 +28,6 @@ using namespace itanium_demangle; -constexpr const char *itanium_demangle::FloatData::spec; -constexpr const char *itanium_demangle::FloatData::spec; -constexpr const char *itanium_demangle::FloatData::spec; - // := _ # when number < 10 // := __ _ # when number >= 10 // extension := decimal-digit+ # at the end of string diff --git a/lib/libcxxabi/src/cxa_exception_storage.cpp b/lib/libcxxabi/src/cxa_exception_storage.cpp index c842da195a..05da6a48e3 100644 --- a/lib/libcxxabi/src/cxa_exception_storage.cpp +++ b/lib/libcxxabi/src/cxa_exception_storage.cpp @@ -56,17 +56,17 @@ extern "C" { namespace __cxxabiv1 { namespace { std::__libcpp_tls_key key_; - std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER; + constinit std::__libcpp_exec_once_flag flag_ = _LIBCPP_EXEC_ONCE_INITIALIZER; void _LIBCPP_TLS_DESTRUCTOR_CC destruct_(void *p) { __free_with_fallback(p); if (0 != std::__libcpp_tls_set(key_, NULL)) - abort_message("cannot zero out thread value for __cxa_get_globals()"); + __abort_message("cannot zero out thread value for __cxa_get_globals()"); } void construct_() { if (0 != std::__libcpp_tls_create(&key_, destruct_)) - abort_message("cannot create thread specific key for __cxa_get_globals()"); + __abort_message("cannot create thread specific key for __cxa_get_globals()"); } } // namespace @@ -80,9 +80,9 @@ extern "C" { retVal = static_cast<__cxa_eh_globals*>( __calloc_with_fallback(1, sizeof(__cxa_eh_globals))); if (NULL == retVal) - abort_message("cannot allocate __cxa_eh_globals"); + __abort_message("cannot allocate __cxa_eh_globals"); if (0 != std::__libcpp_tls_set(key_, retVal)) - abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()"); + __abort_message("std::__libcpp_tls_set failure in __cxa_get_globals()"); } return retVal; } @@ -94,7 +94,7 @@ extern "C" { __cxa_eh_globals *__cxa_get_globals_fast() { // First time through, create the key. if (0 != std::__libcpp_execute_once(&flag_, construct_)) - abort_message("execute once failure in __cxa_get_globals_fast()"); + __abort_message("execute once failure in __cxa_get_globals_fast()"); return static_cast<__cxa_eh_globals*>(std::__libcpp_tls_get(key_)); } } // extern "C" diff --git a/lib/libcxxabi/src/cxa_guard_impl.h b/lib/libcxxabi/src/cxa_guard_impl.h index 320501cb85..191a589176 100644 --- a/lib/libcxxabi/src/cxa_guard_impl.h +++ b/lib/libcxxabi/src/cxa_guard_impl.h @@ -91,7 +91,7 @@ // the former. #ifdef BUILDING_CXA_GUARD # include "abort_message.h" -# define ABORT_WITH_MESSAGE(...) ::abort_message(__VA_ARGS__) +# define ABORT_WITH_MESSAGE(...) ::__abort_message(__VA_ARGS__) #elif defined(TESTING_CXA_GUARD) # define ABORT_WITH_MESSAGE(...) ::abort() #else @@ -156,12 +156,12 @@ private: // PlatformGetThreadID //===----------------------------------------------------------------------===// -#if defined(__APPLE__) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +#if defined(__APPLE__) && _LIBCPP_HAS_THREAD_API_PTHREAD uint32_t PlatformThreadID() { static_assert(sizeof(mach_port_t) == sizeof(uint32_t), ""); return static_cast(pthread_mach_thread_np(std::__libcpp_thread_get_current_id())); } -#elif defined(SYS_gettid) && defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +#elif defined(SYS_gettid) && _LIBCPP_HAS_THREAD_API_PTHREAD uint32_t PlatformThreadID() { static_assert(sizeof(pid_t) == sizeof(uint32_t), ""); return static_cast(syscall(SYS_gettid)); @@ -676,8 +676,8 @@ static_assert(CurrentImplementation != Implementation::Futex || PlatformSupports using SelectedImplementation = SelectImplementation::type; -} // end namespace -} // end namespace __cxxabiv1 +} // namespace +} // namespace __cxxabiv1 #if defined(__clang__) # pragma clang diagnostic pop diff --git a/lib/libcxxabi/src/cxa_handlers.cpp b/lib/libcxxabi/src/cxa_handlers.cpp index 344250dde0..f879ff0d8f 100644 --- a/lib/libcxxabi/src/cxa_handlers.cpp +++ b/lib/libcxxabi/src/cxa_handlers.cpp @@ -33,7 +33,7 @@ __unexpected(unexpected_handler func) { func(); // unexpected handler should not return - abort_message("unexpected_handler unexpectedly returned"); + __abort_message("unexpected_handler unexpectedly returned"); } __attribute__((noreturn)) @@ -58,13 +58,13 @@ __terminate(terminate_handler func) noexcept #endif // _LIBCXXABI_NO_EXCEPTIONS func(); // handler should not return - abort_message("terminate_handler unexpectedly returned"); + __abort_message("terminate_handler unexpectedly returned"); #ifndef _LIBCXXABI_NO_EXCEPTIONS } catch (...) { // handler should not throw exception - abort_message("terminate_handler unexpectedly threw an exception"); + __abort_message("terminate_handler unexpectedly threw an exception"); } #endif // _LIBCXXABI_NO_EXCEPTIONS } diff --git a/lib/libcxxabi/src/cxa_personality.cpp b/lib/libcxxabi/src/cxa_personality.cpp index 843a18a4cb..5f6e75c5be 100644 --- a/lib/libcxxabi/src/cxa_personality.cpp +++ b/lib/libcxxabi/src/cxa_personality.cpp @@ -167,7 +167,7 @@ uintptr_t readPointerHelper(const uint8_t*& p) { return static_cast(value); } -} // end namespace +} // namespace extern "C" { diff --git a/lib/libcxxabi/src/cxa_thread_atexit.cpp b/lib/libcxxabi/src/cxa_thread_atexit.cpp index c6bd0aa323..8546cfe48c 100644 --- a/lib/libcxxabi/src/cxa_thread_atexit.cpp +++ b/lib/libcxxabi/src/cxa_thread_atexit.cpp @@ -89,7 +89,7 @@ namespace { // __cxa_thread_atexit() may be called arbitrarily late (for example, from // global destructors or atexit() handlers). if (std::__libcpp_tls_create(&dtors_key, run_dtors) != 0) { - abort_message("std::__libcpp_tls_create() failed in __cxa_thread_atexit()"); + __abort_message("std::__libcpp_tls_create() failed in __cxa_thread_atexit()"); } } diff --git a/lib/libcxxabi/src/cxa_vector.cpp b/lib/libcxxabi/src/cxa_vector.cpp index 17d942a6e6..857ee27d06 100644 --- a/lib/libcxxabi/src/cxa_vector.cpp +++ b/lib/libcxxabi/src/cxa_vector.cpp @@ -121,7 +121,7 @@ void throw_bad_array_new_length() { #ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_array_new_length(); #else - abort_message("__cxa_vec_new failed to allocate memory"); + __abort_message("__cxa_vec_new failed to allocate memory"); #endif } diff --git a/lib/libcxxabi/src/cxa_virtual.cpp b/lib/libcxxabi/src/cxa_virtual.cpp index c868672e00..8f4fdd0919 100644 --- a/lib/libcxxabi/src/cxa_virtual.cpp +++ b/lib/libcxxabi/src/cxa_virtual.cpp @@ -13,12 +13,12 @@ namespace __cxxabiv1 { extern "C" { _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_pure_virtual(void) { - abort_message("Pure virtual function called!"); + __abort_message("Pure virtual function called!"); } _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void) { - abort_message("Deleted virtual function called!"); + __abort_message("Deleted virtual function called!"); } } // extern "C" } // abi diff --git a/lib/libcxxabi/src/demangle/DemangleConfig.h b/lib/libcxxabi/src/demangle/DemangleConfig.h index d67d89bdb0..06fd223f55 100644 --- a/lib/libcxxabi/src/demangle/DemangleConfig.h +++ b/lib/libcxxabi/src/demangle/DemangleConfig.h @@ -15,7 +15,7 @@ // build systems to override this value. // https://libcxx.llvm.org/UsingLibcxx.html#enabling-the-safe-libc-mode #ifndef _LIBCPP_VERBOSE_ABORT -#define _LIBCPP_VERBOSE_ABORT(...) abort_message(__VA_ARGS__) +#define _LIBCPP_VERBOSE_ABORT(...) __abort_message(__VA_ARGS__) #include "../abort_message.h" #endif diff --git a/lib/libcxxabi/src/demangle/ItaniumDemangle.h b/lib/libcxxabi/src/demangle/ItaniumDemangle.h index 36bf454636..3df41b5f4d 100644 --- a/lib/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/lib/libcxxabi/src/demangle/ItaniumDemangle.h @@ -19,7 +19,6 @@ #include "DemangleConfig.h" #include "StringViewExtras.h" #include "Utility.h" -#include <__cxxabi_config.h> #include #include #include @@ -31,7 +30,7 @@ #include #include -#ifdef _LIBCXXABI_COMPILER_CLANG +#if defined(__clang__) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-template" #endif @@ -157,6 +156,8 @@ public: } }; +class NodeArray; + // Base class of all AST nodes. The AST is built by the parser, then is // traversed by the printLeft/Right functions to produce a demangled string. class Node { @@ -200,8 +201,7 @@ private: Prec Precedence : 6; - // FIXME: Make these protected. -public: +protected: /// Tracks if this node has a component on its right side, in which case we /// need to call printRight. Cache RHSComponentCache : 2; @@ -255,6 +255,9 @@ public: Kind getKind() const { return K; } Prec getPrecedence() const { return Precedence; } + Cache getRHSComponentCache() const { return RHSComponentCache; } + Cache getArrayCache() const { return ArrayCache; } + Cache getFunctionCache() const { return FunctionCache; } virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; } virtual bool hasArraySlow(OutputBuffer &) const { return false; } @@ -292,6 +295,13 @@ public: // implementation. virtual void printRight(OutputBuffer &) const {} + // Print an initializer list of this type. Returns true if we printed a custom + // representation, false if nothing has been printed and the default + // representation should be used. + virtual bool printInitListAsType(OutputBuffer &, const NodeArray &) const { + return false; + } + virtual std::string_view getBaseName() const { return {}; } // Silence compiler warnings, this dtor will never be called. @@ -338,6 +348,10 @@ public: FirstElement = false; } } + + // Print an array of integer literals as a string literal. Returns whether we + // could do so. + bool printAsString(OutputBuffer &OB) const; }; struct NodeArrayNode : Node { @@ -424,8 +438,8 @@ protected: public: QualType(const Node *Child_, Qualifiers Quals_) - : Node(KQualType, Child_->RHSComponentCache, - Child_->ArrayCache, Child_->FunctionCache), + : Node(KQualType, Child_->getRHSComponentCache(), Child_->getArrayCache(), + Child_->getFunctionCache()), Quals(Quals_), Child(Child_) {} Qualifiers getQuals() const { return Quals; } @@ -554,8 +568,8 @@ struct AbiTagAttr : Node { std::string_view Tag; AbiTagAttr(Node *Base_, std::string_view Tag_) - : Node(KAbiTagAttr, Base_->RHSComponentCache, Base_->ArrayCache, - Base_->FunctionCache), + : Node(KAbiTagAttr, Base_->getRHSComponentCache(), Base_->getArrayCache(), + Base_->getFunctionCache()), Base(Base_), Tag(Tag_) {} template void match(Fn F) const { F(Base, Tag); } @@ -615,7 +629,7 @@ class PointerType final : public Node { public: PointerType(const Node *Pointee_) - : Node(KPointerType, Pointee_->RHSComponentCache), + : Node(KPointerType, Pointee_->getRHSComponentCache()), Pointee(Pointee_) {} const Node *getPointee() const { return Pointee; } @@ -699,7 +713,7 @@ class ReferenceType : public Node { public: ReferenceType(const Node *Pointee_, ReferenceKind RK_) - : Node(KReferenceType, Pointee_->RHSComponentCache), + : Node(KReferenceType, Pointee_->getRHSComponentCache()), Pointee(Pointee_), RK(RK_) {} template void match(Fn F) const { F(Pointee, RK); } @@ -742,7 +756,7 @@ class PointerToMemberType final : public Node { public: PointerToMemberType(const Node *ClassType_, const Node *MemberType_) - : Node(KPointerToMemberType, MemberType_->RHSComponentCache), + : Node(KPointerToMemberType, MemberType_->getRHSComponentCache()), ClassType(ClassType_), MemberType(MemberType_) {} template void match(Fn F) const { F(ClassType, MemberType); } @@ -795,6 +809,15 @@ public: OB += "]"; Base->printRight(OB); } + + bool printInitListAsType(OutputBuffer &OB, + const NodeArray &Elements) const override { + if (Base->getKind() == KNameType && + static_cast(Base)->getName() == "char") { + return Elements.printAsString(OB); + } + return false; + } }; class FunctionType final : public Node { @@ -1383,16 +1406,14 @@ class ParameterPack final : public Node { public: ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) { ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown; - if (std::all_of(Data.begin(), Data.end(), [](Node* P) { - return P->ArrayCache == Cache::No; - })) + if (std::all_of(Data.begin(), Data.end(), + [](Node *P) { return P->getArrayCache() == Cache::No; })) ArrayCache = Cache::No; - if (std::all_of(Data.begin(), Data.end(), [](Node* P) { - return P->FunctionCache == Cache::No; - })) + if (std::all_of(Data.begin(), Data.end(), + [](Node *P) { return P->getFunctionCache() == Cache::No; })) FunctionCache = Cache::No; - if (std::all_of(Data.begin(), Data.end(), [](Node* P) { - return P->RHSComponentCache == Cache::No; + if (std::all_of(Data.begin(), Data.end(), [](Node *P) { + return P->getRHSComponentCache() == Cache::No; })) RHSComponentCache = Cache::No; } @@ -2056,17 +2077,23 @@ public: class CallExpr : public Node { const Node *Callee; NodeArray Args; + bool IsParen; // (func)(args ...) ? public: - CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_) - : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {} + CallExpr(const Node *Callee_, NodeArray Args_, bool IsParen_, Prec Prec_) + : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_), + IsParen(IsParen_) {} template void match(Fn F) const { - F(Callee, Args, getPrecedence()); + F(Callee, Args, IsParen, getPrecedence()); } void printLeft(OutputBuffer &OB) const override { + if (IsParen) + OB.printOpen(); Callee->print(OB); + if (IsParen) + OB.printClose(); OB.printOpen(); Args.printWithComma(OB); OB.printClose(); @@ -2226,8 +2253,11 @@ public: template void match(Fn F) const { F(Ty, Inits); } void printLeft(OutputBuffer &OB) const override { - if (Ty) + if (Ty) { + if (Ty->printInitListAsType(OB, Inits)) + return; Ty->print(OB); + } OB += '{'; Inits.printWithComma(OB); OB += '}'; @@ -2434,6 +2464,8 @@ public: if (Type.size() <= 3) OB += Type; } + + std::string_view value() const { return Value; } }; class RequiresExpr : public Node { @@ -2605,6 +2637,94 @@ template struct NodeKind; }; #include "ItaniumNodes.def" +inline bool NodeArray::printAsString(OutputBuffer &OB) const { + auto StartPos = OB.getCurrentPosition(); + auto Fail = [&OB, StartPos] { + OB.setCurrentPosition(StartPos); + return false; + }; + + OB += '"'; + bool LastWasNumericEscape = false; + for (const Node *Element : *this) { + if (Element->getKind() != Node::KIntegerLiteral) + return Fail(); + int integer_value = 0; + for (char c : static_cast(Element)->value()) { + if (c < '0' || c > '9' || integer_value > 25) + return Fail(); + integer_value *= 10; + integer_value += c - '0'; + } + if (integer_value > 255) + return Fail(); + + // Insert a `""` to avoid accidentally extending a numeric escape. + if (LastWasNumericEscape) { + if ((integer_value >= '0' && integer_value <= '9') || + (integer_value >= 'a' && integer_value <= 'f') || + (integer_value >= 'A' && integer_value <= 'F')) { + OB += "\"\""; + } + } + + LastWasNumericEscape = false; + + // Determine how to print this character. + switch (integer_value) { + case '\a': + OB += "\\a"; + break; + case '\b': + OB += "\\b"; + break; + case '\f': + OB += "\\f"; + break; + case '\n': + OB += "\\n"; + break; + case '\r': + OB += "\\r"; + break; + case '\t': + OB += "\\t"; + break; + case '\v': + OB += "\\v"; + break; + + case '"': + OB += "\\\""; + break; + case '\\': + OB += "\\\\"; + break; + + default: + // We assume that the character is ASCII, and use a numeric escape for all + // remaining non-printable ASCII characters. + if (integer_value < 32 || integer_value == 127) { + constexpr char Hex[] = "0123456789ABCDEF"; + OB += '\\'; + if (integer_value > 7) + OB += 'x'; + if (integer_value >= 16) + OB += Hex[integer_value >> 4]; + OB += Hex[integer_value & 0xF]; + LastWasNumericEscape = true; + break; + } + + // Assume all remaining characters are directly printable. + OB += (char)integer_value; + break; + } + } + OB += '"'; + return true; +} + template struct AbstractManglingParser { const char *First; const char *Last; @@ -2678,7 +2798,7 @@ template struct AbstractManglingParser { bool TryToParseTemplateArgs = true; bool PermitForwardTemplateReferences = false; - bool InConstraintExpr = false; + bool HasIncompleteTemplateParameterTracking = false; size_t ParsingLambdaParamsAtLevel = (size_t)-1; unsigned NumSyntheticTemplateParameters[3] = {}; @@ -3240,9 +3360,12 @@ const typename AbstractManglingParser< "operator co_await"}, {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "}, {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"}, - {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"}, + {"cl", OperatorInfo::Call, /*Paren*/ false, Node::Prec::Postfix, + "operator()"}, {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"}, {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"}, + {"cp", OperatorInfo::Call, /*Paren*/ true, Node::Prec::Postfix, + "operator()"}, {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="}, {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary, @@ -3319,7 +3442,7 @@ AbstractManglingParser::parseOperatorEncoding() { return nullptr; // We can't use lower_bound as that can link to symbols in the C++ library, - // and this must remain independant of that. + // and this must remain independent of that. size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds. while (upper != lower) { size_t middle = (upper + lower) / 2; @@ -4207,9 +4330,12 @@ Node *AbstractManglingParser::parseType() { case 'h': First += 2; return make("half"); - // ::= DF _ # ISO/IEC TS 18661 binary floating point (N bits) + // ::= DF16b # C++23 std::bfloat16_t + // ::= DF _ # ISO/IEC TS 18661 binary floating point (N bits) case 'F': { First += 2; + if (consumeIf("16b")) + return make("std::bfloat16_t"); Node *DimensionNumber = make(parseNumber()); if (!DimensionNumber) return nullptr; @@ -4217,6 +4343,101 @@ Node *AbstractManglingParser::parseType() { return nullptr; return make(DimensionNumber); } + // ::= [DS] DA # N1169 fixed-point [_Sat] T _Accum + // ::= [DS] DR # N1169 fixed-point [_Sat] T _Frac + // + // ::= s # short + // ::= t # unsigned short + // ::= i # plain + // ::= j # unsigned + // ::= l # long + // ::= m # unsigned long + case 'A': { + char c = look(2); + First += 3; + switch (c) { + case 's': + return make("short _Accum"); + case 't': + return make("unsigned short _Accum"); + case 'i': + return make("_Accum"); + case 'j': + return make("unsigned _Accum"); + case 'l': + return make("long _Accum"); + case 'm': + return make("unsigned long _Accum"); + default: + return nullptr; + } + } + case 'R': { + char c = look(2); + First += 3; + switch (c) { + case 's': + return make("short _Fract"); + case 't': + return make("unsigned short _Fract"); + case 'i': + return make("_Fract"); + case 'j': + return make("unsigned _Fract"); + case 'l': + return make("long _Fract"); + case 'm': + return make("unsigned long _Fract"); + default: + return nullptr; + } + } + case 'S': { + First += 2; + if (look() != 'D') + return nullptr; + if (look(1) == 'A') { + char c = look(2); + First += 3; + switch (c) { + case 's': + return make("_Sat short _Accum"); + case 't': + return make("_Sat unsigned short _Accum"); + case 'i': + return make("_Sat _Accum"); + case 'j': + return make("_Sat unsigned _Accum"); + case 'l': + return make("_Sat long _Accum"); + case 'm': + return make("_Sat unsigned long _Accum"); + default: + return nullptr; + } + } + if (look(1) == 'R') { + char c = look(2); + First += 3; + switch (c) { + case 's': + return make("_Sat short _Fract"); + case 't': + return make("_Sat unsigned short _Fract"); + case 'i': + return make("_Sat _Fract"); + case 'j': + return make("_Sat unsigned _Fract"); + case 'l': + return make("_Sat long _Fract"); + case 'm': + return make("_Sat unsigned long _Fract"); + default: + return nullptr; + } + } + return nullptr; + } // ::= DB _ # C23 signed _BitInt(N) // ::= DB _ # C23 signed _BitInt(N) // ::= DU _ # C23 unsigned _BitInt(N) @@ -4337,6 +4558,7 @@ Node *AbstractManglingParser::parseType() { // parse them, take the second production. if (TryToParseTemplateArgs && look() == 'I') { + Subs.push_back(Result); Node *TA = getDerived().parseTemplateArgs(); if (TA == nullptr) return nullptr; @@ -4819,7 +5041,8 @@ template Node *AbstractManglingParser::parseConstraintExpr() { // Within this expression, all enclosing template parameter lists are in // scope. - ScopedOverride SaveInConstraintExpr(InConstraintExpr, true); + ScopedOverride SaveIncompleteTemplateParameterTracking( + HasIncompleteTemplateParameterTracking, true); return getDerived().parseExpr(); } @@ -4888,6 +5111,7 @@ Node *AbstractManglingParser::parseRequiresExpr() { // ::= // ::= // ::= cl + E # call +// ::= cp * E # (name) (expr-list), call that would use argument-dependent lookup but for the parentheses // ::= cv # conversion with one argument // ::= cv _ * E # conversion with a different number of arguments // ::= [gs] nw * _ E # new (expr-list) type @@ -5023,7 +5247,7 @@ Node *AbstractManglingParser::parseExpr() { Names.push_back(E); } return make(Callee, popTrailingNodeArray(ExprsBegin), - Op->getPrecedence()); + /*IsParen=*/Op->getFlag(), Op->getPrecedence()); } case OperatorInfo::CCast: { // C Cast: (type)expr @@ -5210,7 +5434,7 @@ Node *AbstractManglingParser::parseExpr() { } } return make(Name, popTrailingNodeArray(ExprsBegin), - Node::Prec::Postfix); + /*IsParen=*/false, Node::Prec::Postfix); } // Only unresolved names remain. @@ -5677,7 +5901,7 @@ Node *AbstractManglingParser::parseTemplateParam() { // substitute them all within a , so print the // parameter numbering instead for now. // TODO: Track all enclosing template parameters and substitute them here. - if (InConstraintExpr) { + if (HasIncompleteTemplateParameterTracking) { return make(std::string_view(Begin, First - 1 - Begin)); } @@ -5738,6 +5962,12 @@ Node *AbstractManglingParser::parseTemplateParamDecl( } if (consumeIf("Tk")) { + // We don't track enclosing template parameter levels well enough to + // reliably demangle template parameter substitutions, so print an arbitrary + // string in place of a parameter for now. + // TODO: Track all enclosing template parameters and demangle substitutions. + ScopedOverride SaveIncompleteTemplateParameterTrackingExpr( + HasIncompleteTemplateParameterTracking, true); Node *Constraint = getDerived().parseName(); if (!Constraint) return nullptr; @@ -5948,7 +6178,7 @@ struct ManglingParser : AbstractManglingParser, Alloc> { DEMANGLE_NAMESPACE_END -#ifdef _LIBCXXABI_COMPILER_CLANG +#if defined(__clang__) #pragma clang diagnostic pop #endif diff --git a/lib/libcxxabi/src/fallback_malloc.cpp b/lib/libcxxabi/src/fallback_malloc.cpp index 76bd2e9bcd..75788fe9be 100644 --- a/lib/libcxxabi/src/fallback_malloc.cpp +++ b/lib/libcxxabi/src/fallback_malloc.cpp @@ -259,7 +259,7 @@ void* __aligned_malloc_with_fallback(size_t size) { #if defined(_WIN32) if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size)) return dest; -#elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) +#elif !_LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION if (void* dest = ::malloc(size)) return dest; #else @@ -286,7 +286,7 @@ void __aligned_free_with_fallback(void* ptr) { if (is_fallback_ptr(ptr)) fallback_free(ptr); else { -#if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) +#if !_LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION ::free(ptr); #else std::__libcpp_aligned_free(ptr); diff --git a/lib/libcxxabi/src/private_typeinfo.cpp b/lib/libcxxabi/src/private_typeinfo.cpp index 9dba91e198..01a1d2603b 100644 --- a/lib/libcxxabi/src/private_typeinfo.cpp +++ b/lib/libcxxabi/src/private_typeinfo.cpp @@ -41,9 +41,11 @@ // Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST does not help since can_catch() calls // is_equal() with use_strcmp=false so the string names are not compared. -#include #include +#include +#include #include + #include "abort_message.h" #ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST @@ -589,10 +591,9 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, // .. and reset the pointer. adjustedPtr = nullptr; } - __base_type->has_unambiguous_public_base( - info, - static_cast(adjustedPtr) + offset_to_base, - (__offset_flags & __public_mask) ? path_below : not_public_path); + __base_type->has_unambiguous_public_base( + info, reinterpret_cast(reinterpret_cast(adjustedPtr) + offset_to_base), + (__offset_flags & __public_mask) ? path_below : not_public_path); } void diff --git a/lib/libcxxabi/src/stdlib_new_delete.cpp b/lib/libcxxabi/src/stdlib_new_delete.cpp index b802559d47..f386b28f0c 100644 --- a/lib/libcxxabi/src/stdlib_new_delete.cpp +++ b/lib/libcxxabi/src/stdlib_new_delete.cpp @@ -24,22 +24,22 @@ # error The _LIBCPP_WEAK macro should be already defined by libc++ #endif -#if defined(_LIBCXXABI_NO_EXCEPTIONS) != defined(_LIBCPP_HAS_NO_EXCEPTIONS) +#if defined(_LIBCXXABI_NO_EXCEPTIONS) != !_LIBCPP_HAS_EXCEPTIONS # error libc++ and libc++abi seem to disagree on whether exceptions are enabled #endif inline void __throw_bad_alloc_shim() { -#ifndef _LIBCPP_HAS_NO_EXCEPTIONS +#if _LIBCPP_HAS_EXCEPTIONS throw std::bad_alloc(); #else - abort_message("bad_alloc was thrown in -fno-exceptions mode"); + __abort_message("bad_alloc was thrown in -fno-exceptions mode"); #endif } #define _LIBCPP_ASSERT_SHIM(expr, str) \ do { \ if (!expr) \ - abort_message(str); \ + __abort_message(str); \ } while (false) // ------------------ BEGIN COPY ------------------ @@ -71,7 +71,7 @@ _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std } _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept { -#ifdef _LIBCPP_HAS_NO_EXCEPTIONS +#if !_LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION _LIBCPP_ASSERT_SHIM( !std::__is_function_overridden(static_cast(&operator new)), @@ -99,7 +99,7 @@ _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](s } _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept { -#ifdef _LIBCPP_HAS_NO_EXCEPTIONS +#if !_LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION _LIBCPP_ASSERT_SHIM( !std::__is_function_overridden(static_cast(&operator new[])), @@ -134,7 +134,7 @@ _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); } -#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) +#if _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) { if (size == 0) @@ -165,7 +165,7 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { } _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { -# ifdef _LIBCPP_HAS_NO_EXCEPTIONS +# if !_LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION _LIBCPP_ASSERT_SHIM( !std::__is_function_overridden(static_cast(&operator new)), @@ -194,7 +194,7 @@ operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { } _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { -# ifdef _LIBCPP_HAS_NO_EXCEPTIONS +# if !_LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION _LIBCPP_ASSERT_SHIM( !std::__is_function_overridden(static_cast(&operator new[])), @@ -240,5 +240,5 @@ _LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignmen ::operator delete[](ptr, alignment); } -#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION +#endif // _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION // ------------------ END COPY ------------------