diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2bb76ae..2e0aa58 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -5937,10 +5937,42 @@ pph_stream_write_binding_table (pph_stream *stream, binding_table bt,
   pph_output_uint (stream, bt->chain_count);
   for (i = 0; i < bt->chain_count; i++)
     {
-      pph_output_tree_or_ref (stream, bt->chain[i]->name, ref_p);
-      pph_output_tree_or_ref (stream, bt->chain[i]->type, ref_p);
+      if (bt->chain[i])
+	{
+	  pph_output_uchar (stream, PPH_RECORD_START);
+	  pph_output_tree_or_ref (stream, bt->chain[i]->name, ref_p);
+	  pph_output_tree_or_ref (stream, bt->chain[i]->type, ref_p);
+	}
+      else
+	pph_output_uchar (stream, PPH_RECORD_END);
     }
   pph_output_uint (stream, bt->entry_count);
 }
 
+
+/* Read and return a binding_entry instance BT from STREAM.  */
+
+binding_table
+pph_stream_read_binding_table (pph_stream *stream)
+{
+  size_t i, chain_count;
+  binding_table bt;
+
+  chain_count = pph_input_uint (stream);
+  bt = binding_table_new (chain_count);
+  for (i = 0; i < chain_count; i++)
+    {
+      unsigned char record_marker = pph_input_uchar (stream);
+      if (record_marker == PPH_RECORD_START)
+	{
+	  tree name = pph_input_tree (stream);
+	  tree type = pph_input_tree (stream);
+	  binding_table_insert (bt, name, type);
+	}
+    }
+  bt->entry_count = pph_input_uint (stream);
+
+  return bt;
+}
+
 #include "gt-cp-name-lookup.h"
diff --git a/gcc/cp/pph-streamer-in.c b/gcc/cp/pph-streamer-in.c
index 38a4561..335fab6 100644
--- a/gcc/cp/pph-streamer-in.c
+++ b/gcc/cp/pph-streamer-in.c
@@ -519,7 +519,7 @@ pph_stream_read_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
 /* Read language specific data in DECL from STREAM.  */
 
 static void
