diff --git a/gcc/cp/pph-in.c b/gcc/cp/pph-in.c
index 088c1a2..ce6aeae 100644
--- a/gcc/cp/pph-in.c
+++ b/gcc/cp/pph-in.c
@@ -998,6 +998,9 @@ pph_in_cxx_binding_1 (pph_stream *stream)
     return (cxx_binding *) pph_cache_find (stream, marker, image_ix, ix,
 					   PPH_cxx_binding);
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   value = pph_in_tree (stream);
   type = pph_in_tree (stream);
   ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cxx_binding, cb,
@@ -1048,6 +1051,9 @@ pph_in_class_binding (pph_stream *stream)
     return (cp_class_binding *) pph_cache_find (stream, marker, image_ix, ix,
 						PPH_cp_class_binding);
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_class_binding, cb,
                       ggc_alloc_cleared_cp_class_binding ());
   cb->base = pph_in_cxx_binding (stream);
@@ -1073,6 +1079,9 @@ pph_in_label_binding (pph_stream *stream)
     return (cp_label_binding *) pph_cache_find (stream, marker, image_ix, ix,
 						PPH_cp_label_binding);
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_label_binding, lb,
                       ggc_alloc_cleared_cp_label_binding ());
   lb->label = pph_in_tree (stream);
@@ -1178,7 +1187,7 @@ pph_in_binding_level (pph_stream *stream)
 /* Read all the merge keys from STREAM into the cp_binding_level BL.  */
 
 static void
-pph_in_binding_merge_keys (pph_stream *stream, cp_binding_level *bl)
+pph_in_merge_key_binding_level (pph_stream *stream, cp_binding_level *bl)
 {
   /* Read all the merge keys and merge into the bindings.  */
   pph_in_merge_key_chain (stream, &bl->names);
@@ -1191,7 +1200,7 @@ pph_in_binding_merge_keys (pph_stream *stream, cp_binding_level *bl)
 /* Read all the merge bodies from STREAM into the cp_binding_level BL.  */
 
 static void
-pph_in_binding_merge_bodies_1 (pph_stream *stream, cp_binding_level *bl)
+pph_in_merge_body_binding_level_1 (pph_stream *stream, cp_binding_level *bl)
 {
   pph_in_merge_body_chain (stream);
   pph_in_merge_body_chain (stream);
@@ -1206,7 +1215,7 @@ pph_in_binding_merge_bodies_1 (pph_stream *stream, cp_binding_level *bl)
 /* Read all the merge bodies from STREAM into the cp_binding_level BL.  */
 
 static void
-pph_in_binding_merge_bodies (pph_stream *stream, cp_binding_level *bl)
+pph_in_merge_body_binding_level (pph_stream *stream, cp_binding_level *bl)
 {
   unsigned ix;
   cp_binding_level *new_bl;
@@ -1219,7 +1228,7 @@ pph_in_binding_merge_bodies (pph_stream *stream, cp_binding_level *bl)
 
   /* The binding level is already allocated.  */
   pph_cache_insert_at (&stream->cache, bl, ix, PPH_cp_binding_level);
-  pph_in_binding_merge_bodies_1 (stream, bl);
+  pph_in_merge_body_binding_level_1 (stream, bl);
 }
 
 
@@ -1244,6 +1253,9 @@ pph_in_language_function (pph_stream *stream)
 							image_ix, ix,
 							PPH_language_function);
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   ALLOC_AND_REGISTER (&stream->cache, ix, PPH_language_function, lf,
                       ggc_alloc_cleared_language_function ());
   lf->base.x_stmt_tree.x_cur_stmt_list = pph_in_tree_vec (stream);
@@ -1297,6 +1309,9 @@ pph_in_struct_function (pph_stream *stream, tree decl)
       return;
     }
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   /* Possibly allocate a new DECL_STRUCT_FUNCTION for DECL.  */
   t = pph_in_tree (stream);
   gcc_assert (t == decl);
@@ -1493,7 +1508,7 @@ pph_in_ld_ns (pph_stream *stream, struct lang_decl_ns *ldns)
   if (ldns->level == NULL)
     ldns->level = pph_in_binding_level (stream);
   else
-    pph_in_binding_merge_bodies (stream, ldns->level);
+    pph_in_merge_body_binding_level (stream, ldns->level);
 }
 
 
@@ -1512,7 +1527,7 @@ pph_in_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
    Otherwise, return the pointer to the lang decl specific.  */
 
 static struct lang_decl *
