]> 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 588dfda04fac5d1f6df1dea59fc316eeeb6255ba..ba20fe79f230639e82a2d1f1c334a06233e256a3 100644 (file)
@@ -21,8 +21,20 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef hash_map_h
 #define hash_map_h
 
+/* 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>
+        typename Traits /* = simple_hashmap_traits<default_hash_traits<Key>,
+                                                   Value> */>
 class GTY((user)) hash_map
 {
   typedef typename Traits::key_type Key;
@@ -151,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;
+      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;
 
-      e->m_value = v;
-      return existed;
+      return !ins;
     }
 
   /* if the passed in key is in the map return its value otherwise NULL.  */
@@ -168,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)
     {
@@ -177,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;
@@ -234,7 +253,8 @@ public:
     /* Can't use std::pair here, because GCC before 4.3 don't handle
        std::pair where template parameters are references well.
        See PR86739.  */
-    struct reference_pair {
+    class reference_pair {
+    public:
       const Key &first;
       Value &second;