]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/hash-map.h
[C++] Protect call to copy_attributes_to_builtin (PR91505)
[thirdparty/gcc.git] / gcc / hash-map.h
index d2eed337ad4530ed9484cba927f80a955b5f8afd..ba20fe79f230639e82a2d1f1c334a06233e256a3 100644 (file)
@@ -1,5 +1,5 @@
 /* A type-safe hash map.
-   Copyright (C) 2014 Free Software Foundation, Inc.
+   Copyright (C) 2014-2019 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,90 +21,23 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef hash_map_h
 #define hash_map_h
 
-#include "hash-table.h"
-
-/* implement default behavior for traits when types allow it.  */
-
-struct default_hashmap_traits
-{
-  /* Hashes the passed in key.  */
-
-  template<typename T>
-  static hashval_t
-  hash (T *p)
-    {
-      return uintptr_t(p) >> 3;
-    }
-
-  /* If the value converts to hashval_t just use it.  */
-
-  template<typename T> static hashval_t hash (T v) { return v; }
-
-  /* Return true if the two keys passed as arguments are equal.  */
-
-  template<typename T>
-  static bool
-  equal_keys (const T &a, const T &b)
-    {
-      return a == b;
-    }
-
-  /* Called to dispose of the key and value before marking the entry as
-     deleted.  */
-
-  template<typename T> static void remove (T &v) { v.~T (); }
-
-  /* Mark the passed in entry as being deleted.  */
-
-  template<typename T>
-  static void
-  mark_deleted (T &e)
-    {
-      mark_key_deleted (e.m_key);
-    }
-
-  /* Mark the passed in entry as being empty.  */
-
-  template<typename T>
-  static void
-  mark_empty (T &e)
-    {
-      mark_key_empty (e.m_key);
-    }
-
-  /* Return true if the passed in entry is marked as deleted.  */
-
-  template<typename T>
-  static bool
-  is_deleted (T &e)
-    {
-      return e.m_key == (void *)1;
-    }
-
-  /* Return true if the passed in entry is marked as empty.  */
-
-  template<typename T> static bool is_empty (T &e) { return e.m_key == NULL; }
-
-private:
-  template<typename T>
-  static void
-  mark_key_deleted (T *&k)
-    {
-      k = reinterpret_cast<T *> (1);
-    }
-
-  template<typename T>
-  static void
-  mark_key_empty (T *&k)
-    {
-      k = static_cast<T *> (0);
-    }
-};
-
-template<typename Key, typename Value,
-        typename Traits = default_hashmap_traits>
-class hash_map
+/* Class hash_map is a hash-value based container mapping objects of
+   KeyId type to those of the Value type.
+   Both KeyId and Value may be non-trivial (non-POD) types provided
+   a suitabe Traits class.  A few default Traits specializations are
+   provided for basic types such as integers, pointers, and std::pair.
+   Inserted elements are value-initialized either to zero for POD types
+   or by invoking their default ctor.  Removed elements are destroyed
+   by invoking their dtor.   On hash_map destruction all elements are
+   removed.  Objects of hash_map type are copy-constructible but not
+   assignable.  */
+
+template<typename KeyId, typename Value,
+        typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>,
+                                                   Value> */>
+class GTY((user)) hash_map
 {
+  typedef typename Traits::key_type Key;
   struct hash_entry
   {
     Key m_key;
@@ -112,7 +45,6 @@ class hash_map
 
     typedef hash_entry value_type;
     typedef Key compare_type;
-    typedef int store_values_directly;
 
     static hashval_t hash (const hash_entry &e)
       {
@@ -135,10 +67,93 @@ class hash_map
 
     static void mark_empty (hash_entry &e) { Traits::mark_empty (e); }
     static bool is_empty (const hash_entry &e) { return Traits::is_empty (e); }
+
+    static void ggc_mx (hash_entry &e)
+      {
+       gt_ggc_mx (e.m_key);
+       gt_ggc_mx (e.m_value);
+      }
+
+    static void ggc_maybe_mx (hash_entry &e)
+      {
+       if (Traits::maybe_mx)
+         ggc_mx (e);
+      }
+
+    static void pch_nx (hash_entry &e)
+      {
+       gt_pch_nx (e.m_key);
+       gt_pch_nx (e.m_value);
+      }
+
+    static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
+      {
+       pch_nx_helper (e.m_key, op, c);
+       pch_nx_helper (e.m_value, op, c);
+      }
+
+    static int keep_cache_entry (hash_entry &e)
+      {
+       return ggc_marked_p (e.m_key);
+      }
+
+  private:
+    template<typename T>
+    static void
+      pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
+       {
+         gt_pch_nx (&x, op, cookie);
+       }
+
+    static void
+      pch_nx_helper (int, gt_pointer_operator, void *)
+       {
+       }
+
+    static void
+      pch_nx_helper (unsigned int, gt_pointer_operator, void *)
+       {
+       }
+
+    static void
+      pch_nx_helper (bool, gt_pointer_operator, void *)
+       {
+       }
+
+    template<typename T>
+      static void
+      pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
+       {
+         op (&x, cookie);
+       }
   };
 
 public:
-  explicit hash_map (size_t n = 13) : m_table (n) {}
+  explicit hash_map (size_t n = 13, bool ggc = false,
+                    bool sanitize_eq_and_hash = true,
+                    bool gather_mem_stats = GATHER_STATISTICS
+                    CXX_MEM_STAT_INFO)
+    : m_table (n, ggc, sanitize_eq_and_hash, gather_mem_stats,
+              HASH_MAP_ORIGIN PASS_MEM_STAT)
+  {
+  }
+
+  explicit hash_map (const hash_map &h, bool ggc = false,
+                    bool sanitize_eq_and_hash = true,
+                    bool gather_mem_stats = GATHER_STATISTICS
+                    CXX_MEM_STAT_INFO)
+    : m_table (h.m_table, ggc, sanitize_eq_and_hash, gather_mem_stats,
+              HASH_MAP_ORIGIN PASS_MEM_STAT) {}
+
+  /* Create a hash_map in ggc memory.  */
+  static hash_map *create_ggc (size_t size,
+                              bool gather_mem_stats = GATHER_STATISTICS
+                              CXX_MEM_STAT_INFO)
+    {
+      hash_map *map = ggc_alloc<hash_map> ();
+      new (map) hash_map (size, true, true, gather_mem_stats PASS_MEM_STAT);
+      return map;
+    }
 
   /* If key k isn't already in the map add key k with value v to the map, and
      return false.  Otherwise set the value of the entry for key k to be v and
@@ -148,12 +163,16 @@ public:
     {
       hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
                                                   INSERT);
-      bool existed = !hash_entry::is_empty (*e);
-      if (!existed)
-       e->m_key = k;
-
-      e->m_value = v;
-      return existed;
+      bool ins = hash_entry::is_empty (*e);
+      if (ins)
+       {
+         e->m_key = k;
+         new ((void *) &e->m_value) Value (v);
+       }
+      else
+       e->m_value = v;
+
+      return !ins;
     }
 
   /* if the passed in key is in the map return its value otherwise NULL.  */
@@ -165,8 +184,8 @@ public:
     }
 
   /* Return a reference to the value for the passed in key, creating the entry
-     if it doesn't already exist.  If existed is not NULL then it is set to false
-     if the key was not previously in the map, and true otherwise.  */
+     if it doesn't already exist.  If existed is not NULL then it is set to
+     false if the key was not previously in the map, and true otherwise.  */
 
   Value &get_or_insert (const Key &k, bool *existed = NULL)
     {
@@ -174,7 +193,10 @@ public:
                                                   INSERT);
       bool ins = Traits::is_empty (*e);
       if (ins)
-       e->m_key = k;
+       {
+         e->m_key = k;
+         new ((void *)&e->m_value) Value ();
+       }
 
       if (existed != NULL)
        *existed = !ins;
@@ -190,7 +212,8 @@ public:
   /* Call the call back on each pair of key and value with the passed in
      arg.  */
 
-  template<typename Arg, bool (*f)(const Key &, const Value &, Arg)>
+  template<typename Arg, bool (*f)(const typename Traits::key_type &,
+                                  const Value &, Arg)>
   void traverse (Arg a) const
     {
       for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
@@ -198,7 +221,8 @@ public:
        f ((*iter).m_key, (*iter).m_value, a);
     }
 
-  template<typename Arg, bool (*f)(const Key &, Value *, Arg)>
+  template<typename Arg, bool (*f)(const typename Traits::key_type &,
+                                  Value *, Arg)>
   void traverse (Arg a) const
     {
       for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
@@ -207,8 +231,99 @@ public:
          break;
     }
 
+  size_t elements () const { return m_table.elements (); }
+
+  void empty () { m_table.empty(); }
+
+  /* Return true when there are no elements in this hash map.  */
+  bool is_empty () const { return m_table.is_empty (); }
+
+  class iterator
+  {
+  public:
+    explicit iterator (const typename hash_table<hash_entry>::iterator &iter) :
+      m_iter (iter) {}
+
+    iterator &operator++ ()
+    {
+      ++m_iter;
+      return *this;
+    }
+
+    /* Can't use std::pair here, because GCC before 4.3 don't handle
+       std::pair where template parameters are references well.
+       See PR86739.  */
+    class reference_pair {
+    public:
+      const Key &first;
+      Value &second;
+
+      reference_pair (const Key &key, Value &value) : first (key), second (value) {}
+
+      template <typename K, typename V>
+      operator std::pair<K, V> () const { return std::pair<K, V> (first, second); }
+    };
+
+    reference_pair operator* ()
+    {
+      hash_entry &e = *m_iter;
+      return reference_pair (e.m_key, e.m_value);
+    }
+
+    bool
+    operator != (const iterator &other) const
+    {
+      return m_iter != other.m_iter;
+    }
+
+  private:
+    typename hash_table<hash_entry>::iterator m_iter;
+  };
+
+  /* Standard iterator retrieval methods.  */
+
+  iterator  begin () const { return iterator (m_table.begin ()); }
+  iterator end () const { return iterator (m_table.end ()); }
+
 private:
+
+  template<typename T, typename U, typename V> friend void gt_ggc_mx (hash_map<T, U, V> *);
+  template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *);
+  template<typename T, typename U, typename V> friend void gt_pch_nx (hash_map<T, U, V> *, gt_pointer_operator, void *);
+  template<typename T, typename U, typename V> friend void gt_cleare_cache (hash_map<T, U, V> *);
+
   hash_table<hash_entry> m_table;
 };
 
+/* ggc marking routines.  */
+
+template<typename K, typename V, typename H>
+static inline void
+gt_ggc_mx (hash_map<K, V, H> *h)
+{
+  gt_ggc_mx (&h->m_table);
+}
+
+template<typename K, typename V, typename H>
+static inline void
+gt_pch_nx (hash_map<K, V, H> *h)
+{
+  gt_pch_nx (&h->m_table);
+}
+
+template<typename K, typename V, typename H>
+static inline void
+gt_cleare_cache (hash_map<K, V, H> *h)
+{
+  if (h)
+    gt_cleare_cache (&h->m_table);
+}
+
+template<typename K, typename V, typename H>
+static inline void
+gt_pch_nx (hash_map<K, V, H> *h, gt_pointer_operator op, void *cookie)
+{
+  op (&h->m_table.m_entries, cookie);
+}
+
 #endif