-pph_in_ref_lang_specific (pph_stream *stream, tree decl)
+pph_in_ref_lang_decl (pph_stream *stream, tree decl)
 {
   struct lang_decl *ld;
   enum pph_record_marker marker;
@@ -1529,6 +1544,9 @@ pph_in_ref_lang_specific (pph_stream *stream, tree decl)
       return NULL;
     }
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   /* Allocate a lang_decl structure for DECL, if not already present.
      Namespace merge keys preallocate it.  */
   ld = DECL_LANG_SPECIFIC (decl);
@@ -1548,12 +1566,12 @@ pph_in_ref_lang_specific (pph_stream *stream, tree decl)
 /* Read language specific data in DECL from STREAM.  */
 
 static void
-pph_in_lang_specific (pph_stream *stream, tree decl)
+pph_in_lang_decl (pph_stream *stream, tree decl)
 {
   struct lang_decl *ld;
   struct lang_decl_base *ldb;
 
-  ld = pph_in_ref_lang_specific (stream, decl);
+  ld = pph_in_ref_lang_decl (stream, decl);
   if (!ld)
     return;
 
@@ -1589,12 +1607,12 @@ pph_in_lang_specific (pph_stream *stream, tree decl)
 /* Read and merge language specific data in DECL from STREAM.  */
 
 static void
-pph_in_merge_lang_specific (pph_stream *stream, tree decl)
+pph_in_merge_lang_decl (pph_stream *stream, tree decl)
 {
   struct lang_decl *ld;
   struct lang_decl_base *ldb;
 
-  ld = pph_in_ref_lang_specific (stream, decl);
+  ld = pph_in_ref_lang_decl (stream, decl);
   if (!ld)
     return;
 
@@ -1676,6 +1694,9 @@ pph_in_sorted_fields_type (pph_stream *stream)
     return (struct sorted_fields_type *)
 	  pph_cache_find (stream, marker, image_ix, ix, PPH_sorted_fields_type);
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   num_fields = pph_in_uint (stream);
   ALLOC_AND_REGISTER (&stream->cache, ix, PPH_sorted_fields_type, v,
                       sorted_fields_type_new (num_fields));
@@ -1759,6 +1780,11 @@ pph_in_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
     ltc->nested_udts = (binding_table) pph_cache_find (stream, marker,
 						       image_ix, ix,
 						       PPH_binding_table);
+  else
+    {
+      /* Remove if we start emitting merge keys for this structure.  */
+      gcc_assert (marker == PPH_RECORD_END);
+    }
 
   ltc->as_base = pph_in_tree (stream);
   ltc->pure_virtuals = pph_in_tree_vec (stream);
@@ -1800,6 +1826,9 @@ pph_in_lang_type (pph_stream *stream)
     return (struct lang_type *) pph_cache_find (stream, marker, image_ix, ix,
 						PPH_lang_type);
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   ALLOC_AND_REGISTER (&stream->cache, ix, PPH_lang_type, lt,
                       ggc_alloc_cleared_lang_type (sizeof (struct lang_type)));
 
@@ -1913,7 +1942,7 @@ pph_in_tcc_declaration_tail (pph_stream *stream, tree decl)
 static void
 pph_in_tcc_declaration (pph_stream *stream, tree decl)
 {
-  pph_in_lang_specific (stream, decl);
+  pph_in_lang_decl (stream, decl);
   pph_in_tcc_declaration_tail (stream, decl);
 }
 
@@ -1923,7 +1952,7 @@ pph_in_tcc_declaration (pph_stream *stream, tree decl)
 static void
 pph_in_merge_tcc_declaration (pph_stream *stream, tree decl)
 {
-  pph_in_merge_lang_specific (stream, decl);
+  pph_in_merge_lang_decl (stream, decl);
   /* FIXME pph: Some of the tail may not be necessary.  */
   pph_in_tcc_declaration_tail (stream, decl);
 }
@@ -2263,7 +2292,7 @@ pph_in_merge_key_namespace_decl (pph_stream *stream, tree decl)
 	  NAMESPACE_LEVEL (decl) = bl;
 	}
 
-      pph_in_binding_merge_keys (stream, bl);
+      pph_in_merge_key_binding_level (stream, bl);
     }
 }
 
