LCOV - code coverage report
Current view: top level - /usr/lib/llvm-19/include/llvm/ADT - SetVector.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 0.0 % 7 0
Test Date: 2026-07-03 19:57:34 Functions: 0.0 % 3 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 8 0

             Branch data     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         [ #  # ]:           0 :   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         [ #  # ]:           0 :   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                 :           0 :   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         [ #  # ]:           0 :     bool result = set_.insert(X).second;
     175         [ #  # ]:           0 :     if (result)
     176                 :           0 :       vector_.push_back(X);
     177                 :           0 :     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