Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:08

0001 //===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file defines the SmallPtrSet class.  See the doxygen comment for
0011 /// SmallPtrSetImplBase for more details on the algorithm used.
0012 //
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_ADT_SMALLPTRSET_H
0016 #define LLVM_ADT_SMALLPTRSET_H
0017 
0018 #include "llvm/ADT/EpochTracker.h"
0019 #include "llvm/Support/MathExtras.h"
0020 #include "llvm/Support/ReverseIteration.h"
0021 #include "llvm/Support/type_traits.h"
0022 #include <algorithm>
0023 #include <cassert>
0024 #include <cstddef>
0025 #include <cstdlib>
0026 #include <cstring>
0027 #include <initializer_list>
0028 #include <iterator>
0029 #include <limits>
0030 #include <utility>
0031 
0032 namespace llvm {
0033 
0034 /// SmallPtrSetImplBase - This is the common code shared among all the
0035 /// SmallPtrSet<>'s, which is almost everything.  SmallPtrSet has two modes, one
0036 /// for small and one for large sets.
0037 ///
0038 /// Small sets use an array of pointers allocated in the SmallPtrSet object,
0039 /// which is treated as a simple array of pointers.  When a pointer is added to
0040 /// the set, the array is scanned to see if the element already exists, if not
0041 /// the element is 'pushed back' onto the array.  If we run out of space in the
0042 /// array, we grow into the 'large set' case.  SmallSet should be used when the
0043 /// sets are often small.  In this case, no memory allocation is used, and only
0044 /// light-weight and cache-efficient scanning is used.
0045 ///
0046 /// Large sets use a classic exponentially-probed hash table.  Empty buckets are
0047 /// represented with an illegal pointer value (-1) to allow null pointers to be
0048 /// inserted.  Tombstones are represented with another illegal pointer value
0049 /// (-2), to allow deletion.  The hash table is resized when the table is 3/4 or
0050 /// more.  When this happens, the table is doubled in size.
0051 ///
0052 class SmallPtrSetImplBase : public DebugEpochBase {
0053   friend class SmallPtrSetIteratorImpl;
0054 
0055 protected:
0056   /// The current set of buckets, in either small or big representation.
0057   const void **CurArray;
0058   /// CurArraySize - The allocated size of CurArray, always a power of two.
0059   unsigned CurArraySize;
0060 
0061   /// Number of elements in CurArray that contain a value or are a tombstone.
0062   /// If small, all these elements are at the beginning of CurArray and the rest
0063   /// is uninitialized.
0064   unsigned NumNonEmpty;
0065   /// Number of tombstones in CurArray.
0066   unsigned NumTombstones;
0067   /// Whether the set is in small representation.
0068   bool IsSmall;
0069 
0070   // Helpers to copy and move construct a SmallPtrSet.
0071   SmallPtrSetImplBase(const void **SmallStorage,
0072                       const SmallPtrSetImplBase &that);
0073   SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize,
0074                       const void **RHSSmallStorage, SmallPtrSetImplBase &&that);
0075 
0076   explicit SmallPtrSetImplBase(const void **SmallStorage, unsigned SmallSize)
0077       : CurArray(SmallStorage), CurArraySize(SmallSize), NumNonEmpty(0),
0078         NumTombstones(0), IsSmall(true) {
0079     assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
0080            "Initial size must be a power of two!");
0081   }
0082 
0083   ~SmallPtrSetImplBase() {
0084     if (!isSmall())
0085       free(CurArray);
0086   }
0087 
0088 public:
0089   using size_type = unsigned;
0090 
0091   SmallPtrSetImplBase &operator=(const SmallPtrSetImplBase &) = delete;
0092 
0093   [[nodiscard]] bool empty() const { return size() == 0; }
0094   size_type size() const { return NumNonEmpty - NumTombstones; }
0095   size_type capacity() const { return CurArraySize; }
0096 
0097   void clear() {
0098     incrementEpoch();
0099     // If the capacity of the array is huge, and the # elements used is small,
0100     // shrink the array.
0101     if (!isSmall()) {
0102       if (size() * 4 < CurArraySize && CurArraySize > 32)
0103         return shrink_and_clear();
0104       // Fill the array with empty markers.
0105       memset(CurArray, -1, CurArraySize * sizeof(void *));
0106     }
0107 
0108     NumNonEmpty = 0;
0109     NumTombstones = 0;
0110   }
0111 
0112   void reserve(size_type NumEntries) {
0113     incrementEpoch();
0114     // Do nothing if we're given zero as a reservation size.
0115     if (NumEntries == 0)
0116       return;
0117     // No need to expand if we're small and NumEntries will fit in the space.
0118     if (isSmall() && NumEntries <= CurArraySize)
0119       return;
0120     // insert_imp_big will reallocate if stores is more than 75% full, on the
0121     // /final/ insertion.
0122     if (!isSmall() && ((NumEntries - 1) * 4) < (CurArraySize * 3))
0123       return;
0124     // We must Grow -- find the size where we'd be 75% full, then round up to
0125     // the next power of two.
0126     size_type NewSize = NumEntries + (NumEntries / 3);
0127     NewSize = 1 << (Log2_32_Ceil(NewSize) + 1);
0128     // Like insert_imp_big, always allocate at least 128 elements.
0129     NewSize = std::max(128u, NewSize);
0130     Grow(NewSize);
0131   }
0132 
0133 protected:
0134   static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); }
0135 
0136   static void *getEmptyMarker() {
0137     // Note that -1 is chosen to make clear() efficiently implementable with
0138     // memset and because it's not a valid pointer value.
0139     return reinterpret_cast<void*>(-1);
0140   }
0141 
0142   const void **EndPointer() const {
0143     return isSmall() ? CurArray + NumNonEmpty : CurArray + CurArraySize;
0144   }
0145 
0146   /// insert_imp - This returns true if the pointer was new to the set, false if
0147   /// it was already in the set.  This is hidden from the client so that the
0148   /// derived class can check that the right type of pointer is passed in.
0149   std::pair<const void *const *, bool> insert_imp(const void *Ptr) {
0150     if (isSmall()) {
0151       // Check to see if it is already in the set.
0152       for (const void **APtr = CurArray, **E = CurArray + NumNonEmpty;
0153            APtr != E; ++APtr) {
0154         const void *Value = *APtr;
0155         if (Value == Ptr)
0156           return std::make_pair(APtr, false);
0157       }
0158 
0159       // Nope, there isn't.  If we stay small, just 'pushback' now.
0160       if (NumNonEmpty < CurArraySize) {
0161         CurArray[NumNonEmpty++] = Ptr;
0162         incrementEpoch();
0163         return std::make_pair(CurArray + (NumNonEmpty - 1), true);
0164       }
0165       // Otherwise, hit the big set case, which will call grow.
0166     }
0167     return insert_imp_big(Ptr);
0168   }
0169 
0170   /// erase_imp - If the set contains the specified pointer, remove it and
0171   /// return true, otherwise return false.  This is hidden from the client so
0172   /// that the derived class can check that the right type of pointer is passed
0173   /// in.
0174   bool erase_imp(const void * Ptr) {
0175     if (isSmall()) {
0176       for (const void **APtr = CurArray, **E = CurArray + NumNonEmpty;
0177            APtr != E; ++APtr) {
0178         if (*APtr == Ptr) {
0179           *APtr = CurArray[--NumNonEmpty];
0180           incrementEpoch();
0181           return true;
0182         }
0183       }
0184       return false;
0185     }
0186 
0187     auto *Bucket = doFind(Ptr);
0188     if (!Bucket)
0189       return false;
0190 
0191     *const_cast<const void **>(Bucket) = getTombstoneMarker();
0192     NumTombstones++;
0193     // Treat this consistently from an API perspective, even if we don't
0194     // actually invalidate iterators here.
0195     incrementEpoch();
0196     return true;
0197   }
0198 
0199   /// Returns the raw pointer needed to construct an iterator.  If element not
0200   /// found, this will be EndPointer.  Otherwise, it will be a pointer to the
0201   /// slot which stores Ptr;
0202   const void *const * find_imp(const void * Ptr) const {
0203     if (isSmall()) {
0204       // Linear search for the item.
0205       for (const void *const *APtr = CurArray, *const *E =
0206                                                    CurArray + NumNonEmpty;
0207            APtr != E; ++APtr)
0208         if (*APtr == Ptr)
0209           return APtr;
0210       return EndPointer();
0211     }
0212 
0213     // Big set case.
0214     if (auto *Bucket = doFind(Ptr))
0215       return Bucket;
0216     return EndPointer();
0217   }
0218 
0219   bool contains_imp(const void *Ptr) const {
0220     if (isSmall()) {
0221       // Linear search for the item.
0222       const void *const *APtr = CurArray;
0223       const void *const *E = CurArray + NumNonEmpty;
0224       for (; APtr != E; ++APtr)
0225         if (*APtr == Ptr)
0226           return true;
0227       return false;
0228     }
0229 
0230     return doFind(Ptr) != nullptr;
0231   }
0232 
0233   bool isSmall() const { return IsSmall; }
0234 
0235 private:
0236   std::pair<const void *const *, bool> insert_imp_big(const void *Ptr);
0237 
0238   const void *const *doFind(const void *Ptr) const;
0239   const void * const *FindBucketFor(const void *Ptr) const;
0240   void shrink_and_clear();
0241 
0242   /// Grow - Allocate a larger backing store for the buckets and move it over.
0243   void Grow(unsigned NewSize);
0244 
0245 protected:
0246   /// swap - Swaps the elements of two sets.
0247   /// Note: This method assumes that both sets have the same small size.
0248   void swap(const void **SmallStorage, const void **RHSSmallStorage,
0249             SmallPtrSetImplBase &RHS);
0250 
0251   void copyFrom(const void **SmallStorage, const SmallPtrSetImplBase &RHS);
0252   void moveFrom(const void **SmallStorage, unsigned SmallSize,
0253                 const void **RHSSmallStorage, SmallPtrSetImplBase &&RHS);
0254 
0255 private:
0256   /// Code shared by moveFrom() and move constructor.
0257   void moveHelper(const void **SmallStorage, unsigned SmallSize,
0258                   const void **RHSSmallStorage, SmallPtrSetImplBase &&RHS);
0259   /// Code shared by copyFrom() and copy constructor.
0260   void copyHelper(const SmallPtrSetImplBase &RHS);
0261 };
0262 
0263 /// SmallPtrSetIteratorImpl - This is the common base class shared between all
0264 /// instances of SmallPtrSetIterator.
0265 class SmallPtrSetIteratorImpl {
0266 protected:
0267   const void *const *Bucket;
0268   const void *const *End;
0269 
0270 public:
0271   explicit SmallPtrSetIteratorImpl(const void *const *BP, const void*const *E)
0272     : Bucket(BP), End(E) {
0273     if (shouldReverseIterate()) {
0274       RetreatIfNotValid();
0275       return;
0276     }
0277     AdvanceIfNotValid();
0278   }
0279 
0280   bool operator==(const SmallPtrSetIteratorImpl &RHS) const {
0281     return Bucket == RHS.Bucket;
0282   }
0283   bool operator!=(const SmallPtrSetIteratorImpl &RHS) const {
0284     return Bucket != RHS.Bucket;
0285   }
0286 
0287 protected:
0288   /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket
0289   /// that is.   This is guaranteed to stop because the end() bucket is marked
0290   /// valid.
0291   void AdvanceIfNotValid() {
0292     assert(Bucket <= End);
0293     while (Bucket != End &&
0294            (*Bucket == SmallPtrSetImplBase::getEmptyMarker() ||
0295             *Bucket == SmallPtrSetImplBase::getTombstoneMarker()))
0296       ++Bucket;
0297   }
0298   void RetreatIfNotValid() {
0299     assert(Bucket >= End);
0300     while (Bucket != End &&
0301            (Bucket[-1] == SmallPtrSetImplBase::getEmptyMarker() ||
0302             Bucket[-1] == SmallPtrSetImplBase::getTombstoneMarker())) {
0303       --Bucket;
0304     }
0305   }
0306 };
0307 
0308 /// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
0309 template <typename PtrTy>
0310 class LLVM_DEBUGEPOCHBASE_HANDLEBASE_EMPTYBASE SmallPtrSetIterator
0311     : public SmallPtrSetIteratorImpl,
0312       DebugEpochBase::HandleBase {
0313   using PtrTraits = PointerLikeTypeTraits<PtrTy>;
0314 
0315 public:
0316   using value_type = PtrTy;
0317   using reference = PtrTy;
0318   using pointer = PtrTy;
0319   using difference_type = std::ptrdiff_t;
0320   using iterator_category = std::forward_iterator_tag;
0321 
0322   explicit SmallPtrSetIterator(const void *const *BP, const void *const *E,
0323                                const DebugEpochBase &Epoch)
0324       : SmallPtrSetIteratorImpl(BP, E), DebugEpochBase::HandleBase(&Epoch) {}
0325 
0326   // Most methods are provided by the base class.
0327 
0328   const PtrTy operator*() const {
0329     assert(isHandleInSync() && "invalid iterator access!");
0330     if (shouldReverseIterate()) {
0331       assert(Bucket > End);
0332       return PtrTraits::getFromVoidPointer(const_cast<void *>(Bucket[-1]));
0333     }
0334     assert(Bucket < End);
0335     return PtrTraits::getFromVoidPointer(const_cast<void*>(*Bucket));
0336   }
0337 
0338   inline SmallPtrSetIterator& operator++() {          // Preincrement
0339     assert(isHandleInSync() && "invalid iterator access!");
0340     if (shouldReverseIterate()) {
0341       --Bucket;
0342       RetreatIfNotValid();
0343       return *this;
0344     }
0345     ++Bucket;
0346     AdvanceIfNotValid();
0347     return *this;
0348   }
0349 
0350   SmallPtrSetIterator operator++(int) {        // Postincrement
0351     SmallPtrSetIterator tmp = *this;
0352     ++*this;
0353     return tmp;
0354   }
0355 };
0356 
0357 /// A templated base class for \c SmallPtrSet which provides the
0358 /// typesafe interface that is common across all small sizes.
0359 ///
0360 /// This is particularly useful for passing around between interface boundaries
0361 /// to avoid encoding a particular small size in the interface boundary.
0362 template <typename PtrType>
0363 class SmallPtrSetImpl : public SmallPtrSetImplBase {
0364   using ConstPtrType = typename add_const_past_pointer<PtrType>::type;
0365   using PtrTraits = PointerLikeTypeTraits<PtrType>;
0366   using ConstPtrTraits = PointerLikeTypeTraits<ConstPtrType>;
0367 
0368 protected:
0369   // Forward constructors to the base.
0370   using SmallPtrSetImplBase::SmallPtrSetImplBase;
0371 
0372 public:
0373   using iterator = SmallPtrSetIterator<PtrType>;
0374   using const_iterator = SmallPtrSetIterator<PtrType>;
0375   using key_type = ConstPtrType;
0376   using value_type = PtrType;
0377 
0378   SmallPtrSetImpl(const SmallPtrSetImpl &) = delete;
0379 
0380   /// Inserts Ptr if and only if there is no element in the container equal to
0381   /// Ptr. The bool component of the returned pair is true if and only if the
0382   /// insertion takes place, and the iterator component of the pair points to
0383   /// the element equal to Ptr.
0384   std::pair<iterator, bool> insert(PtrType Ptr) {
0385     auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr));
0386     return std::make_pair(makeIterator(p.first), p.second);
0387   }
0388 
0389   /// Insert the given pointer with an iterator hint that is ignored. This is
0390   /// identical to calling insert(Ptr), but allows SmallPtrSet to be used by
0391   /// std::insert_iterator and std::inserter().
0392   iterator insert(iterator, PtrType Ptr) {
0393     return insert(Ptr).first;
0394   }
0395 
0396   /// Remove pointer from the set.
0397   ///
0398   /// Returns whether the pointer was in the set. Invalidates iterators if
0399   /// true is returned. To remove elements while iterating over the set, use
0400   /// remove_if() instead.
0401   bool erase(PtrType Ptr) {
0402     return erase_imp(PtrTraits::getAsVoidPointer(Ptr));
0403   }
0404 
0405   /// Remove elements that match the given predicate.
0406   ///
0407   /// This method is a safe replacement for the following pattern, which is not
0408   /// valid, because the erase() calls would invalidate the iterator:
0409   ///
0410   ///     for (PtrType *Ptr : Set)
0411   ///       if (Pred(P))
0412   ///         Set.erase(P);
0413   ///
0414   /// Returns whether anything was removed. It is safe to read the set inside
0415   /// the predicate function. However, the predicate must not modify the set
0416   /// itself, only indicate a removal by returning true.
0417   template <typename UnaryPredicate>
0418   bool remove_if(UnaryPredicate P) {
0419     bool Removed = false;
0420     if (isSmall()) {
0421       const void **APtr = CurArray, **E = CurArray + NumNonEmpty;
0422       while (APtr != E) {
0423         PtrType Ptr = PtrTraits::getFromVoidPointer(const_cast<void *>(*APtr));
0424         if (P(Ptr)) {
0425           *APtr = *--E;
0426           --NumNonEmpty;
0427           incrementEpoch();
0428           Removed = true;
0429         } else {
0430           ++APtr;
0431         }
0432       }
0433       return Removed;
0434     }
0435 
0436     for (const void **APtr = CurArray, **E = EndPointer(); APtr != E; ++APtr) {
0437       const void *Value = *APtr;
0438       if (Value == getTombstoneMarker() || Value == getEmptyMarker())
0439         continue;
0440       PtrType Ptr = PtrTraits::getFromVoidPointer(const_cast<void *>(Value));
0441       if (P(Ptr)) {
0442         *APtr = getTombstoneMarker();
0443         ++NumTombstones;
0444         incrementEpoch();
0445         Removed = true;
0446       }
0447     }
0448     return Removed;
0449   }
0450 
0451   /// count - Return 1 if the specified pointer is in the set, 0 otherwise.
0452   size_type count(ConstPtrType Ptr) const {
0453     return contains_imp(ConstPtrTraits::getAsVoidPointer(Ptr));
0454   }
0455   iterator find(ConstPtrType Ptr) const {
0456     return makeIterator(find_imp(ConstPtrTraits::getAsVoidPointer(Ptr)));
0457   }
0458   bool contains(ConstPtrType Ptr) const {
0459     return contains_imp(ConstPtrTraits::getAsVoidPointer(Ptr));
0460   }
0461 
0462   template <typename IterT>
0463   void insert(IterT I, IterT E) {
0464     for (; I != E; ++I)
0465       insert(*I);
0466   }
0467 
0468   void insert(std::initializer_list<PtrType> IL) {
0469     insert(IL.begin(), IL.end());
0470   }
0471 
0472   iterator begin() const {
0473     if (shouldReverseIterate())
0474       return makeIterator(EndPointer() - 1);
0475     return makeIterator(CurArray);
0476   }
0477   iterator end() const { return makeIterator(EndPointer()); }
0478 
0479 private:
0480   /// Create an iterator that dereferences to same place as the given pointer.
0481   iterator makeIterator(const void *const *P) const {
0482     if (shouldReverseIterate())
0483       return iterator(P == EndPointer() ? CurArray : P + 1, CurArray, *this);
0484     return iterator(P, EndPointer(), *this);
0485   }
0486 };
0487 
0488 /// Equality comparison for SmallPtrSet.
0489 ///
0490 /// Iterates over elements of LHS confirming that each value from LHS is also in
0491 /// RHS, and that no additional values are in RHS.
0492 template <typename PtrType>
0493 bool operator==(const SmallPtrSetImpl<PtrType> &LHS,
0494                 const SmallPtrSetImpl<PtrType> &RHS) {
0495   if (LHS.size() != RHS.size())
0496     return false;
0497 
0498   for (const auto *KV : LHS)
0499     if (!RHS.count(KV))
0500       return false;
0501 
0502   return true;
0503 }
0504 
0505 /// Inequality comparison for SmallPtrSet.
0506 ///
0507 /// Equivalent to !(LHS == RHS).
0508 template <typename PtrType>
0509 bool operator!=(const SmallPtrSetImpl<PtrType> &LHS,
0510                 const SmallPtrSetImpl<PtrType> &RHS) {
0511   return !(LHS == RHS);
0512 }
0513 
0514 /// SmallPtrSet - This class implements a set which is optimized for holding
0515 /// SmallSize or less elements.  This internally rounds up SmallSize to the next
0516 /// power of two if it is not already a power of two.  See the comments above
0517 /// SmallPtrSetImplBase for details of the algorithm.
0518 template<class PtrType, unsigned SmallSize>
0519 class SmallPtrSet : public SmallPtrSetImpl<PtrType> {
0520   // In small mode SmallPtrSet uses linear search for the elements, so it is
0521   // not a good idea to choose this value too high. You may consider using a
0522   // DenseSet<> instead if you expect many elements in the set.
0523   static_assert(SmallSize <= 32, "SmallSize should be small");
0524 
0525   using BaseT = SmallPtrSetImpl<PtrType>;
0526 
0527   // A constexpr version of llvm::bit_ceil.
0528   // TODO: Replace this with std::bit_ceil once C++20 is available.
0529   static constexpr size_t RoundUpToPowerOfTwo(size_t X) {
0530     size_t C = 1;
0531     size_t CMax = C << (std::numeric_limits<size_t>::digits - 1);
0532     while (C < X && C < CMax)
0533       C <<= 1;
0534     return C;
0535   }
0536 
0537   // Make sure that SmallSize is a power of two, round up if not.
0538   static constexpr size_t SmallSizePowTwo = RoundUpToPowerOfTwo(SmallSize);
0539   /// SmallStorage - Fixed size storage used in 'small mode'.
0540   const void *SmallStorage[SmallSizePowTwo];
0541 
0542 public:
0543   SmallPtrSet() : BaseT(SmallStorage, SmallSizePowTwo) {}
0544   SmallPtrSet(const SmallPtrSet &that) : BaseT(SmallStorage, that) {}
0545   SmallPtrSet(SmallPtrSet &&that)
0546       : BaseT(SmallStorage, SmallSizePowTwo, that.SmallStorage,
0547               std::move(that)) {}
0548 
0549   template<typename It>
0550   SmallPtrSet(It I, It E) : BaseT(SmallStorage, SmallSizePowTwo) {
0551     this->insert(I, E);
0552   }
0553 
0554   SmallPtrSet(std::initializer_list<PtrType> IL)
0555       : BaseT(SmallStorage, SmallSizePowTwo) {
0556     this->insert(IL.begin(), IL.end());
0557   }
0558 
0559   SmallPtrSet<PtrType, SmallSize> &
0560   operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) {
0561     if (&RHS != this)
0562       this->copyFrom(SmallStorage, RHS);
0563     return *this;
0564   }
0565 
0566   SmallPtrSet<PtrType, SmallSize> &
0567   operator=(SmallPtrSet<PtrType, SmallSize> &&RHS) {
0568     if (&RHS != this)
0569       this->moveFrom(SmallStorage, SmallSizePowTwo, RHS.SmallStorage,
0570                      std::move(RHS));
0571     return *this;
0572   }
0573 
0574   SmallPtrSet<PtrType, SmallSize> &
0575   operator=(std::initializer_list<PtrType> IL) {
0576     this->clear();
0577     this->insert(IL.begin(), IL.end());
0578     return *this;
0579   }
0580 
0581   /// swap - Swaps the elements of two sets.
0582   void swap(SmallPtrSet<PtrType, SmallSize> &RHS) {
0583     SmallPtrSetImplBase::swap(SmallStorage, RHS.SmallStorage, RHS);
0584   }
0585 };
0586 
0587 } // end namespace llvm
0588 
0589 namespace std {
0590 
0591   /// Implement std::swap in terms of SmallPtrSet swap.
0592   template<class T, unsigned N>
0593   inline void swap(llvm::SmallPtrSet<T, N> &LHS, llvm::SmallPtrSet<T, N> &RHS) {
0594     LHS.swap(RHS);
0595   }
0596 
0597 } // end namespace std
0598 
0599 #endif // LLVM_ADT_SMALLPTRSET_H