Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(818)

Issue 5164048: [pph] Detect state mutation in DECLs/TYPEs [8/8] (Closed)

Can't Edit
Can't Publish+Mail
Start Review
Created:
12 years, 5 months ago by Diego Novillo
Modified:
12 years, 5 months ago
Reviewers:
CC:
Lawrence Crowl, gcc-patches_gcc.gnu.org
Visibility:
Public.

Patch Set 1 #

Unified diffs Side-by-side diffs Delta from patch set Stats (+289 lines, -171 lines) Patch
M gcc/cp/ChangeLog.pph View 1 chunk +32 lines, -0 lines 0 comments Download
M gcc/cp/name-lookup.c View 2 chunks +5 lines, -3 lines 0 comments Download
M gcc/cp/pph-streamer.h View 8 chunks +87 lines, -17 lines 0 comments Download
M gcc/cp/pph-streamer.c View 8 chunks +61 lines, -27 lines 0 comments Download
M gcc/cp/pph-streamer-in.c View 28 chunks +51 lines, -65 lines 0 comments Download
M gcc/cp/pph-streamer-out.c View 23 chunks +48 lines, -55 lines 0 comments Download
M gcc/testsuite/ChangeLog.pph View 1 chunk +5 lines, -0 lines 0 comments Download
M gcc/testsuite/g++.dg/pph/x6dynarray4.cc View 1 chunk +0 lines, -1 line 0 comments Download
M gcc/testsuite/g++.dg/pph/x7dynarray5.cc View 1 chunk +0 lines, -3 lines 0 comments Download

Messages

Total messages: 1
Diego Novillo
12 years, 5 months ago (2011-10-03 15:41:04 UTC) #1
This final patch adds support for type tagging cache entries (and file
records as well).

This resolves the ICEs we were getting in x6dynarray4.cc and
x7dynarray5.cc.  The parser was replacing a LANG_DECL pointer (that
had been freed during decl merging) with a CALL_EXPR.

The patch is somewhat large because it adds a new TAG argument to
the cache functions.  However, it is straightforward.

It uncovered a potential bug, too.  struct c_language_function is
always allocated at the same address as struct language_function
(since that field is the same embedded field).  I was getting cache
data type conflicts because of that, that means that we were getting
different objects from the cache stored at the same location.  I fixed
this by simply embedding the streaming of c_language_function inside
language_function.

Tested on x86_64.  Committed to branch.


Diego.

	* pph-streamer.h (enum pph_tag): Define.
	(struct pph_cache_entry): Add field TAG.
	(pph_cache_insert_at): Add new argument TAG.
	Update all users.
	(pph_cache_lookup): Likewise.
	(pph_cache_lookup_in_includes): Likewise.
	(pph_cache_add): Likewise.
	(pph_out_record_marker): Likewise.
	(pph_in_record_marker): Add new argument *TAG_P.
	Read *TAG_P.  Assert that it is a valid tag.
	(pph_cache_get): Call pph_cache_get_entry.
	(pph_tag_is_tree_code): New.
	(pph_tree_code_to_tag): New.
	(pph_tag_to_tree_code): New.
	* pph-streamer-in.c (ALLOC_AND_REGISTER): Add new argument
	TAG.  Update all users.
	(ALLOC_AND_REGISTER_ALTERNATE): Likewise.
	(pph_in_start_record): Add new argument EXPECTED_TAG.  Update
	all users.
	(pph_in_c_language_function): Inline into ...
	(pph_in_language_function): ... here.
	* pph-streamer-out.c (pph_get_marker_for): Add argument TAG.
	Update all users.
	(pph_out_reference_record): Likewise.
	(pph_out_start_record): Likewise.
	(pph_out_start_tree_record): Re-enable state mutation
	detection.
	(pph_out_c_language_function): Inline into ...
	(pph_out_language_function): ... here.

testsuite/ChangeLog.pph

	* g++.dg/pph/x6dynarray4.cc: Mark partially fixed.
	* g++.dg/pph/x7dynarray5.cc: Mark partially fixed.

diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2cf2edb..dd63715 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -6019,12 +6019,12 @@ pph_out_binding_table (pph_stream *stream, binding_table
bt)
     {
       if (bt->chain[i])
 	{
-	  pph_out_record_marker (stream, PPH_RECORD_START);
+	  pph_out_record_marker (stream, PPH_RECORD_START, PPH_binding_entry);
 	  pph_out_tree (stream, bt->chain[i]->name);
 	  pph_out_tree (stream, bt->chain[i]->type);
 	}
       else
-	pph_out_record_marker (stream, PPH_RECORD_END);
+	pph_out_record_marker (stream, PPH_RECORD_END, PPH_binding_entry);
     }
   pph_out_uint (stream, bt->entry_count);
 }
