| author | |
| committer | |
| log | 38bf94280bb9735a005673d3eae132f75795b854 |
| tree | 7b847d81198bb44be21881c201c19e02b53bca60 |
| parent | f9a11fbfafa7e056c08350f740af8a96a722a235 |
llvm commit b2851aea80e5a8f0cfd6c3c5a56a6b00fb28c6b611 files changed, 244 insertions(+), 220 deletions(-)
lib/libcxxabi/include/__cxxabi_config.h+15-2| ... | @@ -18,6 +18,19 @@ | ... | @@ -18,6 +18,19 @@ |
| 18 | #define __has_attribute(_attribute_) 0 | 18 | #define __has_attribute(_attribute_) 0 |
| 19 | #endif | 19 | #endif |
| 20 | 20 | ||
| 21 | #if defined(__clang__) | ||
| 22 | # define _LIBCXXABI_COMPILER_CLANG | ||
| 23 | # ifndef __apple_build_version__ | ||
| 24 | # define _LIBCXXABI_CLANG_VER (__clang_major__ * 100 + __clang_minor__) | ||
| 25 | # endif | ||
| 26 | #elif defined(__GNUC__) | ||
| 27 | # define _LIBCXXABI_COMPILER_GCC | ||
| 28 | #elif defined(_MSC_VER) | ||
| 29 | # define _LIBCXXABI_COMPILER_MSVC | ||
| 30 | #elif defined(__IBMCPP__) | ||
| 31 | # define _LIBCXXABI_COMPILER_IBM | ||
| 32 | #endif | ||
| 33 | |||
| 21 | #if defined(_WIN32) | 34 | #if defined(_WIN32) |
| 22 | #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) | 35 | #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) |
| 23 | #define _LIBCXXABI_HIDDEN | 36 | #define _LIBCXXABI_HIDDEN |
| ... | @@ -53,7 +66,7 @@ | ... | @@ -53,7 +66,7 @@ |
| 53 | #endif | 66 | #endif |
| 54 | #endif | 67 | #endif |
| 55 | 68 | ||
| 56 | #if defined(_WIN32) | 69 | #if defined(_LIBCXXABI_COMPILER_MSVC) |
| 57 | #define _LIBCXXABI_WEAK | 70 | #define _LIBCXXABI_WEAK |
| 58 | #else | 71 | #else |
| 59 | #define _LIBCXXABI_WEAK __attribute__((__weak__)) | 72 | #define _LIBCXXABI_WEAK __attribute__((__weak__)) |
| ... | @@ -72,7 +85,7 @@ | ... | @@ -72,7 +85,7 @@ |
| 72 | #endif | 85 | #endif |
| 73 | 86 | ||
| 74 | // wasm32 follows the arm32 ABI convention of using 32-bit guard. | 87 | // wasm32 follows the arm32 ABI convention of using 32-bit guard. |
| 75 | #if defined(__arm__) || defined(__wasm32__) | 88 | #if defined(__arm__) || defined(__wasm32__) || defined(__ARM64_ARCH_8_32__) |
| 76 | # define _LIBCXXABI_GUARD_ABI_ARM | 89 | # define _LIBCXXABI_GUARD_ABI_ARM |
| 77 | #endif | 90 | #endif |
| 78 | 91 |
lib/libcxxabi/include/cxxabi.h+10-9| ... | @@ -21,6 +21,7 @@ | ... | @@ -21,6 +21,7 @@ |
| 21 | 21 | ||
| 22 | #define _LIBCPPABI_VERSION 1002 | 22 | #define _LIBCPPABI_VERSION 1002 |
| 23 | #define _LIBCXXABI_NORETURN __attribute__((noreturn)) | 23 | #define _LIBCXXABI_NORETURN __attribute__((noreturn)) |
| 24 | #define _LIBCXXABI_ALWAYS_COLD __attribute__((cold)) | ||
| 24 | 25 | ||
| 25 | #ifdef __cplusplus | 26 | #ifdef __cplusplus |
| 26 | 27 | ||
| ... | @@ -78,13 +79,13 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void); | ... | @@ -78,13 +79,13 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void); |
| 78 | 79 | ||
| 79 | // 3.3.2 One-time Construction API | 80 | // 3.3.2 One-time Construction API |
| 80 | #if defined(_LIBCXXABI_GUARD_ABI_ARM) | 81 | #if defined(_LIBCXXABI_GUARD_ABI_ARM) |
| 81 | extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint32_t *); | 82 | extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *); |
| 82 | extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint32_t *); | 83 | extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *); |
| 83 | extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint32_t *); | 84 | extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *); |
| 84 | #else | 85 | #else |
| 85 | extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint64_t *); | 86 | extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *); |
| 86 | extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint64_t *); | 87 | extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *); |
| 87 | extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint64_t *); | 88 | extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *); |
| 88 | #endif | 89 | #endif |
| 89 | 90 | ||
| 90 | // 3.3.3 Array Construction and Destruction API | 91 | // 3.3.3 Array Construction and Destruction API |
| ... | @@ -136,9 +137,9 @@ __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count, | ... | @@ -136,9 +137,9 @@ __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count, |
| 136 | void (*destructor)(void *)); | 137 | void (*destructor)(void *)); |
| 137 | 138 | ||
| 138 | // 3.3.5.3 Runtime API | 139 | // 3.3.5.3 Runtime API |
| 139 | extern _LIBCXXABI_FUNC_VIS int __cxa_atexit(void (*f)(void *), void *p, | 140 | // These functions are part of the C++ ABI, but they are not defined in libc++abi: |
| 140 | void *d); | 141 | // int __cxa_atexit(void (*)(void *), void *, void *); |
| 141 | extern _LIBCXXABI_FUNC_VIS int __cxa_finalize(void *); | 142 | // void __cxa_finalize(void *); |
| 142 | 143 | ||
| 143 | // 3.4 Demangler API | 144 | // 3.4 Demangler API |
| 144 | extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name, | 145 | extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name, |
lib/libcxxabi/src/cxa_guard_impl.h+24-24| ... | @@ -54,6 +54,14 @@ | ... | @@ -54,6 +54,14 @@ |
| 54 | #endif | 54 | #endif |
| 55 | #endif | 55 | #endif |
| 56 | 56 | ||
| 57 | #if defined(__clang__) | ||
| 58 | # pragma clang diagnostic push | ||
| 59 | # pragma clang diagnostic ignored "-Wtautological-pointer-compare" | ||
| 60 | #elif defined(__GNUC__) | ||
| 61 | # pragma GCC diagnostic push | ||
| 62 | # pragma GCC diagnostic ignored "-Waddress" | ||
| 63 | #endif | ||
| 64 | |||
| 57 | // To make testing possible, this header is included from both cxa_guard.cpp | 65 | // To make testing possible, this header is included from both cxa_guard.cpp |
| 58 | // and a number of tests. | 66 | // and a number of tests. |
| 59 | // | 67 | // |
| ... | @@ -112,25 +120,25 @@ class AtomicInt { | ... | @@ -112,25 +120,25 @@ class AtomicInt { |
| 112 | public: | 120 | public: |
| 113 | using MemoryOrder = std::__libcpp_atomic_order; | 121 | using MemoryOrder = std::__libcpp_atomic_order; |
| 114 | 122 | ||
| 115 | explicit AtomicInt(IntType *b) : b(b) {} | 123 | explicit AtomicInt(IntType *b) : b_(b) {} |
| 116 | AtomicInt(AtomicInt const&) = delete; | 124 | AtomicInt(AtomicInt const&) = delete; |
| 117 | AtomicInt& operator=(AtomicInt const&) = delete; | 125 | AtomicInt& operator=(AtomicInt const&) = delete; |
| 118 | 126 | ||
| 119 | IntType load(MemoryOrder ord) { | 127 | IntType load(MemoryOrder ord) { |
| 120 | return std::__libcpp_atomic_load(b, ord); | 128 | return std::__libcpp_atomic_load(b_, ord); |
| 121 | } | 129 | } |
| 122 | void store(IntType val, MemoryOrder ord) { | 130 | void store(IntType val, MemoryOrder ord) { |
| 123 | std::__libcpp_atomic_store(b, val, ord); | 131 | std::__libcpp_atomic_store(b_, val, ord); |
| 124 | } | 132 | } |
| 125 | IntType exchange(IntType new_val, MemoryOrder ord) { | 133 | IntType exchange(IntType new_val, MemoryOrder ord) { |
| 126 | return std::__libcpp_atomic_exchange(b, new_val, ord); | 134 | return std::__libcpp_atomic_exchange(b_, new_val, ord); |
| 127 | } | 135 | } |
| 128 | bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) { | 136 | bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) { |
| 129 | return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure); | 137 | return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure); |
| 130 | } | 138 | } |
| 131 | 139 | ||
| 132 | private: | 140 | private: |
| 133 | IntType *b; | 141 | IntType *b_; |
| 134 | }; | 142 | }; |
| 135 | 143 | ||
| 136 | //===----------------------------------------------------------------------===// | 144 | //===----------------------------------------------------------------------===// |
| ... | @@ -154,14 +162,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr; | ... | @@ -154,14 +162,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr; |
| 154 | 162 | ||
| 155 | 163 | ||
| 156 | constexpr bool PlatformSupportsThreadID() { | 164 | constexpr bool PlatformSupportsThreadID() { |
| 157 | #ifdef __clang__ | ||
| 158 | #pragma clang diagnostic push | ||
| 159 | #pragma clang diagnostic ignored "-Wtautological-pointer-compare" | ||
| 160 | #endif | ||
| 161 | return +PlatformThreadID != nullptr; | 165 | return +PlatformThreadID != nullptr; |
| 162 | #ifdef __clang__ | ||
| 163 | #pragma clang diagnostic pop | ||
| 164 | #endif | ||
| 165 | } | 166 | } |
| 166 | 167 | ||
| 167 | //===----------------------------------------------------------------------===// | 168 | //===----------------------------------------------------------------------===// |
| ... | @@ -375,18 +376,18 @@ private: | ... | @@ -375,18 +376,18 @@ private: |
| 375 | LockGuard& operator=(LockGuard const&) = delete; | 376 | LockGuard& operator=(LockGuard const&) = delete; |
| 376 | 377 | ||
| 377 | explicit LockGuard(const char* calling_func) | 378 | explicit LockGuard(const char* calling_func) |
| 378 | : calling_func(calling_func) { | 379 | : calling_func_(calling_func) { |
| 379 | if (global_mutex.lock()) | 380 | if (global_mutex.lock()) |
| 380 | ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func); | 381 | ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_); |
| 381 | } | 382 | } |
| 382 | 383 | ||
| 383 | ~LockGuard() { | 384 | ~LockGuard() { |
| 384 | if (global_mutex.unlock()) | 385 | if (global_mutex.unlock()) |
| 385 | ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func); | 386 | ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func_); |
| 386 | } | 387 | } |
| 387 | 388 | ||
| 388 | private: | 389 | private: |
| 389 | const char* const calling_func; | 390 | const char* const calling_func_; |
| 390 | }; | 391 | }; |
| 391 | }; | 392 | }; |
| 392 | 393 | ||
| ... | @@ -411,14 +412,7 @@ constexpr void (*PlatformFutexWake)(int*) = nullptr; | ... | @@ -411,14 +412,7 @@ constexpr void (*PlatformFutexWake)(int*) = nullptr; |
| 411 | #endif | 412 | #endif |
| 412 | 413 | ||
| 413 | constexpr bool PlatformSupportsFutex() { | 414 | constexpr bool PlatformSupportsFutex() { |
| 414 | #ifdef __clang__ | ||
| 415 | #pragma clang diagnostic push | ||
| 416 | #pragma clang diagnostic ignored "-Wtautological-pointer-compare" | ||
| 417 | #endif | ||
| 418 | return +PlatformFutexWait != nullptr; | 415 | return +PlatformFutexWait != nullptr; |
| 419 | #ifdef __clang__ | ||
| 420 | #pragma clang diagnostic pop | ||
| 421 | #endif | ||
| 422 | } | 416 | } |
| 423 | 417 | ||
| 424 | /// InitByteFutex - Manages initialization using atomics and the futex syscall | 418 | /// InitByteFutex - Manages initialization using atomics and the futex syscall |
| ... | @@ -589,4 +583,10 @@ using SelectedImplementation = | ... | @@ -589,4 +583,10 @@ using SelectedImplementation = |
| 589 | } // end namespace | 583 | } // end namespace |
| 590 | } // end namespace __cxxabiv1 | 584 | } // end namespace __cxxabiv1 |
| 591 | 585 | ||
| 586 | #if defined(__clang__) | ||
| 587 | # pragma clang diagnostic pop | ||
| 588 | #elif defined(__GNUC__) | ||
| 589 | # pragma GCC diagnostic pop | ||
| 590 | #endif | ||
| 591 | |||
| 592 | #endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H | 592 | #endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H |
lib/libcxxabi/src/demangle/ItaniumDemangle.h+130-5| ... | @@ -82,6 +82,7 @@ | ... | @@ -82,6 +82,7 @@ |
| 82 | X(PostfixExpr) \ | 82 | X(PostfixExpr) \ |
| 83 | X(ConditionalExpr) \ | 83 | X(ConditionalExpr) \ |
| 84 | X(MemberExpr) \ | 84 | X(MemberExpr) \ |
| 85 | X(SubobjectExpr) \ | ||
| 85 | X(EnclosingExpr) \ | 86 | X(EnclosingExpr) \ |
| 86 | X(CastExpr) \ | 87 | X(CastExpr) \ |
| 87 | X(SizeofParamPackExpr) \ | 88 | X(SizeofParamPackExpr) \ |
| ... | @@ -91,6 +92,7 @@ | ... | @@ -91,6 +92,7 @@ |
| 91 | X(PrefixExpr) \ | 92 | X(PrefixExpr) \ |
| 92 | X(FunctionParam) \ | 93 | X(FunctionParam) \ |
| 93 | X(ConversionExpr) \ | 94 | X(ConversionExpr) \ |
| 95 | X(PointerToMemberConversionExpr) \ | ||
| 94 | X(InitListExpr) \ | 96 | X(InitListExpr) \ |
| 95 | X(FoldExpr) \ | 97 | X(FoldExpr) \ |
| 96 | X(ThrowExpr) \ | 98 | X(ThrowExpr) \ |
| ... | @@ -1656,6 +1658,40 @@ public: | ... | @@ -1656,6 +1658,40 @@ public: |
| 1656 | } | 1658 | } |
| 1657 | }; | 1659 | }; |
| 1658 | 1660 | ||
| 1661 | class SubobjectExpr : public Node { | ||
| 1662 | const Node *Type; | ||
| 1663 | const Node *SubExpr; | ||
| 1664 | StringView Offset; | ||
| 1665 | NodeArray UnionSelectors; | ||
| 1666 | bool OnePastTheEnd; | ||
| 1667 | |||
| 1668 | public: | ||
| 1669 | SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_, | ||
| 1670 | NodeArray UnionSelectors_, bool OnePastTheEnd_) | ||
| 1671 | : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_), | ||
| 1672 | UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {} | ||
| 1673 | |||
| 1674 | template<typename Fn> void match(Fn F) const { | ||
| 1675 | F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd); | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | void printLeft(OutputStream &S) const override { | ||
| 1679 | SubExpr->print(S); | ||
| 1680 | S += ".<"; | ||
| 1681 | Type->print(S); | ||
| 1682 | S += " at offset "; | ||
| 1683 | if (Offset.empty()) { | ||
| 1684 | S += "0"; | ||
| 1685 | } else if (Offset[0] == 'n') { | ||
| 1686 | S += "-"; | ||
| 1687 | S += Offset.dropFront(); | ||
| 1688 | } else { | ||
| 1689 | S += Offset; | ||
| 1690 | } | ||
| 1691 | S += ">"; | ||
| 1692 | } | ||
| 1693 | }; | ||
| 1694 | |||
| 1659 | class EnclosingExpr : public Node { | 1695 | class EnclosingExpr : public Node { |
| 1660 | const StringView Prefix; | 1696 | const StringView Prefix; |
| 1661 | const Node *Infix; | 1697 | const Node *Infix; |
| ... | @@ -1843,6 +1879,28 @@ public: | ... | @@ -1843,6 +1879,28 @@ public: |
| 1843 | } | 1879 | } |
| 1844 | }; | 1880 | }; |
| 1845 | 1881 | ||
| 1882 | class PointerToMemberConversionExpr : public Node { | ||
| 1883 | const Node *Type; | ||
| 1884 | const Node *SubExpr; | ||
| 1885 | StringView Offset; | ||
| 1886 | |||
| 1887 | public: | ||
| 1888 | PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_, | ||
| 1889 | StringView Offset_) | ||
| 1890 | : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_), | ||
| 1891 | Offset(Offset_) {} | ||
| 1892 | |||
| 1893 | template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); } | ||
| 1894 | |||
| 1895 | void printLeft(OutputStream &S) const override { | ||
| 1896 | S += "("; | ||
| 1897 | Type->print(S); | ||
| 1898 | S += ")("; | ||
| 1899 | SubExpr->print(S); | ||
| 1900 | S += ")"; | ||
| 1901 | } | ||
| 1902 | }; | ||
| 1903 | |||
| 1846 | class InitListExpr : public Node { | 1904 | class InitListExpr : public Node { |
| 1847 | const Node *Ty; | 1905 | const Node *Ty; |
| 1848 | NodeArray Inits; | 1906 | NodeArray Inits; |
| ... | @@ -2313,9 +2371,9 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser { | ... | @@ -2313,9 +2371,9 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser { |
| 2313 | TemplateParamList Params; | 2371 | TemplateParamList Params; |
| 2314 | 2372 | ||
| 2315 | public: | 2373 | public: |
| 2316 | ScopedTemplateParamList(AbstractManglingParser *Parser) | 2374 | ScopedTemplateParamList(AbstractManglingParser *TheParser) |
| 2317 | : Parser(Parser), | 2375 | : Parser(TheParser), |
| 2318 | OldNumTemplateParamLists(Parser->TemplateParams.size()) { | 2376 | OldNumTemplateParamLists(TheParser->TemplateParams.size()) { |
| 2319 | Parser->TemplateParams.push_back(&Params); | 2377 | Parser->TemplateParams.push_back(&Params); |
| 2320 | } | 2378 | } |
| 2321 | ~ScopedTemplateParamList() { | 2379 | ~ScopedTemplateParamList() { |
| ... | @@ -2437,6 +2495,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser { | ... | @@ -2437,6 +2495,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser { |
| 2437 | Node *parseConversionExpr(); | 2495 | Node *parseConversionExpr(); |
| 2438 | Node *parseBracedExpr(); | 2496 | Node *parseBracedExpr(); |
| 2439 | Node *parseFoldExpr(); | 2497 | Node *parseFoldExpr(); |
| 2498 | Node *parsePointerToMemberConversionExpr(); | ||
| 2499 | Node *parseSubobjectExpr(); | ||
| 2440 | 2500 | ||
| 2441 | /// Parse the <type> production. | 2501 | /// Parse the <type> production. |
| 2442 | Node *parseType(); | 2502 | Node *parseType(); |
| ... | @@ -4404,6 +4464,50 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() { | ... | @@ -4404,6 +4464,50 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() { |
| 4404 | return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init); | 4464 | return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init); |
| 4405 | } | 4465 | } |
| 4406 | 4466 | ||
| 4467 | // <expression> ::= mc <parameter type> <expr> [<offset number>] E | ||
| 4468 | // | ||
| 4469 | // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 | ||
| 4470 | template <typename Derived, typename Alloc> | ||
| 4471 | Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() { | ||
| 4472 | Node *Ty = getDerived().parseType(); | ||
| 4473 | if (!Ty) | ||
| 4474 | return nullptr; | ||
| 4475 | Node *Expr = getDerived().parseExpr(); | ||
| 4476 | if (!Expr) | ||
| 4477 | return nullptr; | ||
| 4478 | StringView Offset = getDerived().parseNumber(true); | ||
| 4479 | if (!consumeIf('E')) | ||
| 4480 | return nullptr; | ||
| 4481 | return make<PointerToMemberConversionExpr>(Ty, Expr, Offset); | ||
| 4482 | } | ||
| 4483 | |||
| 4484 | // <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E | ||
| 4485 | // <union-selector> ::= _ [<number>] | ||
| 4486 | // | ||
| 4487 | // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 | ||
| 4488 | template <typename Derived, typename Alloc> | ||
| 4489 | Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() { | ||
| 4490 | Node *Ty = getDerived().parseType(); | ||
| 4491 | if (!Ty) | ||
| 4492 | return nullptr; | ||
| 4493 | Node *Expr = getDerived().parseExpr(); | ||
| 4494 | if (!Expr) | ||
| 4495 | return nullptr; | ||
| 4496 | StringView Offset = getDerived().parseNumber(true); | ||
| 4497 | size_t SelectorsBegin = Names.size(); | ||
| 4498 | while (consumeIf('_')) { | ||
| 4499 | Node *Selector = make<NameType>(parseNumber()); | ||
| 4500 | if (!Selector) | ||
| 4501 | return nullptr; | ||
| 4502 | Names.push_back(Selector); | ||
| 4503 | } | ||
| 4504 | bool OnePastTheEnd = consumeIf('p'); | ||
| 4505 | if (!consumeIf('E')) | ||
| 4506 | return nullptr; | ||
| 4507 | return make<SubobjectExpr>( | ||
| 4508 | Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd); | ||
| 4509 | } | ||
| 4510 | |||
| 4407 | // <expression> ::= <unary operator-name> <expression> | 4511 | // <expression> ::= <unary operator-name> <expression> |
| 4408 | // ::= <binary operator-name> <expression> <expression> | 4512 | // ::= <binary operator-name> <expression> <expression> |
| 4409 | // ::= <ternary operator-name> <expression> <expression> <expression> | 4513 | // ::= <ternary operator-name> <expression> <expression> <expression> |
| ... | @@ -4661,6 +4765,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { | ... | @@ -4661,6 +4765,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { |
| 4661 | return nullptr; | 4765 | return nullptr; |
| 4662 | case 'm': | 4766 | case 'm': |
| 4663 | switch (First[1]) { | 4767 | switch (First[1]) { |
| 4768 | case 'c': | ||
| 4769 | First += 2; | ||
| 4770 | return parsePointerToMemberConversionExpr(); | ||
| 4664 | case 'i': | 4771 | case 'i': |
| 4665 | First += 2; | 4772 | First += 2; |
| 4666 | return getDerived().parseBinaryExpr("-"); | 4773 | return getDerived().parseBinaryExpr("-"); |
| ... | @@ -4808,6 +4915,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { | ... | @@ -4808,6 +4915,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { |
| 4808 | return Ex; | 4915 | return Ex; |
| 4809 | return make<CastExpr>("static_cast", T, Ex); | 4916 | return make<CastExpr>("static_cast", T, Ex); |
| 4810 | } | 4917 | } |
| 4918 | case 'o': | ||
| 4919 | First += 2; | ||
| 4920 | return parseSubobjectExpr(); | ||
| 4811 | case 'p': { | 4921 | case 'p': { |
| 4812 | First += 2; | 4922 | First += 2; |
| 4813 | Node *Child = getDerived().parseExpr(); | 4923 | Node *Child = getDerived().parseExpr(); |
| ... | @@ -4975,6 +5085,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() { | ... | @@ -4975,6 +5085,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() { |
| 4975 | switch (look()) { | 5085 | switch (look()) { |
| 4976 | case 'T': | 5086 | case 'T': |
| 4977 | switch (look(1)) { | 5087 | switch (look(1)) { |
| 5088 | // TA <template-arg> # template parameter object | ||
| 5089 | // | ||
| 5090 | // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63 | ||
| 5091 | case 'A': { | ||
| 5092 | First += 2; | ||
| 5093 | Node *Arg = getDerived().parseTemplateArg(); | ||
| 5094 | if (Arg == nullptr) | ||
| 5095 | return nullptr; | ||
| 5096 | return make<SpecialName>("template parameter object for ", Arg); | ||
| 5097 | } | ||
| 4978 | // TV <type> # virtual table | 5098 | // TV <type> # virtual table |
| 4979 | case 'V': { | 5099 | case 'V': { |
| 4980 | First += 2; | 5100 | First += 2; |
| ... | @@ -5103,7 +5223,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() { | ... | @@ -5103,7 +5223,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() { |
| 5103 | decltype(TemplateParams) OldParams; | 5223 | decltype(TemplateParams) OldParams; |
| 5104 | 5224 | ||
| 5105 | public: | 5225 | public: |
| 5106 | SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) { | 5226 | SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) { |
| 5107 | OldParams = std::move(Parser->TemplateParams); | 5227 | OldParams = std::move(Parser->TemplateParams); |
| 5108 | Parser->TemplateParams.clear(); | 5228 | Parser->TemplateParams.clear(); |
| 5109 | } | 5229 | } |
| ... | @@ -5203,7 +5323,12 @@ struct FloatData<long double> | ... | @@ -5203,7 +5323,12 @@ struct FloatData<long double> |
| 5203 | #else | 5323 | #else |
| 5204 | static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms | 5324 | static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms |
| 5205 | #endif | 5325 | #endif |
| 5206 | static const size_t max_demangled_size = 40; | 5326 | // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes. |
| 5327 | // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits. | ||
| 5328 | // Negatives are one character longer than positives. | ||
| 5329 | // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the | ||
| 5330 | // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128. | ||
| 5331 | static const size_t max_demangled_size = 42; | ||
| 5207 | static constexpr const char *spec = "%LaL"; | 5332 | static constexpr const char *spec = "%LaL"; |
| 5208 | }; | 5333 | }; |
| 5209 | 5334 |
lib/libcxxabi/src/demangle/Utility.h+1-1| ... | @@ -52,7 +52,7 @@ class OutputStream { | ... | @@ -52,7 +52,7 @@ class OutputStream { |
| 52 | char *TempPtr = std::end(Temp); | 52 | char *TempPtr = std::end(Temp); |
| 53 | 53 | ||
| 54 | while (N) { | 54 | while (N) { |
| 55 | *--TempPtr = '0' + char(N % 10); | 55 | *--TempPtr = char('0' + N % 10); |
| 56 | N /= 10; | 56 | N /= 10; |
| 57 | } | 57 | } |
| 58 | 58 |
lib/libcxxabi/src/fallback_malloc.cpp+16-23| ... | @@ -6,9 +6,6 @@ | ... | @@ -6,9 +6,6 @@ |
| 6 | // | 6 | // |
| 7 | //===----------------------------------------------------------------------===// | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | ||
| 9 | // Define _LIBCPP_BUILDING_LIBRARY to ensure _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION | ||
| 10 | // is only defined when libc aligned allocation is not available. | ||
| 11 | #define _LIBCPP_BUILDING_LIBRARY | ||
| 12 | #include "fallback_malloc.h" | 9 | #include "fallback_malloc.h" |
| 13 | 10 | ||
| 14 | #include <__threading_support> | 11 | #include <__threading_support> |
| ... | @@ -20,6 +17,7 @@ | ... | @@ -20,6 +17,7 @@ |
| 20 | 17 | ||
| 21 | #include <stdlib.h> // for malloc, calloc, free | 18 | #include <stdlib.h> // for malloc, calloc, free |
| 22 | #include <string.h> // for memset | 19 | #include <string.h> // for memset |
| 20 | #include <new> // for std::__libcpp_aligned_{alloc,free} | ||
| 23 | 21 | ||
| 24 | // A small, simple heap manager based (loosely) on | 22 | // A small, simple heap manager based (loosely) on |
| 25 | // the startup heap manager from FreeBSD, optimized for space. | 23 | // the startup heap manager from FreeBSD, optimized for space. |
| ... | @@ -144,29 +142,26 @@ void fallback_free(void* ptr) { | ... | @@ -144,29 +142,26 @@ void fallback_free(void* ptr) { |
| 144 | mutexor mtx(&heap_mutex); | 142 | mutexor mtx(&heap_mutex); |
| 145 | 143 | ||
| 146 | #ifdef DEBUG_FALLBACK_MALLOC | 144 | #ifdef DEBUG_FALLBACK_MALLOC |
| 147 | std::cout << "Freeing item at " << offset_from_node(cp) << " of size " | 145 | std::printf("Freeing item at %d of size %d\n", offset_from_node(cp), cp->len); |
| 148 | << cp->len << std::endl; | ||
| 149 | #endif | 146 | #endif |
| 150 | 147 | ||
| 151 | for (p = freelist, prev = 0; p && p != list_end; | 148 | for (p = freelist, prev = 0; p && p != list_end; |
| 152 | prev = p, p = node_from_offset(p->next_node)) { | 149 | prev = p, p = node_from_offset(p->next_node)) { |
| 153 | #ifdef DEBUG_FALLBACK_MALLOC | 150 | #ifdef DEBUG_FALLBACK_MALLOC |
| 154 | std::cout << " p, cp, after (p), after(cp) " << offset_from_node(p) << ' ' | 151 | std::printf(" p=%d, cp=%d, after(p)=%d, after(cp)=%d\n", |
| 155 | << offset_from_node(cp) << ' ' << offset_from_node(after(p)) | 152 | offset_from_node(p), offset_from_node(cp), |
| 156 | << ' ' << offset_from_node(after(cp)) << std::endl; | 153 | offset_from_node(after(p)), offset_from_node(after(cp))); |
| 157 | #endif | 154 | #endif |
| 158 | if (after(p) == cp) { | 155 | if (after(p) == cp) { |
| 159 | #ifdef DEBUG_FALLBACK_MALLOC | 156 | #ifdef DEBUG_FALLBACK_MALLOC |
| 160 | std::cout << " Appending onto chunk at " << offset_from_node(p) | 157 | std::printf(" Appending onto chunk at %d\n", offset_from_node(p)); |
| 161 | << std::endl; | ||
| 162 | #endif | 158 | #endif |
| 163 | p->len = static_cast<heap_size>( | 159 | p->len = static_cast<heap_size>( |
| 164 | p->len + cp->len); // make the free heap_node larger | 160 | p->len + cp->len); // make the free heap_node larger |
| 165 | return; | 161 | return; |
| 166 | } else if (after(cp) == p) { // there's a free heap_node right after | 162 | } else if (after(cp) == p) { // there's a free heap_node right after |
| 167 | #ifdef DEBUG_FALLBACK_MALLOC | 163 | #ifdef DEBUG_FALLBACK_MALLOC |
| 168 | std::cout << " Appending free chunk at " << offset_from_node(p) | 164 | std::printf(" Appending free chunk at %d\n", offset_from_node(p)); |
| 169 | << std::endl; | ||
| 170 | #endif | 165 | #endif |
| 171 | cp->len = static_cast<heap_size>(cp->len + p->len); | 166 | cp->len = static_cast<heap_size>(cp->len + p->len); |
| 172 | if (prev == 0) { | 167 | if (prev == 0) { |
| ... | @@ -179,8 +174,7 @@ void fallback_free(void* ptr) { | ... | @@ -179,8 +174,7 @@ void fallback_free(void* ptr) { |
| 179 | } | 174 | } |
| 180 | // Nothing to merge with, add it to the start of the free list | 175 | // Nothing to merge with, add it to the start of the free list |
| 181 | #ifdef DEBUG_FALLBACK_MALLOC | 176 | #ifdef DEBUG_FALLBACK_MALLOC |
| 182 | std::cout << " Making new free list entry " << offset_from_node(cp) | 177 | std::printf(" Making new free list entry %d\n", offset_from_node(cp)); |
| 183 | << std::endl; | ||
| 184 | #endif | 178 | #endif |
| 185 | cp->next_node = offset_from_node(freelist); | 179 | cp->next_node = offset_from_node(freelist); |
| 186 | freelist = cp; | 180 | freelist = cp; |
| ... | @@ -195,11 +189,11 @@ size_t print_free_list() { | ... | @@ -195,11 +189,11 @@ size_t print_free_list() { |
| 195 | 189 | ||
| 196 | for (p = freelist, prev = 0; p && p != list_end; | 190 | for (p = freelist, prev = 0; p && p != list_end; |
| 197 | prev = p, p = node_from_offset(p->next_node)) { | 191 | prev = p, p = node_from_offset(p->next_node)) { |
| 198 | std::cout << (prev == 0 ? "" : " ") << "Offset: " << offset_from_node(p) | 192 | std::printf("%sOffset: %d\tsize: %d Next: %d\n", |
| 199 | << "\tsize: " << p->len << " Next: " << p->next_node << std::endl; | 193 | (prev == 0 ? "" : " "), offset_from_node(p), p->len, p->next_node); |
| 200 | total_free += p->len; | 194 | total_free += p->len; |
| 201 | } | 195 | } |
| 202 | std::cout << "Total Free space: " << total_free << std::endl; | 196 | std::printf("Total Free space: %d\n", total_free); |
| 203 | return total_free; | 197 | return total_free; |
| 204 | } | 198 | } |
| 205 | #endif | 199 | #endif |
| ... | @@ -211,7 +205,7 @@ struct __attribute__((aligned)) __aligned_type {}; | ... | @@ -211,7 +205,7 @@ struct __attribute__((aligned)) __aligned_type {}; |
| 211 | 205 | ||
| 212 | void* __aligned_malloc_with_fallback(size_t size) { | 206 | void* __aligned_malloc_with_fallback(size_t size) { |
| 213 | #if defined(_WIN32) | 207 | #if defined(_WIN32) |
| 214 | if (void* dest = _aligned_malloc(size, alignof(__aligned_type))) | 208 | if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size)) |
| 215 | return dest; | 209 | return dest; |
| 216 | #elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) | 210 | #elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) |
| 217 | if (void* dest = ::malloc(size)) | 211 | if (void* dest = ::malloc(size)) |
| ... | @@ -219,8 +213,7 @@ void* __aligned_malloc_with_fallback(size_t size) { | ... | @@ -219,8 +213,7 @@ void* __aligned_malloc_with_fallback(size_t size) { |
| 219 | #else | 213 | #else |
| 220 | if (size == 0) | 214 | if (size == 0) |
| 221 | size = 1; | 215 | size = 1; |
| 222 | void* dest; | 216 | if (void* dest = std::__libcpp_aligned_alloc(__alignof(__aligned_type), size)) |
| 223 | if (::posix_memalign(&dest, __alignof(__aligned_type), size) == 0) | ||
| 224 | return dest; | 217 | return dest; |
| 225 | #endif | 218 | #endif |
| 226 | return fallback_malloc(size); | 219 | return fallback_malloc(size); |
| ... | @@ -241,10 +234,10 @@ void __aligned_free_with_fallback(void* ptr) { | ... | @@ -241,10 +234,10 @@ void __aligned_free_with_fallback(void* ptr) { |
| 241 | if (is_fallback_ptr(ptr)) | 234 | if (is_fallback_ptr(ptr)) |
| 242 | fallback_free(ptr); | 235 | fallback_free(ptr); |
| 243 | else { | 236 | else { |
| 244 | #if defined(_WIN32) | 237 | #if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) |
| 245 | ::_aligned_free(ptr); | ||
| 246 | #else | ||
| 247 | ::free(ptr); | 238 | ::free(ptr); |
| 239 | #else | ||
| 240 | std::__libcpp_aligned_free(ptr); | ||
| 248 | #endif | 241 | #endif |
| 249 | } | 242 | } |
| 250 | } | 243 | } |
lib/libcxxabi/src/include/refstring.h deleted-131| ... | @@ -1,131 +0,0 @@ | ||
| 1 | //===------------------------ __refstring ---------------------------------===// | ||
| 2 | // | ||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| 4 | // See https://llvm.org/LICENSE.txt for license information. | ||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| 6 | // | ||
| 7 | //===----------------------------------------------------------------------===// | ||
| 8 | |||
| 9 | // FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of | ||
| 10 | // duplicating the file in libc++abi we should require that the libc++ sources | ||
| 11 | // are available when building libc++abi. | ||
| 12 | |||
| 13 | #ifndef _LIBCPPABI_REFSTRING_H | ||
| 14 | #define _LIBCPPABI_REFSTRING_H | ||
| 15 | |||
| 16 | #include <__config> | ||
| 17 | #include <stdexcept> | ||
| 18 | #include <cstddef> | ||
| 19 | #include <cstring> | ||
| 20 | #ifdef __APPLE__ | ||
| 21 | #include <dlfcn.h> | ||
| 22 | #include <mach-o/dyld.h> | ||
| 23 | #endif | ||
| 24 | #include "atomic_support.h" | ||
| 25 | |||
| 26 | _LIBCPP_BEGIN_NAMESPACE_STD | ||
| 27 | |||
| 28 | namespace __refstring_imp { namespace { | ||
| 29 | typedef int count_t; | ||
| 30 | |||
| 31 | struct _Rep_base { | ||
| 32 | std::size_t len; | ||
| 33 | std::size_t cap; | ||
| 34 | count_t count; | ||
| 35 | }; | ||
| 36 | |||
| 37 | inline _Rep_base* rep_from_data(const char *data_) noexcept { | ||
| 38 | char *data = const_cast<char *>(data_); | ||
| 39 | return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); | ||
| 40 | } | ||
| 41 | |||
| 42 | inline char * data_from_rep(_Rep_base *rep) noexcept { | ||
| 43 | char *data = reinterpret_cast<char *>(rep); | ||
| 44 | return data + sizeof(*rep); | ||
| 45 | } | ||
| 46 | |||
| 47 | #if defined(__APPLE__) | ||
| 48 | inline | ||
| 49 | const char* compute_gcc_empty_string_storage() _NOEXCEPT | ||
| 50 | { | ||
| 51 | void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); | ||
| 52 | if (handle == nullptr) | ||
| 53 | return nullptr; | ||
| 54 | void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); | ||
| 55 | if (sym == nullptr) | ||
| 56 | return nullptr; | ||
| 57 | return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); | ||
| 58 | } | ||
| 59 | |||
| 60 | inline | ||
| 61 | const char* | ||
| 62 | get_gcc_empty_string_storage() _NOEXCEPT | ||
| 63 | { | ||
| 64 | static const char* p = compute_gcc_empty_string_storage(); | ||
| 65 | return p; | ||
| 66 | } | ||
| 67 | #endif | ||
| 68 | |||
| 69 | }} // namespace __refstring_imp | ||
| 70 | |||
| 71 | using namespace __refstring_imp; | ||
| 72 | |||
| 73 | inline | ||
| 74 | __libcpp_refstring::__libcpp_refstring(const char* msg) { | ||
| 75 | std::size_t len = strlen(msg); | ||
| 76 | _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); | ||
| 77 | rep->len = len; | ||
| 78 | rep->cap = len; | ||
| 79 | rep->count = 0; | ||
| 80 | char *data = data_from_rep(rep); | ||
| 81 | std::memcpy(data, msg, len + 1); | ||
| 82 | __imp_ = data; | ||
| 83 | } | ||
| 84 | |||
| 85 | inline | ||
| 86 | __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT | ||
| 87 | : __imp_(s.__imp_) | ||
| 88 | { | ||
| 89 | if (__uses_refcount()) | ||
| 90 | __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); | ||
| 91 | } | ||
| 92 | |||
| 93 | inline | ||
| 94 | __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { | ||
| 95 | bool adjust_old_count = __uses_refcount(); | ||
| 96 | struct _Rep_base *old_rep = rep_from_data(__imp_); | ||
| 97 | __imp_ = s.__imp_; | ||
| 98 | if (__uses_refcount()) | ||
| 99 | __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); | ||
| 100 | if (adjust_old_count) | ||
| 101 | { | ||
| 102 | if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) | ||
| 103 | { | ||
| 104 | ::operator delete(old_rep); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | return *this; | ||
| 108 | } | ||
| 109 | |||
| 110 | inline | ||
| 111 | __libcpp_refstring::~__libcpp_refstring() { | ||
| 112 | if (__uses_refcount()) { | ||
| 113 | _Rep_base* rep = rep_from_data(__imp_); | ||
| 114 | if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) { | ||
| 115 | ::operator delete(rep); | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | inline | ||
| 121 | bool __libcpp_refstring::__uses_refcount() const { | ||
| 122 | #ifdef __APPLE__ | ||
| 123 | return __imp_ != get_gcc_empty_string_storage(); | ||
| 124 | #else | ||
| 125 | return true; | ||
| 126 | #endif | ||
| 127 | } | ||
| 128 | |||
| 129 | _LIBCPP_END_NAMESPACE_STD | ||
| 130 | |||
| 131 | #endif //_LIBCPPABI_REFSTRING_H | ||
lib/libcxxabi/src/private_typeinfo.cpp+31-3| ... | @@ -61,6 +61,16 @@ is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp) | ... | @@ -61,6 +61,16 @@ is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp) |
| 61 | return x == y || strcmp(x->name(), y->name()) == 0; | 61 | return x == y || strcmp(x->name(), y->name()) == 0; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static inline ptrdiff_t update_offset_to_base(const char* vtable, | ||
| 65 | ptrdiff_t offset_to_base) { | ||
| 66 | #if __has_feature(cxx_abi_relative_vtable) | ||
| 67 | // VTable components are 32 bits in the relative vtables ABI. | ||
| 68 | return *reinterpret_cast<const int32_t*>(vtable + offset_to_base); | ||
| 69 | #else | ||
| 70 | return *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base); | ||
| 71 | #endif | ||
| 72 | } | ||
| 73 | |||
| 64 | namespace __cxxabiv1 | 74 | namespace __cxxabiv1 |
| 65 | { | 75 | { |
| 66 | 76 | ||
| ... | @@ -297,7 +307,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, | ... | @@ -297,7 +307,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, |
| 297 | if (__offset_flags & __virtual_mask) | 307 | if (__offset_flags & __virtual_mask) |
| 298 | { | 308 | { |
| 299 | const char* vtable = *static_cast<const char*const*>(adjustedPtr); | 309 | const char* vtable = *static_cast<const char*const*>(adjustedPtr); |
| 300 | offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base); | 310 | offset_to_base = update_offset_to_base(vtable, offset_to_base); |
| 301 | } | 311 | } |
| 302 | } | 312 | } |
| 303 | __base_type->has_unambiguous_public_base( | 313 | __base_type->has_unambiguous_public_base( |
| ... | @@ -615,10 +625,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, | ... | @@ -615,10 +625,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, |
| 615 | // Possible future optimization: Take advantage of src2dst_offset | 625 | // Possible future optimization: Take advantage of src2dst_offset |
| 616 | 626 | ||
| 617 | // Get (dynamic_ptr, dynamic_type) from static_ptr | 627 | // Get (dynamic_ptr, dynamic_type) from static_ptr |
| 628 | #if __has_feature(cxx_abi_relative_vtable) | ||
| 629 | // The vtable address will point to the first virtual function, which is 8 | ||
| 630 | // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component). | ||
| 631 | const int32_t* vtable = | ||
| 632 | *reinterpret_cast<const int32_t* const*>(static_ptr); | ||
| 633 | int32_t offset_to_derived = vtable[-2]; | ||
| 634 | const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived; | ||
| 635 | |||
| 636 | // The typeinfo component is now a relative offset to a proxy. | ||
| 637 | int32_t offset_to_ti_proxy = vtable[-1]; | ||
| 638 | const uint8_t* ptr_to_ti_proxy = | ||
| 639 | reinterpret_cast<const uint8_t*>(vtable) + offset_to_ti_proxy; | ||
| 640 | const __class_type_info* dynamic_type = | ||
| 641 | *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy)); | ||
| 642 | #else | ||
| 618 | void **vtable = *static_cast<void ** const *>(static_ptr); | 643 | void **vtable = *static_cast<void ** const *>(static_ptr); |
| 619 | ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]); | 644 | ptrdiff_t offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]); |
| 620 | const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived; | 645 | const void* dynamic_ptr = static_cast<const char*>(static_ptr) + offset_to_derived; |
| 621 | const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]); | 646 | const __class_type_info* dynamic_type = static_cast<const __class_type_info*>(vtable[-1]); |
| 647 | #endif | ||
| 622 | 648 | ||
| 623 | // Initialize answer to nullptr. This will be changed from the search | 649 | // Initialize answer to nullptr. This will be changed from the search |
| 624 | // results if a non-null answer is found. Regardless, this is what will | 650 | // results if a non-null answer is found. Regardless, this is what will |
| ... | @@ -641,6 +667,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, | ... | @@ -641,6 +667,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, |
| 641 | { | 667 | { |
| 642 | // We get here only if there is some kind of visibility problem | 668 | // We get here only if there is some kind of visibility problem |
| 643 | // in client code. | 669 | // in client code. |
| 670 | static_assert(std::atomic<size_t>::is_always_lock_free, ""); | ||
| 644 | static std::atomic<size_t> error_count(0); | 671 | static std::atomic<size_t> error_count(0); |
| 645 | size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); | 672 | size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); |
| 646 | if ((error_count_snapshot & (error_count_snapshot-1)) == 0) | 673 | if ((error_count_snapshot & (error_count_snapshot-1)) == 0) |
| ... | @@ -667,6 +694,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, | ... | @@ -667,6 +694,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, |
| 667 | if (info.path_dst_ptr_to_static_ptr == unknown && | 694 | if (info.path_dst_ptr_to_static_ptr == unknown && |
| 668 | info.path_dynamic_ptr_to_static_ptr == unknown) | 695 | info.path_dynamic_ptr_to_static_ptr == unknown) |
| 669 | { | 696 | { |
| 697 | static_assert(std::atomic<size_t>::is_always_lock_free, ""); | ||
| 670 | static std::atomic<size_t> error_count(0); | 698 | static std::atomic<size_t> error_count(0); |
| 671 | size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); | 699 | size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); |
| 672 | if ((error_count_snapshot & (error_count_snapshot-1)) == 0) | 700 | if ((error_count_snapshot & (error_count_snapshot-1)) == 0) |
| ... | @@ -1265,7 +1293,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info, | ... | @@ -1265,7 +1293,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info, |
| 1265 | if (__offset_flags & __virtual_mask) | 1293 | if (__offset_flags & __virtual_mask) |
| 1266 | { | 1294 | { |
| 1267 | const char* vtable = *static_cast<const char*const*>(current_ptr); | 1295 | const char* vtable = *static_cast<const char*const*>(current_ptr); |
| 1268 | offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base); | 1296 | offset_to_base = update_offset_to_base(vtable, offset_to_base); |
| 1269 | } | 1297 | } |
| 1270 | __base_type->search_above_dst(info, dst_ptr, | 1298 | __base_type->search_above_dst(info, dst_ptr, |
| 1271 | static_cast<const char*>(current_ptr) + offset_to_base, | 1299 | static_cast<const char*>(current_ptr) + offset_to_base, |
| ... | @@ -1285,7 +1313,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info, | ... | @@ -1285,7 +1313,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info, |
| 1285 | if (__offset_flags & __virtual_mask) | 1313 | if (__offset_flags & __virtual_mask) |
| 1286 | { | 1314 | { |
| 1287 | const char* vtable = *static_cast<const char*const*>(current_ptr); | 1315 | const char* vtable = *static_cast<const char*const*>(current_ptr); |
| 1288 | offset_to_base = *reinterpret_cast<const ptrdiff_t*>(vtable + offset_to_base); | 1316 | offset_to_base = update_offset_to_base(vtable, offset_to_base); |
| 1289 | } | 1317 | } |
| 1290 | __base_type->search_below_dst(info, | 1318 | __base_type->search_below_dst(info, |
| 1291 | static_cast<const char*>(current_ptr) + offset_to_base, | 1319 | static_cast<const char*>(current_ptr) + offset_to_base, |
lib/libcxxabi/src/stdlib_exception.cpp-1| ... | @@ -6,7 +6,6 @@ | ... | @@ -6,7 +6,6 @@ |
| 6 | // | 6 | // |
| 7 | //===----------------------------------------------------------------------===// | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | ||
| 9 | #define _LIBCPP_BUILDING_LIBRARY | ||
| 10 | #include <new> | 9 | #include <new> |
| 11 | #include <exception> | 10 | #include <exception> |
| 12 | 11 |
lib/libcxxabi/src/stdlib_new_delete.cpp+16-20| ... | @@ -8,7 +8,6 @@ | ... | @@ -8,7 +8,6 @@ |
| 8 | // This file implements the new and delete operators. | 8 | // This file implements the new and delete operators. |
| 9 | //===----------------------------------------------------------------------===// | 9 | //===----------------------------------------------------------------------===// |
| 10 | 10 | ||
| 11 | #define _LIBCPP_BUILDING_LIBRARY | ||
| 12 | #include "__cxxabi_config.h" | 11 | #include "__cxxabi_config.h" |
| 13 | #include <new> | 12 | #include <new> |
| 14 | #include <cstdlib> | 13 | #include <cstdlib> |
| ... | @@ -28,7 +27,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC | ... | @@ -28,7 +27,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC |
| 28 | if (size == 0) | 27 | if (size == 0) |
| 29 | size = 1; | 28 | size = 1; |
| 30 | void* p; | 29 | void* p; |
| 31 | while ((p = ::malloc(size)) == 0) | 30 | while ((p = ::malloc(size)) == nullptr) |
| 32 | { | 31 | { |
| 33 | // If malloc fails and there is a new_handler, | 32 | // If malloc fails and there is a new_handler, |
| 34 | // call it to try free up memory. | 33 | // call it to try free up memory. |
| ... | @@ -49,7 +48,7 @@ _LIBCXXABI_WEAK | ... | @@ -49,7 +48,7 @@ _LIBCXXABI_WEAK |
| 49 | void* | 48 | void* |
| 50 | operator new(size_t size, const std::nothrow_t&) _NOEXCEPT | 49 | operator new(size_t size, const std::nothrow_t&) _NOEXCEPT |
| 51 | { | 50 | { |
| 52 | void* p = 0; | 51 | void* p = nullptr; |
| 53 | #ifndef _LIBCXXABI_NO_EXCEPTIONS | 52 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 54 | try | 53 | try |
| 55 | { | 54 | { |
| ... | @@ -75,7 +74,7 @@ _LIBCXXABI_WEAK | ... | @@ -75,7 +74,7 @@ _LIBCXXABI_WEAK |
| 75 | void* | 74 | void* |
| 76 | operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT | 75 | operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT |
| 77 | { | 76 | { |
| 78 | void* p = 0; | 77 | void* p = nullptr; |
| 79 | #ifndef _LIBCXXABI_NO_EXCEPTIONS | 78 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 80 | try | 79 | try |
| 81 | { | 80 | { |
| ... | @@ -143,15 +142,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC | ... | @@ -143,15 +142,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC |
| 143 | size = 1; | 142 | size = 1; |
| 144 | if (static_cast<size_t>(alignment) < sizeof(void*)) | 143 | if (static_cast<size_t>(alignment) < sizeof(void*)) |
| 145 | alignment = std::align_val_t(sizeof(void*)); | 144 | alignment = std::align_val_t(sizeof(void*)); |
| 145 | |||
| 146 | // Try allocating memory. If allocation fails and there is a new_handler, | ||
| 147 | // call it to try free up memory, and try again until it succeeds, or until | ||
| 148 | // the new_handler decides to terminate. | ||
| 149 | // | ||
| 150 | // If allocation fails and there is no new_handler, we throw bad_alloc | ||
| 151 | // (or return nullptr if exceptions are disabled). | ||
| 146 | void* p; | 152 | void* p; |
| 147 | #if defined(_LIBCPP_WIN32API) | 153 | while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) |
| 148 | while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr) | ||
| 149 | #else | ||
| 150 | while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0) | ||
| 151 | #endif | ||
| 152 | { | 154 | { |
| 153 | // If posix_memalign fails and there is a new_handler, | ||
| 154 | // call it to try free up memory. | ||
| 155 | std::new_handler nh = std::get_new_handler(); | 155 | std::new_handler nh = std::get_new_handler(); |
| 156 | if (nh) | 156 | if (nh) |
| 157 | nh(); | 157 | nh(); |
| ... | @@ -159,7 +159,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC | ... | @@ -159,7 +159,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC |
| 159 | #ifndef _LIBCXXABI_NO_EXCEPTIONS | 159 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 160 | throw std::bad_alloc(); | 160 | throw std::bad_alloc(); |
| 161 | #else | 161 | #else |
| 162 | p = nullptr; // posix_memalign doesn't initialize 'p' on failure | ||
| 163 | break; | 162 | break; |
| 164 | #endif | 163 | #endif |
| 165 | } | 164 | } |
| ... | @@ -171,7 +170,7 @@ _LIBCXXABI_WEAK | ... | @@ -171,7 +170,7 @@ _LIBCXXABI_WEAK |
| 171 | void* | 170 | void* |
| 172 | operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | 171 | operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT |
| 173 | { | 172 | { |
| 174 | void* p = 0; | 173 | void* p = nullptr; |
| 175 | #ifndef _LIBCXXABI_NO_EXCEPTIONS | 174 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 176 | try | 175 | try |
| 177 | { | 176 | { |
| ... | @@ -197,7 +196,7 @@ _LIBCXXABI_WEAK | ... | @@ -197,7 +196,7 @@ _LIBCXXABI_WEAK |
| 197 | void* | 196 | void* |
| 198 | operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT | 197 | operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT |
| 199 | { | 198 | { |
| 200 | void* p = 0; | 199 | void* p = nullptr; |
| 201 | #ifndef _LIBCXXABI_NO_EXCEPTIONS | 200 | #ifndef _LIBCXXABI_NO_EXCEPTIONS |
| 202 | try | 201 | try |
| 203 | { | 202 | { |
| ... | @@ -216,12 +215,9 @@ _LIBCXXABI_WEAK | ... | @@ -216,12 +215,9 @@ _LIBCXXABI_WEAK |
| 216 | void | 215 | void |
| 217 | operator delete(void* ptr, std::align_val_t) _NOEXCEPT | 216 | operator delete(void* ptr, std::align_val_t) _NOEXCEPT |
| 218 | { | 217 | { |
| 219 | if (ptr) | 218 | if (ptr) { |
| 220 | #if defined(_LIBCPP_WIN32API) | 219 | std::__libcpp_aligned_free(ptr); |
| 221 | ::_aligned_free(ptr); | 220 | } |
| 222 | #else | ||
| 223 | ::free(ptr); | ||
| 224 | #endif | ||
| 225 | } | 221 | } |
| 226 | 222 | ||
| 227 | _LIBCXXABI_WEAK | 223 | _LIBCXXABI_WEAK |
lib/libcxxabi/src/stdlib_stdexcept.cpp+1-1| ... | @@ -6,7 +6,7 @@ | ... | @@ -6,7 +6,7 @@ |
| 6 | // | 6 | // |
| 7 | //===----------------------------------------------------------------------===// | 7 | //===----------------------------------------------------------------------===// |
| 8 | 8 | ||
| 9 | #include "include/refstring.h" | 9 | #include "../../libcxx/src/include/refstring.h" |
| 10 | #include "stdexcept" | 10 | #include "stdexcept" |
| 11 | #include "new" | 11 | #include "new" |
| 12 | #include <cstdlib> | 12 | #include <cstdlib> |