diff options
Diffstat (limited to 'include/llvm/ADT/DenseMap.h')
-rw-r--r-- | include/llvm/ADT/DenseMap.h | 81 |
1 files changed, 75 insertions, 6 deletions
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index ba60b7972a8f..1f50502fff92 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -25,6 +25,7 @@ #include <cassert> #include <cstddef> #include <cstring> +#include <initializer_list> #include <iterator> #include <new> #include <type_traits> @@ -38,6 +39,34 @@ namespace detail { // implementation without requiring two members. template <typename KeyT, typename ValueT> struct DenseMapPair : public std::pair<KeyT, ValueT> { + + // FIXME: Switch to inheriting constructors when we drop support for older + // clang versions. + // NOTE: This default constructor is declared with '{}' rather than + // '= default' to work around a separate bug in clang-3.8. This can + // also go when we switch to inheriting constructors. + DenseMapPair() {} + + DenseMapPair(const KeyT &Key, const ValueT &Value) + : std::pair<KeyT, ValueT>(Key, Value) {} + + DenseMapPair(KeyT &&Key, ValueT &&Value) + : std::pair<KeyT, ValueT>(std::move(Key), std::move(Value)) {} + + template <typename AltKeyT, typename AltValueT> + DenseMapPair(AltKeyT &&AltKey, AltValueT &&AltValue, + typename std::enable_if< + std::is_convertible<AltKeyT, KeyT>::value && + std::is_convertible<AltValueT, ValueT>::value>::type * = 0) + : std::pair<KeyT, ValueT>(std::forward<AltKeyT>(AltKey), + std::forward<AltValueT>(AltValue)) {} + + template <typename AltPairT> + DenseMapPair(AltPairT &&AltPair, + typename std::enable_if<std::is_convertible< + AltPairT, std::pair<KeyT, ValueT>>::value>::type * = 0) + : std::pair<KeyT, ValueT>(std::forward<AltPairT>(AltPair)) {} + KeyT &getFirst() { return std::pair<KeyT, ValueT>::first; } const KeyT &getFirst() const { return std::pair<KeyT, ValueT>::first; } ValueT &getSecond() { return std::pair<KeyT, ValueT>::second; } @@ -46,9 +75,10 @@ struct DenseMapPair : public std::pair<KeyT, ValueT> { } // end namespace detail -template < - typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>, - typename Bucket = detail::DenseMapPair<KeyT, ValueT>, bool IsConst = false> +template <typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapInfo<KeyT>, + typename Bucket = llvm::detail::DenseMapPair<KeyT, ValueT>, + bool IsConst = false> class DenseMapIterator; template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, @@ -393,7 +423,7 @@ protected: setNumTombstones(other.getNumTombstones()); if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) - memcpy(getBuckets(), other.getBuckets(), + memcpy(reinterpret_cast<void *>(getBuckets()), other.getBuckets(), getNumBuckets() * sizeof(BucketT)); else for (size_t i = 0; i < getNumBuckets(); ++i) { @@ -639,9 +669,43 @@ public: } }; +/// Equality comparison for DenseMap. +/// +/// Iterates over elements of LHS confirming that each (key, value) pair in LHS +/// is also in RHS, and that no additional pairs are in RHS. +/// Equivalent to N calls to RHS.find and N value comparisons. Amortized +/// complexity is linear, worst case is O(N^2) (if every hash collides). +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> +bool operator==( + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS, + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) { + if (LHS.size() != RHS.size()) + return false; + + for (auto &KV : LHS) { + auto I = RHS.find(KV.first); + if (I == RHS.end() || I->second != KV.second) + return false; + } + + return true; +} + +/// Inequality comparison for DenseMap. +/// +/// Equivalent to !(LHS == RHS). See operator== for performance notes. +template <typename DerivedT, typename KeyT, typename ValueT, typename KeyInfoT, + typename BucketT> +bool operator!=( + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &LHS, + const DenseMapBase<DerivedT, KeyT, ValueT, KeyInfoT, BucketT> &RHS) { + return !(LHS == RHS); +} + template <typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo<KeyT>, - typename BucketT = detail::DenseMapPair<KeyT, ValueT>> + typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>> class DenseMap : public DenseMapBase<DenseMap<KeyT, ValueT, KeyInfoT, BucketT>, KeyT, ValueT, KeyInfoT, BucketT> { friend class DenseMapBase<DenseMap, KeyT, ValueT, KeyInfoT, BucketT>; @@ -676,6 +740,11 @@ public: this->insert(I, E); } + DenseMap(std::initializer_list<typename BaseT::value_type> Vals) { + init(Vals.size()); + this->insert(Vals.begin(), Vals.end()); + } + ~DenseMap() { this->destroyAll(); operator delete(Buckets); @@ -798,7 +867,7 @@ private: template <typename KeyT, typename ValueT, unsigned InlineBuckets = 4, typename KeyInfoT = DenseMapInfo<KeyT>, - typename BucketT = detail::DenseMapPair<KeyT, ValueT>> + typename BucketT = llvm::detail::DenseMapPair<KeyT, ValueT>> class SmallDenseMap : public DenseMapBase< SmallDenseMap<KeyT, ValueT, InlineBuckets, KeyInfoT, BucketT>, KeyT, |