diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a32108f9d16..36a10f491fa 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -105,7 +105,7 @@ static GTY(()) vec<tree, va_gc> *mangling_aliases;
 /* hash traits for declarations.  Hashes single decls via
    DECL_ASSEMBLER_NAME_RAW.  */
 
-struct mangled_decl_hash : ggc_remove <tree>
+struct mangled_decl_hash : pointer_hash_mark <tree>, ggc_remove <tree>
 {
   typedef tree value_type; /* A DECL.  */
   typedef tree compare_type; /* An identifier.  */
@@ -119,18 +119,6 @@ struct mangled_decl_hash : ggc_remove <tree>
     tree name = DECL_ASSEMBLER_NAME_RAW (existing);
     return candidate == name;
   }
-
-  static inline void mark_empty (value_type &p) {p = NULL_TREE;}
-  static inline bool is_empty (value_type p) {return !p;}
-
-  static bool is_deleted (value_type e)
-  {
-    return e == reinterpret_cast <value_type> (1);
-  }
-  static void mark_deleted (value_type &e)
-  {
-    e = reinterpret_cast <value_type> (1);
-  }
 };
 
 /* A hash table of decls keyed by mangled name.  Used to figure out if
diff --git a/gcc/hash-traits.h b/gcc/hash-traits.h
index 2d17e2c982a..e5c9e88d99f 100644
--- a/gcc/hash-traits.h
+++ b/gcc/hash-traits.h
@@ -136,12 +136,52 @@ int_hash <Type, Empty, Deleted>::is_empty (Type x)
   return x == Empty;
 }
 
+/* Base class for pointer hashers that want to implement marking in a generic
+   way.  */
+
+template <typename Pointer>
+struct pointer_hash_mark
+{
+  static inline void mark_deleted (Pointer &);
+  static inline void mark_empty (Pointer &);
+  static inline bool is_deleted (Pointer);
+  static inline bool is_empty (Pointer);
+};
+
+template <typename Pointer>
+inline void
+pointer_hash_mark <Pointer>::mark_deleted (Pointer &e)
+{
+  e = reinterpret_cast<Pointer> (1);
+}
+
+template <typename Pointer>
+inline void
+pointer_hash_mark <Pointer>::mark_empty (Pointer &e)
+{
+  e = NULL;
+}
+
+template <typename Pointer>
+inline bool
+pointer_hash_mark <Pointer>::is_deleted (Pointer e)
+{
+  return e == reinterpret_cast<Pointer> (1);
+}
+
+template <typename Pointer>
+inline bool
+pointer_hash_mark <Pointer>::is_empty (Pointer e)
+{
+  return e == NULL;
+}
+
 /* Pointer hasher based on pointer equality.  Other types of pointer hash
    can inherit this and override the hash and equal functions with some
    other form of equality (such as string equality).  */
 
 template <typename Type>
-struct pointer_hash
+struct pointer_hash : pointer_hash_mark<Type *>
 {
   typedef Type *value_type;
   typedef Type *compare_type;
@@ -149,10 +189,6 @@ struct pointer_hash
   static inline hashval_t hash (const value_type &);
   static inline bool equal (const value_type &existing,
 			    const compare_type &candidate);
-  static inline void mark_deleted (Type *&);
-  static inline void mark_empty (Type *&);
-  static inline bool is_deleted (Type *);
-  static inline bool is_empty (Type *);
 };
 
 template <typename Type>
@@ -172,34 +208,6 @@ pointer_hash <Type>::equal (const value_type &existing,
   return existing == candidate;
 }
 
-template <typename Type>
-inline void
-pointer_hash <Type>::mark_deleted (Type *&e)
-{
-  e = reinterpret_cast<Type *> (1);
-}
-
-template <typename Type>
-inline void
-pointer_hash <Type>::mark_empty (Type *&e)
-{
-  e = NULL;
-}
-
-template <typename Type>
-inline bool
-pointer_hash <Type>::is_deleted (Type *e)
-{
-  return e == reinterpret_cast<Type *> (1);
-}
-
-template <typename Type>
-inline bool
-pointer_hash <Type>::is_empty (Type *e)
-{
-  return e == NULL;
-}
-
 /* Hasher for "const char *" strings, using string rather than pointer
    equality.  */
 
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 1a0e12e6c0c..6fde7500cf4 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -64,7 +64,8 @@ ipa_edge_args_sum_t *ipa_edge_args_sum;
 
 /* Traits for a hash table for reusing already existing ipa_bits. */
 
-struct ipa_bit_ggc_hash_traits : public ggc_cache_remove <ipa_bits *>
+struct ipa_bit_ggc_hash_traits : pointer_hash_mark <ipa_bits *>,
+                                 ggc_cache_remove <ipa_bits *>
 {
   typedef ipa_bits *value_type;
   typedef ipa_bits *compare_type;
@@ -79,26 +80,6 @@ struct ipa_bit_ggc_hash_traits : public ggc_cache_remove <ipa_bits *>
     {
       return a->value == b->value && a->mask == b->mask;
     }
-  static void
-  mark_empty (ipa_bits *&p)
-    {
-      p = NULL;
-    }
-  static bool
-  is_empty (const ipa_bits *p)
-    {
-      return p == NULL;
-    }
-  static bool
-  is_deleted (const ipa_bits *p)
-    {
-      return p == reinterpret_cast<const ipa_bits *> (1);
-    }
-  static void
-  mark_deleted (ipa_bits *&p)
-    {
-      p = reinterpret_cast<ipa_bits *> (1);
-    }
 };
 
 /* Hash table for avoid repeated allocations of equal ipa_bits.  */
@@ -107,7 +88,9 @@ static GTY ((cache)) hash_table<ipa_bit_ggc_hash_traits> *ipa_bits_hash_table;
 /* Traits for a hash table for reusing value_ranges used for IPA.  Note that
    the equiv bitmap is not hashed and is expected to be NULL.  */
 
-struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <value_range_base *>
+struct ipa_vr_ggc_hash_traits : pointer_hash_mark <value_range_base *>,
+                                ggc_cache_remove <value_range_base *>
+
 {
   typedef value_range_base *value_type;
   typedef value_range_base *compare_type;
@@ -124,26 +107,6 @@ struct ipa_vr_ggc_hash_traits : public ggc_cache_remove <value_range_base *>
     {
       return a->equal_p (*b);
     }
-  static void
-  mark_empty (value_range_base *&p)
-    {
-      p = NULL;
-    }
-  static bool
-  is_empty (const value_range_base *p)
-    {
-      return p == NULL;
-    }
-  static bool
-  is_deleted (const value_range_base *p)
-    {
-      return p == reinterpret_cast<const value_range_base *> (1);
-    }
-  static void
-  mark_deleted (value_range_base *&p)
-    {
-      p = reinterpret_cast<value_range_base *> (1);
-    }
 };
 
 /* Hash table for avoid repeated allocations of equal value_ranges.  */