@@ -2795,8 +2824,8 @@ pph_in_global_binding (pph_stream *stream)
      context.  Since we have registered scope_chain->bindings in the
      same slot IX that the writer used, the trees read now will be
      bound to scope_chain->bindings.  */
-  pph_in_binding_merge_keys (stream, bl);
-  pph_in_binding_merge_bodies_1 (stream, bl);
+  pph_in_merge_key_binding_level (stream, bl);
+  pph_in_merge_body_binding_level_1 (stream, bl);
 }
 
 
diff --git a/gcc/cp/pph-out.c b/gcc/cp/pph-out.c
index e1e21b9..acba5e0 100644
--- a/gcc/cp/pph-out.c
+++ b/gcc/cp/pph-out.c
@@ -549,18 +549,27 @@ pph_out_reference_record (pph_stream *stream, enum pph_record_marker marker,
 
 
 /* Start a new record in STREAM for DATA with data type TAG.  If DATA
-   is NULL write an end-of-record marker and return true.
+   is NULL write an end-of-record marker.
 
    If DATA is not NULL and did not exist in the pickle cache, add it,
    write a start-of-record marker and return true.  This means that we
    could not write a reference marker to DATA and the caller should
    pickle out DATA's physical representation.
 
-   If DATA existed in the cache, write a reference-record marker and
-   return true.  This means that we could write a reference marker to
-   DATA.  */
+   If DATA existed in the cache, one of two things may happen:
 
-static inline bool
+   - If a merge key had been emitted for DATA, it means that DATA has
+     only been partially written.  The rest of it needs to be emitted
+     now.  In these cases, a PPH_RECORD_START_MERGE_BODY marker is
+     written.
+
+   - If DATA had been written before, we do only need to write a
+     reference to it.  In this case, a reference-record marker is
+     written.
+
+   The emitted marker is returned.  */
+
+static inline enum pph_record_marker
 pph_out_start_record (pph_stream *stream, void *data, enum pph_tag tag)
 {
   unsigned include_ix, ix;
@@ -568,20 +577,48 @@ pph_out_start_record (pph_stream *stream, void *data, enum pph_tag tag)
 
   /* Try to write a reference record first.  */
   marker = pph_get_marker_for (stream, data, &include_ix, &ix, tag);
-  if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
+  if (marker == PPH_RECORD_END)
     {
       pph_out_reference_record (stream, marker, include_ix, ix, tag);
-      return true;
+      return marker;
+    }
+  else if (pph_is_reference_marker (marker))
+    {
+      /* If we have already emitted DATA, check whether we need
+	 to write DATA's body.  This happens when DATA is written in
+	 two parts so it can be merged across PPH files.  The first
+	 part is the merge key, which only writes enough data to
+	 identify DATA so it can b merged, the second part consists
+	 of all the remaining fields in DATA (the merge body).  */
+      pph_cache *cache = pph_cache_select (stream, marker, include_ix);
+      pph_cache_entry *e = pph_cache_get_entry (cache, ix);
+      if (e->needs_merge_body)
+	{
+	  marker = PPH_RECORD_START_MERGE_BODY;
+	  e->needs_merge_body = false;
+	}
+      else
+	{
+	  /* This is a regular reference, emit it and tell the caller
+	     that we are done.  */
+	  pph_out_reference_record (stream, marker, include_ix, ix, tag);
+	  return marker;
+	}
+    }
+  else if (marker == PPH_RECORD_START)
+    {
+      /* DATA is in none of the pickle caches.  Add DATA to STREAM's
+	 pickle cache and write the slot where we stored it in.  */
+      pph_cache_add (&stream->cache, data, &ix, tag);
     }
 
-  /* DATA is in none of the pickle caches.  Add DATA to STREAM's
-     pickle cache and write the slot where we stored it in.  */
-  pph_cache_add (&stream->cache, data, &ix, tag);
-  pph_out_record_marker (stream, PPH_RECORD_START, tag);
+  /* The caller will have to write a physical representation for DATA.  */
+  gcc_assert (marker == PPH_RECORD_START
+	      || marker == PPH_RECORD_START_MERGE_BODY);
+  pph_out_record_marker (stream, marker, tag);
   pph_out_uint (stream, ix);
 
-  /* The caller will have to write a physical representation for DATA.  */
-  return false;
+  return marker;
 }
 
 
@@ -631,9 +668,8 @@ pph_cache_should_handle (tree t)
 
 /* Start a record for tree node T in STREAM.  This is like
    pph_out_start_record, but it filters certain special trees that
-   should never be added to the cache.  Additionally, instead of
-   returning a boolean value indicating whether pickling should be
-   done, it returns the actual marker used to start the record.  */
+   should never be added to the cache.  Return the marker used
+   to start the record.  */
 
 static inline enum pph_record_marker
 pph_out_start_tree_record (pph_stream *stream, tree t)
@@ -733,36 +769,52 @@ pph_out_start_tree_record (pph_stream *stream, tree t)
 }
 
 
