Index: gcc/hash-traits.h
===================================================================
--- gcc/hash-traits.h	2015-06-16 10:12:56.580811647 +0100
+++ gcc/hash-traits.h	2015-06-16 10:12:56.576811695 +0100
@@ -190,4 +190,9 @@ struct ggc_ptr_hash : pointer_hash <T>,
 template <typename T>
 struct ggc_cache_ptr_hash : pointer_hash <T>, ggc_cache_remove <T *> {};
 
+template <typename T> struct default_hash_traits;
+
+template <typename T>
+struct default_hash_traits <T *> : ggc_ptr_hash <T> {};
+
 #endif
Index: gcc/hash-set.h
===================================================================
--- gcc/hash-set.h	2015-06-16 10:12:56.580811647 +0100
+++ gcc/hash-set.h	2015-06-16 10:12:56.572811743 +0100
@@ -21,162 +21,9 @@ Software Foundation; either version 3, o
 #ifndef hash_set_h
 #define hash_set_h
 
-/* implement default behavior for traits when types allow it.  */
-
-struct default_hashset_traits
-{
-  /* Hashes the passed in key.  */
-
-  template<typename T>
-  static hashval_t
-  hash (T *p)
-    {
-      return uintptr_t (p) >> 3;
-    }
-
-  template<typename T> static hashval_t hash(const T &v) { return v; }
-
-  /* Return true if the two keys passed as arguments are equal.  */
-
-  template<typename T>
-  static bool
-  equal (const T &a, const T &b)
-    {
-      return a == b;
-    }
-
-  /* Called to dispose of the key 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)
-    {
-      e = reinterpret_cast<void *> (1);
-    }
-
-  /* Mark the passed in entry as being empty.  */
-
-  template<typename T>
-  static void
-  mark_empty (T *&e)
-    {
-      e = NULL;
-    }
-
-  /* Return true if the passed in entry is marked as deleted.  */
-
-  template<typename T>
-  static bool
-  is_deleted (T *e)
-    {
-      return e == reinterpret_cast<void *> (1);
-    }
-
-  /* Return true if the passed in entry is marked as empty.  */
-
-  template<typename T> static bool is_empty (T *e) { return e == NULL; }
-
-  /* ggc walking routine, mark all objects refered to by this one.  */
-
-  template<typename T>
-  static void
-  ggc_mx (T &x)
-    {
-      extern void gt_ggc_mx (T &);
-      gt_ggc_mx (x);
-    }
-
-  /* pch walking routine, note all objects refered to by this element.  */
-
-  template<typename T>
-  static void
-  pch_nx (T &x)
-    {
-      extern void gt_pch_nx (T &);
-      gt_pch_nx (x);
-    }
-};
-
-template<typename Key, typename Traits = default_hashset_traits>
+template<typename Key, typename Traits = default_hash_traits<Key> >
 class hash_set
 {
-  struct hash_entry
-  {
-    Key m_key;
-
-    typedef hash_entry value_type;
-    typedef Key compare_type;
-
-    static hashval_t hash (const hash_entry &e)
-      {
-       	return Traits::hash (e.m_key);
-      }
-
-    static bool equal (const hash_entry &a, const Key &b)
-       	{
-	  return Traits::equal (a.m_key, b);
-       	}
-
-    static void remove (hash_entry &e) { Traits::remove (e.m_key); }
-
-    static void
-    mark_deleted (hash_entry &e)
-      {
-       	Traits::mark_deleted (e.m_key);
-      }
-
-    static bool is_deleted (const hash_entry &e)
-      {
-       	return Traits::is_deleted (e.m_key);
-      }
-
-    static void
-    mark_empty (hash_entry &e)
-      {
-	Traits::mark_empty (e.m_key);
-      }
-
-    static bool
-    is_empty (const hash_entry &e)
-      {
-	return Traits::is_empty (e.m_key);
-      }
-
-    static void ggc_mx (hash_entry &e)
-      {
-	Traits::ggc_mx (e.m_key);
-      }
-
-    static void pch_nx (hash_entry &e)
-      {
-	Traits::pch_nx (e.m_key);
-      }
-
-    static void pch_nx (hash_entry &e, gt_pointer_operator op, void *c)
-      {
-	pch_nx_helper (e.m_key, op, c);
-      }
-
-  private:
-    template<typename T>
-    static void
-      pch_nx_helper (T &x, gt_pointer_operator op, void *cookie)
-	{
-	  gt_pch_nx (&x, op, cookie);
-	}
-
-    template<typename T>
-      static void
-      pch_nx_helper (T *&x, gt_pointer_operator op, void *cookie)
-	{
-	  op (&x, cookie);
-	}
-  };
-
 public:
   explicit hash_set (size_t n = 13, bool ggc = false CXX_MEM_STAT_INFO)
     : m_table (n, ggc, true, HASH_SET_ORIGIN PASS_MEM_STAT) {}
@@ -196,11 +43,10 @@ template<typename Key, typename Traits =
 
   bool add (const Key &k)
     {
-      hash_entry *e = m_table.find_slot_with_hash (k, Traits::hash (k),
-						   INSERT);
-      bool existed = !hash_entry::is_empty (*e);
+      Key *e = m_table.find_slot_with_hash (k, Traits::hash (k), INSERT);
+      bool existed = !Traits::is_empty (*e);
       if (!existed)
-	e->m_key = k;
+	*e = k;
 
       return existed;
     }
@@ -209,8 +55,8 @@ template<typename Key, typename Traits =
 
   bool contains (const Key &k)
     {
-      hash_entry &e = m_table.find_with_hash (k, Traits::hash (k));
-      return !Traits::is_empty (e.m_key);
+      Key &e = m_table.find_with_hash (k, Traits::hash (k));
+      return !Traits::is_empty (e);
     }
 
   /* Call the call back on each pair of key and value with the passed in
@@ -219,9 +65,9 @@ template<typename Key, typename Traits =
   template<typename Arg, bool (*f)(const Key &, Arg)>
   void traverse (Arg a) const
     {
-      for (typename hash_table<hash_entry>::iterator iter = m_table.begin ();
+      for (typename hash_table<Traits>::iterator iter = m_table.begin ();
 	   iter != m_table.end (); ++iter)
-	f ((*iter).m_key, a);
+	f (*iter, a);
     }
 
   /* Return the number of elements in the set.  */
@@ -234,7 +80,7 @@ template<typename Key, typename Traits =
   template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *);
       template<typename T, typename U> friend void gt_pch_nx (hash_set<T, U> *, gt_pointer_operator, void *);
 
