diff --git a/lib/libcxxabi/src/cxa_default_handlers.cpp b/lib/libcxxabi/src/cxa_default_handlers.cpp index b029982ea8..97a6765fde 100644 --- a/lib/libcxxabi/src/cxa_default_handlers.cpp +++ b/lib/libcxxabi/src/cxa_default_handlers.cpp @@ -9,6 +9,7 @@ // new_handler. //===----------------------------------------------------------------------===// +#include // std::abort #include #include #include "abort_message.h" @@ -94,7 +95,7 @@ static void demangling_unexpected_handler() static constexpr std::terminate_handler default_terminate_handler = demangling_terminate_handler; static constexpr std::terminate_handler default_unexpected_handler = demangling_unexpected_handler; #else // !LIBCXXABI_SILENT_TERMINATE -static constexpr std::terminate_handler default_terminate_handler = ::abort; +static constexpr std::terminate_handler default_terminate_handler = std::abort; static constexpr std::terminate_handler default_unexpected_handler = std::terminate; #endif // !LIBCXXABI_SILENT_TERMINATE diff --git a/lib/libcxxabi/src/demangle/DemangleConfig.h b/lib/libcxxabi/src/demangle/DemangleConfig.h index 06fd223f55..7904e9d1eb 100644 --- a/lib/libcxxabi/src/demangle/DemangleConfig.h +++ b/lib/libcxxabi/src/demangle/DemangleConfig.h @@ -19,6 +19,14 @@ #include "../abort_message.h" #endif +#ifndef _LIBCPP_LOG_HARDENING_FAILURE +// Libc++abi does not have any functionality to log and continue, so we drop +// error messages when we build the demangler with `observe` assertion semantic. +// Once the layering with libc++ is improved, this could use the libc++ +// functionality to log hardening failures. +#define _LIBCPP_LOG_HARDENING_FAILURE(message) ((void)0) +#endif + #include #ifdef _MSC_VER diff --git a/lib/libcxxabi/src/demangle/ItaniumDemangle.h b/lib/libcxxabi/src/demangle/ItaniumDemangle.h index 3df41b5f4d..b306b20134 100644 --- a/lib/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/lib/libcxxabi/src/demangle/ItaniumDemangle.h @@ -21,6 +21,7 @@ #include "Utility.h" #include #include +#include #include #include #include @@ -38,8 +39,10 @@ DEMANGLE_NAMESPACE_BEGIN template class PODSmallVector { - static_assert(std::is_trivial::value, - "T is required to be a trivial type"); + static_assert(std::is_trivially_copyable::value, + "T is required to be a trivially copyable type"); + static_assert(std::is_trivially_default_constructible::value, + "T is required to be trivially default constructible"); T *First = nullptr; T *Last = nullptr; T *Cap = nullptr; @@ -162,18 +165,18 @@ class NodeArray; // traversed by the printLeft/Right functions to produce a demangled string. class Node { public: - enum Kind : unsigned char { + enum Kind : uint8_t { #define NODE(NodeKind) K##NodeKind, #include "ItaniumNodes.def" }; /// Three-way bool to track a cached value. Unknown is possible if this node /// has an unexpanded parameter pack below it that may affect this cache. - enum class Cache : unsigned char { Yes, No, Unknown, }; + enum class Cache : uint8_t { Yes, No, Unknown, }; /// Operator precedence for expression nodes. Used to determine required /// parens in expression emission. - enum class Prec { + enum class Prec : uint8_t { Primary, Postfix, Unary, @@ -281,20 +284,11 @@ public: } void print(OutputBuffer &OB) const { - printLeft(OB); + OB.printLeft(*this); if (RHSComponentCache != Cache::No) - printRight(OB); + OB.printRight(*this); } - // Print the "left" side of this Node into OutputBuffer. - virtual void printLeft(OutputBuffer &) const = 0; - - // Print the "right". This distinction is necessary to represent C++ types - // that appear on the RHS of their subtype, such as arrays or functions. - // Since most types don't have such a component, provide a default - // 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. @@ -310,6 +304,24 @@ public: #ifndef NDEBUG DEMANGLE_DUMP_METHOD void dump() const; #endif + +private: + friend class OutputBuffer; + + // Print the "left" side of this Node into OutputBuffer. + // + // Note, should only be called from OutputBuffer implementations. + // Call \ref OutputBuffer::printLeft instead. + virtual void printLeft(OutputBuffer &) const = 0; + + // Print the "right". This distinction is necessary to represent C++ types + // that appear on the RHS of their subtype, such as arrays or functions. + // Since most types don't have such a component, provide a default + // implementation. + // + // Note, should only be called from OutputBuffer implementations. + // Call \ref OutputBuffer::printRight instead. + virtual void printRight(OutputBuffer &) const {} }; class NodeArray { @@ -458,11 +470,11 @@ public: } void printLeft(OutputBuffer &OB) const override { - Child->printLeft(OB); + OB.printLeft(*Child); printQuals(OB); } - void printRight(OutputBuffer &OB) const override { Child->printRight(OB); } + void printRight(OutputBuffer &OB) const override { OB.printRight(*Child); } }; class ConversionOperatorType final : public Node { @@ -491,7 +503,7 @@ public: template void match(Fn F) const { F(Ty, Postfix); } void printLeft(OutputBuffer &OB) const override { - Ty->printLeft(OB); + OB.printLeft(*Ty); OB += Postfix; } }; @@ -577,7 +589,7 @@ struct AbiTagAttr : Node { std::string_view getBaseName() const override { return Base->getBaseName(); } void printLeft(OutputBuffer &OB) const override { - Base->printLeft(OB); + OB.printLeft(*Base); OB += "[abi:"; OB += Tag; OB += "]"; @@ -603,8 +615,6 @@ class ObjCProtoName : public Node { const Node *Ty; std::string_view Protocol; - friend class PointerType; - public: ObjCProtoName(const Node *Ty_, std::string_view Protocol_) : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {} @@ -616,6 +626,8 @@ public: static_cast(Ty)->getName() == "objc_object"; } + std::string_view getProtocol() const { return Protocol; } + void printLeft(OutputBuffer &OB) const override { Ty->print(OB); OB += "<"; @@ -644,7 +656,7 @@ public: // We rewrite objc_object* into id. if (Pointee->getKind() != KObjCProtoName || !static_cast(Pointee)->isObjCObject()) { - Pointee->printLeft(OB); + OB.printLeft(*Pointee); if (Pointee->hasArray(OB)) OB += " "; if (Pointee->hasArray(OB) || Pointee->hasFunction(OB)) @@ -653,7 +665,7 @@ public: } else { const auto *objcProto = static_cast(Pointee); OB += "id<"; - OB += objcProto->Protocol; + OB += objcProto->getProtocol(); OB += ">"; } } @@ -663,7 +675,7 @@ public: !static_cast(Pointee)->isObjCObject()) { if (Pointee->hasArray(OB) || Pointee->hasFunction(OB)) OB += ")"; - Pointee->printRight(OB); + OB.printRight(*Pointee); } } }; @@ -729,7 +741,7 @@ public: std::pair Collapsed = collapse(OB); if (!Collapsed.second) return; - Collapsed.second->printLeft(OB); + OB.printLeft(*Collapsed.second); if (Collapsed.second->hasArray(OB)) OB += " "; if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB)) @@ -746,7 +758,7 @@ public: return; if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB)) OB += ")"; - Collapsed.second->printRight(OB); + OB.printRight(*Collapsed.second); } }; @@ -766,7 +778,7 @@ public: } void printLeft(OutputBuffer &OB) const override { - MemberType->printLeft(OB); + OB.printLeft(*MemberType); if (MemberType->hasArray(OB) || MemberType->hasFunction(OB)) OB += "("; else @@ -778,7 +790,7 @@ public: void printRight(OutputBuffer &OB) const override { if (MemberType->hasArray(OB) || MemberType->hasFunction(OB)) OB += ")"; - MemberType->printRight(OB); + OB.printRight(*MemberType); } }; @@ -798,7 +810,7 @@ public: bool hasRHSComponentSlow(OutputBuffer &) const override { return true; } bool hasArraySlow(OutputBuffer &) const override { return true; } - void printLeft(OutputBuffer &OB) const override { Base->printLeft(OB); } + void printLeft(OutputBuffer &OB) const override { OB.printLeft(*Base); } void printRight(OutputBuffer &OB) const override { if (OB.back() != ']') @@ -807,7 +819,7 @@ public: if (Dimension) Dimension->print(OB); OB += "]"; - Base->printRight(OB); + OB.printRight(*Base); } bool printInitListAsType(OutputBuffer &OB, @@ -851,7 +863,7 @@ public: // by printing out the return types's left, then print our parameters, then // finally print right of the return type. void printLeft(OutputBuffer &OB) const override { - Ret->printLeft(OB); + OB.printLeft(*Ret); OB += " "; } @@ -859,7 +871,7 @@ public: OB.printOpen(); Params.printWithComma(OB); OB.printClose(); - Ret->printRight(OB); + OB.printRight(*Ret); if (CVQuals & QualConst) OB += " const"; @@ -964,6 +976,8 @@ public: FunctionRefQual getRefQual() const { return RefQual; } NodeArray getParams() const { return Params; } const Node *getReturnType() const { return Ret; } + const Node *getAttrs() const { return Attrs; } + const Node *getRequires() const { return Requires; } bool hasRHSComponentSlow(OutputBuffer &) const override { return true; } bool hasFunctionSlow(OutputBuffer &) const override { return true; } @@ -972,10 +986,11 @@ public: void printLeft(OutputBuffer &OB) const override { if (Ret) { - Ret->printLeft(OB); + OB.printLeft(*Ret); if (!Ret->hasRHSComponent(OB)) OB += " "; } + Name->print(OB); } @@ -983,8 +998,9 @@ public: OB.printOpen(); Params.printWithComma(OB); OB.printClose(); + if (Ret) - Ret->printRight(OB); + OB.printRight(*Ret); if (CVQuals & QualConst) OB += " const"; @@ -1324,14 +1340,14 @@ public: template void match(Fn F) const { F(Name, Type); } void printLeft(OutputBuffer &OB) const override { - Type->printLeft(OB); + OB.printLeft(*Type); if (!Type->hasRHSComponent(OB)) OB += " "; } void printRight(OutputBuffer &OB) const override { Name->print(OB); - Type->printRight(OB); + OB.printRight(*Type); } }; @@ -1376,11 +1392,11 @@ public: template void match(Fn F) const { F(Param); } void printLeft(OutputBuffer &OB) const override { - Param->printLeft(OB); + OB.printLeft(*Param); OB += "..."; } - void printRight(OutputBuffer &OB) const override { Param->printRight(OB); } + void printRight(OutputBuffer &OB) const override { OB.printRight(*Param); } }; /// An unexpanded parameter pack (either in the expression or type context). If @@ -1445,13 +1461,13 @@ public: initializePackExpansion(OB); size_t Idx = OB.CurrentPackIndex; if (Idx < Data.size()) - Data[Idx]->printLeft(OB); + OB.printLeft(*Data[Idx]); } void printRight(OutputBuffer &OB) const override { initializePackExpansion(OB); size_t Idx = OB.CurrentPackIndex; if (Idx < Data.size()) - Data[Idx]->printRight(OB); + OB.printRight(*Data[Idx]); } }; @@ -1609,13 +1625,13 @@ struct ForwardTemplateReference : Node { if (Printing) return; ScopedOverride SavePrinting(Printing, true); - Ref->printLeft(OB); + OB.printLeft(*Ref); } void printRight(OutputBuffer &OB) const override { if (Printing) return; ScopedOverride SavePrinting(Printing, true); - Ref->printRight(OB); + OB.printRight(*Ref); } }; @@ -1767,7 +1783,7 @@ public: void printLeft(OutputBuffer &OB) const override { OB += "~"; - Base->printLeft(OB); + OB.printLeft(*Base); } }; @@ -2047,7 +2063,7 @@ public: { ScopedOverride LT(OB.GtIsGt, 0); OB += "<"; - To->printLeft(OB); + OB.printLeft(*To); OB += ">"; } OB.printOpen(); @@ -3406,7 +3422,7 @@ const typename AbstractManglingParser< {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"}, {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="}, {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"}, - {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem, + {"pm", OperatorInfo::Member, /*Named*/ true, Node::Prec::PtrMem, "operator->*"}, {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"}, {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"}, @@ -4452,7 +4468,9 @@ Node *AbstractManglingParser::parseType() { return nullptr; if (!consumeIf('_')) return nullptr; - return make(Size, Signed); + // The front end expects this to be available for Substitution + Result = make(Size, Signed); + break; } // ::= Di # char32_t case 'i': @@ -5739,14 +5757,16 @@ struct FloatData template <> struct FloatData { -#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \ - defined(__wasm__) || defined(__riscv) || defined(__loongarch__) || \ - defined(__ve__) - static const size_t mangled_size = 32; -#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__) - static const size_t mangled_size = 16; +#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106 + static const size_t mangled_size = 32; +#elif __LDBL_MANT_DIG__ == 53 || defined(_MSC_VER) + // MSVC doesn't define __LDBL_MANT_DIG__, but it has long double equal to + // regular double on all current architectures. + static const size_t mangled_size = 16; +#elif __LDBL_MANT_DIG__ == 64 + static const size_t mangled_size = 20; #else - static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms +#error Unknown size for __LDBL_MANT_DIG__ #endif // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes. // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits. @@ -6176,6 +6196,10 @@ struct ManglingParser : AbstractManglingParser, Alloc> { Alloc>::AbstractManglingParser; }; +inline void OutputBuffer::printLeft(const Node &N) { N.printLeft(*this); } + +inline void OutputBuffer::printRight(const Node &N) { N.printRight(*this); } + DEMANGLE_NAMESPACE_END #if defined(__clang__) diff --git a/lib/libcxxabi/src/demangle/Utility.h b/lib/libcxxabi/src/demangle/Utility.h index f1fad35d60..8829f3fa13 100644 --- a/lib/libcxxabi/src/demangle/Utility.h +++ b/lib/libcxxabi/src/demangle/Utility.h @@ -27,6 +27,8 @@ DEMANGLE_NAMESPACE_BEGIN +class Node; + // Stream that AST nodes write their string representation into after the AST // has been parsed. class OutputBuffer { @@ -79,10 +81,24 @@ public: OutputBuffer(const OutputBuffer &) = delete; OutputBuffer &operator=(const OutputBuffer &) = delete; + virtual ~OutputBuffer() {} + operator std::string_view() const { return std::string_view(Buffer, CurrentPosition); } + /// Called by the demangler when printing the demangle tree. By + /// default calls into \c Node::print{Left|Right} but can be overriden + /// by clients to track additional state when printing the demangled name. + virtual void printLeft(const Node &N); + virtual void printRight(const Node &N); + + /// Called when we write to this object anywhere other than the end. + virtual void notifyInsertion(size_t /*Position*/, size_t /*Count*/) {} + + /// Called when we make the \c CurrentPosition of this object smaller. + virtual void notifyDeletion(size_t /*OldPos*/, size_t /*NewPos*/) {} + /// If a ParameterPackExpansion (or similar type) is encountered, the offset /// into the pack that we're currently printing. unsigned CurrentPackIndex = std::numeric_limits::max(); @@ -120,12 +136,16 @@ public: OutputBuffer &prepend(std::string_view R) { size_t Size = R.size(); + if (!Size) + return *this; grow(Size); std::memmove(Buffer + Size, Buffer, CurrentPosition); std::memcpy(Buffer, &*R.begin(), Size); CurrentPosition += Size; + notifyInsertion(/*Position=*/0, /*Count=*/Size); + return *this; } @@ -161,14 +181,20 @@ public: DEMANGLE_ASSERT(Pos <= CurrentPosition, ""); if (N == 0) return; + grow(N); std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos); std::memcpy(Buffer + Pos, S, N); CurrentPosition += N; + + notifyInsertion(Pos, N); } size_t getCurrentPosition() const { return CurrentPosition; } - void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } + void setCurrentPosition(size_t NewPos) { + notifyDeletion(CurrentPosition, NewPos); + CurrentPosition = NewPos; + } char back() const { DEMANGLE_ASSERT(CurrentPosition, ""); diff --git a/lib/libcxxabi/src/stdlib_new_delete.cpp b/lib/libcxxabi/src/stdlib_new_delete.cpp index f386b28f0c..b5ed59958d 100644 --- a/lib/libcxxabi/src/stdlib_new_delete.cpp +++ b/lib/libcxxabi/src/stdlib_new_delete.cpp @@ -63,7 +63,7 @@ static void* operator_new_impl(std::size_t size) { return p; } -_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC { +_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new, (std::size_t size)) _THROW_BAD_ALLOC { void* p = operator_new_impl(size); if (p == nullptr) __throw_bad_alloc_shim(); @@ -74,7 +74,7 @@ _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept { #if !_LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION _LIBCPP_ASSERT_SHIM( - !std::__is_function_overridden(static_cast(&operator new)), + (!std::__is_function_overridden < void*(std::size_t), &operator new>()), "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, " "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because " "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case " @@ -94,15 +94,13 @@ _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept { #endif } -_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC { - return ::operator new(size); -} +_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new[], (size_t size)) _THROW_BAD_ALLOC { return ::operator new(size); } _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept { #if !_LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION _LIBCPP_ASSERT_SHIM( - !std::__is_function_overridden(static_cast(&operator new[])), + (!std::__is_function_overridden < void*(std::size_t), &operator new[]>()), "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, " "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because " "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case " @@ -156,8 +154,7 @@ static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignm return p; } -_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* -operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { +_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new, (std::size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC { void* p = operator_new_aligned_impl(size, alignment); if (p == nullptr) __throw_bad_alloc_shim(); @@ -168,7 +165,7 @@ _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const s # if !_LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION _LIBCPP_ASSERT_SHIM( - !std::__is_function_overridden(static_cast(&operator new)), + (!std::__is_function_overridden < void*(std::size_t, std::align_val_t), &operator new>()), "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, " "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will " @@ -188,8 +185,7 @@ _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const s # endif } -_LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* -operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { +_LIBCPP_OVERRIDABLE_FUNCTION(void*, operator new[], (size_t size, std::align_val_t alignment)) _THROW_BAD_ALLOC { return ::operator new(size, alignment); } @@ -197,14 +193,13 @@ _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const # if !_LIBCPP_HAS_EXCEPTIONS # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION _LIBCPP_ASSERT_SHIM( - !std::__is_function_overridden(static_cast(&operator new[])), + (!std::__is_function_overridden < void*(std::size_t, std::align_val_t), &operator new[]>()), "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, " "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will " "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, " "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you " - "override " - "`operator new[](size_t, align_val_t, nothrow_t)` as well."); + "override `operator new[](size_t, align_val_t, nothrow_t)` as well."); # endif return operator_new_aligned_impl(size, alignment);