LCOV - code coverage report
Current view: top level - /usr/lib/llvm-19/include/llvm/ADT - SetVector.h (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 100.0 % 7 7
Test Date: 2026-02-27 05:14:50 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit

            Line data    Source code
       1              : //===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===//
       2              : //
       3              : // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
       4              : // See https://llvm.org/LICENSE.txt for license information.
       5              : // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
       6              : //
       7              : //===----------------------------------------------------------------------===//
       8              : ///
       9              : /// \file
      10              : /// This file implements a set that has insertion order iteration
      11              : /// characteristics. This is useful for keeping a set of things that need to be
      12              : /// visited later but in a deterministic order (insertion order). The interface
      13              : /// is purposefully minimal.
      14              : ///
      15              : /// This file defines SetVector and SmallSetVector, which performs no
      16              : /// allocations if the SetVector has less than a certain number of elements.
      17              : ///
      18              : //===----------------------------------------------------------------------===//
      19              : 
      20              : #ifndef LLVM_ADT_SETVECTOR_H
      21              : #define LLVM_ADT_SETVECTOR_H
      22              : 
      23              : #include "llvm/ADT/ArrayRef.h"
      24              : #include "llvm/ADT/DenseSet.h"
      25              : #include "llvm/ADT/STLExtras.h"
      26              : #include "llvm/ADT/SmallVector.h"
      27              : #include "llvm/Support/Compiler.h"
      28              : #include <cassert>
      29              : #include <iterator>
      30              : 
      31              : namespace llvm {
      32              : 
      33              : /// A vector that has set insertion semantics.
      34              : ///
      35              : /// This adapter class provides a way to keep a set of things that also has the
      36              : /// property of a deterministic iteration order. The order of iteration is the
      37              : /// order of insertion.
      38              : ///
      39              : /// The key and value types are derived from the Set and Vector types
      40              : /// respectively. This allows the vector-type operations and set-type operations
      41              : /// to have different types. In particular, this is useful when storing pointers
      42              : /// as "Foo *" values but looking them up as "const Foo *" keys.
      43              : ///
      44              : /// No constraint is placed on the key and value types, although it is assumed
      45              : /// that value_type can be converted into key_type for insertion. Users must be
      46              : /// aware of any loss of information in this conversion. For example, setting
      47              : /// value_type to float and key_type to int can produce very surprising results,
      48              : /// but it is not explicitly disallowed.
      49              : ///
      50              : /// The parameter N specifies the "small" size of the container, which is the
      51              : /// number of elements upto which a linear scan over the Vector will be used
      52              : /// when searching for elements instead of checking Set, due to it being better
      53              : /// for performance. A value of 0 means that this mode of operation is not used,
      54              : /// and is the default value.
      55              : template <typename T, typename Vector = SmallVector<T, 0>,
      56              :           typename Set = DenseSet<T>, unsigned N = 0>
      57              : class SetVector {
      58              :   // Much like in SmallPtrSet, this value should not be too high to prevent
      59              :   // excessively long linear scans from occuring.
      60              :   static_assert(N <= 32, "Small size should be less than or equal to 32!");
      61              : 
      62              : public:
      63              :   using value_type = typename Vector::value_type;
      64              :   using key_type = typename Set::key_type;
      65              :   using reference = value_type &;
      66              :   using const_reference = const value_type &;
      67              :   using set_type = Set;
      68              :   using vector_type = Vector;
      69              :   using iterator = typename vector_type::const_iterator;
      70              :   using const_iterator = typename vector_type::const_iterator;
      71              :   using reverse_iterator = typename vector_type::const_reverse_iterator;
      72              :   using const_reverse_iterator = typename vector_type::const_reverse_iterator;
      73              :   using size_type = typename vector_type::size_type;
      74              : 
      75              :   /// Construct an empty SetVector
      76         1005 :   SetVector() = default;
      77              : 
      78              :   /// Initialize a SetVector with a range of elements
      79              :   template<typename It>
      80              :   SetVector(It Start, It End) {
      81              :     insert(Start, End);
      82              :   }
      83              : 
      84         1005 :   ArrayRef<value_type> getArrayRef() const { return vector_; }
      85              : 
      86              :   /// Clear the SetVector and return the underlying vector.
      87              :   Vector takeVector() {
      88              :     set_.clear();
      89              :     return std::move(vector_);
      90              :   }
      91              : 
      92              :   /// Determine if the SetVector is empty or not.
      93              :   bool empty() const {
      94              :     return vector_.empty();
      95              :   }
      96              : 
      97              :   /// Determine the number of elements in the SetVector.
      98              :   size_type size() const {
      99              :     return vector_.size();
     100              :   }
     101              : 
     102              :   /// Get an iterator to the beginning of the SetVector.
     103              :   iterator begin() {
     104              :     return vector_.begin();
     105              :   }
     106              : 
     107              :   /// Get a const_iterator to the beginning of the SetVector.
     108              :   const_iterator begin() const {
     109              :     return vector_.begin();
     110              :   }
     111              : 
     112              :   /// Get an iterator to the end of the SetVector.
     113              :   iterator end() {
     114              :     return vector_.end();
     115              :   }
     116              : 
     117              :   /// Get a const_iterator to the end of the SetVector.
     118              :   const_iterator end() const {
     119              :     return vector_.end();
     120              :   }
     121              : 
     122              :   /// Get an reverse_iterator to the end of the SetVector.
     123              :   reverse_iterator rbegin() {
     124              :     return vector_.rbegin();
     125              :   }
     126              : 
     127              :   /// Get a const_reverse_iterator to the end of the SetVector.
     128              :   const_reverse_iterator rbegin() const {
     129              :     return vector_.rbegin();
     130              :   }
     131              : 
     132              :   /// Get a reverse_iterator to the beginning of the SetVector.
     133              :   reverse_iterator rend() {
     134              :     return vector_.rend();
     135              :   }
     136              : 
     137              :   /// Get a const_reverse_iterator to the beginning of the SetVector.
     138              :   const_reverse_iterator rend() const {
     139              :     return vector_.rend();
     140              :   }
     141              : 
     142              :   /// Return the first element of the SetVector.
     143              :   const value_type &front() const {
     144              :     assert(!empty() && "Cannot call front() on empty SetVector!");
     145              :     return vector_.front();
     146              :   }
     147              : 
     148              :   /// Return the last element of the SetVector.
     149              :   const value_type &back() const {
     150              :     assert(!empty() && "Cannot call back() on empty SetVector!");
     151              :     return vector_.back();
     152              :   }
     153              : 
     154              :   /// Index into the SetVector.
     155              :   const_reference operator[](size_type n) const {
     156              :     assert(n < vector_.size() && "SetVector access out of range!");
     157              :     return vector_[n];
     158              :   }
     159              : 
     160              :   /// Insert a new element into the SetVector.
     161              :   /// \returns true if the element was inserted into the SetVector.
     162         2192 :   bool insert(const value_type &X) {
     163              :     if constexpr (canBeSmall())
     164              :       if (isSmall()) {
     165              :         if (!llvm::is_contained(vector_, X)) {
     166              :           vector_.push_back(X);
     167              :           if (vector_.size() > N)
     168              :             makeBig();
     169              :           return true;
     170              :         }
     171              :         return false;
     172              :       }
     173              : 
     174         2192 :     bool result = set_.insert(X).second;
     175         2192 :     if (result)
     176         2192 :       vector_.push_back(X);
     177         2192 :     return result;
     178              :   }
     179              : 
     180              :   /// Insert a range of elements into the SetVector.
     181              :   template<typename It>
     182              :   void insert(It Start, It End) {
     183              :     for (; Start != End; ++Start)
     184              :       insert(*Start);
     185              :   }
     186              : 
     187              :   /// Remove an item from the set vector.
     188              :   bool remove(const value_type& X) {
     189              :     if constexpr (canBeSmall())
     190              :       if (isSmall()) {
     191              :         typename vector_type::iterator I = find(vector_, X);
     192              :         if (I != vector_.end()) {
     193              :           vector_.erase(I);
     194              :           return true;
     195              :         }
     196              :         return false;
     197              :       }
     198              : 
     199              :     if (set_.erase(X)) {
     200              :       typename vector_type::iterator I = find(vector_, X);
     201              :       assert(I != vector_.end() && "Corrupted SetVector instances!");
     202              :       vector_.erase(I);
     203              :       return true;
     204              :     }
     205              :     return false;
     206              :   }
     207              : 
     208              :   /// Erase a single element from the set vector.
     209              :   /// \returns an iterator pointing to the next element that followed the
     210              :   /// element erased. This is the end of the SetVector if the last element is
     211              :   /// erased.
     212              :   iterator erase(const_iterator I) {
     213              :     if constexpr (canBeSmall())
     214              :       if (isSmall())
     215              :         return vector_.erase(I);
     216              : 
     217              :     const key_type &V = *I;
     218              :     assert(set_.count(V) && "Corrupted SetVector instances!");
     219              :     set_.erase(V);
     220              :     return vector_.erase(I);
     221              :   }
     222              : 
     223              :   /// Remove items from the set vector based on a predicate function.
     224              :   ///
     225              :   /// This is intended to be equivalent to the following code, if we could
     226              :   /// write it:
     227              :   ///
     228              :   /// \code
     229              :   ///   V.erase(remove_if(V, P), V.end());
     230              :   /// \endcode
     231              :   ///
     232              :   /// However, SetVector doesn't expose non-const iterators, making any
     233              :   /// algorithm like remove_if impossible to use.
     234              :   ///
     235              :   /// \returns true if any element is removed.
     236              :   template <typename UnaryPredicate>
     237              :   bool remove_if(UnaryPredicate P) {
     238              :     typename vector_type::iterator I = [this, P] {
     239              :       if constexpr (canBeSmall())
     240              :         if (isSmall())
     241              :           return llvm::remove_if(vector_, P);
     242              : 
     243              :       return llvm::remove_if(vector_,
     244              :                              TestAndEraseFromSet<UnaryPredicate>(P, set_));
     245              :     }();
     246              : 
     247              :     if (I == vector_.end())
     248              :       return false;
     249              :     vector_.erase(I, vector_.end());
     250              :     return true;
     251              :   }
     252              : 
     253              :   /// Check if the SetVector contains the given key.
     254              :   bool contains(const key_type &key) const {
     255              :     if constexpr (canBeSmall())
     256              :       if (isSmall())
     257              :         return is_contained(vector_, key);
     258              : 
     259              :     return set_.find(key) != set_.end();
     260              :   }
     261              : 
     262              :   /// Count the number of elements of a given key in the SetVector.
     263              :   /// \returns 0 if the element is not in the SetVector, 1 if it is.
     264              :   size_type count(const key_type &key) const {
     265              :     if constexpr (canBeSmall())
     266              :       if (isSmall())
     267              :         return is_contained(vector_, key);
     268              : 
     269              :     return set_.count(key);
     270              :   }
     271              : 
     272              :   /// Completely clear the SetVector
     273              :   void clear() {
     274              :     set_.clear();
     275              :     vector_.clear();
     276              :   }
     277              : 
     278              :   /// Remove the last element of the SetVector.
     279              :   void pop_back() {
     280              :     assert(!empty() && "Cannot remove an element from an empty SetVector!");
     281              :     set_.erase(back());
     282              :     vector_.pop_back();
     283              :   }
     284              : 
     285              :   [[nodiscard]] value_type pop_back_val() {
     286              :     value_type Ret = back();
     287              :     pop_back();
     288              :     return Ret;
     289              :   }
     290              : 
     291              :   bool operator==(const SetVector &that) const {
     292              :     return vector_ == that.vector_;
     293              :   }
     294              : 
     295              :   bool operator!=(const SetVector &that) const {
     296              :     return vector_ != that.vector_;
     297              :   }
     298              : 
     299              :   /// Compute This := This u S, return whether 'This' changed.
     300              :   /// TODO: We should be able to use set_union from SetOperations.h, but
     301              :   ///       SetVector interface is inconsistent with DenseSet.
     302              :   template <class STy>
     303              :   bool set_union(const STy &S) {
     304              :     bool Changed = false;
     305              : 
     306              :     for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE;
     307              :          ++SI)
     308              :       if (insert(*SI))
     309              :         Changed = true;
     310              : 
     311              :     return Changed;
     312              :   }
     313              : 
     314              :   /// Compute This := This - B
     315              :   /// TODO: We should be able to use set_subtract from SetOperations.h, but
     316              :   ///       SetVector interface is inconsistent with DenseSet.
     317              :   template <class STy>
     318              :   void set_subtract(const STy &S) {
     319              :     for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE;
     320              :          ++SI)
     321              :       remove(*SI);
     322              :   }
     323              : 
     324              :   void swap(SetVector<T, Vector, Set, N> &RHS) {
     325              :     set_.swap(RHS.set_);
     326              :     vector_.swap(RHS.vector_);
     327              :   }
     328              : 
     329              : private:
     330              :   /// A wrapper predicate designed for use with std::remove_if.
     331              :   ///
     332              :   /// This predicate wraps a predicate suitable for use with std::remove_if to
     333              :   /// call set_.erase(x) on each element which is slated for removal.
     334              :   template <typename UnaryPredicate>
     335              :   class TestAndEraseFromSet {
     336              :     UnaryPredicate P;
     337              :     set_type &set_;
     338              : 
     339              :   public:
     340              :     TestAndEraseFromSet(UnaryPredicate P, set_type &set_)
     341              :         : P(std::move(P)), set_(set_) {}
     342              : 
     343              :     template <typename ArgumentT>
     344              :     bool operator()(const ArgumentT &Arg) {
     345              :       if (P(Arg)) {
     346              :         set_.erase(Arg);
     347              :         return true;
     348              :       }
     349              :       return false;
     350              :     }
     351              :   };
     352              : 
     353              :   [[nodiscard]] static constexpr bool canBeSmall() { return N != 0; }
     354              : 
     355              :   [[nodiscard]] bool isSmall() const { return set_.empty(); }
     356              : 
     357              :   void makeBig() {
     358              :     if constexpr (canBeSmall())
     359              :       for (const auto &entry : vector_)
     360              :         set_.insert(entry);
     361              :   }
     362              : 
     363              :   set_type set_;         ///< The set.
     364              :   vector_type vector_;   ///< The vector.
     365              : };
     366              : 
     367              : /// A SetVector that performs no allocations if smaller than
     368              : /// a certain size.
     369              : template <typename T, unsigned N>
     370              : class SmallSetVector : public SetVector<T, SmallVector<T, N>, DenseSet<T>, N> {
     371              : public:
     372              :   SmallSetVector() = default;
     373              : 
     374              :   /// Initialize a SmallSetVector with a range of elements
     375              :   template<typename It>
     376              :   SmallSetVector(It Start, It End) {
     377              :     this->insert(Start, End);
     378              :   }
     379              : };
     380              : 
     381              : } // end namespace llvm
     382              : 
     383              : namespace std {
     384              : 
     385              : /// Implement std::swap in terms of SetVector swap.
     386              : template <typename T, typename V, typename S, unsigned N>
     387              : inline void swap(llvm::SetVector<T, V, S, N> &LHS,
     388              :                  llvm::SetVector<T, V, S, N> &RHS) {
     389              :   LHS.swap(RHS);
     390              : }
     391              : 
     392              : /// Implement std::swap in terms of SmallSetVector swap.
     393              : template<typename T, unsigned N>
     394              : inline void
     395              : swap(llvm::SmallSetVector<T, N> &LHS, llvm::SmallSetVector<T, N> &RHS) {
     396              :   LHS.swap(RHS);
     397              : }
     398              : 
     399              : } // end namespace std
     400              : 
     401              : #endif // LLVM_ADT_SETVECTOR_H
        

Generated by: LCOV version 2.0-1