@@ -6042,7 +6042,9 @@ pph_in_binding_table (pph_stream *stream)
   bt = binding_table_new (chain_count);
   for (i = 0; i < chain_count; i++)
     {
-      enum pph_record_marker marker = pph_in_record_marker (stream);
+      enum pph_tag tag;
+      enum pph_record_marker marker = pph_in_record_marker (stream, &tag);
+      gcc_assert (tag == PPH_binding_entry);
       if (marker == PPH_RECORD_START)
 	{
 	  tree name = pph_in_tree (stream);
diff --git a/gcc/cp/pph-streamer-in.c b/gcc/cp/pph-streamer-in.c
index a2bad3d..197937c 100644
--- a/gcc/cp/pph-streamer-in.c
+++ b/gcc/cp/pph-streamer-in.c
@@ -56,10 +56,10 @@ static int pph_reading_includes = 0;
    registered in the PPH streamer cache.  DATA is the pointer returned
    by the memory allocation call in ALLOC_EXPR.  IX is the cache slot 
    in CACHE where the newly allocated DATA should be registered at.  */
-#define ALLOC_AND_REGISTER(CACHE, IX, DATA, ALLOC_EXPR)	\
+#define ALLOC_AND_REGISTER(CACHE, IX, TAG, DATA, ALLOC_EXPR)	\
     do {							\
       (DATA) = (ALLOC_EXPR);					\
-      pph_cache_insert_at (CACHE, DATA, IX);			\
+      pph_cache_insert_at (CACHE, DATA, IX, TAG);		\
     } while (0)
 
 /* Same as ALLOC_AND_REGISTER, but instead of registering DATA into the
@@ -68,10 +68,11 @@ static int pph_reading_includes = 0;
    to a different instance when aggregating individual PPH files into
    the current translation unit (see pph_in_binding_level for an
    example).  */
-#define ALLOC_AND_REGISTER_ALTERNATE(CACHE, IX, DATA, ALLOC_EXPR, ALT_DATA)\
+#define ALLOC_AND_REGISTER_ALTERNATE(CACHE, IX, TAG, DATA, ALLOC_EXPR,  \
+                                     ALT_DATA)                  \
     do {							\
       (DATA) = (ALLOC_EXPR);					\
-      pph_cache_insert_at (CACHE, ALT_DATA, IX);		\
+      pph_cache_insert_at (CACHE, ALT_DATA, IX, TAG);		\
     } while (0)
 
 /* Set in pph_in_and_merge_line_table. Represents the source_location offset
@@ -145,11 +146,13 @@ pph_init_read (pph_stream *stream)
 }
 
 
-/* Read and return a record header from STREAM.  When a PPH_RECORD_START
-   marker is read, the next word read is an index into the streamer
-   cache where the rematerialized data structure should be stored.
-   When the writer stored this data structure for the first time, it
-   added it to its own streamer cache at slot number *CACHE_IX_P.
+/* Read and return a record header from STREAM.  EXPECTED_TAG indicates
+   the data type that should be stored in this record.  When a
+   PPH_RECORD_START marker is read, the next word read is an index
+   into the streamer cache where the rematerialized data structure
+   should be stored. When the writer stored this data structure for
+   the first time, it added it to its own streamer cache at slot
+   number *CACHE_IX_P.
 
    This way, if the same data structure was written a second time to
    the stream, instead of writing the whole structure again, only the
@@ -171,9 +174,16 @@ pph_init_read (pph_stream *stream)
 
 static inline enum pph_record_marker
 pph_in_start_record (pph_stream *stream, unsigned *include_ix_p,
-		     unsigned *cache_ix_p)
+		     unsigned *cache_ix_p, enum pph_tag expected_tag)
 {
-  enum pph_record_marker marker = pph_in_record_marker (stream);
+  enum pph_tag read_tag;
+  enum pph_record_marker marker = pph_in_record_marker (stream, &read_tag);
+
+  /* If the caller expects any tree, make sure we get a valid tree code.  */
+  if (expected_tag == PPH_any_tree)
+    gcc_assert (read_tag < PPH_any_tree);
+  else
+    gcc_assert (read_tag == expected_tag);
 
   *include_ix_p = (unsigned) -1;
   *cache_ix_p = (unsigned) -1;
@@ -428,7 +438,7 @@ pph_in_cxx_binding_1 (pph_stream *stream)
   enum pph_record_marker marker;
   unsigned ix, image_ix;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cxx_binding);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -439,7 +449,8 @@ pph_in_cxx_binding_1 (pph_stream *stream)
 
   value = pph_in_tree (stream);
   type = pph_in_tree (stream);
-  ALLOC_AND_REGISTER (&stream->cache, ix, cb, cxx_binding_make (value, type));
+  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cxx_binding, cb,
+                      cxx_binding_make (value, type));
   cb->scope = pph_in_binding_level (stream, NULL);
   bp = pph_in_bitpack (stream);
   cb->value_is_inherited = bp_unpack_value (&bp, 1);
@@ -479,7 +490,7 @@ pph_in_class_binding (pph_stream *stream)
   enum pph_record_marker marker;
   unsigned image_ix, ix;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_class_binding);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -488,7 +499,7 @@ pph_in_class_binding (pph_stream *stream)
       return (cp_class_binding *) pph_cache_get (cache, ix);
     }
 
-  ALLOC_AND_REGISTER (&stream->cache, ix, cb,
+  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_class_binding, cb,
                       ggc_alloc_cleared_cp_class_binding ());
   cb->base = pph_in_cxx_binding (stream);
   cb->identifier = pph_in_tree (stream);
@@ -506,7 +517,7 @@ pph_in_label_binding (pph_stream *stream)
   enum pph_record_marker marker;
   unsigned image_ix, ix;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_label_binding);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -515,7 +526,7 @@ pph_in_label_binding (pph_stream *stream)
       return (cp_label_binding *) pph_cache_get (cache, ix);
     }
 
-  ALLOC_AND_REGISTER (&stream->cache, ix, lb,
+  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_label_binding, lb,
                       ggc_alloc_cleared_cp_label_binding ());
   lb->label = pph_in_tree (stream);
   lb->prev_value = pph_in_tree (stream);
@@ -551,7 +562,7 @@ pph_in_binding_level (pph_stream *stream, cp_binding_level
*to_register)
   enum pph_record_marker marker;
   tree entity;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cp_binding_level);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -563,10 +574,10 @@ pph_in_binding_level (pph_stream *stream, cp_binding_level
*to_register)
   /* If TO_REGISTER is set, register that binding level instead of the newly
      allocated binding level into slot IX.  */
   if (to_register == NULL)
-    ALLOC_AND_REGISTER (&stream->cache, ix, bl,
+    ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cp_binding_level, bl,
 			ggc_alloc_cleared_cp_binding_level ());
   else
-    ALLOC_AND_REGISTER_ALTERNATE (&stream->cache, ix, bl,
+    ALLOC_AND_REGISTER_ALTERNATE (&stream->cache, ix, PPH_cp_binding_level, bl,
 				  ggc_alloc_cleared_cp_binding_level (),
 				  to_register);
 
@@ -631,33 +642,6 @@ pph_in_tree_common (pph_stream *stream, tree t)
   TREE_CHAIN (t) = pph_in_tree (stream);
 }
 
