From a2dcb432905698f37d9452c507f35e05af4bc9f0 Mon Sep 17 00:00:00 2001 From: Force Charlie Date: Sun, 31 Dec 2023 18:31:48 +0800 Subject: [PATCH] Sync bela --- vendor/bela.lock | 2 +- vendor/bela/include/bela/__phmap/VERSION | 2 +- vendor/bela/include/bela/__phmap/phmap.h | 333 +++++---- vendor/bela/include/bela/__phmap/phmap_base.h | 214 ++++-- vendor/bela/include/bela/__phmap/phmap_bits.h | 10 +- vendor/bela/include/bela/__phmap/phmap_dump.h | 12 +- .../bela/__strings/str_join_internal.hpp | 2 +- .../__strings/str_join_narrow_internal.hpp | 2 +- .../bela/__strings/str_split_internal.hpp | 2 +- .../__strings/str_split_narrow_internal.hpp | 2 +- vendor/bela/include/bela/ascii.hpp | 2 +- vendor/bela/include/bela/escaping.hpp | 2 +- vendor/bela/include/bela/macros.hpp | 2 +- vendor/bela/include/bela/match.hpp | 2 +- vendor/bela/include/bela/numbers.hpp | 2 +- vendor/bela/include/bela/str_cat.hpp | 2 +- vendor/bela/include/bela/str_join.hpp | 2 +- vendor/bela/include/bela/str_join_narrow.hpp | 2 +- vendor/bela/include/bela/str_replace.hpp | 2 +- vendor/bela/include/bela/str_split.hpp | 2 +- vendor/bela/include/bela/str_split_narrow.hpp | 2 +- vendor/bela/include/bela/strings.hpp | 2 +- vendor/bela/include/bela/strip.hpp | 2 +- vendor/bela/include/bela/subsitute.hpp | 2 +- vendor/bela/include/bela/time.hpp | 2 +- vendor/bela/src/bela/ascii.cc | 2 +- vendor/bela/src/bela/escaping.cc | 2 +- vendor/bela/src/bela/match.cc | 2 +- vendor/bela/src/bela/numbers.cc | 2 +- vendor/bela/src/bela/str_cat.cc | 2 +- vendor/bela/src/bela/str_replace.cc | 2 +- vendor/bela/src/bela/str_split.cc | 2 +- vendor/bela/src/bela/str_split_narrow.cc | 2 +- vendor/bela/src/bela/subsitute.cc | 2 +- vendor/bela/src/belahash/blake3.lock | 2 +- vendor/bela/src/belahash/blake3/blake3.h | 2 +- .../src/belahash/blake3/blake3_dispatch.c | 6 +- vendor/bela/src/belahash/blake3/blake3_impl.h | 6 +- vendor/bela/src/belatime/duration.cc | 2 +- vendor/bela/src/belatime/time.cc | 2 +- vendor/bela/src/belaund/llvm/VERSION | 2 +- .../llvm/include/llvm/Demangle/Demangle.h | 5 +- .../include/llvm/Demangle/DemangleConfig.h | 5 + .../include/llvm/Demangle/ItaniumDemangle.h | 637 +++++++++++++++--- .../include/llvm/Demangle/ItaniumNodes.def | 9 + .../llvm/include/llvm/Demangle/README.txt | 2 +- .../llvm/include/llvm/Demangle/Utility.h | 8 +- .../belaund/llvm/lib/Demangle/Demangle.cpp | 14 +- 48 files changed, 986 insertions(+), 345 deletions(-) diff --git a/vendor/bela.lock b/vendor/bela.lock index d576ecad..ffd7ce05 100644 --- a/vendor/bela.lock +++ b/vendor/bela.lock @@ -1 +1 @@ -https://github.com/fcharlie/bela/tree/da3e775d8f96a1eb13e7e8cd4f0bb506f06e910f +https://github.com/fcharlie/bela/tree/7ea43482892f03eac1850fd4e6bcf9cd572b4ecf diff --git a/vendor/bela/include/bela/__phmap/VERSION b/vendor/bela/include/bela/__phmap/VERSION index 832dbd9e..32fd6d16 100644 --- a/vendor/bela/include/bela/__phmap/VERSION +++ b/vendor/bela/include/bela/__phmap/VERSION @@ -1,2 +1,2 @@ https://github.com/greg7mdp/parallel-hashmap.git -81ca45376940d4bfd56754608c8ed6c1900ab1e9 +946ebad67a21212d11a0dd4deb7cdedc297d47bc diff --git a/vendor/bela/include/bela/__phmap/phmap.h b/vendor/bela/include/bela/__phmap/phmap.h index ad761108..87812bd2 100644 --- a/vendor/bela/include/bela/__phmap/phmap.h +++ b/vendor/bela/include/bela/__phmap/phmap.h @@ -357,7 +357,7 @@ inline size_t H1(size_t hashval, const ctrl_t* ) { #endif -inline h2_t H2(size_t hashval) { return (h2_t)(ctrl_t)(hashval & 0x7F); } +inline ctrl_t H2(size_t hashval) { return (ctrl_t)(hashval & 0x7F); } inline bool IsEmpty(ctrl_t c) { return c == kEmpty; } inline bool IsFull(ctrl_t c) { return c >= static_cast(0); } @@ -1271,8 +1271,8 @@ class raw_hash_set if (empty()) return; if (capacity_) { - if constexpr (!std::is_trivially_destructible::value || - std::is_same::value) { + PHMAP_IF_CONSTEXPR((!std::is_trivially_destructible::value || + std::is_same::value)) { // node map or not trivially destructible... we need to iterate and destroy values one by one for (size_t i = 0; i != capacity_; ++i) { if (IsFull(ctrl_[i])) { @@ -1448,8 +1448,7 @@ class raw_hash_set // This overload kicks in if we cannot deduce the key from args. It constructs // value_type unconditionally and then either moves it into the table or // destroys. - template ::value, int>::type = 0> + template ::value, int>::type = 0> std::pair emplace(Args&&... args) { typename phmap::aligned_storage::type raw; @@ -1507,6 +1506,10 @@ class raw_hash_set friend class raw_hash_set; public: + slot_type* slot() const { + return *slot_; + } + template void operator()(Args&&... args) const { assert(*slot_); @@ -1547,12 +1550,13 @@ class raw_hash_set template iterator lazy_emplace_with_hash(const key_arg& key, size_t hashval, F&& f) { - auto res = find_or_prepare_insert(key, hashval); - if (res.second) { - lazy_emplace_at(res.first, std::forward(f)); - this->set_ctrl(res.first, H2(hashval)); + size_t offset = _find_key(key, hashval); + if (offset == (size_t)-1) { + offset = prepare_insert(hashval); + lazy_emplace_at(offset, std::forward(f)); + this->set_ctrl(offset, H2(hashval)); } - return iterator_at(res.first); + return iterator_at(offset); } template @@ -1564,12 +1568,13 @@ class raw_hash_set template void emplace_single_with_hash(const key_arg& key, size_t hashval, F&& f) { - auto res = find_or_prepare_insert(key, hashval); - if (res.second) { - lazy_emplace_at(res.first, std::forward(f)); - this->set_ctrl(res.first, H2(hashval)); + size_t offset = _find_key(key, hashval); + if (offset == (size_t)-1) { + offset = prepare_insert(hashval); + lazy_emplace_at(offset, std::forward(f)); + this->set_ctrl(offset, H2(hashval)); } else - _erase(iterator_at(res.first)); + _erase(iterator_at(offset)); } @@ -1806,7 +1811,7 @@ class raw_hash_set size_t bucket_count() const { return capacity_; } float load_factor() const { - return capacity_ ? static_cast(size()) / capacity_ : 0.0; + return capacity_ ? static_cast(static_cast(size()) / capacity_) : 0.0f; } float max_load_factor() const { return 1.0f; } void max_load_factor(float) { @@ -1897,12 +1902,14 @@ class raw_hash_set std::pair emplace_decomposable(const K& key, size_t hashval, Args&&... args) { - auto res = find_or_prepare_insert(key, hashval); - if (res.second) { - emplace_at(res.first, std::forward(args)...); - this->set_ctrl(res.first, H2(hashval)); + size_t offset = _find_key(key, hashval); + if (offset == (size_t)-1) { + offset = prepare_insert(hashval); + emplace_at(offset, std::forward(args)...); + this->set_ctrl(offset, H2(hashval)); + return {iterator_at(offset), true}; } - return {iterator_at(res.first), res.second}; + return {iterator_at(offset), false}; } struct EmplaceDecomposable @@ -2009,8 +2016,8 @@ class raw_hash_set if (!capacity_) return; - if constexpr (!std::is_trivially_destructible::value || - std::is_same::value) { + PHMAP_IF_CONSTEXPR((!std::is_trivially_destructible::value || + std::is_same::value)) { // node map, or not trivially destructible... we need to iterate and destroy values one by one // std::cout << "either this is a node map or " << type_name() << " is not trivially_destructible\n"; for (size_t i = 0; i != capacity_; ++i) { @@ -2194,7 +2201,7 @@ class raw_hash_set protected: template - std::pair find_or_prepare_insert(const K& key, size_t hashval) { + size_t _find_key(const K& key, size_t hashval) { auto seq = probe(hashval); while (true) { Group g{ctrl_ + seq.offset()}; @@ -2202,12 +2209,20 @@ class raw_hash_set if (PHMAP_PREDICT_TRUE(PolicyTraits::apply( EqualElement{key, eq_ref()}, PolicyTraits::element(slots_ + seq.offset((size_t)i))))) - return {seq.offset((size_t)i), false}; + return seq.offset((size_t)i); } if (PHMAP_PREDICT_TRUE(g.MatchEmpty())) break; seq.next(); } - return {prepare_insert(hashval), true}; + return (size_t)-1; + } + + template + std::pair find_or_prepare_insert(const K& key, size_t hashval) { + size_t offset = _find_key(key, hashval); + if (offset == (size_t)-1) + return {prepare_insert(hashval), true}; + return {offset, false}; } size_t prepare_insert(size_t hashval) PHMAP_ATTRIBUTE_NOINLINE { @@ -2479,26 +2494,30 @@ class raw_hash_map : public raw_hash_set template std::pair insert_or_assign_impl(K&& k, V&& v) { size_t hashval = this->hash(k); - auto res = this->find_or_prepare_insert(k, hashval); - if (res.second) { - this->emplace_at(res.first, std::forward(k), std::forward(v)); - this->set_ctrl(res.first, H2(hashval)); - } else - Policy::value(&*this->iterator_at(res.first)) = std::forward(v); - return {this->iterator_at(res.first), res.second}; + size_t offset = this->_find_key(k, hashval); + if (offset == (size_t)-1) { + offset = this->prepare_insert(hashval); + this->emplace_at(offset, std::forward(k), std::forward(v)); + this->set_ctrl(offset, H2(hashval)); + return {this->iterator_at(offset), true}; + } + Policy::value(&*this->iterator_at(offset)) = std::forward(v); + return {this->iterator_at(offset), false}; } template std::pair try_emplace_impl(K&& k, Args&&... args) { size_t hashval = this->hash(k); - auto res = this->find_or_prepare_insert(k, hashval); - if (res.second) { - this->emplace_at(res.first, std::piecewise_construct, + size_t offset = this->_find_key(k, hashval); + if (offset == (size_t)-1) { + offset = this->prepare_insert(hashval); + this->emplace_at(offset, std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(args)...)); - this->set_ctrl(res.first, H2(hashval)); + this->set_ctrl(offset, H2(hashval)); + return {this->iterator_at(offset), true}; } - return {this->iterator_at(res.first), res.second}; + return {this->iterator_at(offset), false}; } }; @@ -2564,7 +2583,11 @@ class parallel_hash_set using key_arg = typename KeyArgImpl::template type; protected: - using Lockable = phmap::LockableImpl; + using Lockable = phmap::LockableImpl; + using UniqueLock = typename Lockable::UniqueLock; + using SharedLock = typename Lockable::SharedLock; + using ReadWriteLock = typename Lockable::ReadWriteLock; + // -------------------------------------------------------------------- struct Inner : public Lockable @@ -2615,9 +2638,7 @@ class parallel_hash_set // -------------------------------------------------------------------- template using RequiresInsertable = typename std::enable_if< - phmap::disjunction, - SameAsElementReference>::value, - int>::type; + phmap::disjunction, SameAsElementReference>::value, int>::type; // RequiresNotInit is a workaround for gcc prior to 7.1. // See https://godbolt.org/g/Y4xsUh. @@ -2944,7 +2965,7 @@ class parallel_hash_set PHMAP_ATTRIBUTE_REINITIALIZES void clear() { for (auto& inner : sets_) { - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); inner.set_.clear(); } } @@ -2953,7 +2974,7 @@ class parallel_hash_set // ---------------------------------------- void clear(std::size_t submap_index) { Inner& inner = sets_[submap_index]; - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); inner.set_.clear(); } @@ -3046,11 +3067,11 @@ class parallel_hash_set Inner& inner = sets_[subidx(hashval)]; auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); auto res = set.insert(std::move(node), hashval); return { make_iterator(&inner, res.position), - res.inserted, - res.inserted ? node_type() : std::move(res.node) }; + res.inserted, + res.inserted ? node_type() : std::move(res.node) }; } iterator insert(const_iterator, node_type&& node) { @@ -3070,15 +3091,6 @@ class parallel_hash_set // ---------------------------------- // same as emplace, but hashval is provided // -------------------------------------------------------------------- - template - std::pair emplace_decomposable_with_hash(const K& key, size_t hashval, Args&&... args) - { - Inner& inner = sets_[subidx(hashval)]; - auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); - return make_rv(&inner, set.emplace_decomposable(key, hashval, std::forward(args)...)); - } - struct EmplaceDecomposableHashval { template @@ -3099,8 +3111,7 @@ class parallel_hash_set // // Creates no std::string copies and makes no heap allocations. // m.emplace("abc", "xyz"); // -------------------------------------------------------------------- - template ::value, int>::type = 0> + template ::value, int>::type = 0> std::pair emplace_with_hash(size_t hashval, Args&&... args) { return PolicyTraits::apply(EmplaceDecomposableHashval{*this, hashval}, std::forward(args)...); @@ -3110,8 +3121,7 @@ class parallel_hash_set // value_type unconditionally and then either moves it into the table or // destroys. // -------------------------------------------------------------------- - template ::value, int>::type = 0> + template ::value, int>::type = 0> std::pair emplace_with_hash(size_t hashval, Args&&... args) { typename phmap::aligned_storage::type raw; slot_type* slot = reinterpret_cast(&raw); @@ -3120,9 +3130,8 @@ class parallel_hash_set const auto& elem = PolicyTraits::element(slot); Inner& inner = sets_[subidx(hashval)]; auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); - typename EmbeddedSet::template InsertSlotWithHash f { - inner, std::move(*slot), hashval}; + UniqueLock m(inner); + typename EmbeddedSet::template InsertSlotWithHash f { inner, std::move(*slot), hashval }; return make_rv(PolicyTraits::apply(f, elem)); } @@ -3131,26 +3140,36 @@ class parallel_hash_set return emplace_with_hash(hashval, std::forward(args)...).first; } - template - iterator lazy_emplace_with_hash(const key_arg& key, size_t hashval, F&& f) { - Inner& inner = sets_[subidx(hashval)]; - auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); - return make_iterator(&inner, set.lazy_emplace_with_hash(key, hashval, std::forward(f))); - } - // -------------------------------------------------------------------- // end of phmap expension // -------------------------------------------------------------------- template - std::pair emplace_decomposable(const K& key, Args&&... args) + std::pair emplace_decomposable_with_hash(const K& key, size_t hashval, Args&&... args) { - size_t hashval = this->hash(key); Inner& inner = sets_[subidx(hashval)]; auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); - return make_rv(&inner, set.emplace_decomposable(key, hashval, std::forward(args)...)); + ReadWriteLock m(inner); + + size_t offset = set._find_key(key, hashval); + if (offset == (size_t)-1 && m.switch_to_unique()) { + // we did an unlock/lock, and another thread could have inserted the same key, so we need to + // do a find() again. + offset = set._find_key(key, hashval); + } + if (offset == (size_t)-1) { + offset = set.prepare_insert(hashval); + set.emplace_at(offset, std::forward(args)...); + set.set_ctrl(offset, H2(hashval)); + return make_rv(&inner, {set.iterator_at(offset), true}); + } + return make_rv(&inner, {set.iterator_at(offset), false}); + } + + template + std::pair emplace_decomposable(const K& key, Args&&... args) + { + return emplace_decomposable_with_hash(key, this->hash(key), std::forward(args)...); } struct EmplaceDecomposable @@ -3172,19 +3191,16 @@ class parallel_hash_set // // Creates no std::string copies and makes no heap allocations. // m.emplace("abc", "xyz"); // -------------------------------------------------------------------- - template ::value, int>::type = 0> + template ::value, int>::type = 0> std::pair emplace(Args&&... args) { - return PolicyTraits::apply(EmplaceDecomposable{*this}, - std::forward(args)...); + return PolicyTraits::apply(EmplaceDecomposable{*this}, std::forward(args)...); } // This overload kicks in if we cannot deduce the key from args. It constructs // value_type unconditionally and then either moves it into the table or // destroys. // -------------------------------------------------------------------- - template ::value, int>::type = 0> + template ::value, int>::type = 0> std::pair emplace(Args&&... args) { typename phmap::aligned_storage::type raw; slot_type* slot = reinterpret_cast(&raw); @@ -3192,11 +3208,10 @@ class parallel_hash_set PolicyTraits::construct(&alloc_ref(), slot, std::forward(args)...); const auto& elem = PolicyTraits::element(slot); - Inner& inner = sets_[subidx(hashval)]; - auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); - typename EmbeddedSet::template InsertSlotWithHash f { - inner, std::move(*slot), hashval}; + Inner& inner = sets_[subidx(hashval)]; + auto& set = inner.set_; + UniqueLock m(inner); + typename EmbeddedSet::template InsertSlotWithHash f { inner, std::move(*slot), hashval }; return make_rv(PolicyTraits::apply(f, elem)); } @@ -3221,12 +3236,27 @@ class parallel_hash_set // lazy_emplace // ------------ template - iterator lazy_emplace(const key_arg& key, F&& f) { - auto hashval = this->hash(key); + iterator lazy_emplace_with_hash(const key_arg& key, size_t hashval, F&& f) { Inner& inner = sets_[subidx(hashval)]; auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); - return make_iterator(&inner, set.lazy_emplace_with_hash(key, hashval, std::forward(f))); + ReadWriteLock m(inner); + size_t offset = set._find_key(key, hashval); + if (offset == (size_t)-1 && m.switch_to_unique()) { + // we did an unlock/lock, and another thread could have inserted the same key, so we need to + // do a find() again. + offset = set._find_key(key, hashval); + } + if (offset == (size_t)-1) { + offset = set.prepare_insert(hashval); + set.lazy_emplace_at(offset, std::forward(f)); + set.set_ctrl(offset, H2(hashval)); + } + return make_iterator(&inner, set.iterator_at(offset)); + } + + template + iterator lazy_emplace(const key_arg& key, F&& f) { + return lazy_emplace_with_hash(key, this->hash(key), std::forward(f)); } // emplace_single @@ -3235,14 +3265,13 @@ class parallel_hash_set void emplace_single_with_hash(const key_arg& key, size_t hashval, F&& f) { Inner& inner = sets_[subidx(hashval)]; auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); set.emplace_single_with_hash(key, hashval, std::forward(f)); } template void emplace_single(const key_arg& key, F&& f) { - auto hashval = this->hash(key); - emplace_single_with_hash(key, hashval, std::forward(f)); + emplace_single_with_hash(key, this->hash(key), std::forward(f)); } // if set contains key, lambda is called with the value_type (under read lock protection), @@ -3251,7 +3280,7 @@ class parallel_hash_set template bool if_contains(const key_arg& key, F&& f) const { return const_cast(this)->template - modify_if_impl(key, std::forward(f)); + modify_if_impl(key, std::forward(f)); } // if set contains key, lambda is called with the value_type without read lock protection, @@ -3269,7 +3298,7 @@ class parallel_hash_set // ---------------------------------------------------------------------------------------------------- template bool modify_if(const key_arg& key, F&& f) { - return modify_if_impl(key, std::forward(f)); + return modify_if_impl(key, std::forward(f)); } // ----------------------------------------------------------------------------------------- @@ -3293,23 +3322,33 @@ class parallel_hash_set // ---------------------------------------------------------------------------------------------------- template bool erase_if(const key_arg& key, F&& f) { - return erase_if_impl(key, std::forward(f)); + return !!erase_if_impl(key, std::forward(f)); } template - bool erase_if_impl(const key_arg& key, F&& f) { + size_type erase_if_impl(const key_arg& key, F&& f) { #if __cplusplus >= 201703L static_assert(std::is_invocable::value); #endif - L m; - auto it = this->template find(key, this->hash(key), m); - if (it == this->end()) return false; + auto hashval = this->hash(key); + Inner& inner = sets_[subidx(hashval)]; + auto& set = inner.set_; + L m(inner); + auto it = set.find(key, hashval); + if (it == set.end()) + return 0; + if (m.switch_to_unique()) { + // we did an unlock/lock, need to call `find()` again + it = set.find(key, hashval); + if (it == set.end()) + return 0; + } if (std::forward(f)(const_cast(*it))) { - this->erase(it); - return true; + set._erase(it); + return 1; } - return false; + return 0; } // if map already contains key, the first lambda is called with the mapped value (under @@ -3321,15 +3360,17 @@ class parallel_hash_set template bool lazy_emplace_l(const key_arg& key, FExists&& fExists, FEmplace&& fEmplace) { size_t hashval = this->hash(key); - typename Lockable::UniqueLock m; + ReadWriteLock m; auto res = this->find_or_prepare_insert_with_hash(hashval, key, m); Inner* inner = std::get<0>(res); if (std::get<2>(res)) { + // key not found. call fEmplace lambda which should invoke passed constructor inner->set_.lazy_emplace_at(std::get<1>(res), std::forward(fEmplace)); inner->set_.set_ctrl(std::get<1>(res), H2(hashval)); } else { + // key found. Call fExists lambda. In case of the set, non "key" part of value_type can be changed auto it = this->iterator_at(inner, inner->set_.iterator_at(std::get<1>(res))); - std::forward(fExists)(const_cast(*it)); // in case of the set, non "key" part of value_type can be changed + std::forward(fExists)(const_cast(*it)); } return std::get<2>(res); } @@ -3344,7 +3385,7 @@ class parallel_hash_set template void for_each(F&& fCallback) const { for (auto const& inner : sets_) { - typename Lockable::SharedLock m(const_cast(inner)); + SharedLock m(const_cast(inner)); std::for_each(inner.set_.begin(), inner.set_.end(), fCallback); } } @@ -3353,7 +3394,7 @@ class parallel_hash_set template void for_each_m(F&& fCallback) { for (auto& inner : sets_) { - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); std::for_each(inner.set_.begin(), inner.set_.end(), fCallback); } } @@ -3364,7 +3405,7 @@ class parallel_hash_set std::for_each( std::forward(policy), sets_.begin(), sets_.end(), [&](auto const& inner) { - typename Lockable::SharedLock m(const_cast(inner)); + SharedLock m(const_cast(inner)); std::for_each(inner.set_.begin(), inner.set_.end(), fCallback); } ); @@ -3375,7 +3416,7 @@ class parallel_hash_set std::for_each( std::forward(policy), sets_.begin(), sets_.end(), [&](auto& inner) { - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); std::for_each(inner.set_.begin(), inner.set_.end(), fCallback); } ); @@ -3391,7 +3432,7 @@ class parallel_hash_set void with_submap(size_t idx, F&& fCallback) const { const Inner& inner = sets_[idx]; const auto& set = inner.set_; - typename Lockable::SharedLock m(const_cast(inner)); + SharedLock m(const_cast(inner)); fCallback(set); } @@ -3399,7 +3440,7 @@ class parallel_hash_set void with_submap_m(size_t idx, F&& fCallback) { Inner& inner = sets_[idx]; auto& set = inner.set_; - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); fCallback(set); } @@ -3421,17 +3462,8 @@ class parallel_hash_set // -------------------------------------------------------------------- template size_type erase(const key_arg& key) { - auto hashval = this->hash(key); - Inner& inner = sets_[subidx(hashval)]; - auto& set = inner.set_; - typename Lockable::UpgradeLock m(inner); - auto it = set.find(key, hashval); - if (it == set.end()) - return 0; - - typename Lockable::UpgradeToUnique unique(m); - set._erase(it); - return 1; + auto always_erase = [](const value_type&){ return true; }; + return erase_if_impl(key, std::move(always_erase)); } // -------------------------------------------------------------------- @@ -3456,7 +3488,7 @@ class parallel_hash_set Inner* inner = it.inner_; assert(inner != nullptr); auto& set = inner->set_; - // typename Lockable::UniqueLock m(*inner); // don't lock here + // UniqueLock m(*inner); // don't lock here set._erase(it.it_); } @@ -3530,7 +3562,7 @@ class parallel_hash_set size_t nn = n / num_tables; for (auto& inner : sets_) { - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); inner.set_.rehash(nn); } } @@ -3538,7 +3570,7 @@ class parallel_hash_set void reserve(size_t n) { size_t target = GrowthToLowerboundCapacity(n); - size_t normalized = 16 * NormalizeCapacity(n / num_tables); + size_t normalized = num_tables * NormalizeCapacity(n / num_tables); rehash(normalized > target ? normalized : target); } @@ -3566,7 +3598,7 @@ class parallel_hash_set void prefetch_hash(size_t hashval) const { const Inner& inner = sets_[subidx(hashval)]; const auto& set = inner.set_; - typename Lockable::SharedLock m(const_cast(inner)); + SharedLock m(const_cast(inner)); set.prefetch_hash(hashval); } @@ -3585,7 +3617,7 @@ class parallel_hash_set // -------------------------------------------------------------------- template iterator find(const key_arg& key, size_t hashval) { - typename Lockable::SharedLock m; + SharedLock m; return find(key, hashval, m); } @@ -3633,7 +3665,7 @@ class parallel_hash_set size_t sz = 0; for (const auto& inner : sets_) { - typename Lockable::SharedLock m(const_cast(inner)); + SharedLock m(const_cast(inner)); sz += inner.set_.bucket_count(); } return sz; @@ -3729,7 +3761,7 @@ class parallel_hash_set void drop_deletes_without_resize() PHMAP_ATTRIBUTE_NOINLINE { for (auto& inner : sets_) { - typename Lockable::UniqueLock m(inner); + UniqueLock m(inner); inner.set_.drop_deletes_without_resize(); } } @@ -3738,7 +3770,7 @@ class parallel_hash_set size_t hashval = PolicyTraits::apply(HashElement{hash_ref()}, elem); Inner& inner = sets_[subidx(hashval)]; auto& set = inner.set_; - typename Lockable::SharedLock m(const_cast(inner)); + SharedLock m(const_cast(inner)); return set.has_element(elem, hashval); } @@ -3759,7 +3791,7 @@ class parallel_hash_set } protected: - template + template pointer find_ptr(const key_arg& key, size_t hashval, L& mutexlock) { Inner& inner = sets_[subidx(hashval)]; @@ -3768,7 +3800,7 @@ class parallel_hash_set return set.find_ptr(key, hashval); } - template + template iterator find(const key_arg& key, size_t hashval, L& mutexlock) { Inner& inner = sets_[subidx(hashval)]; auto& set = inner.set_; @@ -3778,17 +3810,26 @@ class parallel_hash_set template std::tuple - find_or_prepare_insert_with_hash(size_t hashval, const K& key, typename Lockable::UniqueLock &mutexlock) { + find_or_prepare_insert_with_hash(size_t hashval, const K& key, ReadWriteLock &mutexlock) { Inner& inner = sets_[subidx(hashval)]; auto& set = inner.set_; - mutexlock = std::move(typename Lockable::UniqueLock(inner)); - auto p = set.find_or_prepare_insert(key, hashval); // std::pair - return std::make_tuple(&inner, p.first, p.second); + mutexlock = std::move(ReadWriteLock(inner)); + size_t offset = set._find_key(key, hashval); + if (offset == (size_t)-1 && mutexlock.switch_to_unique()) { + // we did an unlock/lock, and another thread could have inserted the same key, so we need to + // do a find() again. + offset = set._find_key(key, hashval); + } + if (offset == (size_t)-1) { + offset = set.prepare_insert(hashval); + return std::make_tuple(&inner, offset, true); + } + return std::make_tuple(&inner, offset, false); } template std::tuple - find_or_prepare_insert(const K& key, typename Lockable::UniqueLock &mutexlock) { + find_or_prepare_insert(const K& key, ReadWriteLock &mutexlock) { return find_or_prepare_insert_with_hash(this->hash(key), key, mutexlock); } @@ -3856,7 +3897,10 @@ class parallel_hash_map : public parallel_hash_set::value && IsTransparent::value>; using Base = typename parallel_hash_map::parallel_hash_set; - using Lockable = phmap::LockableImpl; + using Lockable = phmap::LockableImpl; + using UniqueLock = typename Lockable::UniqueLock; + using SharedLock = typename Lockable::SharedLock; + using ReadWriteLock = typename Lockable::ReadWriteLock; public: using key_type = typename Policy::key_type; @@ -4007,7 +4051,7 @@ class parallel_hash_map : public parallel_hash_set bool try_emplace_l(K&& k, F&& f, Args&&... args) { size_t hashval = this->hash(k); - typename Lockable::UniqueLock m; + ReadWriteLock m; auto res = this->find_or_prepare_insert_with_hash(hashval, k, m); typename Base::Inner *inner = std::get<0>(res); if (std::get<2>(res)) { @@ -4017,7 +4061,8 @@ class parallel_hash_map : public parallel_hash_setset_.set_ctrl(std::get<1>(res), H2(hashval)); } else { auto it = this->iterator_at(inner, inner->set_.iterator_at(std::get<1>(res))); - std::forward(f)(const_cast(*it)); // in case of the set, non "key" part of value_type can be changed + // call lambda. in case of the set, non "key" part of value_type can be changed + std::forward(f)(const_cast(*it)); } return std::get<2>(res); } @@ -4027,7 +4072,7 @@ class parallel_hash_map : public parallel_hash_set std::pair try_emplace_p(K&& k, Args&&... args) { size_t hashval = this->hash(k); - typename Lockable::UniqueLock m; + ReadWriteLock m; auto res = this->find_or_prepare_insert_with_hash(hashval, k, m); typename Base::Inner *inner = std::get<0>(res); if (std::get<2>(res)) { @@ -4057,7 +4102,7 @@ class parallel_hash_map : public parallel_hash_set std::pair insert_or_assign_impl(K&& k, V&& v) { size_t hashval = this->hash(k); - typename Lockable::UniqueLock m; + ReadWriteLock m; auto res = this->find_or_prepare_insert_with_hash(hashval, k, m); typename Base::Inner *inner = std::get<0>(res); if (std::get<2>(res)) { @@ -4077,7 +4122,7 @@ class parallel_hash_map : public parallel_hash_set std::pair try_emplace_impl_with_hash(size_t hashval, K&& k, Args&&... args) { - typename Lockable::UniqueLock m; + ReadWriteLock m; auto res = this->find_or_prepare_insert_with_hash(hashval, k, m); typename Base::Inner *inner = std::get<0>(res); if (std::get<2>(res)) { @@ -4537,7 +4582,7 @@ struct HashtableDebugAccess{ key, set.eq_ref()}, diff --git a/vendor/bela/include/bela/__phmap/phmap_base.h b/vendor/bela/include/bela/__phmap/phmap_base.h index 3483d5b3..09d48547 100644 --- a/vendor/bela/include/bela/__phmap/phmap_base.h +++ b/vendor/bela/include/bela/__phmap/phmap_base.h @@ -654,82 +654,84 @@ namespace base_internal { namespace { #ifdef PHMAP_HAVE_EXCEPTIONS - #define PHMAP_THROW_IMPL(e) throw e + #define PHMAP_THROW_IMPL_MSG(e, message) throw e(message) + #define PHMAP_THROW_IMPL(e) throw e() #else - #define PHMAP_THROW_IMPL(...) std::abort() + #define PHMAP_THROW_IMPL_MSG(e, message) do { (void)(message); std::abort(); } while(0) + #define PHMAP_THROW_IMPL(e) std::abort() #endif } // namespace static inline void ThrowStdLogicError(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::logic_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::logic_error, what_arg); } static inline void ThrowStdLogicError(const char* what_arg) { - PHMAP_THROW_IMPL(std::logic_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::logic_error, what_arg); } static inline void ThrowStdInvalidArgument(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::invalid_argument(what_arg)); + PHMAP_THROW_IMPL_MSG(std::invalid_argument, what_arg); } static inline void ThrowStdInvalidArgument(const char* what_arg) { - PHMAP_THROW_IMPL(std::invalid_argument(what_arg)); + PHMAP_THROW_IMPL_MSG(std::invalid_argument, what_arg); } static inline void ThrowStdDomainError(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::domain_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::domain_error, what_arg); } static inline void ThrowStdDomainError(const char* what_arg) { - PHMAP_THROW_IMPL(std::domain_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::domain_error, what_arg); } static inline void ThrowStdLengthError(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::length_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::length_error, what_arg); } static inline void ThrowStdLengthError(const char* what_arg) { - PHMAP_THROW_IMPL(std::length_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::length_error, what_arg); } static inline void ThrowStdOutOfRange(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::out_of_range(what_arg)); + PHMAP_THROW_IMPL_MSG(std::out_of_range, what_arg); } static inline void ThrowStdOutOfRange(const char* what_arg) { - PHMAP_THROW_IMPL(std::out_of_range(what_arg)); + PHMAP_THROW_IMPL_MSG(std::out_of_range, what_arg); } static inline void ThrowStdRuntimeError(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::runtime_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::runtime_error, what_arg); } static inline void ThrowStdRuntimeError(const char* what_arg) { - PHMAP_THROW_IMPL(std::runtime_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::runtime_error, what_arg); } static inline void ThrowStdRangeError(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::range_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::range_error, what_arg); } static inline void ThrowStdRangeError(const char* what_arg) { - PHMAP_THROW_IMPL(std::range_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::range_error, what_arg); } static inline void ThrowStdOverflowError(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::overflow_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::overflow_error, what_arg); } static inline void ThrowStdOverflowError(const char* what_arg) { - PHMAP_THROW_IMPL(std::overflow_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::overflow_error, what_arg); } static inline void ThrowStdUnderflowError(const std::string& what_arg) { - PHMAP_THROW_IMPL(std::underflow_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::underflow_error, what_arg); } static inline void ThrowStdUnderflowError(const char* what_arg) { - PHMAP_THROW_IMPL(std::underflow_error(what_arg)); + PHMAP_THROW_IMPL_MSG(std::underflow_error, what_arg); } static inline void ThrowStdBadFunctionCall() { - PHMAP_THROW_IMPL(std::bad_function_call()); + PHMAP_THROW_IMPL(std::bad_function_call); } static inline void ThrowStdBadAlloc() { - PHMAP_THROW_IMPL(std::bad_alloc()); + PHMAP_THROW_IMPL(std::bad_alloc); } } // namespace base_internal @@ -4375,14 +4377,14 @@ namespace memory_internal { // ---------------------------------------------------------------------------- template struct OffsetOf { - static constexpr size_t kFirst = (size_t)-1; - static constexpr size_t kSecond = (size_t)-1; + static constexpr size_t kFirst = static_cast(-1); + static constexpr size_t kSecond = static_cast(-1); }; template struct OffsetOf::type> { - static constexpr size_t kFirst = offsetof(Pair, first); + static constexpr size_t kFirst = offsetof(Pair, first); static constexpr size_t kSecond = offsetof(Pair, second); }; @@ -4627,8 +4629,13 @@ class LockableBaseImpl template explicit DoNothing(T&&) {} DoNothing& operator=(const DoNothing&) { return *this; } DoNothing& operator=(DoNothing&&) noexcept { return *this; } - void swap(DoNothing &) {} + void swap(DoNothing &) noexcept {} bool owns_lock() const noexcept { return true; } + void lock() {} + void unlock() {} + void lock_shared() {} + void unlock_shared() {} + bool switch_to_unique() { return false; } }; // ---------------------------------------------------- @@ -4703,6 +4710,8 @@ class LockableBaseImpl } mutex_type *mutex() const noexcept { return m_; } + + bool switch_to_unique() { return false; } private: mutex_type *m_; @@ -4782,9 +4791,101 @@ class LockableBaseImpl mutex_type *mutex() const noexcept { return m_; } + bool switch_to_unique() { return false; } + + private: + mutex_type *m_; + bool locked_; + }; + + // ---------------------------------------------------- + class ReadWriteLock + { + public: + using mutex_type = MutexType; + + ReadWriteLock() : m_(nullptr), locked_(false), locked_shared_(false) {} + + explicit ReadWriteLock(mutex_type &m) : m_(&m), locked_(false), locked_shared_(true) { + m_->lock_shared(); + } + + ReadWriteLock(mutex_type& m, defer_lock_t) noexcept : + m_(&m), locked_(false), locked_shared_(false) + {} + + ReadWriteLock(ReadWriteLock &&o) noexcept : + m_(std::move(o.m_)), locked_(o.locked_), locked_shared_(o.locked_shared_) { + o.locked_ = false; + o.locked_shared_ = false; + o.m_ = nullptr; + } + + ReadWriteLock& operator=(ReadWriteLock&& other) noexcept { + ReadWriteLock temp(std::move(other)); + swap(temp); + return *this; + } + + ~ReadWriteLock() { + if (locked_shared_) + m_->unlock_shared(); + else if (locked_) + m_->unlock(); + } + + void lock_shared() { + assert(!locked_); + if (!locked_shared_) { + m_->lock_shared(); + locked_shared_ = true; + } + } + + void unlock_shared() { + if (locked_shared_) { + m_->unlock_shared(); + locked_shared_ = false; + } + } + + void lock() { + assert(!locked_shared_); + if (!locked_) { + m_->lock(); + locked_ = true; + } + } + + void unlock() { + if (locked_) { + m_->unlock(); + locked_ = false; + } + } + + bool owns_lock() const noexcept { return locked_; } + bool owns_shared_lock() const noexcept { return locked_shared_; } + + void swap(ReadWriteLock &o) noexcept { + std::swap(m_, o.m_); + std::swap(locked_, o.locked_); + std::swap(locked_shared_, o.locked_shared_); + } + + mutex_type *mutex() const noexcept { return m_; } + + bool switch_to_unique() { + assert(locked_shared_); + unlock_shared(); + lock(); + return true; + } + private: mutex_type *m_; bool locked_; + bool locked_shared_; }; // ---------------------------------------------------- @@ -4856,12 +4957,11 @@ class LockableBaseImpl // using Lockable = phmap::LockableImpl; // Lockable m; // -// Lockable::UpgradeLock read_lock(m); // take a upgradable lock -// -// { -// Lockable::UpgradeToUnique unique_lock(read_lock); -// // now locked for write -// } +// Lockable::ReadWriteLock read_lock(m); // take a lock (read if supported, otherwise write) +// ... do something +// +// m.switch_to_unique(); // returns true if we had a read lock and switched to write +// // now locked for write // // --------------------------------------------------------------------------- // Generic mutex support (always write locks) @@ -4873,11 +4973,10 @@ class LockableImpl : public Mtx_ using mutex_type = Mtx_; using Base = LockableBaseImpl; using SharedLock = typename Base::WriteLock; - using UpgradeLock = typename Base::WriteLock; using UniqueLock = typename Base::WriteLock; + using ReadWriteLock = typename Base::WriteLock; using SharedLocks = typename Base::WriteLocks; using UniqueLocks = typename Base::WriteLocks; - using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership }; // --------------------------------------------------------------------------- @@ -4890,15 +4989,15 @@ class LockableImpl: public phmap::NullMutex using mutex_type = phmap::NullMutex; using Base = LockableBaseImpl; using SharedLock = typename Base::DoNothing; - using UpgradeLock = typename Base::DoNothing; + using ReadWriteLock = typename Base::DoNothing; using UniqueLock = typename Base::DoNothing; - using UpgradeToUnique = typename Base::DoNothing; using SharedLocks = typename Base::DoNothing; using UniqueLocks = typename Base::DoNothing; }; // -------------------------------------------------------------------------- // Abseil Mutex support (read and write lock support) +// use: `phmap::AbslMutex` instead of `std::mutex` // -------------------------------------------------------------------------- #ifdef ABSL_SYNCHRONIZATION_MUTEX_H_ @@ -4919,11 +5018,44 @@ class LockableImpl: public phmap::NullMutex using mutex_type = phmap::AbslMutex; using Base = LockableBaseImpl; using SharedLock = typename Base::ReadLock; - using UpgradeLock = typename Base::WriteLock; + using ReadWriteLock = typename Base::ReadWriteLock; using UniqueLock = typename Base::WriteLock; using SharedLocks = typename Base::ReadLocks; using UniqueLocks = typename Base::WriteLocks; - using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership + }; + +#endif + +// -------------------------------------------------------------------------- +// Microsoft SRWLOCK support (read and write lock support) +// use: `phmap::srwlock` instead of `std::mutex` +// -------------------------------------------------------------------------- +#if defined(_MSC_VER) && defined(SRWLOCK_INIT) + + class srwlock { + SRWLOCK _lock; + public: + srwlock() { InitializeSRWLock(&_lock); } + void lock() { AcquireSRWLockExclusive(&_lock); } + void unlock() { ReleaseSRWLockExclusive(&_lock); } + bool try_lock() { return !!TryAcquireSRWLockExclusive(&_lock); } + void lock_shared() { AcquireSRWLockShared(&_lock); } + void unlock_shared() { ReleaseSRWLockShared(&_lock); } + bool try_lock_shared() { return !!TryAcquireSRWLockShared(&_lock); } + }; + + + template<> + class LockableImpl : public srwlock + { + public: + using mutex_type = srwlock; + using Base = LockableBaseImpl; + using SharedLock = typename Base::ReadLock; + using ReadWriteLock = typename Base::ReadWriteLock; + using UniqueLock = typename Base::WriteLock; + using SharedLocks = typename Base::ReadLocks; + using UniqueLocks = typename Base::WriteLocks; }; #endif @@ -4941,11 +5073,10 @@ class LockableImpl: public phmap::NullMutex using mutex_type = boost::shared_mutex; using Base = LockableBaseImpl; using SharedLock = boost::shared_lock; - using UpgradeLock = boost::unique_lock; // assume can't upgrade + using ReadWriteLock = typename Base::ReadWriteLock; using UniqueLock = boost::unique_lock; using SharedLocks = typename Base::ReadLocks; using UniqueLocks = typename Base::WriteLocks; - using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership }; #endif // BOOST_THREAD_SHARED_MUTEX_HPP @@ -4963,11 +5094,10 @@ class LockableImpl: public phmap::NullMutex using mutex_type = std::shared_mutex; using Base = LockableBaseImpl; using SharedLock = std::shared_lock; - using UpgradeLock = std::unique_lock; // assume can't upgrade + using ReadWriteLock = typename Base::ReadWriteLock; using UniqueLock = std::unique_lock; using SharedLocks = typename Base::ReadLocks; using UniqueLocks = typename Base::WriteLocks; - using UpgradeToUnique = typename Base::DoNothing; // we already have unique ownership }; #endif // PHMAP_HAVE_SHARED_MUTEX diff --git a/vendor/bela/include/bela/__phmap/phmap_bits.h b/vendor/bela/include/bela/__phmap/phmap_bits.h index 314e91d5..5db8ab9b 100644 --- a/vendor/bela/include/bela/__phmap/phmap_bits.h +++ b/vendor/bela/include/bela/__phmap/phmap_bits.h @@ -276,7 +276,7 @@ PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountLeadingZeros64Slow(uint64_t n) { if (n >> 16) zeroes -= 16, n >>= 16; if (n >> 8) zeroes -= 8, n >>= 8; if (n >> 4) zeroes -= 4, n >>= 4; - return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; + return (uint32_t)("\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes); } PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountLeadingZeros64(uint64_t n) { @@ -284,17 +284,17 @@ PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountLeadingZeros64(uint64_t n) { // MSVC does not have __buitin_clzll. Use _BitScanReverse64. unsigned long result = 0; // NOLINT(runtime/int) if (_BitScanReverse64(&result, n)) { - return (int)(63 - result); + return (uint32_t)(63 - result); } return 64; #elif defined(_MSC_VER) && !defined(__clang__) // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse unsigned long result = 0; // NOLINT(runtime/int) if ((n >> 32) && _BitScanReverse(&result, (unsigned long)(n >> 32))) { - return 31 - result; + return (uint32_t)(31 - result); } if (_BitScanReverse(&result, (unsigned long)n)) { - return 63 - result; + return (uint32_t)(63 - result); } return 64; #elif defined(__GNUC__) || defined(__clang__) @@ -309,7 +309,7 @@ PHMAP_BASE_INTERNAL_FORCEINLINE uint32_t CountLeadingZeros64(uint64_t n) { if (n == 0) { return 64; } - return __builtin_clzll(n); + return (uint32_t)__builtin_clzll(n); #else return CountLeadingZeros64Slow(n); #endif diff --git a/vendor/bela/include/bela/__phmap/phmap_dump.h b/vendor/bela/include/bela/__phmap/phmap_dump.h index 87393892..4dac1764 100644 --- a/vendor/bela/include/bela/__phmap/phmap_dump.h +++ b/vendor/bela/include/bela/__phmap/phmap_dump.h @@ -169,8 +169,12 @@ class BinaryOutputArchive { ofs_.open(file_path, std::ofstream::out | std::ofstream::trunc | std::ofstream::binary); } + ~BinaryOutputArchive() = default; + BinaryOutputArchive(const BinaryOutputArchive&) = delete; + BinaryOutputArchive& operator=(const BinaryOutputArchive&) = delete; + bool saveBinary(const void *p, size_t sz) { - ofs_.write(reinterpret_cast(p), sz); + ofs_.write(reinterpret_cast(p), (std::streamsize)sz); return true; } @@ -197,9 +201,13 @@ class BinaryInputArchive { BinaryInputArchive(const char * file_path) { ifs_.open(file_path, std::ofstream::in | std::ofstream::binary); } + + ~BinaryInputArchive() = default; + BinaryInputArchive(const BinaryInputArchive&) = delete; + BinaryInputArchive& operator=(const BinaryInputArchive&) = delete; bool loadBinary(void* p, size_t sz) { - ifs_.read(reinterpret_cast(p), sz); + ifs_.read(reinterpret_cast(p), (std::streamsize)sz); return true; } diff --git a/vendor/bela/include/bela/__strings/str_join_internal.hpp b/vendor/bela/include/bela/__strings/str_join_internal.hpp index 9a4a2d51..099c5597 100644 --- a/vendor/bela/include/bela/__strings/str_join_internal.hpp +++ b/vendor/bela/include/bela/__strings/str_join_internal.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/__strings/str_join_narrow_internal.hpp b/vendor/bela/include/bela/__strings/str_join_narrow_internal.hpp index 9a918c0f..f5c7e0b8 100644 --- a/vendor/bela/include/bela/__strings/str_join_narrow_internal.hpp +++ b/vendor/bela/include/bela/__strings/str_join_narrow_internal.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/__strings/str_split_internal.hpp b/vendor/bela/include/bela/__strings/str_split_internal.hpp index 0c0471fe..ddf67b8d 100644 --- a/vendor/bela/include/bela/__strings/str_split_internal.hpp +++ b/vendor/bela/include/bela/__strings/str_split_internal.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/__strings/str_split_narrow_internal.hpp b/vendor/bela/include/bela/__strings/str_split_narrow_internal.hpp index d6a7e349..54bd4860 100644 --- a/vendor/bela/include/bela/__strings/str_split_narrow_internal.hpp +++ b/vendor/bela/include/bela/__strings/str_split_narrow_internal.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/ascii.hpp b/vendor/bela/include/bela/ascii.hpp index cd0cd882..f6003c72 100644 --- a/vendor/bela/include/bela/ascii.hpp +++ b/vendor/bela/include/bela/ascii.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/escaping.hpp b/vendor/bela/include/bela/escaping.hpp index 509150e2..4ad485fd 100644 --- a/vendor/bela/include/bela/escaping.hpp +++ b/vendor/bela/include/bela/escaping.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/macros.hpp b/vendor/bela/include/bela/macros.hpp index 877574b6..96f9bcf9 100644 --- a/vendor/bela/include/bela/macros.hpp +++ b/vendor/bela/include/bela/macros.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/match.hpp b/vendor/bela/include/bela/match.hpp index 2d91c286..58ed34f8 100644 --- a/vendor/bela/include/bela/match.hpp +++ b/vendor/bela/include/bela/match.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/numbers.hpp b/vendor/bela/include/bela/numbers.hpp index 0068b30d..dead9d4c 100644 --- a/vendor/bela/include/bela/numbers.hpp +++ b/vendor/bela/include/bela/numbers.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/str_cat.hpp b/vendor/bela/include/bela/str_cat.hpp index 3c3735b4..c680433a 100644 --- a/vendor/bela/include/bela/str_cat.hpp +++ b/vendor/bela/include/bela/str_cat.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/str_join.hpp b/vendor/bela/include/bela/str_join.hpp index f7374693..100fed2a 100644 --- a/vendor/bela/include/bela/str_join.hpp +++ b/vendor/bela/include/bela/str_join.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/str_join_narrow.hpp b/vendor/bela/include/bela/str_join_narrow.hpp index 958e9694..55617643 100644 --- a/vendor/bela/include/bela/str_join_narrow.hpp +++ b/vendor/bela/include/bela/str_join_narrow.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/str_replace.hpp b/vendor/bela/include/bela/str_replace.hpp index 7134f035..fcd8fcf8 100644 --- a/vendor/bela/include/bela/str_replace.hpp +++ b/vendor/bela/include/bela/str_replace.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/str_split.hpp b/vendor/bela/include/bela/str_split.hpp index 8867b99f..1122a965 100644 --- a/vendor/bela/include/bela/str_split.hpp +++ b/vendor/bela/include/bela/str_split.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/str_split_narrow.hpp b/vendor/bela/include/bela/str_split_narrow.hpp index c76dfbfa..85cfd7af 100644 --- a/vendor/bela/include/bela/str_split_narrow.hpp +++ b/vendor/bela/include/bela/str_split_narrow.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/strings.hpp b/vendor/bela/include/bela/strings.hpp index e99260a2..c4840725 100644 --- a/vendor/bela/include/bela/strings.hpp +++ b/vendor/bela/include/bela/strings.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/strip.hpp b/vendor/bela/include/bela/strip.hpp index 8be2084f..e5162a2b 100644 --- a/vendor/bela/include/bela/strip.hpp +++ b/vendor/bela/include/bela/strip.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/subsitute.hpp b/vendor/bela/include/bela/subsitute.hpp index 6a635c1b..73647371 100644 --- a/vendor/bela/include/bela/subsitute.hpp +++ b/vendor/bela/include/bela/subsitute.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/include/bela/time.hpp b/vendor/bela/include/bela/time.hpp index 35f047d7..36d85e6d 100644 --- a/vendor/bela/include/bela/time.hpp +++ b/vendor/bela/include/bela/time.hpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/ascii.cc b/vendor/bela/src/bela/ascii.cc index 29a282a9..102b4589 100644 --- a/vendor/bela/src/bela/ascii.cc +++ b/vendor/bela/src/bela/ascii.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/escaping.cc b/vendor/bela/src/bela/escaping.cc index 8b44835b..a0ce8f96 100644 --- a/vendor/bela/src/bela/escaping.cc +++ b/vendor/bela/src/bela/escaping.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/match.cc b/vendor/bela/src/bela/match.cc index 66ef2efe..5b0eb34a 100644 --- a/vendor/bela/src/bela/match.cc +++ b/vendor/bela/src/bela/match.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/numbers.cc b/vendor/bela/src/bela/numbers.cc index 19c6ae68..cd709a63 100644 --- a/vendor/bela/src/bela/numbers.cc +++ b/vendor/bela/src/bela/numbers.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/str_cat.cc b/vendor/bela/src/bela/str_cat.cc index ff27d703..42900839 100644 --- a/vendor/bela/src/bela/str_cat.cc +++ b/vendor/bela/src/bela/str_cat.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/str_replace.cc b/vendor/bela/src/bela/str_replace.cc index d64d955e..b2517361 100644 --- a/vendor/bela/src/bela/str_replace.cc +++ b/vendor/bela/src/bela/str_replace.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/str_split.cc b/vendor/bela/src/bela/str_split.cc index e01491b5..520649e4 100644 --- a/vendor/bela/src/bela/str_split.cc +++ b/vendor/bela/src/bela/str_split.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/str_split_narrow.cc b/vendor/bela/src/bela/str_split_narrow.cc index 3accc9b7..5c426ef9 100644 --- a/vendor/bela/src/bela/str_split_narrow.cc +++ b/vendor/bela/src/bela/str_split_narrow.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/bela/subsitute.cc b/vendor/bela/src/bela/subsitute.cc index b471f601..b27bec11 100644 --- a/vendor/bela/src/bela/subsitute.cc +++ b/vendor/bela/src/bela/subsitute.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/belahash/blake3.lock b/vendor/bela/src/belahash/blake3.lock index 8fd0179f..74922d5f 100644 --- a/vendor/bela/src/belahash/blake3.lock +++ b/vendor/bela/src/belahash/blake3.lock @@ -1,2 +1,2 @@ https://github.com/BLAKE3-team/BLAKE3 -12823b87604cbb7bcd0e5cdc347a53f80b2a617c +4d32708f511fd85c6b0fb131295cc73224246738 diff --git a/vendor/bela/src/belahash/blake3/blake3.h b/vendor/bela/src/belahash/blake3/blake3.h index 21e0d7b9..f694dcf2 100644 --- a/vendor/bela/src/belahash/blake3/blake3.h +++ b/vendor/bela/src/belahash/blake3/blake3.h @@ -30,7 +30,7 @@ extern "C" { #endif -#define BLAKE3_VERSION_STRING "1.4.1" +#define BLAKE3_VERSION_STRING "1.5.0" #define BLAKE3_KEY_LEN 32 #define BLAKE3_OUT_LEN 32 #define BLAKE3_BLOCK_LEN 64 diff --git a/vendor/bela/src/belahash/blake3/blake3_dispatch.c b/vendor/bela/src/belahash/blake3/blake3_dispatch.c index e681e871..af6c3dad 100644 --- a/vendor/bela/src/belahash/blake3/blake3_dispatch.c +++ b/vendor/bela/src/belahash/blake3/blake3_dispatch.c @@ -32,9 +32,9 @@ #define ATOMIC_LOAD(x) x #define ATOMIC_STORE(x, y) x = y #elif defined(_MSC_VER) -#define ATOMIC_INT long -#define ATOMIC_LOAD(x) _InterlockedOr(&x, 0) -#define ATOMIC_STORE(x, y) _InterlockedExchange(&x, y) +#define ATOMIC_INT LONG +#define ATOMIC_LOAD(x) InterlockedOr(&x, 0) +#define ATOMIC_STORE(x, y) InterlockedExchange(&x, y) #else #define ATOMIC_INT int #define ATOMIC_LOAD(x) x diff --git a/vendor/bela/src/belahash/blake3/blake3_impl.h b/vendor/bela/src/belahash/blake3/blake3_impl.h index 3ba9ceb0..beab5cf5 100644 --- a/vendor/bela/src/belahash/blake3/blake3_impl.h +++ b/vendor/bela/src/belahash/blake3/blake3_impl.h @@ -51,7 +51,11 @@ enum blake3_flags { #if !defined(BLAKE3_USE_NEON) // If BLAKE3_USE_NEON not manually set, autodetect based on AArch64ness #if defined(IS_AARCH64) - #define BLAKE3_USE_NEON 1 + #if defined(__ARM_BIG_ENDIAN) + #define BLAKE3_USE_NEON 0 + #else + #define BLAKE3_USE_NEON 1 + #endif #else #define BLAKE3_USE_NEON 0 #endif diff --git a/vendor/bela/src/belatime/duration.cc b/vendor/bela/src/belatime/duration.cc index 810cea46..5a7f03e5 100644 --- a/vendor/bela/src/belatime/duration.cc +++ b/vendor/bela/src/belatime/duration.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/belatime/time.cc b/vendor/bela/src/belatime/time.cc index 8efbfb8d..c41c01cb 100644 --- a/vendor/bela/src/belatime/time.cc +++ b/vendor/bela/src/belatime/time.cc @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Copyright © 2023, Bela contributors +// Copyright © 2024, Bela contributors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/vendor/bela/src/belaund/llvm/VERSION b/vendor/bela/src/belaund/llvm/VERSION index 9264009d..5318fc03 100644 --- a/vendor/bela/src/belaund/llvm/VERSION +++ b/vendor/bela/src/belaund/llvm/VERSION @@ -1 +1 @@ -llvm-project:8be07adfb42d8d5d060b807d5445b6fefc949bee \ No newline at end of file +llvm-project:946ebad67a21212d11a0dd4deb7cdedc297d47bc \ No newline at end of file diff --git a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/Demangle.h b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/Demangle.h index e1f73c42..70cfc141 100644 --- a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/Demangle.h +++ b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/Demangle.h @@ -67,7 +67,8 @@ char *dlangDemangle(std::string_view MangledName); /// demangling occurred. std::string demangle(std::string_view MangledName); -bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result); +bool nonMicrosoftDemangle(std::string_view MangledName, std::string &Result, + bool CanHaveLeadingDot = true); /// "Partial" demangler. This supports demangling a string into an AST /// (typically an intermediate stage in itaniumDemangle) and querying certain @@ -102,7 +103,7 @@ struct ItaniumPartialDemangler { char *getFunctionParameters(char *Buf, size_t *N) const; char *getFunctionReturnType(char *Buf, size_t *N) const; - /// If this function has any any cv or reference qualifiers. These imply that + /// If this function has any cv or reference qualifiers. These imply that /// the function is a non-static member function. bool hasFunctionQualifiers() const; diff --git a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/DemangleConfig.h b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/DemangleConfig.h index 2ff95dd8..30f72ffe 100644 --- a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/DemangleConfig.h +++ b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/DemangleConfig.h @@ -86,6 +86,11 @@ #define DEMANGLE_FALLTHROUGH #endif +#ifndef DEMANGLE_ASSERT +#include +#define DEMANGLE_ASSERT(__expr, __msg) assert((__expr) && (__msg)) +#endif + #define DEMANGLE_NAMESPACE_BEGIN namespace llvm { namespace itanium_demangle { #define DEMANGLE_NAMESPACE_END } } diff --git a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/ItaniumDemangle.h b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/ItaniumDemangle.h index 550e1699..e0ff035d 100644 --- a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -20,7 +20,6 @@ #include "StringViewExtras.h" #include "Utility.h" #include -#include #include #include #include @@ -31,6 +30,11 @@ #include #include +#ifdef _LIBCXXABI_COMPILER_CLANG +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-template" +#endif + DEMANGLE_NAMESPACE_BEGIN template class PODSmallVector { @@ -55,13 +59,13 @@ template class PODSmallVector { if (isInline()) { auto *Tmp = static_cast(std::malloc(NewCap * sizeof(T))); if (Tmp == nullptr) - std::terminate(); + std::abort(); std::copy(First, Last, Tmp); First = Tmp; } else { First = static_cast(std::realloc(First, NewCap * sizeof(T))); if (First == nullptr) - std::terminate(); + std::abort(); } Last = First + S; Cap = First + NewCap; @@ -123,12 +127,12 @@ template class PODSmallVector { // NOLINTNEXTLINE(readability-identifier-naming) void pop_back() { - assert(Last != First && "Popping empty vector!"); + DEMANGLE_ASSERT(Last != First, "Popping empty vector!"); --Last; } - void dropBack(size_t Index) { - assert(Index <= size() && "dropBack() can't expand!"); + void shrinkToSize(size_t Index) { + DEMANGLE_ASSERT(Index <= size(), "shrinkToSize() can't expand!"); Last = First + Index; } @@ -138,11 +142,11 @@ template class PODSmallVector { bool empty() const { return First == Last; } size_t size() const { return static_cast(Last - First); } T &back() { - assert(Last != First && "Calling back() on empty vector!"); + DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!"); return *(Last - 1); } T &operator[](size_t Index) { - assert(Index < size() && "Invalid access!"); + DEMANGLE_ASSERT(Index < size(), "Invalid access!"); return *(begin() + Index); } void clear() { Last = First; } @@ -528,6 +532,23 @@ class ElaboratedTypeSpefType : public Node { } }; +class TransformedType : public Node { + std::string_view Transform; + Node *BaseType; +public: + TransformedType(std::string_view Transform_, Node *BaseType_) + : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {} + + template void match(Fn F) const { F(Transform, BaseType); } + + void printLeft(OutputBuffer &OB) const override { + OB += Transform; + OB += '('; + BaseType->print(OB); + OB += ')'; + } +}; + struct AbiTagAttr : Node { Node *Base; std::string_view Tag; @@ -867,26 +888,53 @@ class DynamicExceptionSpec : public Node { } }; +/// Represents the explicitly named object parameter. +/// E.g., +/// \code{.cpp} +/// struct Foo { +/// void bar(this Foo && self); +/// }; +/// \endcode +class ExplicitObjectParameter final : public Node { + Node *Base; + +public: + ExplicitObjectParameter(Node *Base_) + : Node(KExplicitObjectParameter), Base(Base_) { + DEMANGLE_ASSERT( + Base != nullptr, + "Creating an ExplicitObjectParameter without a valid Base Node."); + } + + template void match(Fn F) const { F(Base); } + + void printLeft(OutputBuffer &OB) const override { + OB += "this "; + Base->print(OB); + } +}; + class FunctionEncoding final : public Node { const Node *Ret; const Node *Name; NodeArray Params; const Node *Attrs; + const Node *Requires; Qualifiers CVQuals; FunctionRefQual RefQual; public: FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_, - const Node *Attrs_, Qualifiers CVQuals_, - FunctionRefQual RefQual_) + const Node *Attrs_, const Node *Requires_, + Qualifiers CVQuals_, FunctionRefQual RefQual_) : Node(KFunctionEncoding, /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, /*FunctionCache=*/Cache::Yes), Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_), - CVQuals(CVQuals_), RefQual(RefQual_) {} + Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {} template void match(Fn F) const { - F(Ret, Name, Params, Attrs, CVQuals, RefQual); + F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual); } Qualifiers getCVQuals() const { return CVQuals; } @@ -929,6 +977,11 @@ class FunctionEncoding final : public Node { if (Attrs != nullptr) Attrs->print(OB); + + if (Requires != nullptr) { + OB += " requires "; + Requires->print(OB); + } } }; @@ -1000,6 +1053,24 @@ struct NestedName : Node { } }; +struct MemberLikeFriendName : Node { + Node *Qual; + Node *Name; + + MemberLikeFriendName(Node *Qual_, Node *Name_) + : Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {} + + template void match(Fn F) const { F(Qual, Name); } + + std::string_view getBaseName() const override { return Name->getBaseName(); } + + void printLeft(OutputBuffer &OB) const override { + Qual->print(OB); + OB += "::friend "; + Name->print(OB); + } +}; + struct ModuleName : Node { ModuleName *Parent; Node *Name; @@ -1165,6 +1236,24 @@ class SyntheticTemplateParamName final : public Node { } }; +class TemplateParamQualifiedArg final : public Node { + Node *Param; + Node *Arg; + +public: + TemplateParamQualifiedArg(Node *Param_, Node *Arg_) + : Node(KTemplateParamQualifiedArg), Param(Param_), Arg(Arg_) {} + + template void match(Fn F) const { F(Param, Arg); } + + Node *getArg() { return Arg; } + + void printLeft(OutputBuffer &OB) const override { + // Don't print Param to keep the output consistent. + Arg->print(OB); + } +}; + /// A template type parameter declaration, 'typename T'. class TypeTemplateParamDecl final : public Node { Node *Name; @@ -1180,6 +1269,26 @@ class TypeTemplateParamDecl final : public Node { void printRight(OutputBuffer &OB) const override { Name->print(OB); } }; +/// A constrained template type parameter declaration, 'C T'. +class ConstrainedTypeTemplateParamDecl final : public Node { + Node *Constraint; + Node *Name; + +public: + ConstrainedTypeTemplateParamDecl(Node *Constraint_, Node *Name_) + : Node(KConstrainedTypeTemplateParamDecl, Cache::Yes), + Constraint(Constraint_), Name(Name_) {} + + template void match(Fn F) const { F(Constraint, Name); } + + void printLeft(OutputBuffer &OB) const override { + Constraint->print(OB); + OB += " "; + } + + void printRight(OutputBuffer &OB) const override { Name->print(OB); } +}; + /// A non-type template parameter declaration, 'int N'. class NonTypeTemplateParamDecl final : public Node { Node *Name; @@ -1208,13 +1317,14 @@ class NonTypeTemplateParamDecl final : public Node { class TemplateTemplateParamDecl final : public Node { Node *Name; NodeArray Params; + Node *Requires; public: - TemplateTemplateParamDecl(Node *Name_, NodeArray Params_) + TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_) : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_), - Params(Params_) {} + Params(Params_), Requires(Requires_) {} - template void match(Fn F) const { F(Name, Params); } + template void match(Fn F) const { F(Name, Params, Requires); } void printLeft(OutputBuffer &OB) const override { ScopedOverride LT(OB.GtIsGt, 0); @@ -1223,7 +1333,13 @@ class TemplateTemplateParamDecl final : public Node { OB += "> typename "; } - void printRight(OutputBuffer &OB) const override { Name->print(OB); } + void printRight(OutputBuffer &OB) const override { + Name->print(OB); + if (Requires != nullptr) { + OB += " requires "; + Requires->print(OB); + } + } }; /// A template parameter pack declaration, 'typename ...T'. @@ -1320,7 +1436,7 @@ class ParameterPack final : public Node { /// A variadic template argument. This node represents an occurrence of /// JE in some . It isn't itself unexpanded, unless -/// one of it's Elements is. The parser inserts a ParameterPack into the +/// one of its Elements is. The parser inserts a ParameterPack into the /// TemplateParams table if the this pack belongs to apply to an /// . class TemplateArgumentPack final : public Node { @@ -1386,11 +1502,13 @@ class ParameterPackExpansion final : public Node { class TemplateArgs final : public Node { NodeArray Params; + Node *Requires; public: - TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {} + TemplateArgs(NodeArray Params_, Node *Requires_) + : Node(KTemplateArgs), Params(Params_), Requires(Requires_) {} - template void match(Fn F) const { F(Params); } + template void match(Fn F) const { F(Params, Requires); } NodeArray getParams() { return Params; } @@ -1399,6 +1517,7 @@ class TemplateArgs final : public Node { OB += "<"; Params.printWithComma(OB); OB += ">"; + // Don't print the requires clause to keep the output simple. } }; @@ -1583,7 +1702,7 @@ class SpecialSubstitution final : public ExpandedSpecialSubstitution { std::string_view SV = ExpandedSpecialSubstitution::getBaseName(); if (isInstantiation()) { // The instantiations are typedefs that drop the "basic_" prefix. - assert(llvm::itanium_demangle::starts_with(SV, "basic_")); + DEMANGLE_ASSERT(starts_with(SV, "basic_"), ""); SV.remove_prefix(sizeof("basic_") - 1); } return SV; @@ -1649,17 +1768,21 @@ class UnnamedTypeName : public Node { class ClosureTypeName : public Node { NodeArray TemplateParams; + const Node *Requires1; NodeArray Params; + const Node *Requires2; std::string_view Count; public: - ClosureTypeName(NodeArray TemplateParams_, NodeArray Params_, + ClosureTypeName(NodeArray TemplateParams_, const Node *Requires1_, + NodeArray Params_, const Node *Requires2_, std::string_view Count_) : Node(KClosureTypeName), TemplateParams(TemplateParams_), - Params(Params_), Count(Count_) {} + Requires1(Requires1_), Params(Params_), Requires2(Requires2_), + Count(Count_) {} template void match(Fn F) const { - F(TemplateParams, Params, Count); + F(TemplateParams, Requires1, Params, Requires2, Count); } void printDeclarator(OutputBuffer &OB) const { @@ -1669,12 +1792,22 @@ class ClosureTypeName : public Node { TemplateParams.printWithComma(OB); OB += ">"; } + if (Requires1 != nullptr) { + OB += " requires "; + Requires1->print(OB); + OB += " "; + } OB.printOpen(); Params.printWithComma(OB); OB.printClose(); + if (Requires2 != nullptr) { + OB += " requires "; + Requires2->print(OB); + } } void printLeft(OutputBuffer &OB) const override { + // FIXME: This demangling is not particularly readable. OB += "\'lambda"; OB += Count; OB += "\'"; @@ -2303,6 +2436,95 @@ class IntegerLiteral : public Node { } }; +class RequiresExpr : public Node { + NodeArray Parameters; + NodeArray Requirements; +public: + RequiresExpr(NodeArray Parameters_, NodeArray Requirements_) + : Node(KRequiresExpr), Parameters(Parameters_), + Requirements(Requirements_) {} + + template void match(Fn F) const { F(Parameters, Requirements); } + + void printLeft(OutputBuffer &OB) const override { + OB += "requires"; + if (!Parameters.empty()) { + OB += ' '; + OB.printOpen(); + Parameters.printWithComma(OB); + OB.printClose(); + } + OB += ' '; + OB.printOpen('{'); + for (const Node *Req : Requirements) { + Req->print(OB); + } + OB += ' '; + OB.printClose('}'); + } +}; + +class ExprRequirement : public Node { + const Node *Expr; + bool IsNoexcept; + const Node *TypeConstraint; +public: + ExprRequirement(const Node *Expr_, bool IsNoexcept_, + const Node *TypeConstraint_) + : Node(KExprRequirement), Expr(Expr_), IsNoexcept(IsNoexcept_), + TypeConstraint(TypeConstraint_) {} + + template void match(Fn F) const { + F(Expr, IsNoexcept, TypeConstraint); + } + + void printLeft(OutputBuffer &OB) const override { + OB += " "; + if (IsNoexcept || TypeConstraint) + OB.printOpen('{'); + Expr->print(OB); + if (IsNoexcept || TypeConstraint) + OB.printClose('}'); + if (IsNoexcept) + OB += " noexcept"; + if (TypeConstraint) { + OB += " -> "; + TypeConstraint->print(OB); + } + OB += ';'; + } +}; + +class TypeRequirement : public Node { + const Node *Type; +public: + TypeRequirement(const Node *Type_) + : Node(KTypeRequirement), Type(Type_) {} + + template void match(Fn F) const { F(Type); } + + void printLeft(OutputBuffer &OB) const override { + OB += " typename "; + Type->print(OB); + OB += ';'; + } +}; + +class NestedRequirement : public Node { + const Node *Constraint; +public: + NestedRequirement(const Node *Constraint_) + : Node(KNestedRequirement), Constraint(Constraint_) {} + + template void match(Fn F) const { F(Constraint); } + + void printLeft(OutputBuffer &OB) const override { + OB += " requires "; + Constraint->print(OB); + OB += ';'; + } +}; + template struct FloatData; namespace float_literal_impl { @@ -2371,7 +2593,7 @@ void Node::visit(Fn F) const { return F(static_cast(this)); #include "ItaniumNodes.def" } - assert(0 && "unknown mangling node kind"); + DEMANGLE_ASSERT(0, "unknown mangling node kind"); } /// Determine the kind of a node from its type. @@ -2397,6 +2619,8 @@ template struct AbstractManglingParser { // table. PODSmallVector Subs; + // A list of template argument values corresponding to a template parameter + // list. using TemplateParamList = PODSmallVector; class ScopedTemplateParamList { @@ -2411,9 +2635,11 @@ template struct AbstractManglingParser { Parser->TemplateParams.push_back(&Params); } ~ScopedTemplateParamList() { - assert(Parser->TemplateParams.size() >= OldNumTemplateParamLists); - Parser->TemplateParams.dropBack(OldNumTemplateParamLists); + DEMANGLE_ASSERT(Parser->TemplateParams.size() >= OldNumTemplateParamLists, + ""); + Parser->TemplateParams.shrinkToSize(OldNumTemplateParamLists); } + TemplateParamList *params() { return &Params; } }; // Template parameter table. Like the above, but referenced like "T42_". @@ -2428,12 +2654,31 @@ template struct AbstractManglingParser { // parameter list, the corresponding parameter list pointer will be null. PODSmallVector TemplateParams; + class SaveTemplateParams { + AbstractManglingParser *Parser; + decltype(TemplateParams) OldParams; + decltype(OuterTemplateParams) OldOuterParams; + + public: + SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) { + OldParams = std::move(Parser->TemplateParams); + OldOuterParams = std::move(Parser->OuterTemplateParams); + Parser->TemplateParams.clear(); + Parser->OuterTemplateParams.clear(); + } + ~SaveTemplateParams() { + Parser->TemplateParams = std::move(OldParams); + Parser->OuterTemplateParams = std::move(OldOuterParams); + } + }; + // Set of unresolved forward references. These can occur in a // conversion operator's type, and are resolved in the enclosing . PODSmallVector ForwardTemplateRefs; bool TryToParseTemplateArgs = true; bool PermitForwardTemplateReferences = false; + bool InConstraintExpr = false; size_t ParsingLambdaParamsAtLevel = (size_t)-1; unsigned NumSyntheticTemplateParameters[3] = {}; @@ -2472,16 +2717,15 @@ template struct AbstractManglingParser { } NodeArray popTrailingNodeArray(size_t FromPosition) { - assert(FromPosition <= Names.size()); + DEMANGLE_ASSERT(FromPosition <= Names.size(), ""); NodeArray res = makeNodeArray(Names.begin() + (long)FromPosition, Names.end()); - Names.dropBack(FromPosition); + Names.shrinkToSize(FromPosition); return res; } bool consumeIf(std::string_view S) { - if (llvm::itanium_demangle::starts_with( - std::string_view(First, Last - First), S)) { + if (starts_with(std::string_view(First, Last - First), S)) { First += S.size(); return true; } @@ -2514,11 +2758,16 @@ template struct AbstractManglingParser { bool parseSeqId(size_t *Out); Node *parseSubstitution(); Node *parseTemplateParam(); - Node *parseTemplateParamDecl(); + Node *parseTemplateParamDecl(TemplateParamList *Params); Node *parseTemplateArgs(bool TagTemplates = false); Node *parseTemplateArg(); - /// Parse the production. + bool isTemplateParamDecl() { + return look() == 'T' && + std::string_view("yptnk").find(look(1)) != std::string_view::npos; + } + + /// Parse the production. Node *parseExpr(); Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec); Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec); @@ -2531,6 +2780,8 @@ template struct AbstractManglingParser { Node *parseFoldExpr(); Node *parsePointerToMemberConversionExpr(Node::Prec Prec); Node *parseSubobjectExpr(); + Node *parseConstraintExpr(); + Node *parseRequiresExpr(); /// Parse the production. Node *parseType(); @@ -2554,6 +2805,7 @@ template struct AbstractManglingParser { Qualifiers CVQualifiers = QualNone; FunctionRefQual ReferenceQualifier = FrefQualNone; size_t ForwardTemplateRefsBegin; + bool HasExplicitObjectParameter = false; NameState(AbstractManglingParser *Enclosing) : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {} @@ -2569,7 +2821,7 @@ template struct AbstractManglingParser { return true; ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx]; } - ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin); + ForwardTemplateRefs.shrinkToSize(State.ForwardTemplateRefsBegin); return false; } @@ -2633,10 +2885,10 @@ template struct AbstractManglingParser { std::string_view getSymbol() const { std::string_view Res = Name; if (Kind < Unnameable) { - assert(llvm::itanium_demangle::starts_with(Res, "operator") && - "operator name does not start with 'operator'"); + DEMANGLE_ASSERT(starts_with(Res, "operator"), + "operator name does not start with 'operator'"); Res.remove_prefix(sizeof("operator") - 1); - if (llvm::itanium_demangle::starts_with(Res, ' ')) + if (starts_with(Res, ' ')) Res.remove_prefix(1); } return Res; @@ -2722,6 +2974,10 @@ Node *AbstractManglingParser::parseLocalName(NameState *State) { return make(Encoding, StringLitName); } + // The template parameters of the inner name are unrelated to those of the + // enclosing context. + SaveTemplateParams SaveTemplateParamsScope(this); + if (consumeIf('d')) { parseNumber(true); if (!consumeIf('_')) @@ -2777,9 +3033,9 @@ AbstractManglingParser::parseUnscopedName(NameState *State, return Res; } -// ::= [] L? [] +// ::= [] F? L? [] // ::= [] [] -// ::= [] L? [] +// ::= [] F? L? [] // ::= [] L? [] // # structured binding declaration // ::= [] L? DC + E @@ -2789,6 +3045,8 @@ Node *AbstractManglingParser::parseUnqualifiedName( if (getDerived().parseModuleNameOpt(Module)) return nullptr; + bool IsMemberLikeFriend = Scope && consumeIf('F'); + consumeIf('L'); Node *Result; @@ -2819,7 +3077,9 @@ Node *AbstractManglingParser::parseUnqualifiedName( Result = make(Module, Result); if (Result != nullptr) Result = getDerived().parseAbiTags(Result); - if (Result != nullptr && Scope != nullptr) + if (Result != nullptr && IsMemberLikeFriend) + Result = make(Scope, Result); + else if (Result != nullptr && Scope != nullptr) Result = make(Scope, Result); return Result; @@ -2851,7 +3111,8 @@ bool AbstractManglingParser::parseModuleNameOpt( // // ::= Ul E [ ] _ // -// ::= + # Parameter types or "v" if the lambda has no parameters +// ::= * [Q ] +// + # or "v" if the lambda has no parameters template Node * AbstractManglingParser::parseUnnamedTypeName(NameState *State) { @@ -2872,10 +3133,10 @@ AbstractManglingParser::parseUnnamedTypeName(NameState *State) { ScopedTemplateParamList LambdaTemplateParams(this); size_t ParamsBegin = Names.size(); - while (look() == 'T' && - std::string_view("yptn").find(look(1)) != std::string_view::npos) { - Node *T = parseTemplateParamDecl(); - if (!T) + while (getDerived().isTemplateParamDecl()) { + Node *T = + getDerived().parseTemplateParamDecl(LambdaTemplateParams.params()); + if (T == nullptr) return nullptr; Names.push_back(T); } @@ -2906,20 +3167,38 @@ AbstractManglingParser::parseUnnamedTypeName(NameState *State) { if (TempParams.empty()) TemplateParams.pop_back(); - if (!consumeIf("vE")) { + Node *Requires1 = nullptr; + if (consumeIf('Q')) { + Requires1 = getDerived().parseConstraintExpr(); + if (Requires1 == nullptr) + return nullptr; + } + + if (!consumeIf("v")) { do { Node *P = getDerived().parseType(); if (P == nullptr) return nullptr; Names.push_back(P); - } while (!consumeIf('E')); + } while (look() != 'E' && look() != 'Q'); } NodeArray Params = popTrailingNodeArray(ParamsBegin); + Node *Requires2 = nullptr; + if (consumeIf('Q')) { + Requires2 = getDerived().parseConstraintExpr(); + if (Requires2 == nullptr) + return nullptr; + } + + if (!consumeIf('E')) + return nullptr; + std::string_view Count = parseNumber(); if (!consumeIf('_')) return nullptr; - return make(TempParams, Params, Count); + return make(TempParams, Requires1, Params, Requires2, + Count); } if (consumeIf("Ub")) { (void)parseNumber(); @@ -2940,7 +3219,7 @@ Node *AbstractManglingParser::parseSourceName(NameState *) { return nullptr; std::string_view Name(First, Length); First += Length; - if (llvm::itanium_demangle::starts_with(Name, "_GLOBAL__N")) + if (starts_with(Name, "_GLOBAL__N")) return make("(anonymous namespace)"); return make(Name); } @@ -3185,15 +3464,25 @@ AbstractManglingParser::parseNestedName(NameState *State) { if (!consumeIf('N')) return nullptr; - Qualifiers CVTmp = parseCVQualifiers(); - if (State) State->CVQualifiers = CVTmp; + // 'H' specifies that the encoding that follows + // has an explicit object parameter. + if (!consumeIf('H')) { + Qualifiers CVTmp = parseCVQualifiers(); + if (State) + State->CVQualifiers = CVTmp; - if (consumeIf('O')) { - if (State) State->ReferenceQualifier = FrefQualRValue; - } else if (consumeIf('R')) { - if (State) State->ReferenceQualifier = FrefQualLValue; - } else { - if (State) State->ReferenceQualifier = FrefQualNone; + if (consumeIf('O')) { + if (State) + State->ReferenceQualifier = FrefQualRValue; + } else if (consumeIf('R')) { + if (State) + State->ReferenceQualifier = FrefQualLValue; + } else { + if (State) + State->ReferenceQualifier = FrefQualNone; + } + } else if (State) { + State->HasExplicitObjectParameter = true; } Node *SoFar = nullptr; @@ -3441,7 +3730,7 @@ Node *AbstractManglingParser::parseUnresolvedName(bool Global) { } } - assert(SoFar != nullptr); + DEMANGLE_ASSERT(SoFar != nullptr, ""); Node *Base = getDerived().parseBaseUnresolvedName(); if (Base == nullptr) @@ -3709,7 +3998,7 @@ Node *AbstractManglingParser::parseQualifiedType() { return nullptr; // extension ::= U # objc-type - if (llvm::itanium_demangle::starts_with(Qual, "objcproto")) { + if (starts_with(Qual, "objcproto")) { constexpr size_t Len = sizeof("objcproto") - 1; std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len); std::string_view Proto; @@ -3889,7 +4178,15 @@ Node *AbstractManglingParser::parseType() { // Typically, s are not considered substitution candidates, // but the exception to that exception is vendor extended types (Itanium C++ // ABI 5.9.1). - Result = make(Res); + if (consumeIf('I')) { + Node *BaseType = parseType(); + if (BaseType == nullptr) + return nullptr; + if (!consumeIf('E')) + return nullptr; + Result = make(Res, BaseType); + } else + Result = make(Res); break; } case 'D': @@ -3956,6 +4253,17 @@ Node *AbstractManglingParser::parseType() { case 'c': First += 2; return make("decltype(auto)"); + // ::= Dk # constrained auto + // ::= DK # constrained decltype(auto) + case 'k': + case 'K': { + std::string_view Kind = look(1) == 'k' ? " auto" : " decltype(auto)"; + First += 2; + Node *Constraint = getDerived().parseName(); + if (!Constraint) + return nullptr; + return make(Constraint, Kind); + } // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) case 'n': First += 2; @@ -4507,6 +4815,75 @@ Node *AbstractManglingParser::parseSubobjectExpr() { Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd); } +template +Node *AbstractManglingParser::parseConstraintExpr() { + // Within this expression, all enclosing template parameter lists are in + // scope. + ScopedOverride SaveInConstraintExpr(InConstraintExpr, true); + return getDerived().parseExpr(); +} + +template +Node *AbstractManglingParser::parseRequiresExpr() { + NodeArray Params; + if (consumeIf("rQ")) { + // ::= rQ _ + E + size_t ParamsBegin = Names.size(); + while (!consumeIf('_')) { + Node *Type = getDerived().parseType(); + if (Type == nullptr) + return nullptr; + Names.push_back(Type); + } + Params = popTrailingNodeArray(ParamsBegin); + } else if (!consumeIf("rq")) { + // ::= rq + E + return nullptr; + } + + size_t ReqsBegin = Names.size(); + do { + Node *Constraint = nullptr; + if (consumeIf('X')) { + // ::= X [N] [R ] + Node *Expr = getDerived().parseExpr(); + if (Expr == nullptr) + return nullptr; + bool Noexcept = consumeIf('N'); + Node *TypeReq = nullptr; + if (consumeIf('R')) { + TypeReq = getDerived().parseName(); + if (TypeReq == nullptr) + return nullptr; + } + Constraint = make(Expr, Noexcept, TypeReq); + } else if (consumeIf('T')) { + // ::= T + Node *Type = getDerived().parseType(); + if (Type == nullptr) + return nullptr; + Constraint = make(Type); + } else if (consumeIf('Q')) { + // ::= Q + // + // FIXME: We use instead of . Either + // the requires expression is already inside a constraint expression, in + // which case it makes no difference, or we're in a requires-expression + // that might be partially-substituted, where the language behavior is + // not yet settled and clang mangles after substitution. + Node *NestedReq = getDerived().parseExpr(); + if (NestedReq == nullptr) + return nullptr; + Constraint = make(NestedReq); + } + if (Constraint == nullptr) + return nullptr; + Names.push_back(Constraint); + } while (!consumeIf('E')); + + return make(Params, popTrailingNodeArray(ReqsBegin)); +} + // ::= // ::= // ::= @@ -4743,6 +5120,8 @@ Node *AbstractManglingParser::parseExpr() { return Ex; return make("noexcept ", Ex, Node::Prec::Unary); } + if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q')) + return parseRequiresExpr(); if (consumeIf("so")) return parseSubobjectExpr(); if (consumeIf("sp")) { @@ -5021,29 +5400,14 @@ Node *AbstractManglingParser::parseSpecialName() { } // ::= +// [`Q` ] // ::= // ::= template Node *AbstractManglingParser::parseEncoding() { // The template parameters of an encoding are unrelated to those of the // enclosing context. - class SaveTemplateParams { - AbstractManglingParser *Parser; - decltype(TemplateParams) OldParams; - decltype(OuterTemplateParams) OldOuterParams; - - public: - SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) { - OldParams = std::move(Parser->TemplateParams); - OldOuterParams = std::move(Parser->OuterTemplateParams); - Parser->TemplateParams.clear(); - Parser->OuterTemplateParams.clear(); - } - ~SaveTemplateParams() { - Parser->TemplateParams = std::move(OldParams); - Parser->OuterTemplateParams = std::move(OldOuterParams); - } - } SaveTemplateParams(this); + SaveTemplateParams SaveTemplateParamsScope(this); if (look() == 'G' || look() == 'T') return getDerived().parseSpecialName(); @@ -5087,22 +5451,35 @@ Node *AbstractManglingParser::parseEncoding() { return nullptr; } - if (consumeIf('v')) - return make(ReturnType, Name, NodeArray(), - Attrs, NameInfo.CVQualifiers, - NameInfo.ReferenceQualifier); + NodeArray Params; + if (!consumeIf('v')) { + size_t ParamsBegin = Names.size(); + do { + Node *Ty = getDerived().parseType(); + if (Ty == nullptr) + return nullptr; - size_t ParamsBegin = Names.size(); - do { - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) + const bool IsFirstParam = ParamsBegin == Names.size(); + if (NameInfo.HasExplicitObjectParameter && IsFirstParam) + Ty = make(Ty); + + if (Ty == nullptr) + return nullptr; + + Names.push_back(Ty); + } while (!IsEndOfEncoding() && look() != 'Q'); + Params = popTrailingNodeArray(ParamsBegin); + } + + Node *Requires = nullptr; + if (consumeIf('Q')) { + Requires = getDerived().parseConstraintExpr(); + if (!Requires) return nullptr; - Names.push_back(Ty); - } while (!IsEndOfEncoding()); + } - return make(ReturnType, Name, - popTrailingNodeArray(ParamsBegin), - Attrs, NameInfo.CVQualifiers, + return make(ReturnType, Name, Params, Attrs, Requires, + NameInfo.CVQualifiers, NameInfo.ReferenceQualifier); } @@ -5129,7 +5506,8 @@ template <> struct FloatData { #if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \ - defined(__wasm__) || defined(__riscv) || defined(__loongarch__) + 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; @@ -5263,6 +5641,7 @@ Node *AbstractManglingParser::parseSubstitution() { // ::= TL _ _ template Node *AbstractManglingParser::parseTemplateParam() { + const char *Begin = First; if (!consumeIf('T')) return nullptr; @@ -5284,6 +5663,14 @@ Node *AbstractManglingParser::parseTemplateParam() { return nullptr; } + // We don't track enclosing template parameter levels well enough to reliably + // 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) { + return make(std::string_view(Begin, First - 1 - Begin)); + } + // If we're in a context where this refers to a // further ahead in the mangled name (currently just conversion // operator types), then we should only look it up in the right context. @@ -5292,7 +5679,8 @@ Node *AbstractManglingParser::parseTemplateParam() { Node *ForwardRef = make(Index); if (!ForwardRef) return nullptr; - assert(ForwardRef->getKind() == Node::KForwardTemplateReference); + DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference, + ""); ForwardTemplateRefs.push_back( static_cast(ForwardRef)); return ForwardRef; @@ -5321,11 +5709,13 @@ Node *AbstractManglingParser::parseTemplateParam() { // ::= Tt * E # template parameter // ::= Tp # parameter pack template -Node *AbstractManglingParser::parseTemplateParamDecl() { +Node *AbstractManglingParser::parseTemplateParamDecl( + TemplateParamList *Params) { auto InventTemplateParamName = [&](TemplateParamKind Kind) { unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++; Node *N = make(Kind, Index); - if (N) TemplateParams.back()->push_back(N); + if (N && Params) + Params->push_back(N); return N; }; @@ -5336,6 +5726,16 @@ Node *AbstractManglingParser::parseTemplateParamDecl() { return make(Name); } + if (consumeIf("Tk")) { + Node *Constraint = getDerived().parseName(); + if (!Constraint) + return nullptr; + Node *Name = InventTemplateParamName(TemplateParamKind::Type); + if (!Name) + return nullptr; + return make(Constraint, Name); + } + if (consumeIf("Tn")) { Node *Name = InventTemplateParamName(TemplateParamKind::NonType); if (!Name) @@ -5352,18 +5752,25 @@ Node *AbstractManglingParser::parseTemplateParamDecl() { return nullptr; size_t ParamsBegin = Names.size(); ScopedTemplateParamList TemplateTemplateParamParams(this); - while (!consumeIf("E")) { - Node *P = parseTemplateParamDecl(); + Node *Requires = nullptr; + while (!consumeIf('E')) { + Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params()); if (!P) return nullptr; Names.push_back(P); + if (consumeIf('Q')) { + Requires = getDerived().parseConstraintExpr(); + if (Requires == nullptr || !consumeIf('E')) + return nullptr; + break; + } } - NodeArray Params = popTrailingNodeArray(ParamsBegin); - return make(Name, Params); + NodeArray InnerParams = popTrailingNodeArray(ParamsBegin); + return make(Name, InnerParams, Requires); } if (consumeIf("Tp")) { - Node *P = parseTemplateParamDecl(); + Node *P = parseTemplateParamDecl(Params); if (!P) return nullptr; return make(P); @@ -5377,6 +5784,7 @@ Node *AbstractManglingParser::parseTemplateParamDecl() { // ::= # simple expressions // ::= J * E # argument pack // ::= LZ E # extension +// ::= template Node *AbstractManglingParser::parseTemplateArg() { switch (look()) { @@ -5411,6 +5819,18 @@ Node *AbstractManglingParser::parseTemplateArg() { // ::= # simple expressions return getDerived().parseExprPrimary(); } + case 'T': { + // Either or a . + if (!getDerived().isTemplateParamDecl()) + return getDerived().parseType(); + Node *Param = getDerived().parseTemplateParamDecl(nullptr); + if (!Param) + return nullptr; + Node *Arg = getDerived().parseTemplateArg(); + if (!Arg) + return nullptr; + return make(Param, Arg); + } default: return getDerived().parseType(); } @@ -5433,30 +5853,39 @@ AbstractManglingParser::parseTemplateArgs(bool TagTemplates) { } size_t ArgsBegin = Names.size(); + Node *Requires = nullptr; while (!consumeIf('E')) { if (TagTemplates) { - auto OldParams = std::move(TemplateParams); Node *Arg = getDerived().parseTemplateArg(); - TemplateParams = std::move(OldParams); if (Arg == nullptr) return nullptr; Names.push_back(Arg); Node *TableEntry = Arg; + if (Arg->getKind() == Node::KTemplateParamQualifiedArg) { + TableEntry = + static_cast(TableEntry)->getArg(); + } if (Arg->getKind() == Node::KTemplateArgumentPack) { TableEntry = make( static_cast(TableEntry)->getElements()); if (!TableEntry) return nullptr; } - TemplateParams.back()->push_back(TableEntry); + OuterTemplateParams.push_back(TableEntry); } else { Node *Arg = getDerived().parseTemplateArg(); if (Arg == nullptr) return nullptr; Names.push_back(Arg); } + if (consumeIf('Q')) { + Requires = getDerived().parseConstraintExpr(); + if (!Requires || !consumeIf('E')) + return nullptr; + break; + } } - return make(popTrailingNodeArray(ArgsBegin)); + return make(popTrailingNodeArray(ArgsBegin), Requires); } // ::= _Z @@ -5508,4 +5937,8 @@ struct ManglingParser : AbstractManglingParser, Alloc> { DEMANGLE_NAMESPACE_END +#ifdef _LIBCXXABI_COMPILER_CLANG +#pragma clang diagnostic pop +#endif + #endif // DEMANGLE_ITANIUMDEMANGLE_H diff --git a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/ItaniumNodes.def b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/ItaniumNodes.def index c0e277d5..33055266 100644 --- a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/ItaniumNodes.def +++ b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/ItaniumNodes.def @@ -19,6 +19,7 @@ NODE(QualType) NODE(ConversionOperatorType) NODE(PostfixQualifiedType) NODE(ElaboratedTypeSpefType) +NODE(TransformedType) NODE(NameType) NODE(AbiTagAttr) NODE(EnableIfAttr) @@ -36,6 +37,7 @@ NODE(SpecialName) NODE(CtorVtableSpecialName) NODE(QualifiedName) NODE(NestedName) +NODE(MemberLikeFriendName) NODE(LocalName) NODE(ModuleName) NODE(ModuleEntity) @@ -44,7 +46,9 @@ NODE(PixelVectorType) NODE(BinaryFPType) NODE(BitIntType) NODE(SyntheticTemplateParamName) +NODE(TemplateParamQualifiedArg) NODE(TypeTemplateParamDecl) +NODE(ConstrainedTypeTemplateParamDecl) NODE(NonTypeTemplateParamDecl) NODE(TemplateTemplateParamDecl) NODE(TemplateParamPackDecl) @@ -91,5 +95,10 @@ NODE(DoubleLiteral) NODE(LongDoubleLiteral) NODE(BracedExpr) NODE(BracedRangeExpr) +NODE(RequiresExpr) +NODE(ExprRequirement) +NODE(TypeRequirement) +NODE(NestedRequirement) +NODE(ExplicitObjectParameter) #undef NODE diff --git a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/README.txt b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/README.txt index 76470f61..d38f6abb 100644 --- a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/README.txt +++ b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/README.txt @@ -34,7 +34,7 @@ differences, we want to keep the "core" generic demangling library identical between both copies to simplify development and testing. If you're working on the generic library, then do the work first in -libcxxabi, then run the cp-to-llvm.sh script in src/demangle. This +libcxxabi, then run libcxxabi/src/demangle/cp-to-llvm.sh. This script takes as an optional argument the path to llvm, and copies the changes you made to libcxxabi over. Note that this script just blindly overwrites all changes to the generic library in llvm, so be diff --git a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/Utility.h b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/Utility.h index a906d238..e893ccee 100644 --- a/vendor/bela/src/belaund/llvm/include/llvm/Demangle/Utility.h +++ b/vendor/bela/src/belaund/llvm/include/llvm/Demangle/Utility.h @@ -19,11 +19,9 @@ #include "DemangleConfig.h" #include -#include #include #include #include -#include #include #include @@ -49,7 +47,7 @@ class OutputBuffer { BufferCapacity = Need; Buffer = static_cast(std::realloc(Buffer, BufferCapacity)); if (Buffer == nullptr) - std::terminate(); + std::abort(); } } @@ -160,7 +158,7 @@ class OutputBuffer { } void insert(size_t Pos, const char *S, size_t N) { - assert(Pos <= CurrentPosition); + DEMANGLE_ASSERT(Pos <= CurrentPosition, ""); if (N == 0) return; grow(N); @@ -173,7 +171,7 @@ class OutputBuffer { void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } char back() const { - assert(CurrentPosition); + DEMANGLE_ASSERT(CurrentPosition, ""); return Buffer[CurrentPosition - 1]; } diff --git a/vendor/bela/src/belaund/llvm/lib/Demangle/Demangle.cpp b/vendor/bela/src/belaund/llvm/lib/Demangle/Demangle.cpp index f2aa571d..83f3cdc8 100644 --- a/vendor/bela/src/belaund/llvm/lib/Demangle/Demangle.cpp +++ b/vendor/bela/src/belaund/llvm/lib/Demangle/Demangle.cpp @@ -24,7 +24,8 @@ std::string llvm::demangle(std::string_view MangledName) { return Result; if (starts_with(MangledName, '_') && - nonMicrosoftDemangle(MangledName.substr(1), Result)) + nonMicrosoftDemangle(MangledName.substr(1), Result, + /*CanHaveLeadingDot=*/false)) return Result; if (char *Demangled = microsoftDemangle(MangledName, nullptr, nullptr)) { @@ -46,8 +47,15 @@ static bool isRustEncoding(std::string_view S) { return starts_with(S, "_R"); } static bool isDLangEncoding(std::string_view S) { return starts_with(S, "_D"); } bool llvm::nonMicrosoftDemangle(std::string_view MangledName, - std::string &Result) { + std::string &Result, bool CanHaveLeadingDot) { char *Demangled = nullptr; + + // Do not consider the dot prefix as part of the demangled symbol name. + if (CanHaveLeadingDot && MangledName.size() > 0 && MangledName[0] == '.') { + MangledName.remove_prefix(1); + Result = "."; + } + if (isItaniumEncoding(MangledName)) Demangled = itaniumDemangle(MangledName); else if (isRustEncoding(MangledName)) @@ -58,7 +66,7 @@ bool llvm::nonMicrosoftDemangle(std::string_view MangledName, if (!Demangled) return false; - Result = Demangled; + Result += Demangled; std::free(Demangled); return true; }