-  hash_table<hash_entry> m_table;
+  hash_table<Traits> m_table;
 };
 
 /* ggc marking routines.  */
Index: gcc/ipa-devirt.c
===================================================================
--- gcc/ipa-devirt.c	2015-06-16 10:12:56.580811647 +0100
+++ gcc/ipa-devirt.c	2015-06-16 10:12:56.576811695 +0100
@@ -164,8 +164,11 @@ typedef struct
   tree second;
 } type_pair;
 
-struct pair_traits : default_hashset_traits
+template <>
+struct default_hash_traits <type_pair> : typed_noop_remove <type_pair>
 {
+  typedef type_pair value_type;
+  typedef type_pair compare_type;
   static hashval_t
   hash (type_pair p)
   {
@@ -194,7 +197,7 @@ struct pair_traits : default_hashset_tra
 };
 
 static bool odr_types_equivalent_p (tree, tree, bool, bool *,
-				    hash_set<type_pair,pair_traits> *,
+				    hash_set<type_pair> *,
 				    location_t, location_t);
 
 static bool odr_violation_reported = false;
@@ -771,7 +774,7 @@ set_type_binfo (tree type, tree binfo)
 
 static bool
 odr_subtypes_equivalent_p (tree t1, tree t2,
-			   hash_set<type_pair,pair_traits> *visited,
+			   hash_set<type_pair> *visited,
 			   location_t loc1, location_t loc2)
 {
 
@@ -1337,7 +1340,7 @@ warn_types_mismatch (tree t1, tree t2, l
 
 static bool
 odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
-			hash_set<type_pair,pair_traits> *visited,
+			hash_set<type_pair> *visited,
 			location_t loc1, location_t loc2)
 {
   /* Check first for the obvious case of pointer identity.  */
@@ -1787,7 +1790,7 @@ odr_types_equivalent_p (tree t1, tree t2
 bool
 odr_types_equivalent_p (tree type1, tree type2)
 {
-  hash_set<type_pair,pair_traits> visited;
+  hash_set<type_pair> visited;
 
 #ifdef ENABLE_CHECKING
   gcc_assert (odr_or_derived_type_p (type1) && odr_or_derived_type_p (type2));
@@ -1867,7 +1870,7 @@ add_type_duplicate (odr_type val, tree t
   bool base_mismatch = false;
   unsigned int i;
   bool warned = false;
-  hash_set<type_pair,pair_traits> visited;
+  hash_set<type_pair> visited;
 
   gcc_assert (in_lto_p);
   vec_safe_push (val->types, type);