-/* Read and return an instance of struct c_language_function from STREAM.  */
-
-static struct c_language_function *
-pph_in_c_language_function (pph_stream *stream)
-{
-  struct c_language_function *clf;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-
-  marker = pph_in_start_record (stream, &image_ix, &ix);
-  if (marker == PPH_RECORD_END)
-    return NULL;
-  else if (pph_is_reference_marker (marker))
-    {
-      pph_cache *cache = pph_cache_select (stream, marker, image_ix);
-      return (struct c_language_function *) pph_cache_get (cache, ix);
-    }
-
-  ALLOC_AND_REGISTER (&stream->cache, ix, clf,
-		      ggc_alloc_cleared_c_language_function ());
-  clf->x_stmt_tree.x_cur_stmt_list = pph_in_tree_vec (stream);
-  clf->x_stmt_tree.stmts_are_full_exprs_p = pph_in_uint (stream);
-
-  return clf;
-}
-
-
 /* Read and return an instance of struct language_function from STREAM.  */
 
 static struct language_function *
@@ -668,7 +652,7 @@ pph_in_language_function (pph_stream *stream)
   enum pph_record_marker marker;
   unsigned image_ix, ix;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_language_function);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -677,10 +661,10 @@ pph_in_language_function (pph_stream *stream)
       return (struct language_function *) pph_cache_get (cache, ix);
     }
 
-  ALLOC_AND_REGISTER (&stream->cache, ix, lf,
+  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_language_function, lf,
                       ggc_alloc_cleared_language_function ());
-  memcpy (&lf->base, pph_in_c_language_function (stream),
-	  sizeof (struct c_language_function));
+  lf->base.x_stmt_tree.x_cur_stmt_list = pph_in_tree_vec (stream);
+  lf->base.x_stmt_tree.stmts_are_full_exprs_p = pph_in_uint (stream);
   lf->x_cdtor_label = pph_in_tree (stream);
   lf->x_current_class_ptr = pph_in_tree (stream);
   lf->x_current_class_ref = pph_in_tree (stream);
@@ -764,7 +748,7 @@ pph_in_struct_function (pph_stream *stream, tree decl)
   struct function *fn;
   tree t;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_function);
   if (marker == PPH_RECORD_END)
     return;
   else if (pph_is_reference_marker (marker))
@@ -783,7 +767,7 @@ pph_in_struct_function (pph_stream *stream, tree decl)
 
   /* Now register it.  We would normally use ALLOC_AND_REGISTER,
      but allocate_struct_function does not return a pointer.  */
-  pph_cache_insert_at (&stream->cache, fn, ix);
+  pph_cache_insert_at (&stream->cache, fn, ix, PPH_function);
 
   input_struct_function_base (fn, stream->encoder.r.data_in,
 			      stream->encoder.r.ib);
@@ -874,7 +858,7 @@ pph_in_lang_specific (pph_stream *stream, tree decl)
   enum pph_record_marker marker;
   unsigned image_ix, ix;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_lang_decl);
   if (marker == PPH_RECORD_END)
     return;
   else if (pph_is_reference_marker (marker))
@@ -891,7 +875,7 @@ pph_in_lang_specific (pph_stream *stream, tree decl)
 
   /* Now register it.  We would normally use ALLOC_AND_REGISTER,
      but retrofit_lang_decl does not return a pointer.  */
-  pph_cache_insert_at (&stream->cache, ld, ix);
+  pph_cache_insert_at (&stream->cache, ld, ix, PPH_lang_decl);
 
   /* Read all the fields in lang_decl_base.  */
   ldb = &ld->u.base;
@@ -971,7 +955,7 @@ pph_in_sorted_fields_type (pph_stream *stream)
   enum pph_record_marker marker;
   unsigned image_ix, ix;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix,
PPH_sorted_fields_type);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -981,7 +965,7 @@ pph_in_sorted_fields_type (pph_stream *stream)
     }
 
   num_fields = pph_in_uint (stream);
-  ALLOC_AND_REGISTER (&stream->cache, ix, v,
+  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_sorted_fields_type, v,
                       sorted_fields_type_new (num_fields));
   for (i = 0; i < num_fields; i++)
     v->elts[i] = pph_in_tree (stream);
@@ -1052,11 +1036,12 @@ pph_in_lang_type_class (pph_stream *stream, struct
lang_type_class *ltc)
   ltc->typeinfo_var = pph_in_tree (stream);
   ltc->vbases = pph_in_tree_vec (stream);
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_binding_table);
   if (marker == PPH_RECORD_START)
     {
       ltc->nested_udts = pph_in_binding_table (stream);
-      pph_cache_insert_at (&stream->cache, ltc->nested_udts, ix);
+      pph_cache_insert_at (&stream->cache, ltc->nested_udts, ix,
+                           PPH_binding_table);
     }
   else if (pph_is_reference_marker (marker))
     {
@@ -1097,7 +1082,7 @@ pph_in_lang_type (pph_stream *stream)
   enum pph_record_marker marker;
   unsigned image_ix, ix;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_lang_type);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -1106,7 +1091,7 @@ pph_in_lang_type (pph_stream *stream)
       return (struct lang_type *) pph_cache_get (cache, ix);
     }
 
-  ALLOC_AND_REGISTER (&stream->cache, ix, lt,
+  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_lang_type, lt,
                       ggc_alloc_cleared_lang_type (sizeof (struct lang_type)));
 
   pph_in_lang_type_header (stream, &lt->u.h);
@@ -1314,7 +1299,7 @@ pph_in_cgraph_node (pph_stream *stream)
   tree fndecl;
   struct bitpack_d bp;
 
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_cgraph_node);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -1324,7 +1309,8 @@ pph_in_cgraph_node (pph_stream *stream)
     }
 
   fndecl = pph_in_tree (stream);
-  ALLOC_AND_REGISTER (&stream->cache, ix, node, cgraph_create_node (fndecl));
+  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cgraph_node, node,
+                      cgraph_create_node (fndecl));
 
   node->origin = pph_in_cgraph_node (stream);
   node->nested = pph_in_cgraph_node (stream);
@@ -2104,7 +2090,7 @@ pph_read_namespace_tree (pph_stream *stream, tree
enclosing_namespace)
   enum LTO_tags tag;
 
   /* Read record start and test cache.  */
-  marker = pph_in_start_record (stream, &image_ix, &ix);
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
   if (marker == PPH_RECORD_END)
     return NULL;
   else if (pph_is_reference_marker (marker))