-/* Start a merge key record for EXPR on STREAM.  */
+/* Start a merge key record for DATA on STREAM.  TAG identifies the
+   data type of DATA.  Return true if a merge key for DATA had already
+   been emitted.  */
 
 static bool
-pph_out_start_merge_key_record (pph_stream *stream, tree expr)
+pph_out_start_merge_key_record (pph_stream *stream, void *data,
+				enum pph_tag tag)
 {
-  enum pph_tag tag;
   enum pph_record_marker marker;
   pph_cache_entry *e;
   unsigned include_ix, ix;
 
-  tag = pph_tree_code_to_tag (expr);
-  marker = pph_get_marker_for (stream, expr, &include_ix, &ix, tag);
-
+  marker = pph_get_marker_for (stream, data, &include_ix, &ix, tag);
   if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
     {
+      /* We had already emitted a merge key for DATA, write a
+	 reference and return true.  */
       pph_out_reference_record (stream, marker, include_ix, ix, tag);
       return true;
     }
 
-  /* This should be the first time that we try to write EXPR.  */
+  /* This should be the first time that we try to write DATA.  */
   gcc_assert (marker == PPH_RECORD_START);
 
   pph_out_record_marker (stream, PPH_RECORD_START_MERGE_KEY, tag);
-  e = pph_cache_add (&stream->cache, expr, &ix, tag);
+  e = pph_cache_add (&stream->cache, data, &ix, tag);
   e->needs_merge_body = true;
   pph_out_uint (stream, ix);
+
+  /* Tell the caller that this is the first time this merge key is
+     emitted.  */
   return false;
 }
 
 
+/* Start a merge key record for EXPR on STREAM.  Return true if a
+   merge key for EXPR had already been emitted.  */
+
+static bool
+pph_out_start_merge_key_tree_record (pph_stream *stream, tree expr)
+{
+  enum pph_tag tag = pph_tree_code_to_tag (expr);
+  return pph_out_start_merge_key_record (stream, expr, tag);
+}
+
+
 
 /********************************************************** lexical elements */
 
