LCOV - code coverage report
Current view: top level - gcc - ordered-hash-map.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 58 58
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 53 53
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* A type-safe hash map that retains the insertion order of keys.
       2              :    Copyright (C) 2019-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : 
      21              : #ifndef GCC_ORDERED_HASH_MAP_H
      22              : #define GCC_ORDERED_HASH_MAP_H
      23              : 
      24              : /* Notes:
      25              :    - The keys must be PODs, since vec<> uses assignment to populate slots
      26              :      without properly initializing them.
      27              :    - doesn't have GTY support.
      28              :    - supports removal, but retains order of original insertion.
      29              :      (Removal might be better handled by using a doubly-linked list
      30              :      of nodes, holding the values).  */
      31              : 
      32              : template<typename KeyId, typename Value,
      33              :          typename Traits>
      34              : class ordered_hash_map
      35              : {
      36              :   typedef typename Traits::key_type Key;
      37              : 
      38              : public:
      39        21109 :   ordered_hash_map () {}
      40              : 
      41            4 :   ordered_hash_map (const ordered_hash_map &other)
      42            4 :   : m_map (other.m_map),
      43            8 :     m_keys (other.m_keys.length ()),
      44            4 :     m_key_index (other.m_key_index)
      45              :   {
      46              :      unsigned i;
      47              :      Key key;
      48            8 :      FOR_EACH_VEC_ELT (other.m_keys, i, key)
      49            4 :        m_keys.quick_push (key);
      50            4 :   }
      51              : 
      52              :   /* If key K isn't already in the map add key K with value V to the map, and
      53              :      return false.  Otherwise set the value of the entry for key K to be V and
      54              :      return true.  */
      55              : 
      56       205835 :   bool put (const Key &k, const Value &v)
      57              :   {
      58       205835 :     bool existed = m_map.put (k, v);
      59       205835 :     if (!existed)
      60              :       {
      61              :         bool key_present;
      62       205835 :         int &slot = m_key_index.get_or_insert (k, &key_present);
      63       205835 :         if (!key_present)
      64              :           {
      65       205831 :              slot = m_keys.length ();
      66       205831 :              m_keys.safe_push (k);
      67              :           }
      68              :       }
      69       205835 :     return existed;
      70              :   }
      71              : 
      72              :   /* If the passed in key is in the map return its value otherwise NULL.  */
      73              : 
      74      2648469 :   Value *get (const Key &k)
      75              :   {
      76      2287061 :     return m_map.get (k);
      77              :   }
      78              : 
      79              :   /* Return a reference to the value for the passed in key, creating the entry
      80              :     if it doesn't already exist.  If existed is not NULL then it is set to
      81              :     false if the key was not previously in the map, and true otherwise.  */
      82              : 
      83           16 :   Value &get_or_insert (const Key &k, bool *existed = NULL)
      84              :   {
      85              :     bool _existed;
      86           16 :     Value &ret = m_map.get_or_insert (k, &_existed);
      87              : 
      88           16 :     if (!_existed)
      89              :       {
      90              :         bool key_present;
      91            8 :         int &slot = m_key_index.get_or_insert (k, &key_present);
      92            8 :         if (!key_present)
      93              :           {
      94            8 :             slot = m_keys.length ();
      95            8 :             m_keys.safe_push (k);
      96              :           }
      97              :       }
      98              : 
      99           16 :     if (existed)
     100           16 :       *existed = _existed;
     101              : 
     102           16 :     return ret;
     103              :   }
     104              : 
     105              :   /* Removing a key removes it from the map, but retains the insertion
     106              :      order.  */
     107              : 
     108            8 :   void remove (const Key &k)
     109              :   {
     110            8 :      m_map.remove (k);
     111              :   }
     112              : 
     113          473 :   size_t elements () const { return m_map.elements (); }
     114              : 
     115          564 :   void empty () { m_map.empty(); }
     116              : 
     117              :   class iterator
     118              :   {
     119              :   public:
     120       102763 :     explicit iterator (const ordered_hash_map &map, unsigned idx) :
     121        18826 :       m_ordered_hash_map (map), m_idx (idx) {}
     122              : 
     123       150423 :     iterator &operator++ ()
     124              :     {
     125              :        /* Increment m_idx until we find a non-deleted element, or go beyond
     126              :           the end.  */
     127              :        while (1)
     128              :          {
     129       150441 :            ++m_idx;
     130       150441 :            if (valid_index_p ())
     131              :              break;
     132              :         }
     133       150423 :       return *this;
     134              :     }
     135              : 
     136              :     /* Can't use std::pair here, because GCC before 4.3 don't handle
     137              :        std::pair where template parameters are references well.
     138              :        See PR86739.  */
     139              :     struct reference_pair {
     140              :       const Key &first;
     141              :       Value &second;
     142              : 
     143       210967 :       reference_pair (const Key &key, Value &value)
     144              :       : first (key), second (value) {}
     145              : 
     146              :       template <typename K, typename V>
     147              :       operator std::pair<K, V> () const { return std::pair<K, V> (first, second); }
     148              :     };
     149              : 
     150       210967 :     reference_pair operator* ()
     151              :     {
     152       210967 :       const Key &k = m_ordered_hash_map.m_keys[m_idx];
     153              :       Value *slot
     154       210967 :         = const_cast<ordered_hash_map &> (m_ordered_hash_map).get (k);
     155       210967 :       gcc_assert (slot);
     156       210967 :       return reference_pair (k, *slot);
     157              :     }
     158              : 
     159              :     bool
     160       169249 :     operator != (const iterator &other) const
     161              :     {
     162       168963 :       return m_idx != other.m_idx;
     163              :     }
     164              : 
     165              :     /* Treat one-beyond-the-end as valid, for handling the "end" case.  */
     166              : 
     167       169553 :     bool valid_index_p () const
     168              :     {
     169       334091 :       if (m_idx > m_ordered_hash_map.m_keys.length ())
     170              :         return false;
     171       169553 :       if (m_idx == m_ordered_hash_map.m_keys.length ())
     172              :         return true;
     173       150441 :       const Key &k = m_ordered_hash_map.m_keys[m_idx];
     174              :       Value *slot
     175       150441 :         = const_cast<ordered_hash_map &> (m_ordered_hash_map).get (k);
     176       150441 :       return slot != NULL;
     177              :     }
     178              : 
     179              :     const ordered_hash_map &m_ordered_hash_map;
     180              :     unsigned m_idx;
     181              :   };
     182              : 
     183              :   /* Standard iterator retrieval methods.  */
     184              : 
     185        18826 :   iterator begin () const
     186              :   {
     187        18826 :     iterator i = iterator (*this, 0);
     188        19112 :     while (!i.valid_index_p () && i != end ())
     189          286 :       ++i;
     190        18826 :     return i;
     191              :   }
     192       162859 :   iterator end () const { return iterator (*this, m_keys.length ()); }
     193              : 
     194              : private:
     195              :   /* The assignment operator is not yet implemented; prevent erroneous
     196              :      usage of unsafe compiler-generated one.  */
     197              :   void operator= (const ordered_hash_map &);
     198              : 
     199              :   /* The underlying map.  */
     200              :   hash_map<KeyId, Value, Traits> m_map;
     201              : 
     202              :   /* The ordering of the keys.  */
     203              :   auto_vec<Key> m_keys;
     204              : 
     205              :   /* For each key that's ever been in the map, its index within m_keys.  */
     206              :   hash_map<KeyId, int> m_key_index;
     207              : };
     208              : 
     209              : /* Two-argument form.  */
     210              : 
     211              : template<typename Key, typename Value,
     212              :          typename Traits = simple_hashmap_traits<default_hash_traits<Key>,
     213              :                                                  Value> >
     214              : class ordered_hash_map;
     215              : 
     216              : #endif /* GCC_ORDERED_HASH_MAP_H */
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.