@@ -2174,7 +2160,7 @@ pph_read_namespace_tree (pph_stream *stream, tree
enclosing_namespace)
   /* Add the new tree to the cache and read its body.  The tree
      is added to the cache before we read its body to handle
      circular references and references from children nodes.  */
-  pph_cache_insert_at (&stream->cache, expr, ix);
+  pph_cache_insert_at (&stream->cache, expr, ix, pph_tree_code_to_tag (expr));
   pph_read_tree_body (stream, expr);
 
   /* If needed, sign the recently materialized tree to detect
diff --git a/gcc/cp/pph-streamer-out.c b/gcc/cp/pph-streamer-out.c
index 516eabb..6b5c7b9 100644
--- a/gcc/cp/pph-streamer-out.c
+++ b/gcc/cp/pph-streamer-out.c
@@ -227,17 +227,19 @@ pph_cache_should_handle (tree t)
 
 
 /* Return a PPH record marker according to whether DATA is NULL or
-   it can be found in one of the caches associated with STREAM.
+   it can be found in one of the caches associated with STREAM.  TAG
+   is the data type for DATA.
 
    If DATA is in any of the caches, return the corresponding slot in
    *IX_P.  If DATA is in the cache of an image included by STREAM,
    return the image's index in *INCLUDE_IX_P.
 
-   In all other cases, *IX_P and *INCLUDE_IX_P will be set to -1.  */
+   In all other cases, *IX_P and *INCLUDE_IX_P will be set to -1 (if
+   given).  */
 
 static enum pph_record_marker
 pph_get_marker_for (pph_stream *stream, void *data, unsigned *include_ix_p,
-                    unsigned *ix_p)
+                    unsigned *ix_p, enum pph_tag tag)
 {
   if (ix_p)
     *ix_p = -1u;
@@ -250,17 +252,17 @@ pph_get_marker_for (pph_stream *stream, void *data,
unsigned *include_ix_p,
     return PPH_RECORD_END;
 
   /* If DATA is in STREAM's cache, return an internal reference marker.  */
-  if (pph_cache_lookup (&stream->cache, data, ix_p))
+  if (pph_cache_lookup (&stream->cache, data, ix_p, tag))
     return PPH_RECORD_IREF;
 
   /* If DATA is in the cache of an included image, return an external
      reference marker.  */
-  if (pph_cache_lookup_in_includes (data, include_ix_p, ix_p))
+  if (pph_cache_lookup_in_includes (data, include_ix_p, ix_p, tag))
     return PPH_RECORD_XREF;
 
   /* If DATA is a pre-loaded tree node, return a pre-loaded reference
      marker.  */
-  if (pph_cache_lookup (NULL, data, ix_p))
+  if (pph_cache_lookup (NULL, data, ix_p, tag))
     return PPH_RECORD_PREF;
 
   /* DATA is in none of the caches.  It should be pickled out.  */
@@ -268,17 +270,18 @@ pph_get_marker_for (pph_stream *stream, void *data,
unsigned *include_ix_p,
 }
 
 
-/* Write a reference record on STREAM.  MARKER is the tag indicating what
-   kind of reference to write.  IX is the cache slot index to write.
+/* Write a reference record on STREAM.  MARKER is the tag indicating
+   what kind of reference to write.  TAG indicates the data type to be
+   stored in this record.  IX is the cache slot index to write.
    INCLUDE_IX is used for PPH_RECORD_XREF records.  */
 
 static inline void
 pph_out_reference_record (pph_stream *stream, enum pph_record_marker marker,
-                          unsigned include_ix, unsigned ix)
+                          unsigned include_ix, unsigned ix, enum pph_tag tag)
 {
   gcc_assert (marker == PPH_RECORD_END || pph_is_reference_marker (marker));
 
-  pph_out_record_marker (stream, marker);
+  pph_out_record_marker (stream, marker, tag);
 
   if (pph_is_reference_marker (marker))
     {
@@ -296,8 +299,8 @@ pph_out_reference_record (pph_stream *stream, enum
pph_record_marker marker,
 }
 
 
-/* Start a new record in STREAM for DATA.  If DATA is NULL
-   write an end-of-record marker and return true.
+/* 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.
 
    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
@@ -309,23 +312,23 @@ pph_out_reference_record (pph_stream *stream, enum
pph_record_marker marker,
    DATA.  */
 
 static inline bool
-pph_out_start_record (pph_stream *stream, void *data)
+pph_out_start_record (pph_stream *stream, void *data, enum pph_tag tag)
 {
   unsigned include_ix, ix;
   enum pph_record_marker marker;
 
   /* Try to write a reference record first.  */
-  marker = pph_get_marker_for (stream, data, &include_ix, &ix);
+  marker = pph_get_marker_for (stream, data, &include_ix, &ix, tag);
   if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
     {
-      pph_out_reference_record (stream, marker, include_ix, ix);
+      pph_out_reference_record (stream, marker, include_ix, ix, tag);
       return true;
     }
 
   /* 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);
-  pph_out_record_marker (stream, PPH_RECORD_START);
+  pph_cache_add (&stream->cache, data, &ix, tag);
+  pph_out_record_marker (stream, PPH_RECORD_START, tag);
   pph_out_uint (stream, ix);
 
   /* The caller will have to write a physical representation for DATA.  */
@@ -344,11 +347,13 @@ pph_out_start_tree_record (pph_stream *stream, tree t)
 {
   unsigned include_ix, ix;
   enum pph_record_marker marker;
+  enum pph_tag tag;
 
   /* Determine what kind of record we will be writing.  */
-  marker = pph_get_marker_for (stream, t, &include_ix, &ix);
+  tag = pph_tree_code_to_tag (t);
+  marker = pph_get_marker_for (stream, t, &include_ix, &ix, tag);
 
-  /* DECLs and TYPEs that have been read from an external PPH image
+  /* Signed tree nodes that have been read from an external PPH image
      may have mutated while parsing this header.  In that case,
      we need to write a mutated reference record and re-pickle the
      tree.  */
@@ -357,13 +362,13 @@ pph_out_start_tree_record (pph_stream *stream, tree t)
       pph_cache *cache = pph_cache_select (stream, marker, include_ix);
       pph_cache_entry *e = pph_cache_get_entry (cache, ix);
       unsigned crc = pph_get_signature (t, NULL);
-      if (0 && crc != e->crc)
+      if (crc != e->crc)
         marker = PPH_RECORD_START_MUTATED;
     }
 
   /* Write a record header according to the value of MARKER.  */
   if (marker == PPH_RECORD_END || pph_is_reference_marker (marker))
-    pph_out_reference_record (stream, marker, include_ix, ix);
+    pph_out_reference_record (stream, marker, include_ix, ix, tag);
   else if (marker == PPH_RECORD_START)
     {
       /* We want to prevent some trees from hitting the cache.
@@ -375,11 +380,11 @@ pph_out_start_tree_record (pph_stream *stream, tree t)
       if (!pph_cache_should_handle (t))
         marker = PPH_RECORD_START_NO_CACHE;
 
-      pph_out_record_marker (stream, marker);
+      pph_out_record_marker (stream, marker, tag);
       if (marker == PPH_RECORD_START)
         {
           unsigned ix;
-          pph_cache_add (&stream->cache, t, &ix);
+          pph_cache_add (&stream->cache, t, &ix, tag);
           pph_out_uint (stream, ix);
         }
     }
@@ -399,8 +404,8 @@ pph_out_start_tree_record (pph_stream *stream, tree t)
          external version of T.  This way the reader will get the
          location of T from the external reference and overwrite it
          with the contents that we are going to write here.  */
-      pph_cache_add (&stream->cache, t, &internal_ix);
-      pph_out_record_marker (stream, marker);
+      pph_cache_add (&stream->cache, t, &internal_ix, tag);
+      pph_out_record_marker (stream, marker, tag);
 
       /* Write the location of T in the external cache.  */
       gcc_assert (include_ix != -1u);
@@ -549,11 +554,11 @@ pph_tree_matches (tree t, unsigned filter)
     return false;
 
   if ((filter & PPHF_NO_PREFS)
-      && pph_cache_lookup (NULL, t, NULL))
+      && pph_cache_lookup (NULL, t, NULL, pph_tree_code_to_tag (t)))
     return false;
 
   if ((filter & PPHF_NO_XREFS)
-      && pph_cache_lookup_in_includes (t, NULL, NULL))
+      && pph_cache_lookup_in_includes (t, NULL, NULL, pph_tree_code_to_tag
(t)))
     return false;
 
   return true;
@@ -688,7 +693,7 @@ pph_out_cxx_binding_1 (pph_stream *stream, cxx_binding *cb)
 {
   struct bitpack_d bp;
 
-  if (pph_out_start_record (stream, cb))
+  if (pph_out_start_record (stream, cb, PPH_cxx_binding))
     return;
 
   pph_out_tree (stream, cb->value);
@@ -726,7 +731,7 @@ 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))
+  if (pph_out_start_record (stream, cb, PPH_cp_class_binding))
     return;
 
   pph_out_cxx_binding (stream, cb->base);
@@ -739,7 +744,7 @@ 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))
+  if (pph_out_start_record (stream, lb, PPH_cp_label_binding))
     return;
 
   pph_out_tree (stream, lb->label);