-pph_stream_read_lang_specific_data (pph_stream *stream, tree decl)
+pph_stream_read_lang_specific (pph_stream *stream, tree decl)
 {
   struct lang_decl *ld;
   struct lang_decl_base *ldb;
@@ -583,6 +583,185 @@ pph_stream_alloc_tree (enum tree_code code,
 }
 
 
+/* Read all the fields in lang_type_header instance LTH from STREAM.  */
+
+static void
+pph_stream_read_lang_type_header (pph_stream *stream,
+				   struct lang_type_header *lth)
+{
+  struct bitpack_d bp;
+
+  if (!pph_start_record (stream))
+    return;
+
+  bp = pph_input_bitpack (stream);
+  lth->is_lang_type_class = bp_unpack_value (&bp, 1);
+  lth->has_type_conversion = bp_unpack_value (&bp, 1);
+  lth->has_copy_ctor = bp_unpack_value (&bp, 1);
+  lth->has_default_ctor = bp_unpack_value (&bp, 1);
+  lth->const_needs_init = bp_unpack_value (&bp, 1);
+  lth->ref_needs_init = bp_unpack_value (&bp, 1);
+  lth->has_const_copy_assign = bp_unpack_value (&bp, 1);
+}
+
+
+/* Read the vector V of tree_pair_s instances from STREAM.  */
+
+static VEC(tree_pair_s,gc) *
+pph_stream_read_tree_pair_vec (pph_stream *stream)
+{
+  unsigned i, num;
+  VEC(tree_pair_s,gc) *v;
+
+  num = pph_input_uint (stream);
+  for (i = 0, v = NULL; i < num; i++)
+    {
+      tree_pair_s p;
+      p.purpose = pph_input_tree (stream);
+      p.value = pph_input_tree (stream);
+      VEC_safe_push (tree_pair_s, gc, v, &p);
+    }
+
+  return v;
+}
+
+
+/* Read a struct sorted_fields_type instance SFT to STREAM.  REF_P is
+   true if the tree nodes should be written as references.  */
+
+static struct sorted_fields_type *
+pph_stream_read_sorted_fields_type (pph_stream *stream)
+{
+  unsigned i, num_fields;
+  struct sorted_fields_type *v;
+
+  if (!pph_start_record (stream))
+    return NULL;
+
+  num_fields = pph_input_uint (stream);
+  v = sorted_fields_type_new (num_fields);
+  for (i = 0; i < num_fields; i++)
+    v->elts[i] = pph_input_tree (stream);
+
+  return v;
+}
+
+
+/* Read all the fields in lang_type_class instance LTC to STREAM.
+   REF_P is true if all the trees in the structure should be written
+   as references.  */
+
+static void
+pph_stream_read_lang_type_class (pph_stream *stream,
+				  struct lang_type_class *ltc)
+{
+  struct bitpack_d bp;
+
+  if (!pph_start_record (stream))
+    return;
+
+  ltc->align = pph_input_uchar (stream);
+
+  bp = pph_input_bitpack (stream);
+  ltc->has_mutable = bp_unpack_value (&bp, 1);
+  ltc->com_interface = bp_unpack_value (&bp, 1);
+  ltc->non_pod_class = bp_unpack_value (&bp, 1);
+  ltc->nearly_empty_p = bp_unpack_value (&bp, 1);
+  ltc->user_align = bp_unpack_value (&bp, 1);
+  ltc->has_copy_assign = bp_unpack_value (&bp, 1);
+  ltc->has_new = bp_unpack_value (&bp, 1);
+  ltc->has_array_new = bp_unpack_value (&bp, 1);
+  ltc->gets_delete = bp_unpack_value (&bp, 2);
+  ltc->interface_only = bp_unpack_value (&bp, 1);
+  ltc->interface_unknown = bp_unpack_value (&bp, 1);
+  ltc->contains_empty_class_p = bp_unpack_value (&bp, 1);
+  ltc->anon_aggr = bp_unpack_value (&bp, 1);
+  ltc->non_zero_init = bp_unpack_value (&bp, 1);
+  ltc->empty_p = bp_unpack_value (&bp, 1);
+  ltc->vec_new_uses_cookie = bp_unpack_value (&bp, 1);
+  ltc->declared_class = bp_unpack_value (&bp, 1);
+  ltc->diamond_shaped = bp_unpack_value (&bp, 1);
+  ltc->repeated_base = bp_unpack_value (&bp, 1);
+  ltc->being_defined = bp_unpack_value (&bp, 1);
+  ltc->java_interface = bp_unpack_value (&bp, 1);
+  ltc->debug_requested = bp_unpack_value (&bp, 1);
+  ltc->fields_readonly = bp_unpack_value (&bp, 1);
+  ltc->use_template = bp_unpack_value (&bp, 2);
+  ltc->ptrmemfunc_flag = bp_unpack_value (&bp, 1);
+  ltc->was_anonymous = bp_unpack_value (&bp, 1);
+  ltc->lazy_default_ctor = bp_unpack_value (&bp, 1);
+  ltc->lazy_copy_ctor = bp_unpack_value (&bp, 1);
+  ltc->lazy_copy_assign = bp_unpack_value (&bp, 1);
+  ltc->lazy_destructor = bp_unpack_value (&bp, 1);
+  ltc->has_const_copy_ctor = bp_unpack_value (&bp, 1);
+  ltc->has_complex_copy_ctor = bp_unpack_value (&bp, 1);
+  ltc->has_complex_copy_assign = bp_unpack_value (&bp, 1);
+  ltc->non_aggregate = bp_unpack_value (&bp, 1);
+  ltc->has_complex_dflt = bp_unpack_value (&bp, 1);
+  ltc->has_list_ctor = bp_unpack_value (&bp, 1);
+  ltc->non_std_layout = bp_unpack_value (&bp, 1);
+  ltc->is_literal = bp_unpack_value (&bp, 1);
+  ltc->lazy_move_ctor = bp_unpack_value (&bp, 1);
+  ltc->lazy_move_assign = bp_unpack_value (&bp, 1);
+  ltc->has_complex_move_ctor = bp_unpack_value (&bp, 1);
+  ltc->has_complex_move_assign = bp_unpack_value (&bp, 1);
+  ltc->has_constexpr_ctor = bp_unpack_value (&bp, 1);
+
+  ltc->primary_base = pph_input_tree (stream);
+  ltc->vcall_indices = pph_stream_read_tree_pair_vec (stream);
+  ltc->vtables = pph_input_tree (stream);
+  ltc->typeinfo_var = pph_input_tree (stream);
+  ltc->vbases = pph_stream_read_tree_vec (stream);
+  if (pph_start_record (stream))
+    ltc->nested_udts = pph_stream_read_binding_table (stream);
+  ltc->as_base = pph_input_tree (stream);
+  ltc->pure_virtuals = pph_stream_read_tree_vec (stream);
+  ltc->friend_classes = pph_input_tree (stream);
+  ltc->methods = pph_stream_read_tree_vec (stream);
+  ltc->key_method = pph_input_tree (stream);
+  ltc->decl_list = pph_input_tree (stream);
+  ltc->template_info = pph_input_tree (stream);
+  ltc->befriending_classes = pph_input_tree (stream);
+  ltc->objc_info = pph_input_tree (stream);
+  ltc->sorted_fields = pph_stream_read_sorted_fields_type (stream);
+  ltc->lambda_expr = pph_input_tree (stream);
+}
+
+
+/* Read all fields of struct lang_type_ptrmem instance LTP from STREAM.  */
+
+static void
+pph_stream_read_lang_type_ptrmem (pph_stream *stream,
+				  struct lang_type_ptrmem *ltp)
+{
+  if (!pph_start_record (stream))
+    return;
+
+  ltp->record = pph_input_tree (stream);
+}
+
+
+/* Read all the lang-specific fields of TYPE from STREAM.  */
+
+static void
+pph_stream_read_lang_type (pph_stream *stream, tree type)
+{
+  struct lang_type *lt;
+
+  if (!pph_start_record (stream))
+    return;
+
+  lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+  TYPE_LANG_SPECIFIC (type) = lt;
+
+  pph_stream_read_lang_type_header (stream, &lt->u.h);
+  if (lt->u.h.is_lang_type_class)
+    pph_stream_read_lang_type_class (stream, &lt->u.c);
+  else
+    pph_stream_read_lang_type_ptrmem (stream, &lt->u.ptrmem);
+}
+
+
 /* Callback for reading ASTs from a stream.  This reads all the fields
    that are not processed by default by the common tree pickler.
    IB, DATA_IN are as in lto_read_tree.  EXPR is the partially materialized
@@ -601,7 +780,7 @@ pph_stream_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
 	  || TREE_CODE (expr) == PARM_DECL
 	  || LANG_DECL_HAS_MIN (expr))
 	{
-	  pph_stream_read_lang_specific_data (stream, expr);
+	  pph_stream_read_lang_specific (stream, expr);
 	  if (TREE_CODE (expr) == FUNCTION_DECL)
 	    DECL_SAVED_TREE (expr) = pph_input_tree (stream);
 	}
@@ -617,4 +796,6 @@ pph_stream_read_tree (struct lto_input_block *ib ATTRIBUTE_UNUSED,
 	  append_to_statement_list (stmt, &expr);
 	}
     }
+  else if (TYPE_P (expr))
+    pph_stream_read_lang_type (stream, expr);
 }
diff --git a/gcc/cp/pph-streamer-out.c b/gcc/cp/pph-streamer-out.c
index b5f2c97..16c8543 100644
--- a/gcc/cp/pph-streamer-out.c
+++ b/gcc/cp/pph-streamer-out.c
@@ -539,13 +539,11 @@ pph_stream_write_ld_parm (pph_stream *stream, struct lang_decl_parm *ldp)
    references.  */
 
 static void
-pph_stream_write_lang_specific_data (pph_stream *stream, tree decl, bool ref_p)
+pph_stream_write_lang_specific (pph_stream *stream, tree decl, bool ref_p)
 {
   struct lang_decl *ld;
   struct lang_decl_base *ldb;
 
-  gcc_assert (DECL_P (decl));
-
   ld = DECL_LANG_SPECIFIC (decl);
   if (!pph_start_record (stream, ld))
     return;
@@ -585,7 +583,12 @@ static void
 pph_stream_write_lang_type_header (pph_stream *stream,
 				   struct lang_type_header *lth)
 {
-  struct bitpack_d bp = bitpack_create (stream->ob->main_stream);
+  struct bitpack_d bp;
+
+  if (!pph_start_record (stream, lth))
+    return;
+
+  bp = bitpack_create (stream->ob->main_stream);
   bp_pack_value (&bp, lth->is_lang_type_class, 1);
   bp_pack_value (&bp, lth->has_type_conversion, 1);
   bp_pack_value (&bp, lth->has_copy_ctor, 1);
@@ -593,7 +596,7 @@ pph_stream_write_lang_type_header (pph_stream *stream,
   bp_pack_value (&bp, lth->const_needs_init, 1);
   bp_pack_value (&bp, lth->ref_needs_init, 1);
   bp_pack_value (&bp, lth->has_const_copy_assign, 1);
-  lto_output_bitpack (&bp);
+  pph_output_bitpack (stream, &bp);
 }
 
 
@@ -625,6 +628,9 @@ pph_stream_write_sorted_fields_type (pph_stream *stream,
 {
   int i;
 
+  if (!pph_start_record (stream, sft))
+    return;
+
   pph_output_uint (stream, sft->len);
   for (i = 0; i < sft->len; i++)
     pph_output_tree_or_ref (stream, sft->elts[i], ref_p);
@@ -690,14 +696,15 @@ pph_stream_write_lang_type_class (pph_stream *stream,
   bp_pack_value (&bp, ltc->has_complex_move_ctor, 1);
   bp_pack_value (&bp, ltc->has_complex_move_assign, 1);
   bp_pack_value (&bp, ltc->has_constexpr_ctor, 1);
-  lto_output_bitpack (&bp);
+  pph_output_bitpack (stream, &bp);
 
   pph_output_tree_or_ref (stream, ltc->primary_base, ref_p);
   pph_stream_write_tree_pair_vec (stream, ltc->vcall_indices, ref_p);
   pph_output_tree_or_ref (stream, ltc->vtables, ref_p);
   pph_output_tree_or_ref (stream, ltc->typeinfo_var, ref_p);
   pph_stream_write_tree_vec (stream, ltc->vbases, ref_p);
-  pph_stream_write_binding_table (stream, ltc->nested_udts, ref_p);
+  if (pph_start_record (stream, ltc->nested_udts))
+    pph_stream_write_binding_table (stream, ltc->nested_udts, ref_p);
   pph_output_tree_or_ref (stream, ltc->as_base, ref_p);
   pph_stream_write_tree_vec (stream, ltc->pure_virtuals, ref_p);
   pph_output_tree_or_ref (stream, ltc->friend_classes, ref_p);
@@ -719,6 +726,9 @@ static void
 pph_stream_write_lang_type_ptrmem (pph_stream *stream, struct
 				   lang_type_ptrmem *ltp, bool ref_p)
 {
+  if (!pph_start_record (stream, ltp))
+    return;
+
   pph_output_tree_or_ref (stream, ltp->record, ref_p);
 }
 
@@ -730,7 +740,11 @@ pph_stream_write_lang_type_ptrmem (pph_stream *stream, struct
 static void
 pph_stream_write_lang_type (pph_stream *stream, tree type, bool ref_p)
 {
-  struct lang_type *lt = TYPE_LANG_SPECIFIC (type);
+  struct lang_type *lt;
+
+  lt = TYPE_LANG_SPECIFIC (type);
+  if (!pph_start_record (stream, lt))
+    return;
 
   pph_stream_write_lang_type_header (stream, &lt->u.h);
   if (lt->u.h.is_lang_type_class)
@@ -770,7 +784,7 @@ pph_stream_write_tree (struct output_block *ob, tree expr, bool ref_p)
 	  || TREE_CODE (expr) == PARM_DECL
 	  || LANG_DECL_HAS_MIN (expr))
 	{
-	  pph_stream_write_lang_specific_data (stream, expr, ref_p);
+	  pph_stream_write_lang_specific (stream, expr, ref_p);
 
 	  if (TREE_CODE (expr) == FUNCTION_DECL)
 	    pph_output_tree_aux (stream, DECL_SAVED_TREE (expr), ref_p);
diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h
index 0a3a4c8..0bc2b4e 100644
--- a/gcc/cp/pph-streamer.h
+++ b/gcc/cp/pph-streamer.h
@@ -108,9 +108,12 @@ void pph_stream_write_tree (struct output_block *, tree, bool ref_p);
 void pph_stream_pack_value_fields (struct bitpack_d *, tree);
 void pph_stream_output_tree_header (struct output_block *, tree);
 void pph_output_chain_filtered (pph_stream *, tree, bool, enum chain_filter);
+
+/* In name-lookup.c.  */
 struct binding_table_s;
 void pph_stream_write_binding_table (pph_stream *, struct binding_table_s *,
 				     bool);
+struct binding_table_s *pph_stream_read_binding_table (pph_stream *);
 
 /* In pph-streamer-in.c.  */
 void pph_stream_init_read (pph_stream *);

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1fcd0d7..692af78 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4729,6 +4729,7 @@ extern void fixup_attribute_variants		(tree);
 extern tree* decl_cloned_function_p		(const_tree, bool);
 extern void clone_function_decl			(tree, int);
 extern void adjust_clone_args			(tree);
+extern struct sorted_fields_type *sorted_fields_type_new (int);
 
 /* in cvt.c */
 extern tree convert_to_reference		(tree, tree, int, int, tree);