@@ -1156,10 +1208,15 @@ static void
 pph_out_cxx_binding_1 (pph_stream *stream, cxx_binding *cb)
 {
   struct bitpack_d bp;
+  enum pph_record_marker marker;
 
-  if (pph_out_start_record (stream, cb, PPH_cxx_binding))
+  marker = pph_out_start_record (stream, cb, PPH_cxx_binding);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   pph_out_tree (stream, cb->value);
   pph_out_tree (stream, cb->type);
   pph_out_binding_level (stream, cb->scope, PPHF_NONE);
@@ -1195,9 +1252,15 @@ pph_out_cxx_binding (pph_stream *stream, cxx_binding *cb)
 static void
 pph_out_class_binding (pph_stream *stream, cp_class_binding *cb)
 {
-  if (pph_out_start_record (stream, cb, PPH_cp_class_binding))
+  enum pph_record_marker marker;
+
+  marker = pph_out_start_record (stream, cb, PPH_cp_class_binding);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   pph_out_cxx_binding (stream, cb->base);
   pph_out_tree (stream, cb->identifier);
 }
@@ -1208,9 +1271,15 @@ pph_out_class_binding (pph_stream *stream, cp_class_binding *cb)
 static void
 pph_out_label_binding (pph_stream *stream, cp_label_binding *lb)
 {
-  if (pph_out_start_record (stream, lb, PPH_cp_label_binding))
+  enum pph_record_marker marker;
+
+  marker = pph_out_start_record (stream, lb, PPH_cp_label_binding);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   pph_out_tree (stream, lb->label);
   pph_out_tree (stream, lb->prev_value);
 }
@@ -1262,7 +1331,10 @@ static void
 pph_out_binding_level (pph_stream *stream, cp_binding_level *bl,
 		       unsigned filter)
 {
-  if (pph_out_start_record (stream, bl, PPH_cp_binding_level))
+  enum pph_record_marker marker;
+
+  marker = pph_out_start_record (stream, bl, PPH_cp_binding_level);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
   pph_out_chain_filtered (stream, bl->names, filter);
@@ -1277,7 +1349,7 @@ pph_out_binding_level (pph_stream *stream, cp_binding_level *bl,
 /* Write an index of mergeable objects from cp_binding_level BL to STREAM.  */
 
 static void
-pph_out_binding_merge_keys (pph_stream *stream, cp_binding_level *bl)
+pph_out_merge_key_binding_level (pph_stream *stream, cp_binding_level *bl)
 {
   unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
   pph_out_merge_key_chain (stream, bl->names, filter);
@@ -1290,7 +1362,7 @@ pph_out_binding_merge_keys (pph_stream *stream, cp_binding_level *bl)
 /* Write bodies of mergeable objects from cp_binding_level BL to STREAM.  */
 
 static void
-pph_out_binding_merge_bodies (pph_stream *stream, cp_binding_level *bl)
+pph_out_merge_body_binding_level (pph_stream *stream, cp_binding_level *bl)
 {
   unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
   pph_out_merge_body_chain (stream, bl->names, filter);
@@ -1311,10 +1383,15 @@ static void
 pph_out_language_function (pph_stream *stream, struct language_function *lf)
 {
   struct bitpack_d bp;
+  enum pph_record_marker marker;
 
-  if (pph_out_start_record (stream, lf, PPH_language_function))
+  marker = pph_out_start_record (stream, lf, PPH_language_function);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   pph_out_tree_vec (stream, lf->base.x_stmt_tree.x_cur_stmt_list);
   pph_out_uint (stream, lf->base.x_stmt_tree.stmts_are_full_exprs_p);
   pph_out_tree (stream, lf->x_cdtor_label);
@@ -1364,10 +1441,15 @@ static void
 pph_out_struct_function (pph_stream *stream, struct function *fn)
 {
   struct pph_tree_info pti;
+  enum pph_record_marker marker;
 
-  if (pph_out_start_record (stream, fn, PPH_function))
+  marker = pph_out_start_record (stream, fn, PPH_function);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   pph_out_tree (stream, fn->decl);
   output_struct_function_base (stream->encoder.w.ob, fn);
 
@@ -1530,13 +1612,15 @@ pph_out_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
 /* Write all the lang-specific data in DECL to STREAM.  */
 
 static void
-pph_out_lang_specific (pph_stream *stream, tree decl)
+pph_out_lang_decl (pph_stream *stream, tree decl)
 {
   struct lang_decl *ld;
   struct lang_decl_base *ldb;
+  enum pph_record_marker marker;
 
   ld = DECL_LANG_SPECIFIC (decl);
-  if (pph_out_start_record (stream, ld, PPH_lang_decl))
+  marker = pph_out_start_record (stream, ld, PPH_lang_decl);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
   /* Write all the fields in lang_decl_base.  */
@@ -1610,10 +1694,15 @@ static void
 pph_out_sorted_fields_type (pph_stream *stream, struct sorted_fields_type *sft)
 {
   int i;
+  enum pph_record_marker marker;
 
-  if (pph_out_start_record (stream, sft, PPH_sorted_fields_type))
+  marker = pph_out_start_record (stream, sft, PPH_sorted_fields_type);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   pph_out_uint (stream, sft->len);
   for (i = 0; i < sft->len; i++)
     pph_out_tree (stream, sft->elts[i]);
@@ -1680,8 +1769,16 @@ pph_out_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
   pph_out_tree (stream, ltc->vtables);
   pph_out_tree (stream, ltc->typeinfo_var);
   pph_out_tree_vec (stream, ltc->vbases);
-  if (!pph_out_start_record (stream, ltc->nested_udts, PPH_binding_table))
-    pph_out_binding_table (stream, ltc->nested_udts);
+  {
+    enum pph_record_marker marker;
+    marker = pph_out_start_record (stream, ltc->nested_udts, PPH_binding_table);
+    if (!pph_is_reference_or_end_marker (marker))
+      {
+	/* Remove if we start emitting merge keys for this structure.  */
+	gcc_assert (marker == PPH_RECORD_START);
+	pph_out_binding_table (stream, ltc->nested_udts);
+      }
+  }
   pph_out_tree (stream, ltc->as_base);
   pph_out_tree_vec (stream, ltc->pure_virtuals);
   pph_out_tree (stream, ltc->friend_classes);
@@ -1711,11 +1808,16 @@ static void
 pph_out_lang_type (pph_stream *stream, tree type)
 {
   struct lang_type *lt;
+  enum pph_record_marker marker;
 
   lt = TYPE_LANG_SPECIFIC (type);
-  if (pph_out_start_record (stream, lt, PPH_lang_type))
+  marker = pph_out_start_record (stream, lt, PPH_lang_type);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   pph_out_lang_type_header (stream, &lt->u.h);
   if (lt->u.h.is_lang_type_class)
     pph_out_lang_type_class (stream, &lt->u.c);
@@ -1762,7 +1864,7 @@ pph_out_tcc_type (pph_stream *stream, tree type)
 static void
 pph_out_tcc_declaration (pph_stream *stream, tree decl)
 {
-  pph_out_lang_specific (stream, decl);
+  pph_out_lang_decl (stream, decl);
   pph_out_tree (stream, DECL_INITIAL (decl));
 
   /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes.
@@ -2146,7 +2248,7 @@ pph_out_merge_key_namespace_decl (pph_stream *stream, tree decl)
   is_namespace_alias = (DECL_NAMESPACE_ALIAS (decl) != NULL_TREE);
   pph_out_bool (stream, is_namespace_alias);
   if (!is_namespace_alias)
-    pph_out_binding_merge_keys (stream, NAMESPACE_LEVEL (decl));
+    pph_out_merge_key_binding_level (stream, NAMESPACE_LEVEL (decl));
 }
 
 
@@ -2157,7 +2259,7 @@ pph_out_merge_key_tree (pph_stream *stream, tree expr)
 {
   gcc_assert (pph_tree_is_mergeable (expr));
 
-  if (pph_out_start_merge_key_record (stream, expr))
+  if (pph_out_start_merge_key_tree_record (stream, expr))
     return;
 
   if (flag_pph_tracer)
@@ -2205,7 +2307,7 @@ pph_out_tree (pph_stream *stream, tree expr)
 
   /* If EXPR is NULL or it already existed in the pickle cache,
      nothing else needs to be done.  */
-  if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
   if (streamer_handle_as_builtin_p (expr))
@@ -2291,10 +2393,15 @@ static void
 pph_out_cgraph_node (pph_stream *stream, struct cgraph_node *node)
 {
   struct bitpack_d bp;
+  enum pph_record_marker marker;
 
-  if (pph_out_start_record (stream, node, PPH_cgraph_node))
+  marker = pph_out_start_record (stream, node, PPH_cgraph_node);
+  if (pph_is_reference_or_end_marker (marker))
     return;
 
+  /* Remove if we start emitting merge keys for this structure.  */
+  gcc_assert (marker == PPH_RECORD_START);
+
   pph_out_tree (stream, node->decl);
   pph_out_cgraph_node (stream, node->origin);
   pph_out_cgraph_node (stream, node->nested);
@@ -2505,10 +2612,12 @@ pph_out_global_binding (pph_stream *stream)
   bl = scope_chain->bindings;
   pph_out_start_record (stream, bl, PPH_cp_binding_level);
 
-  /* Emit all the merge keys for objects that need to be merged when reading
-     multiple PPH images.  */
-  pph_out_binding_merge_keys (stream, bl);
-  pph_out_binding_merge_bodies (stream, bl);
+  /* Emit all the merge keys for objects that need to be merged when
+     reading multiple PPH images.  */
+  pph_out_merge_key_binding_level (stream, bl);
+
+  /* Now emit all the bodies.  */
+  pph_out_merge_body_binding_level (stream, bl);
 }
 
 
diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h
index 5397afc..e31b15e 100644
--- a/gcc/cp/pph-streamer.h
+++ b/gcc/cp/pph-streamer.h
@@ -349,6 +349,14 @@ pph_is_reference_marker (enum pph_record_marker marker)
          || marker == PPH_RECORD_PREF;
 }
 
+/* Return true if MARKER is a reference or an END marker.  */
+
+static inline bool
+pph_is_reference_or_end_marker (enum pph_record_marker marker)
+{
+  return marker == PPH_RECORD_END || pph_is_reference_marker (marker);
+}
+
 
 /* Return true if tree T needs to be signed to detect state mutations.
    This is used when multiple PPH images contain different versions of