@@ -904,7 +909,7 @@ static void
 pph_out_binding_level (pph_stream *stream, cp_binding_level *bl,
 		       unsigned filter)
 {
-  if (pph_out_start_record (stream, bl))
+  if (pph_out_start_record (stream, bl, PPH_cp_binding_level))
     return;
 
   pph_out_binding_level_1 (stream, bl, filter);
@@ -921,20 +926,6 @@ pph_out_tree_common (pph_stream *stream, tree t)
 }
 
 
-/* Write all the fields of c_language_function instance CLF to STREAM.  */
-
-static void
-pph_out_c_language_function (pph_stream *stream,
-			     struct c_language_function *clf)
-{
-  if (pph_out_start_record (stream, clf))
-    return;
-
-  pph_out_tree_vec (stream, clf->x_stmt_tree.x_cur_stmt_list);
-  pph_out_uint (stream, clf->x_stmt_tree.stmts_are_full_exprs_p);
-}
-
-
 /* Write all the fields of language_function instance LF to STREAM.  */
 
 static void
@@ -942,10 +933,11 @@ pph_out_language_function (pph_stream *stream, struct
language_function *lf)
 {
   struct bitpack_d bp;
 
-  if (pph_out_start_record (stream, lf))
+  if (pph_out_start_record (stream, lf, PPH_language_function))
     return;
 
-  pph_out_c_language_function (stream, &lf->base);
+  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);
   pph_out_tree (stream, lf->x_current_class_ptr);
   pph_out_tree (stream, lf->x_current_class_ref);
@@ -1040,7 +1032,7 @@ pph_out_struct_function (pph_stream *stream, struct
function *fn)
 {
   struct pph_tree_info pti;
 
-  if (pph_out_start_record (stream, fn))
+  if (pph_out_start_record (stream, fn, PPH_function))
     return;
 
   pph_out_tree (stream, fn->decl);
@@ -1126,7 +1118,7 @@ pph_out_lang_specific (pph_stream *stream, tree decl)
   struct lang_decl_base *ldb;
 
   ld = DECL_LANG_SPECIFIC (decl);
-  if (pph_out_start_record (stream, ld))
+  if (pph_out_start_record (stream, ld, PPH_lang_decl))
     return;
 
   /* Write all the fields in lang_decl_base.  */
@@ -1201,7 +1193,7 @@ pph_out_sorted_fields_type (pph_stream *stream, struct
sorted_fields_type *sft)
 {
   int i;
 
-  if (pph_out_start_record (stream, sft))
+  if (pph_out_start_record (stream, sft, PPH_sorted_fields_type))
     return;
 
   pph_out_uint (stream, sft->len);
@@ -1270,7 +1262,7 @@ 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))
+  if (!pph_out_start_record (stream, ltc->nested_udts, PPH_binding_table))
     pph_out_binding_table (stream, ltc->nested_udts);
   pph_out_tree (stream, ltc->as_base);
   pph_out_tree_vec (stream, ltc->pure_virtuals);
