Patchwork [pph] Make tracing more robust. (issue5616043)

login
register
mail settings
Submitter Lawrence Crowl
Date Feb. 1, 2012, 7:24 p.m.
Message ID <20120201192411.1F5A722265F@jade.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/138967/
State New
Headers show

Comments

Lawrence Crowl - Feb. 1, 2012, 7:24 p.m.
This patch makes tracing more robust.  It attempts to use type dumping
where possible, use the PPH merge name where possible, and otherwise
use "?". It protects protecting existing type dump machinery against
some unexpected nulls.  It changes tree streaming to write decl
minimal fields first, so that they can be used while reading other
fields.

The patch adds some new tests for the upcoming type merging.

Tested on x64.



--
This patch is available for review at http://codereview.appspot.com/5616043

Patch

Index: gcc/testsuite/ChangeLog.pph

2012-02-01   Lawrence Crowl  <crowl@google.com>

	* g++.dg/pph/c0struct.h: Rename to c0struct2.h.
	* g++.dg/pph/c0struct1.h: New.  Has no typedefs.
	* g++.dg/pph/c1struct.cc: Rename to c1struct2.cc.
	* g++.dg/pph/c1struct1.cc: New.  Has no typedefs.
	* g++.dg/pph/x0struct0.h: Rename to x0struct2.h.
	* g++.dg/pph/x0struct1.h: New.  Has no typedefs.
	* g++.dg/pph/x1struct2.h: Rename to x1struct3.h.
	* g++.dg/pph/x1struct1.h: Rename to x1struct2.h.
	* g++.dg/pph/x1struct1.h: New.  Has no typedefs.
	* g++.dg/pph/x2struct2.cc: Rename to x2struct3.cc.
	* g++.dg/pph/x2struct1.cc: Rename to x2struct2.cc.
	* g++.dg/pph/x2struct1.cc: New.  Has no typedefs.

Index: gcc/cp/ChangeLog.pph

2012-02-01   Lawrence Crowl  <crowl@google.com>

	* pph-streamer.h (pph_trace_tree):  Add name parameter.  Adjust callers
	to match.
	* pph-core.c (pph_trace_tree):  Add name parameter to override
	pretty-printing the tree.
	* error.c (dump_type): Protect against null TYPE_NAME.
	(dump_aggr_type): Factor out test for template.
	(is_template): New.  Protect against null DECL_TEMPLATE_PARMS.
	* pph-out.c (pph_out_merge_body_namespace_decl): Factor out assert for
	mergable trees into separate cases.  Merging of types is currently
	unexpected and disabled.
	* pph-in.c (pph_in_merge_key_namespace_decl): Remove redundant assert
	for mergable trees.
	(pph_in_merge_key_namespace_decl): Factor out assert for mergable trees
	into separate cases.  Merging of types is currently unexpected and
	disabled.

Index: gcc/ChangeLog.pph

2012-02-01   Lawrence Crowl  <crowl@google.com>

	* tree-streamer-out.c (streamer_write_tree_body): Write decl minimal
	fields first, so that they can be used when reading other fields.
	* tree-streamer-in.c (streamer_write_tree_body): Read decl minimal
	fields first, so that they can be used when reading other fields.