@@ -1303,7 +1295,7 @@ pph_out_lang_type (pph_stream *stream, tree type)
   struct lang_type *lt;
 
   lt = TYPE_LANG_SPECIFIC (type);
-  if (pph_out_start_record (stream, lt))
+  if (pph_out_start_record (stream, lt, PPH_lang_type))
     return;
 
   pph_out_lang_type_header (stream, &lt->u.h);
@@ -1349,8 +1341,9 @@ pph_out_scope_chain (pph_stream *stream)
      reference to it, instead of writing its fields.  */
   {
     unsigned ix;
-    pph_cache_add (&stream->cache, scope_chain->bindings, &ix);
-    pph_out_record_marker (stream, PPH_RECORD_START);
+    pph_cache_add (&stream->cache, scope_chain->bindings, &ix,
+                   PPH_cp_binding_level);
+    pph_out_record_marker (stream, PPH_RECORD_START, PPH_cp_binding_level);
     pph_out_uint (stream, ix);
     pph_out_binding_level_1 (stream, scope_chain->bindings,
 			     PPHF_NO_XREFS | PPHF_NO_PREFS);
@@ -1424,7 +1417,7 @@ pph_out_cgraph_node (pph_stream *stream, struct
cgraph_node *node)
 {
   struct bitpack_d bp;
 
-  if (pph_out_start_record (stream, node))
+  if (pph_out_start_record (stream, node, PPH_cgraph_node))
     return;
 
   pph_out_tree (stream, node->decl);
diff --git a/gcc/cp/pph-streamer.c b/gcc/cp/pph-streamer.c
index 26bc6cd..ed5b66e 100644
--- a/gcc/cp/pph-streamer.c
+++ b/gcc/cp/pph-streamer.c
@@ -52,20 +52,24 @@ pph_cache_preload (pph_cache *cache)
   unsigned i;
 
   for (i = itk_char; i < itk_none; i++)
-    pph_cache_add (cache, integer_types[i], NULL);
+    pph_cache_add (cache, integer_types[i], NULL,
+                   pph_tree_code_to_tag (integer_types[i]));
 
   for (i = 0; i < TYPE_KIND_LAST; i++)
-    pph_cache_add (cache, sizetype_tab[i], NULL);
+    pph_cache_add (cache, sizetype_tab[i], NULL,
+                   pph_tree_code_to_tag (sizetype_tab[i]));
 
   /* global_trees[] can have NULL entries in it.  Skip them.  */
   for (i = 0; i < TI_MAX; i++)
     if (global_trees[i])
-      pph_cache_add (cache, global_trees[i], NULL);
+      pph_cache_add (cache, global_trees[i], NULL,
+                     pph_tree_code_to_tag (global_trees[i]));
 
   /* c_global_trees[] can have NULL entries in it.  Skip them.  */
   for (i = 0; i < CTI_MAX; i++)
     if (c_global_trees[i])
-      pph_cache_add (cache, c_global_trees[i], NULL);
+      pph_cache_add (cache, c_global_trees[i], NULL,
+                     pph_tree_code_to_tag (c_global_trees[i]));
 
   /* cp_global_trees[] can have NULL entries in it.  Skip them.  */
   for (i = 0; i < CPTI_MAX; i++)
@@ -75,13 +79,16 @@ pph_cache_preload (pph_cache *cache)
 	continue;
 
       if (cp_global_trees[i])
-	pph_cache_add (cache, cp_global_trees[i], NULL);
+	pph_cache_add (cache, cp_global_trees[i], NULL,
+                       pph_tree_code_to_tag (cp_global_trees[i]));
     }
 
   /* Add other well-known nodes that should always be taken from the
      current compilation context.  */
-  pph_cache_add (cache, global_namespace, NULL);
-  pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL);
+  pph_cache_add (cache, global_namespace, NULL,
+                 pph_tree_code_to_tag (global_namespace));
+  pph_cache_add (cache, DECL_CONTEXT (global_namespace), NULL,
+                 pph_tree_code_to_tag (DECL_CONTEXT (global_namespace)));
 }
 
 
@@ -402,15 +409,17 @@ pph_trace_bitpack (pph_stream *stream, struct bitpack_d
*bp)
 }
 
 
-/* Insert DATA in CACHE at slot IX.  As a restriction to prevent
-   stomping on cache entries, this will not allow inserting
-   into the same slot more than once.  */
+/* Insert DATA in CACHE at slot IX.  TAG represents the data structure
+   pointed-to by DATA.  As a restriction to prevent stomping on cache
+   entries, this will not allow inserting into the same slot more than
+   once.  */
 
 void
-pph_cache_insert_at (pph_cache *cache, void *data, unsigned ix)
+pph_cache_insert_at (pph_cache *cache, void *data, unsigned ix,
+                     enum pph_tag tag)
 {
   void **map_slot;
-  pph_cache_entry e = { data, 0, 0 };
+  pph_cache_entry e = { data, tag, 0, 0 };
 
   map_slot = pointer_map_insert (cache->m, data);
 
@@ -424,12 +433,16 @@ pph_cache_insert_at (pph_cache *cache, void *data,
unsigned ix)
 }
 
 
-/* Return true if DATA exists in CACHE.  If IX_P is not NULL, store the cache
-   slot where DATA resides in *IX_P (or (unsigned)-1 if DATA is not found).
-   If CACHE is NULL use pph_preloaded_cache by default.  */
+/* Return true if DATA exists in CACHE.  If IX_P is not NULL, store
+   the cache slot where DATA resides in *IX_P (or (unsigned)-1 if DATA
+   is not found). If CACHE is NULL use pph_preloaded_cache.
+
+   If a cache hit is found, the data type tag for the entry must match
+   TAG.  */
 
 bool
-pph_cache_lookup (pph_cache *cache, void *data, unsigned *ix_p)
+pph_cache_lookup (pph_cache *cache, void *data, unsigned *ix_p,
+                  enum pph_tag tag)
 {
   void **map_slot;
   unsigned ix;
@@ -450,6 +463,14 @@ pph_cache_lookup (pph_cache *cache, void *data, unsigned
*ix_p)
       gcc_assert (slot_ix == (intptr_t)(unsigned) slot_ix);
       ix = (unsigned) slot_ix;
       existed_p = true;
+
+      /* If the caller is looking for a specific tag, make sure
+         it matches the tag we pulled from the cache.  */
+      if (tag != PPH_null)
+        {
+          pph_cache_entry *e = pph_cache_get_entry (cache, ix);
+          gcc_assert (tag == e->tag);
+        }
     }
 
   if (ix_p)
@@ -459,7 +480,8 @@ pph_cache_lookup (pph_cache *cache, void *data, unsigned
*ix_p)
 }
 
 
-/* Return true if DATA is in the pickle cache of one of the included images.
+/* Return true if DATA is in the pickle cache of one of the included
+   images.  TAG is the expected data type TAG for data.
 
    If DATA is found:
       - the index for INCLUDE_P into IMAGE->INCLUDES is returned in
@@ -475,18 +497,30 @@ pph_cache_lookup (pph_cache *cache, void *data, unsigned
*ix_p)
 
 bool
 pph_cache_lookup_in_includes (void *data, unsigned *include_ix_p,
-                              unsigned *ix_p)
+                              unsigned *ix_p, enum pph_tag tag)
 {
   unsigned include_ix, ix;
   pph_stream *include;
   bool found_it;
 
+  /* When searching the external caches, do not try to find a match
+     for TAG.  Since this is an external cache, the parser may have
+     re-allocated the object pointed by DATA (e.g., when merging
+     decls).  In this case, TAG will be different from the tag we find
+     in the cache, so instead of ICEing, we ignore the match so the
+     caller is forced to pickle DATA.  */
   found_it = false;
   FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, include_ix, include)
-    if (pph_cache_lookup (&include->cache, data, &ix))
+    if (pph_cache_lookup (&include->cache, data, &ix, PPH_null))
       {
-	found_it = true;
-	break;
+        pph_cache_entry *e = pph_cache_get_entry (&include->cache, ix);
+
+        /* Only consider DATA found if its data type matches TAG.  If
+           not, it means that the object pointed by DATA has changed,
+           so DATA will need to be re-pickled.  */
+        if (e->tag == tag)
+          found_it = true;
+        break;
       }
 
   if (!found_it)
@@ -505,23 +539,23 @@ pph_cache_lookup_in_includes (void *data, unsigned
*include_ix_p,
 }
 
 
-/* Add pointer DATA to CACHE.  If IX_P is not NULL, on exit *IX_P will contain
-   the slot number where DATA is stored.  Return true if DATA already existed
-   in the CACHE, false otherwise.  */
+/* Add pointer DATA with data type TAG to CACHE.  If IX_P is not NULL,
+   on exit *IX_P will contain the slot number where DATA is stored.
+   Return true if DATA already existed in the CACHE, false otherwise.  */
 
 bool
-pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p)
+pph_cache_add (pph_cache *cache, void *data, unsigned *ix_p, enum pph_tag tag)
 {
   unsigned ix;
   bool existed_p;
 
-  if (pph_cache_lookup (cache, data, &ix))
+  if (pph_cache_lookup (cache, data, &ix, tag))
     existed_p = true;
   else
     {
       existed_p = false;
       ix = VEC_length (pph_cache_entry, cache->v);
-      pph_cache_insert_at (cache, data, ix);
+      pph_cache_insert_at (cache, data, ix, tag);
     }
 
   if (ix_p)
diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h
index 2f1b390..fd1b267 100644
--- a/gcc/cp/pph-streamer.h
+++ b/gcc/cp/pph-streamer.h
@@ -71,6 +71,42 @@ enum pph_record_marker {
   PPH_RECORD_PREF
 };
 
+/* Record type tags.  Every record saved on a PPH image contains a data
+   tag to identify the data structure saved in that record.  */
+enum pph_tag {
+  PPH_null = 0,
+
+  /* The tags below are named after the data types they represent.
+
+     Note that to simplify tag management, we reserve enough
+     values to fit all the tree codes.  This guarantees that for
+     every tree code C and PPH tag T, (unsigned) C == (unsigned) T.
+
+     The value PPH_any_tree is used when reading tree records.  Since
+     the reader does not have enough context, it will generally not
+     know what kind of tree is about to read, all it knows is that it
+     should be a valid tree code.  */
+  PPH_any_tree = MAX_TREE_CODES,
+
+  /* Maintain the tags below in alphabetical order.  */
+  PPH_binding_entry,
+  PPH_binding_table,
+  PPH_cgraph_node,
+  PPH_cp_binding_level,
+  PPH_cp_class_binding,
+  PPH_cp_label_binding,
+  PPH_cxx_binding,
+  PPH_function,
+  PPH_lang_decl,
+  PPH_lang_type,
+  PPH_language_function,
+  PPH_sorted_fields_type,
+
+  /* This tag must always be last.  */
+  PPH_NUM_TAGS
+};
+
+
 /* Line table markers. We only stream line table entries from the parent header
    file, other entries are referred to by the name of the file which is then
    loaded as an include at the correct point in time.  */
@@ -130,6 +166,9 @@ typedef struct pph_cache_entry {
   /* Pointer to cached data.  */
   void *data;
 
+  /* Tag describing the type of the cached data.  */
+  enum pph_tag tag;
+
   /* Checksum information for DATA.  */
   unsigned int crc;
 
@@ -285,10 +324,11 @@ void pph_trace_string_with_length (pph_stream *, const
char *, unsigned);
 void pph_trace_location (pph_stream *, location_t);
 void pph_trace_chain (pph_stream *, tree);
 void pph_trace_bitpack (pph_stream *, struct bitpack_d *);
-void pph_cache_insert_at (pph_cache *, void *, unsigned);
-bool pph_cache_lookup (pph_cache *, void *, unsigned *);
-bool pph_cache_lookup_in_includes (void *, unsigned *, unsigned *);
-bool pph_cache_add (pph_cache *, void *, unsigned *);
+void pph_cache_insert_at (pph_cache *, void *, unsigned, enum pph_tag);
+bool pph_cache_lookup (pph_cache *, void *, unsigned *, enum pph_tag);
+bool pph_cache_lookup_in_includes (void *, unsigned *, unsigned *,
+                                   enum pph_tag);
+bool pph_cache_add (pph_cache *, void *, unsigned *, enum pph_tag);
 void pph_cache_sign (pph_cache *, unsigned, unsigned, size_t);
 unsigned pph_get_signature (tree, size_t *);
 
@@ -366,15 +406,6 @@ pph_cache_select (pph_stream *stream, enum
pph_record_marker marker,
     }
 }
 
-/* Return the data pointer at slot IX in CACHE  */
-static inline void *
-pph_cache_get (pph_cache *cache, unsigned ix)
-{
-  pph_cache_entry *e = VEC_index (pph_cache_entry, cache->v, ix);
-  gcc_assert (e);
-  return e->data;
-}
-
 /* Return entry IX in CACHE.  */
 static inline pph_cache_entry *
 pph_cache_get_entry (pph_cache *cache, unsigned ix)
@@ -382,6 +413,14 @@ pph_cache_get_entry (pph_cache *cache, unsigned ix)
   return VEC_index (pph_cache_entry, cache->v, ix);
 }
 