Index: gcc/testsuite/g++.dg/pph/c0struct2.h
===================================================================
--- gcc/testsuite/g++.dg/pph/c0struct2.h	(revision 183736)
+++ gcc/testsuite/g++.dg/pph/c0struct2.h	(working copy)
@@ -1,5 +1,5 @@ 
-#ifndef C0STRUCT_H
-#define C0STRUCT_H
+#ifndef C0STRUCT2_H
+#define C0STRUCT2_H
 typedef int type;
 type gbl = 1;
 struct B {
Index: gcc/testsuite/g++.dg/pph/x0struct1.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x0struct1.h	(revision 0)
+++ gcc/testsuite/g++.dg/pph/x0struct1.h	(revision 0)
@@ -0,0 +1,5 @@ 
+#ifndef X0STRUCT1_H
+#define X0STRUCT1_H
+struct B {
+};
+#endif
Index: gcc/testsuite/g++.dg/pph/c0struct.h
===================================================================
--- gcc/testsuite/g++.dg/pph/c0struct.h	(revision 183805)
+++ gcc/testsuite/g++.dg/pph/c0struct.h	(working copy)
@@ -1,9 +0,0 @@ 
-#ifndef C0STRUCT_H
-#define C0STRUCT_H
-typedef int type;
-type gbl = 1;
-struct B {
-    type fld;
-};
-typedef B thing;
-#endif
Index: gcc/testsuite/g++.dg/pph/x0struct2.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x0struct2.h	(revision 183736)
+++ gcc/testsuite/g++.dg/pph/x0struct2.h	(working copy)
@@ -1,5 +1,5 @@ 
-#ifndef X0STRUCT0_H
-#define X0STRUCT0_H
+#ifndef X0STRUCT2_H
+#define X0STRUCT2_H
 typedef int type;
 struct B {
 };
Index: gcc/testsuite/g++.dg/pph/c1struct1.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/c1struct1.cc	(revision 0)
+++ gcc/testsuite/g++.dg/pph/c1struct1.cc	(revision 0)
@@ -0,0 +1,4 @@ 
+#include "c0struct1.h"
+
+B var1;
+B var2 = { 3 };
Index: gcc/testsuite/g++.dg/pph/x2struct1.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x2struct1.cc	(revision 183805)
+++ gcc/testsuite/g++.dg/pph/x2struct1.cc	(working copy)
@@ -1,10 +1,9 @@ 
 #include "x1struct1.h"
 
-type D::method()
+int D::method()
 { static int x = 2;
   return fld + mbr; }
 
-type D::mbr = 4;
-typedef D D2;
-D2 var1;
-D2 var2 = var1;
+int D::mbr = 4;
+D var1;
+D var2 = var1;
Index: gcc/testsuite/g++.dg/pph/c1struct.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/c1struct.cc	(revision 183805)
+++ gcc/testsuite/g++.dg/pph/c1struct.cc	(working copy)
@@ -1,4 +0,0 @@ 
-#include "c0struct.h"
-
-thing var1;
-thing var2 = { 3 };
Index: gcc/testsuite/g++.dg/pph/c1struct2.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/c1struct2.cc	(revision 183736)
+++ gcc/testsuite/g++.dg/pph/c1struct2.cc	(working copy)
@@ -1,4 +1,4 @@ 
-#include "c0struct.h"
+#include "c0struct2.h"
 
 thing var1;
 thing var2 = { 3 };
Index: gcc/testsuite/g++.dg/pph/x1struct1.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x1struct1.h	(revision 183805)
+++ gcc/testsuite/g++.dg/pph/x1struct1.h	(working copy)
@@ -1,11 +1,11 @@ 
 #ifndef X1STRUCT1_H
 #define X1STRUCT1_H
-#include "x0struct0.h"
-struct D : public thing {
-    type method();
-    type another()
+#include "x0struct1.h"
+struct D : public B {
+    int method();
+    int another()
     { return fld + mbr; }
-    type fld;
-    static type mbr;
+    int fld;
+    static int mbr;
 };
 #endif
Index: gcc/testsuite/g++.dg/pph/x2struct2.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x2struct2.cc	(revision 183805)
+++ gcc/testsuite/g++.dg/pph/x2struct2.cc	(working copy)
@@ -2,7 +2,7 @@ 
 
 type D::method()
 { static int x = 2;
-  return fld + mbr + gbl; }
+  return fld + mbr; }
 
 type D::mbr = 4;
 typedef D D2;
Index: gcc/testsuite/g++.dg/pph/x1struct2.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x1struct2.h	(revision 183736)
+++ gcc/testsuite/g++.dg/pph/x1struct2.h	(working copy)
@@ -1,6 +1,6 @@ 
-#ifndef X1STRUCT1_H
-#define X1STRUCT1_H
-#include "x0struct0.h"
+#ifndef X1STRUCT2_H
+#define X1STRUCT2_H
+#include "x0struct2.h"
 struct D : public thing {
     type method();
     type another()
Index: gcc/testsuite/g++.dg/pph/x2struct3.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x2struct3.cc	(revision 0)
+++ gcc/testsuite/g++.dg/pph/x2struct3.cc	(revision 0)
@@ -0,0 +1,10 @@ 
+#include "x1struct3.h"
+
+type D::method()
+{ static int x = 2;
+  return fld + mbr + gbl; }
+
+type D::mbr = 4;
+typedef D D2;
+D2 var1;
+D2 var2 = var1;
Index: gcc/testsuite/g++.dg/pph/x1struct3.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x1struct3.h	(revision 183736)
+++ gcc/testsuite/g++.dg/pph/x1struct3.h	(working copy)
@@ -1,6 +1,6 @@ 
 #ifndef X1STRUCT_H
 #define X1STRUCT_H
-#include "c0struct.h"
+#include "c0struct2.h"
 struct D : thing {
     type method();
     type another()
Index: gcc/testsuite/g++.dg/pph/c0struct1.h
===================================================================
--- gcc/testsuite/g++.dg/pph/c0struct1.h	(revision 0)
+++ gcc/testsuite/g++.dg/pph/c0struct1.h	(revision 0)
@@ -0,0 +1,7 @@ 
+#ifndef C0STRUCT1_H
+#define C0STRUCT1_H
+int gbl = 1;
+struct B {
+    int fld;
+};
+#endif
Index: gcc/testsuite/g++.dg/pph/x0struct0.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x0struct0.h	(revision 183805)
+++ gcc/testsuite/g++.dg/pph/x0struct0.h	(working copy)
@@ -1,7 +0,0 @@ 
-#ifndef X0STRUCT0_H
-#define X0STRUCT0_H
-typedef int type;
-struct B {
-};
-typedef B thing;
-#endif
Index: gcc/cp/pph-core.c
===================================================================
--- gcc/cp/pph-core.c	(revision 183805)
+++ gcc/cp/pph-core.c	(working copy)
@@ -364,7 +364,8 @@  pph_trace_marker (enum pph_record_marker
 /* Print tracing information for a possibly MERGEABLE tree T.  */
 
 void
-pph_trace_tree (tree t, enum pph_trace_end end, enum pph_trace_kind kind)
+pph_trace_tree (tree t, const char *name,
+		enum pph_trace_end end, enum pph_trace_kind kind)
 {
   char end_char, kind_char, decl_char;
   bool is_merge, is_decl;
@@ -390,7 +391,7 @@  pph_trace_tree (tree t, enum pph_trace_e
 	break;
       case pph_trace_mutate:
 	kind_char = '=';
-	is_merge = false;
+	is_merge = true;
 	break;
       case pph_trace_normal:
 	kind_char = '.';
@@ -421,9 +422,9 @@  pph_trace_tree (tree t, enum pph_trace_e
   if (emit)
     {
       fprintf (pph_logfile, "PPH: %c%c%c ", end_char, kind_char, decl_char);
-      if (kind == pph_trace_unmerged_key || end == pph_trace_front)
-	fprintf (pph_logfile, "%s -------\n",
-			      pph_tree_code_text (TREE_CODE (t)));
+      if (name)
+	fprintf (pph_logfile, "%p %s %s\n", (void*)t,
+			      pph_tree_code_text (TREE_CODE (t)), name);
       else
         pph_dump_tree_name (pph_logfile, t, 0);
     }
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c	(revision 183805)
+++ gcc/cp/error.c	(working copy)
@@ -463,12 +463,21 @@  dump_type (tree t, int flags)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      pp_cxx_cv_qualifier_seq (cxx_pp, t);
-      if (TYPE_IDENTIFIER (t))
-	pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
-      else
-	pp_cxx_canonical_template_parameter
-	  (cxx_pp, TEMPLATE_TYPE_PARM_INDEX (t));
+      {
+	tree decl = TYPE_NAME (t);
+	pp_cxx_cv_qualifier_seq (cxx_pp, t);
+	if (decl)
+	  {
+	    tree ident = DECL_NAME (decl);
+	    if (ident)
+	      pp_cxx_tree_identifier (cxx_pp, ident);
+	    else
+	      pp_cxx_canonical_template_parameter
+		    (cxx_pp, TEMPLATE_TYPE_PARM_INDEX (t));
+	  }
+	else
+	  pp_cxx_ws_string (cxx_pp, "<nameless>");
+      }
       break;
 
       /* This is not always necessary for pointers and such, but doing this
@@ -593,6 +602,27 @@  class_key_or_enum_as_string (tree t)
     return "struct";
 }
 
+
+/* Determine if a tree T is a template.  */
+
+static bool is_template (tree t)
+{
+  tree ti_tmpl, parms;
+  if (TREE_CODE (t) == ENUMERAL_TYPE)
+    return false;
+  if (!TYPE_LANG_SPECIFIC (t))
+    return false;
+  if (!CLASSTYPE_TEMPLATE_INFO (t))
+    return false;
+  ti_tmpl = CLASSTYPE_TI_TEMPLATE (t);
+  if (TREE_CODE (ti_tmpl) != TEMPLATE_DECL)
+    return true;
+  parms = DECL_TEMPLATE_PARMS (ti_tmpl);
+  if (parms)
+    return PRIMARY_TEMPLATE_P (ti_tmpl);
+  return false;
+}
+
 /* Print out a class declaration T under the control of FLAGS,
    in the form `class foo'.  */
 
@@ -629,10 +659,7 @@  dump_aggr_type (tree t, int flags)
 	  typdef = 0;
 	}
 
-      tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
-		&& TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
-		&& (TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
-		    || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
+      tmplate = !typdef && is_template (t);
       
       if (! (flags & TFF_UNQUALIFIED_NAME))
 	dump_scope (CP_DECL_CONTEXT (name), flags | TFF_SCOPE);
Index: gcc/cp/pph-out.c
===================================================================
--- gcc/cp/pph-out.c	(revision 183805)
+++ gcc/cp/pph-out.c	(working copy)
@@ -2290,7 +2290,7 @@  pph_out_merge_key_namespace_decl (pph_st
   pph_out_merge_name (stream, decl);
 
   if (flag_pph_tracer)
-    pph_trace_tree (decl, pph_trace_front, pph_trace_key_out);
+    pph_trace_tree (decl, NULL, pph_trace_front, pph_trace_key_out);
 
   pph_out_tree (stream, DECL_NAME (decl));
 
@@ -2302,7 +2302,7 @@  pph_out_merge_key_namespace_decl (pph_st
     pph_out_merge_key_binding_level (stream, NAMESPACE_LEVEL (decl));
 
   if (flag_pph_tracer)
-    pph_trace_tree (decl, pph_trace_back, pph_trace_key_out);
+    pph_trace_tree (decl, NULL, pph_trace_back, pph_trace_key_out);
 }
 
 
@@ -2319,7 +2319,7 @@  pph_out_merge_body_namespace_decl (pph_s
   pph_out_tree_header (stream, decl);
 
   if (flag_pph_tracer)
-    pph_trace_tree (decl, pph_trace_front, pph_trace_merge_body);
+    pph_trace_tree (decl, NULL, pph_trace_front, pph_trace_merge_body);
 
   /* If EXPR is a namespace alias, it will not have an associated
      binding.  In that case, tell the reader not to bother with it.  */
@@ -2329,7 +2329,7 @@  pph_out_merge_body_namespace_decl (pph_s
     pph_out_merge_body_binding_level (stream, NAMESPACE_LEVEL (decl));
 
   if (flag_pph_tracer)
-    pph_trace_tree (decl, pph_trace_back, pph_trace_merge_body);
+    pph_trace_tree (decl, NULL, pph_trace_back, pph_trace_merge_body);
 }
 
 
@@ -2338,40 +2338,30 @@  pph_out_merge_body_namespace_decl (pph_s
 static void
 pph_out_merge_key_tree (pph_stream *stream, tree expr)
 {
-  gcc_assert (pph_tree_is_mergeable (expr));
-
   if (pph_out_start_merge_key_tree_record (stream, expr))
     return;
 
   if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_front, pph_trace_key_out);
+    pph_trace_tree (expr, NULL, pph_trace_front, pph_trace_key_out);
 
   /* Write merge key information.  This includes EXPR's header (needed
-     to re-allocate EXPR in the reader) and the merge key, used to
-     lookup EXPR in the reader's context and merge if necessary.  */
+     to re-allocate EXPR in the reader). */
   pph_out_tree_header (stream, expr);
-  pph_out_merge_name (stream, expr);
+
   if (DECL_P (expr))
     {
-#if 0
-/* FIXME pph: Distable tree merging for the moment.  */
-      else if (TREE_CODE (expr) == TYPE_DECL)
-        pph_out_merge_key_tree (stream, TREE_TYPE (expr));
+      /* Write the merge name, used to lookup EXPR in the reader's context
+	 and merge if necessary.  */
+      pph_out_merge_name (stream, expr);
     }
-  else if (CLASS_TYPE_P (expr))
+  else
     {
-      unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
-      pph_out_merge_key_chain (stream, TYPE_FIELDS (expr), filter);
-      pph_out_merge_key_chain (stream, TYPE_METHODS (expr), filter);
-      /* FIXME pph: Nested types are broken.
-      pph_out_binding_table (stream, CLASSTYPE_NESTED_UTDS (expr));
-      pph_out_merge_key_chain (stream, CLASSTYPE_DECL_LIST (expr), filter);
-      */
-#endif
+      gcc_assert (TYPE_P (expr));
+      gcc_assert (false);
     }
 
   if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_back, pph_trace_key_out);
+    pph_trace_tree (expr, NULL, pph_trace_back, pph_trace_key_out);
 }
 
 
@@ -2411,7 +2401,7 @@  pph_out_tree (pph_stream *stream, tree e
     }
 
   if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_front,
+    pph_trace_tree (expr, NULL, pph_trace_front,
 	marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
 	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
 	: pph_trace_normal);
@@ -2443,7 +2433,7 @@  pph_out_tree (pph_stream *stream, tree e
     gcc_unreachable ();
 
   if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_back,
+    pph_trace_tree (expr, NULL, pph_trace_back,
 	marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
 	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
 	: pph_trace_normal);
Index: gcc/cp/pph-streamer.h
===================================================================
--- gcc/cp/pph-streamer.h	(revision 183805)
+++ gcc/cp/pph-streamer.h	(working copy)
@@ -260,7 +260,8 @@  pph_stream *pph_stream_open (const char 
 void pph_stream_close (pph_stream *);
 void pph_stream_close_no_flush (pph_stream *);
 void pph_trace_marker (enum pph_record_marker marker, enum pph_tag tag);
-void pph_trace_tree (tree, enum pph_trace_end, enum pph_trace_kind);
+void pph_trace_tree (tree, const char *,
+		     enum pph_trace_end, enum pph_trace_kind);
 pph_cache_entry *pph_cache_insert_at (pph_cache *, void *, unsigned,
 				      enum pph_tag);
 pph_cache_entry *pph_cache_lookup (pph_cache *, void *, unsigned *,
Index: gcc/cp/pph-in.c
===================================================================
--- gcc/cp/pph-in.c	(revision 183805)
+++ gcc/cp/pph-in.c	(working copy)
@@ -2281,11 +2281,9 @@  pph_in_merge_key_namespace_decl (pph_str
   gcc_assert (decl == NULL || TREE_CODE (decl) == NAMESPACE_DECL);
 
   read_decl = pph_in_tree_header (stream, &fully_read_p);
-  gcc_assert (!fully_read_p && pph_tree_is_mergeable (read_decl));
+  gcc_assert (!fully_read_p && TREE_CODE (read_decl) == NAMESPACE_DECL);
   name = pph_in_string (stream);
 
-  gcc_assert (TREE_CODE (read_decl) == NAMESPACE_DECL);
-
   if (!decl)
     {
       /* The record is new, so we need to link it in.  */
@@ -2303,7 +2301,7 @@  pph_in_merge_key_namespace_decl (pph_str
     }
 
   if (flag_pph_tracer)
-    pph_trace_tree (decl, pph_trace_front, pph_trace_unmerged_key);
+    pph_trace_tree (decl, name, pph_trace_front, pph_trace_unmerged_key);
 
   name_id = pph_in_tree (stream);
   if (decl == read_decl)
@@ -2334,7 +2332,7 @@  pph_in_merge_key_namespace_decl (pph_str
     }
 
   if (flag_pph_tracer)
-    pph_trace_tree (decl, pph_trace_back, pph_trace_unmerged_key);
+    pph_trace_tree (decl, name, pph_trace_back, pph_trace_unmerged_key);
 }
 
 
@@ -2382,7 +2380,7 @@  pph_in_merge_body_namespace_decl (pph_st
     }
 
   if (flag_pph_tracer)
-    pph_trace_tree (decl, pph_trace_front, pph_trace_merge_body);
+    pph_trace_tree (decl, "?", pph_trace_front, pph_trace_merge_body);
 
   gcc_assert (DECL_NAME (decl));
 
@@ -2399,7 +2397,7 @@  pph_in_merge_body_namespace_decl (pph_st
     }
 
   if (flag_pph_tracer)
-    pph_trace_tree (decl, pph_trace_back, pph_trace_merge_body);
+    pph_trace_tree (decl, NULL, pph_trace_back, pph_trace_merge_body);
 }
 
 
@@ -2427,47 +2425,37 @@  pph_in_merge_key_tree (pph_stream *strea
   /* Materialize a new node from STREAM.  This will also read all the
      language-independent bitfields for the new tree.  */
   read_expr = pph_in_tree_header (stream, &fully_read_p);
-  gcc_assert (!fully_read_p && pph_tree_is_mergeable (read_expr));
-  name = pph_in_string (stream);
-
-  /* If we are merging into an existing CHAIN.  Look for a match in
-     CHAIN to READ_EXPR's header.  If we found a match, EXPR will be
-     the existing tree that matches READ_EXPR. Otherwise, EXPR is the
-     newly allocated READ_EXPR.  */
-  expr = (chain) ? pph_merge_into_chain (read_expr, name, chain) : read_expr;
-  gcc_assert (expr != NULL);
+  gcc_assert (!fully_read_p);
 
-  pph_cache_insert_at (&stream->cache, expr, ix, pph_tree_code_to_tag (expr));
+  if (DECL_P (read_expr))
+    {
+      gcc_assert (chain);
+      name = pph_in_string (stream);
+      /* If we are merging into an existing CHAIN.  Look for a match in
+         CHAIN to READ_EXPR's header.  If we found a match, EXPR will be
+         the existing tree that matches READ_EXPR. Otherwise, EXPR is the
+         newly allocated READ_EXPR.  */
+      expr = pph_merge_into_chain (read_expr, name, chain);
+      gcc_assert (expr != NULL);
+      pph_cache_insert_at (&stream->cache, expr, ix,
+			   pph_tree_code_to_tag (expr));
 
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_front,
-		    expr == read_expr ? pph_trace_unmerged_key
-				      : pph_trace_merged_key);
+      if (flag_pph_tracer)
+        pph_trace_tree (expr, name, pph_trace_front,
+		        expr == read_expr ? pph_trace_unmerged_key
+				          : pph_trace_merged_key);
 
-  if (DECL_P (expr))
-    {
-#if 0
-/* FIXME pph: Disable type merging for the moment.  */
-      else if (TREE_CODE (expr) == TYPE_DECL)
-        /* Types are not on a chain.  */
-        TREE_TYPE (expr) = pph_in_merge_key_tree (stream, NULL);
+      if (flag_pph_tracer)
+        pph_trace_tree (expr, name, pph_trace_back,
+		        expr == read_expr ? pph_trace_unmerged_key
+				          : pph_trace_merged_key);
     }
-  else if (CLASS_TYPE_P (expr))
+  else
     {
-      pph_in_merge_key_chain (stream, &TYPE_FIELDS (expr));
-      pph_in_merge_key_chain (stream, &TYPE_METHODS (expr));
-      /*FIXME pph: Nested types are broken.
-      pph_in_binding_table (stream, &CLASSTYPE_NESTED_UTDS (expr));
-      pph_in_merge_key_chain (stream, &CLASSTYPE_DECL_LIST (expr));
-      */
-#endif
+      gcc_assert (TYPE_P (read_expr));
+      gcc_assert (false);
     }
 
-  if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_back,
-		    expr == read_expr ? pph_trace_unmerged_key
-				      : pph_trace_merged_key);
-
   return expr;
 }
 
@@ -2527,7 +2515,7 @@  pph_in_tree (pph_stream *stream)
     pph_cache_insert_at (&stream->cache, expr, ix, pph_tree_code_to_tag (expr));
 
   if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_front,
+    pph_trace_tree (expr, "?", pph_trace_front,
 	marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
 	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
 	: pph_trace_normal );
@@ -2538,7 +2526,7 @@  pph_in_tree (pph_stream *stream)
     pph_in_tree_body (stream, expr);
 
   if (flag_pph_tracer)
-    pph_trace_tree (expr, pph_trace_back,
+    pph_trace_tree (expr, NULL, pph_trace_back,
 	marker == PPH_RECORD_START_MERGE_BODY ? pph_trace_merge_body
 	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
 	: pph_trace_normal);
Index: gcc/tree-streamer-out.c
===================================================================
--- gcc/tree-streamer-out.c	(revision 183805)
+++ gcc/tree-streamer-out.c	(working copy)
@@ -808,6 +808,9 @@  streamer_write_tree_body (struct output_
 
   code = TREE_CODE (expr);
 
+  if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
+    write_ts_decl_minimal_tree_pointers (ob, expr, ref_p);
+
   if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
     write_ts_common_tree_pointers (ob, expr, ref_p);
 
@@ -817,9 +820,6 @@  streamer_write_tree_body (struct output_
   if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
     write_ts_complex_tree_pointers (ob, expr, ref_p);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
-    write_ts_decl_minimal_tree_pointers (ob, expr, ref_p);
-
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
     write_ts_decl_common_tree_pointers (ob, expr, ref_p);
 
Index: gcc/tree-streamer-in.c
===================================================================
--- gcc/tree-streamer-in.c	(revision 183805)
+++ gcc/tree-streamer-in.c	(working copy)
@@ -942,6 +942,9 @@  streamer_read_tree_body (struct lto_inpu
 
   code = TREE_CODE (expr);
 
+  if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
+    lto_input_ts_decl_minimal_tree_pointers (ib, data_in, expr);
+
   if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
     lto_input_ts_common_tree_pointers (ib, data_in, expr);
 
@@ -951,9 +954,6 @@  streamer_read_tree_body (struct lto_inpu
   if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX))
     lto_input_ts_complex_tree_pointers (ib, data_in, expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL))
-    lto_input_ts_decl_minimal_tree_pointers (ib, data_in, expr);
-
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
     lto_input_ts_decl_common_tree_pointers (ib, data_in, expr);