+/* Return the data pointer at slot IX in CACHE  */
+static inline void *
+pph_cache_get (pph_cache *cache, unsigned ix)
+{
+  pph_cache_entry *e = pph_cache_get_entry (cache, ix);
+  return e->data;
+}
+
 /* Output array A of cardinality C of ASTs to STREAM.  */
 /* FIXME pph: hold for alternate routine. */
 #if 0
@@ -694,17 +733,22 @@ pph_in_bitpack (pph_stream *stream)
   return bp;
 }
 
-/* Write record MARKER to STREAM.  */
+/* Write record MARKER for data type TAG to STREAM.  */
 static inline void
-pph_out_record_marker (pph_stream *stream, enum pph_record_marker marker)
+pph_out_record_marker (pph_stream *stream, enum pph_record_marker marker,
+                       enum pph_tag tag)
 {
   gcc_assert (marker == (enum pph_record_marker)(unsigned char) marker);
   pph_out_uchar (stream, marker);
+
+  gcc_assert (tag == (enum pph_tag)(unsigned) tag);
+  pph_out_uint (stream, tag);
 }
 
-/* Read and return a record marker from STREAM.  */
+/* Read and return a record marker from STREAM.  On return, *TAG_P will
+   contain the tag for the data type stored in this record.  */
 static inline enum pph_record_marker
-pph_in_record_marker (pph_stream *stream)
+pph_in_record_marker (pph_stream *stream, enum pph_tag *tag_p)
 {
   enum pph_record_marker m = (enum pph_record_marker) pph_in_uchar (stream);
   gcc_assert (m == PPH_RECORD_START
@@ -714,6 +758,10 @@ pph_in_record_marker (pph_stream *stream)
 	      || m == PPH_RECORD_IREF
 	      || m == PPH_RECORD_XREF
 	      || m == PPH_RECORD_PREF);
+
+  *tag_p = (enum pph_tag) pph_in_uint (stream);
+  gcc_assert ((unsigned) *tag_p < (unsigned) PPH_NUM_TAGS);
+
   return m;
 }
 
@@ -755,4 +803,26 @@ tree_needs_signature (tree t)
   return DECL_P (t) || TYPE_P (t);
 }
 
+/* Return true if PPH tag TAG corresponds to a valid tree code.  */
+static inline bool
+pph_tag_is_tree_code (enum pph_tag tag)
+{
+  return (unsigned) tag < (unsigned) MAX_TREE_CODES;
+}
+
+/* Return the PPH tag associated with tree node T.  */
+static inline enum pph_tag
+pph_tree_code_to_tag (tree t)
+{
+  return t ? (enum pph_tag) TREE_CODE (t) : PPH_null;
+}
+
+/* Return the tree code associated with PPH tag TAG.  */
+static inline enum tree_code
+pph_tag_to_tree_code (enum pph_tag tag)
+{
+  gcc_assert (pph_tag_is_tree_code (tag));
+  return (enum tree_code) tag;
+}
+
 #endif  /* GCC_CP_PPH_STREAMER_H  */
diff --git a/gcc/testsuite/ChangeLog.pph b/gcc/testsuite/ChangeLog.pph
index ba9738d..b010e1f 100644
--- a/gcc/testsuite/ChangeLog.pph
+++ b/gcc/testsuite/ChangeLog.pph
@@ -1,3 +1,8 @@
+2011-10-03   Diego Novillo  <dnovillo@google.com>
+
+	* g++.dg/pph/x6dynarray4.cc: Mark partially fixed.
+	* g++.dg/pph/x7dynarray5.cc: Mark partially fixed.
+
 2011-10-01   Diego Novillo  <dnovillo@google.com>
 
 	* g++.dg/pph/p4mean.cc: Remove XFAILs.  Add -w -fpermissive flags.
diff --git a/gcc/testsuite/g++.dg/pph/x6dynarray4.cc
b/gcc/testsuite/g++.dg/pph/x6dynarray4.cc
index 2dfd24b..2c3761a 100644
--- a/gcc/testsuite/g++.dg/pph/x6dynarray4.cc
+++ b/gcc/testsuite/g++.dg/pph/x6dynarray4.cc
@@ -1,5 +1,4 @@
 // { dg-xfail-if "BOGUS" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "internal compiler error: Segmentation fault" "" { xfail *-*-* }
0 }
 #include "x6dynarray5.h"
 
 #include <algorithm>
diff --git a/gcc/testsuite/g++.dg/pph/x7dynarray5.cc
b/gcc/testsuite/g++.dg/pph/x7dynarray5.cc
index 045b0bb..1e0565e 100644
--- a/gcc/testsuite/g++.dg/pph/x7dynarray5.cc
+++ b/gcc/testsuite/g++.dg/pph/x7dynarray5.cc
@@ -1,6 +1,4 @@
 // { dg-xfail-if "BOGUS" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "internal compiler error: Segmentation fault" "" { xfail *-*-* }
0 }
-
 #include "x0dynarray4.h"
 #include "x6dynarray5.h"
 
-- 
1.7.3.1


--
This patch is available for review at http://codereview.appspot.com/5164048
Sign in to reply to this message.

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b