This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[pph] Do not emit callgraph nodes to PPH images [2/2] (issue5804043)


Part 1: Remove callgraph nodes from PPH images.

This patch fixes several failures by refusing to generat code while
writing PPH images.  Instead, the writer saves state information for
the reader to expand and declare symbols via rest_of_decl_compilation
and expand_or_defer_fn/expand_or_defer_fn_1.

In the process, I had to deal with some global state that is used
during expansion.  The idea is that during generation, calls to any of
the above functions are cut short.  The symbol being expanded is added
to the PPH symbol table, together with all the state needed to re-play
the action during reading.

This slims down the data we save on PPH images and makes the writer
slightly faster by not doing any code generation actions (similarly to
how LTO operates in WPA mode).

I still need to cleanup the flags used to recognize if PPH is enabled.
PPH is a C++-only feature, but we are accessing its flags from
toplev.c.  In a subsequent pass, I'll move those flags to common code
and mark it as a C++-exclusive feature.

This change also required merging the DECL_NOT_REALLY_EXTERN.  It was
being clobbered during merging, and it's used by the expansion code.
Not merging it properly was causing several failures because
FUNCTION_DECLs were being dropped out of the cgraph.

We were also mis-merging DECL_RESULT and DECL_ARGUMENTS.  When a
function decl F already had a body, we do not want to take the result
and arguments from the decl that we are merging in.  This causes
trouble later during RTL expansion because the pointers used in the
body are different than those stored in DECL_RESULT and
DECL_ARGUMENTS.

2012-03-13   Diego Novillo  <dnovillo@google.com>

c-family/ChangeLog.pph
	* c-common.h (pph_writer_enabled_p): Declare.
	(pph_enabled_p): Declare.
	* c-opts.c (pph_writer_enabled_p): New.
	(pph_enabled_p): New.
	* c.opt (fpph-gen): Add Var(flag_pph_gen).

cp/ChangeLog.pph
	* decl.c (cp_rest_of_decl_compilation): When generating a PPH
	file, call pph_add_decl_to_symtab and return.
	* pph-core.c (tag_strings): Remove "PPH_cgraph_node".
	* pph-in.c (pph_in_merge_ld_base): Merge
	ldb->not_really_extern with |=.
	(pph_in_merge_lang_indep_tree_body): Preserve existing
	DECL_ARGUMENTS for a FUNCTION_DECL only if the decl already
	has a DECL_SAVED_TREE.
	(pph_reset_external): Remove.  Update all users.
	(pph_in_nonnull_tree): Overwrite *FIELD only if it is
	currently NULL.
	(pph_in_cgraph_node): Remove.  Update all users.
	(pph_node_already_emitted): Remove.  Update all users.
	(pph_fn_already_expanded): New.
	(pph_in_symtab): Call it.
	Read all new fields in pph_symtab_entry.
	Handle PPH_SYMTAB_EXPAND and PPH_SYMTAB_EXPAND_1 actions.
	* pph-out.c (pph_out_struct_function_for_decl): Remove.
	(pph_out_symtab_action): Assert that the action is in the set
	of known action.
	(pph_out_cgraph_node): Remove.  Update all users.
	(pph_out_cgraph_node_for_decl): Remove.  Update all users.
	(pph_add_decl_to_symtab): Capture global state required to
	re-play symtab actions in the reader.
	(pph_out_symtab): Write all new fields from pph_symtab_entry.
	* pph-streamer.h (struct pph_symtab_entry): Add fields AT_EOF,
	X_PROCESSING_TEMPLATE_DECL and FUNCTION_DEPTH.
	* pph.h (enum pph_symtab_action): Add value PPH_SYMTAB_EXPAND_1.
	(enum pph_tag): Remove value PPH_cgraph_node.  Update all
	users.
	(pph_writer_enabled_p): Move to c-family/c-opts.c.
	(pph_enabled_p): Likewise.
	* cp/semantics.c (expand_or_defer_fn_1): If we are generating
	a PPH file, add it to the symbol table and return.
	(expand_or_defer_fn): Likewise.
	* toplev.c (compile_file): If -fpph-gen is used, do not
	generate code.

testsuite/ChangeLog.pph
	* g++.dg/pph/x2incomplete4.cc: Mark fixed.
	* g++.dg/pph/x4incomplete4123.cc: Likewise.
	* g++.dg/pph/x4incomplete4321.cc: Likewise.
	* g++.dg/pph/x4keyed.cc: Likewise.
	* g++.dg/pph/x4keyex.cc: Likewise.
	* g++.dg/pph/x4keyno.cc: Likewise.
	* g++.dg/pph/x6dynarray5.h: Update expected failure patterns.
	* g++.dg/pph/x7dynarray6.cc: Likewise.
	* g++.dg/pph/x7rtti.cc: Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/pph@185345 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/c-family/ChangeLog.pph                   |    8 +
 gcc/c-family/c-common.h                      |   10 +
 gcc/c-family/c-opts.c                        |   18 ++
 gcc/c-family/c.opt                           |    2 +-
 gcc/cp/ChangeLog.pph                         |   40 ++++
 gcc/cp/decl.c                                |    9 +-
 gcc/cp/pph-core.c                            |    1 -
 gcc/cp/pph-in.c                              |  275 ++++++++++----------------
 gcc/cp/pph-out.c                             |  138 +++----------
 gcc/cp/pph-streamer.h                        |    7 +
 gcc/cp/pph.h                                 |   24 +--
 gcc/cp/semantics.c                           |   12 +-
 gcc/testsuite/ChangeLog.pph                  |   12 ++
 gcc/testsuite/g++.dg/pph/x2incomplete4.cc    |    4 -
 gcc/testsuite/g++.dg/pph/x4incomplete4123.cc |    3 -
 gcc/testsuite/g++.dg/pph/x4incomplete4321.cc |    3 -
 gcc/testsuite/g++.dg/pph/x4keyed.cc          |    3 -
 gcc/testsuite/g++.dg/pph/x4keyex.cc          |   20 --
 gcc/testsuite/g++.dg/pph/x4keyno.cc          |    5 -
 gcc/testsuite/g++.dg/pph/x6dynarray5.h       |    4 +-
 gcc/testsuite/g++.dg/pph/x7dynarray6.cc      |    1 -
 gcc/testsuite/g++.dg/pph/x7rtti.cc           |    9 +-
 gcc/toplev.c                                 |    2 +-
 23 files changed, 260 insertions(+), 350 deletions(-)

diff --git a/gcc/c-family/ChangeLog.pph b/gcc/c-family/ChangeLog.pph
index bf2304b..8c896d7 100644
--- a/gcc/c-family/ChangeLog.pph
+++ b/gcc/c-family/ChangeLog.pph
@@ -1,3 +1,11 @@
+2012-03-13   Diego Novillo  <dnovillo@google.com>
+
+	* c-common.h (pph_writer_enabled_p): Declare.
+	(pph_enabled_p): Declare.
+	* c-opts.c (pph_writer_enabled_p): New.
+	(pph_enabled_p): New.
+	* c.opt (fpph-gen): Add Var(flag_pph_gen).
+
 2012-03-09   Lawrence Crowl  <crowl@google.com>
 
 	* c.opt (-fprimary-system-header-okay): New.
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 315e99e..a1f4e81 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -590,6 +590,16 @@ extern const char *pph_out_file;
 extern bool
 pph_reader_enabled_p (void);
 
+/* Return true if we are generating a PPH file.  */
+
+extern bool
+pph_writer_enabled_p (void);
+
+/* Return true if we are either generating or reading a PPH file.  */
+
+extern bool
+pph_enabled_p (void);
+
 /* Disable the PPH reader.  */
 
 extern void
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 8c02010..63be92b 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -132,6 +132,24 @@ static void c_finish_options (void);
 static strstrmap_t *include_pph_mapping;
 
 
+/* Return true if we are generating a PPH image.  */
+
+bool
+pph_writer_enabled_p (void)
+{
+  return flag_pph_gen;
+}
+
+
+/* Return true if PPH has been enabled.  */
+
+bool
+pph_enabled_p (void)
+{
+  return pph_writer_enabled_p () || pph_reader_enabled_p ();
+}
+
+
 /* Return true if we have any map from INCLUDE to PPH file.  */
 
 bool
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 7caae53..021bf0a 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -990,7 +990,7 @@ C++ Var(flag_pph_dump_tree)
 -fpph-dump-tree	Dump global namespace tree around PPH reads/writes.
 
 fpph-gen
-C++
+C++ Var(flag_pph_gen)
 -fpph-gen	Generate a PPH image from the input file
 
 fpph-hdr=
diff --git a/gcc/cp/ChangeLog.pph b/gcc/cp/ChangeLog.pph
index 697ae2b..edb83f5 100644
--- a/gcc/cp/ChangeLog.pph
+++ b/gcc/cp/ChangeLog.pph
@@ -1,5 +1,45 @@
 2012-03-13   Diego Novillo  <dnovillo@google.com>
 
+	* decl.c (cp_rest_of_decl_compilation): When generating a PPH
+	file, call pph_add_decl_to_symtab and return.
+	* pph-core.c (tag_strings): Remove "PPH_cgraph_node".
+	* pph-in.c (pph_in_merge_ld_base): Merge
+	ldb->not_really_extern with |=.
+	(pph_in_merge_lang_indep_tree_body): Preserve existing
+	DECL_ARGUMENTS for a FUNCTION_DECL only if the decl already
+	has a DECL_SAVED_TREE.
+	(pph_reset_external): Remove.  Update all users.
+	(pph_in_nonnull_tree): Overwrite *FIELD only if it is
+	currently NULL.
+	(pph_in_cgraph_node): Remove.  Update all users.
+	(pph_node_already_emitted): Remove.  Update all users.
+	(pph_fn_already_expanded): New.
+	(pph_in_symtab): Call it.
+	Read all new fields in pph_symtab_entry.
+	Handle PPH_SYMTAB_EXPAND and PPH_SYMTAB_EXPAND_1 actions.
+	* pph-out.c (pph_out_struct_function_for_decl): Remove.
+	(pph_out_symtab_action): Assert that the action is in the set
+	of known action.
+	(pph_out_cgraph_node): Remove.  Update all users.
+	(pph_out_cgraph_node_for_decl): Remove.  Update all users.
+	(pph_add_decl_to_symtab): Capture global state required to
+	re-play symtab actions in the reader.
+	(pph_out_symtab): Write all new fields from pph_symtab_entry.
+	* pph-streamer.h (struct pph_symtab_entry): Add fields AT_EOF,
+	X_PROCESSING_TEMPLATE_DECL and FUNCTION_DEPTH.
+	* pph.h (enum pph_symtab_action): Add value PPH_SYMTAB_EXPAND_1.
+	(enum pph_tag): Remove value PPH_cgraph_node.  Update all
+	users.
+	(pph_writer_enabled_p): Move to c-family/c-opts.c.
+	(pph_enabled_p): Likewise.
+	* cp/semantics.c (expand_or_defer_fn_1): If we are generating
+	a PPH file, add it to the symbol table and return.
+	(expand_or_defer_fn): Likewise.
+	* toplev.c (compile_file): If -fpph-gen is used, do not
+	generate code.
+
+2012-03-13   Diego Novillo  <dnovillo@google.com>
+
 	* decl.c (record_builtin_type): Call pph_register_builtin_type.
 	* pph-core.c (pph_cache_add_full_tree_r): New.
 	(pph_cache_add_full_tree): New.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ab2b7d2..ddc5444 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5961,11 +5961,14 @@ value_dependent_init_p (tree init)
 void
 cp_rest_of_decl_compilation (tree decl, int top_level, int at_end)
 {
-  rest_of_decl_compilation (decl, top_level, at_end);
-
   /* If we are generating a PPH image, add DECL to its symbol table.  */
   if (pph_writer_enabled_p ())
-    pph_add_decl_to_symtab (decl, PPH_SYMTAB_DECLARE, top_level, at_end);
+    {
+      pph_add_decl_to_symtab (decl, PPH_SYMTAB_DECLARE, top_level, at_end);
+      return;
+    }
+
+  rest_of_decl_compilation (decl, top_level, at_end);
 }
 
 
diff --git a/gcc/cp/pph-core.c b/gcc/cp/pph-core.c
index 8c79017..f2984df 100644
--- a/gcc/cp/pph-core.c
+++ b/gcc/cp/pph-core.c
@@ -338,7 +338,6 @@ static const char *tag_strings[] =
   "PPH_any_tree",
   "PPH_binding_entry",
   "PPH_binding_table",
-  "PPH_cgraph_node",
   "PPH_cp_binding_level",
   "PPH_cp_class_binding",
   "PPH_cp_label_binding",
diff --git a/gcc/cp/pph-in.c b/gcc/cp/pph-in.c
index 12685a9..a328e13 100644
--- a/gcc/cp/pph-in.c
+++ b/gcc/cp/pph-in.c
@@ -1483,7 +1483,7 @@ pph_in_merge_ld_base (pph_stream *stream, struct lang_decl_base *ldb)
   ldb->selector = bp_unpack_value (&bp, 16);
   ldb->language = (enum languages) bp_unpack_value (&bp, 4);
   ldb->use_template = bp_unpack_value (&bp, 2);
-  ldb->not_really_extern = bp_unpack_value (&bp, 1);
+  ldb->not_really_extern |= bp_unpack_value (&bp, 1);
   ldb->initialized_in_class = bp_unpack_value (&bp, 1);
   ldb->repo_available_p = bp_unpack_value (&bp, 1);
   ldb->threadprivate_or_deleted_p = bp_unpack_value (&bp, 1);
@@ -1647,7 +1647,13 @@ pph_in_lang_indep_tree_body (pph_stream *stream, tree expr)
 }
 
 
-/* Stream in the language-independent parts of EXPR's body.  */
+/* Merge in from STREAM the language-independent parts of EXPR's body.
+   This merging operates in three phases: (1) fields that need to be
+   preserved are saved, (2) the new body for EXPR is read-in, (3)
+   preserved fields are restored back into EXPR.
+
+   This three stage merging is needed because the generic tree reader
+   is not merge-aware.  */
 
 static void
 pph_in_merge_lang_indep_tree_body (pph_stream *stream, tree expr)
@@ -1657,7 +1663,10 @@ pph_in_merge_lang_indep_tree_body (pph_stream *stream, tree expr)
   tree decl_comdat_group = NULL;
   bool decl_declared_inline = false;
   tree decl_result = NULL;
+  tree decl_arguments = NULL;
 
+  /* Preserve some fields which should not be overwritten by the DECL
+     that we are merging in.  */
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
     {
       decl_comdat = DECL_COMDAT (expr);
@@ -1670,16 +1679,19 @@ pph_in_merge_lang_indep_tree_body (pph_stream *stream, tree expr)
 	 tree decl_section_name = DECL_SECTION_NAME (expr);
       */
     }
+
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     {
       decl_declared_inline = DECL_DECLARED_INLINE_P (expr);
-    }
-  if (code == FUNCTION_DECL)
-    {
-      decl_result = DECL_RESULT (expr);
-      /* FIXME pph: These too?
-	 decl_arguments = DECL_ARGUMENTS (expr);
-      */
+
+      /* DECL_RESULT and DECL_ARGUMENTS are used inside the body
+	 of a function.  Preserve them only if EXPR already has a
+	 body.  */
+      if (DECL_SAVED_TREE (expr))
+	{
+	  decl_result = DECL_RESULT (expr);
+	  decl_arguments = DECL_ARGUMENTS (expr);
+	}
     }
 
   /* FIXME pph: Also see the functions below for more potential fields.
@@ -1689,8 +1701,11 @@ pph_in_merge_lang_indep_tree_body (pph_stream *stream, tree expr)
 	lto_input_ts_decl_non_common_tree_pointers
   */
 
+  /* Read the body of the new decl (this overwrites all the fields of
+     EXPR).  */
   pph_in_lang_indep_tree_body (stream, expr);
 
+  /* Restore values that we do not want overwritten.  */
   if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
     {
       decl_comdat ? DECL_COMDAT (expr) = true : 0;
@@ -1703,16 +1718,19 @@ pph_in_merge_lang_indep_tree_body (pph_stream *stream, tree expr)
 	 decl_section_name ? DECL_SECTION_NAME (expr) = decl_section_name : 0;
       */
     }
+
   if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL))
     {
       decl_declared_inline ? DECL_DECLARED_INLINE_P (expr) = true : 0;
-    }
-  if (code == FUNCTION_DECL)
-    {
-      decl_result ? DECL_RESULT (expr) = decl_result : 0;
-      /* FIXME pph: These too?
-	 decl_arguments ? DECL_ARGUMENTS (expr) = decl_arguments : 0;
-      */
+
+      /* DECL_RESULT and DECL_ARGUMENTS are used inside the body
+	 of a function.  Preserve them only if EXPR already has a
+	 body.  */
+      if (DECL_SAVED_TREE (expr))
+	{
+	  decl_result ? DECL_RESULT (expr) = decl_result : 0;
+	  decl_arguments ? DECL_ARGUMENTS (expr) = decl_arguments : 0;
+	}
     }
 }
 
@@ -1997,26 +2015,6 @@ pph_in_tcc_type (pph_stream *stream, tree type)
 }
 
 
-/* Reset the external state for a function DECL.  */
-
-static void
-pph_reset_external (tree decl)
-{
-  /* When the declaration was compiled originally, the parser marks
-     it DECL_EXTERNAL, to avoid emitting it more than once.  It also
-     remembers the true external state in DECL_NOT_REALLY_EXTERN.  So,
-     if both bits are set, the declaration should not be considered
-     external.  */
-  gcc_assert (DECL_LANG_SPECIFIC (decl));
-  if (DECL_NOT_REALLY_EXTERN (decl)
-      && DECL_EXTERNAL (decl))
-    {
-      DECL_EXTERNAL (decl) = 0;
-      DECL_NOT_REALLY_EXTERN (decl) = 0;
-    }
-}
-
-
 /* Read from STREAM the body of tcc_declaration tree DECL.  */
 
 static void
@@ -2042,7 +2040,6 @@ pph_in_tcc_declaration (pph_stream *stream, tree decl)
     case FUNCTION_DECL:
       TREE_CHAIN (decl) = pph_in_tree (stream);
       DECL_SAVED_TREE (decl) = pph_in_tree (stream);
-      pph_reset_external (decl);
       break;
 
     case TYPE_DECL:
@@ -2067,7 +2064,7 @@ pph_in_nonnull_tree (tree *field, pph_stream *stream)
 {
   tree candidate;
   candidate = pph_in_tree (stream);
-  if (candidate)
+  if (candidate && *field == NULL)
     *field = candidate;
 }
 
@@ -2081,7 +2078,6 @@ pph_in_merge_tcc_declaration (pph_stream *stream, tree decl)
   pph_in_lang_decl (stream, decl);
 
   /* FIXME pph: Some of the following may not be necessary.  */
-
   pph_in_nonnull_tree (&DECL_INITIAL (decl), stream);
   pph_in_nonnull_tree (&DECL_ABSTRACT_ORIGIN (decl), stream);
 
@@ -2102,7 +2098,6 @@ pph_in_merge_tcc_declaration (pph_stream *stream, tree decl)
     case FUNCTION_DECL:
       /* ignore TREE_CHAIN (decl) = */ pph_in_tree (stream);
       pph_in_nonnull_tree (&DECL_SAVED_TREE (decl), stream);
-      pph_reset_external (decl);
       break;
 
     case TYPE_DECL:
@@ -2315,10 +2310,8 @@ pph_in_merge_tree_body (pph_stream *stream, tree expr)
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
       case tcc_declaration:
-	{
-	  pph_in_merge_tcc_declaration (stream, expr);
-	}
-       break;
+	pph_in_merge_tcc_declaration (stream, expr);
+	break;
 
       case tcc_type:
 	pph_in_lang_indep_tree_body (stream, expr);
@@ -2841,90 +2834,6 @@ pph_in_symtab_action (pph_stream *stream)
 }
 
 
-/* Read and return a callgraph node from STREAM.  If this is the first
-   time we read this node, add it to the callgraph.  */
-
-static struct cgraph_node *
-pph_in_cgraph_node (pph_stream *stream)
-{
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
-  struct cgraph_node *node;
-  tree fndecl;
-  struct bitpack_d bp;
-
-  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))
-    return (struct cgraph_node *) pph_cache_find (stream, marker, image_ix,
-						  ix, PPH_cgraph_node);
-
-  fndecl = pph_in_tree (stream);
-  ALLOC_AND_REGISTER (&stream->cache, ix, PPH_cgraph_node, node,
-                      cgraph_get_create_node (fndecl));
-
-  node->origin = pph_in_cgraph_node (stream);
-  node->nested = pph_in_cgraph_node (stream);
-  node->next_nested = pph_in_cgraph_node (stream);
-  node->next_needed = pph_in_cgraph_node (stream);
-  node->next_sibling_clone = pph_in_cgraph_node (stream);
-  node->prev_sibling_clone = pph_in_cgraph_node (stream);
-  node->clones = pph_in_cgraph_node (stream);
-  node->clone_of = pph_in_cgraph_node (stream);
-  node->same_comdat_group = pph_in_cgraph_node (stream);
-  gcc_assert (node->call_site_hash == NULL);
-  node->former_clone_of = pph_in_tree (stream);
-  gcc_assert (node->aux == NULL);
-  gcc_assert (VEC_empty (ipa_opt_pass, node->ipa_transforms_to_apply));
-
-  gcc_assert (VEC_empty (ipa_ref_t, node->ref_list.references));
-  gcc_assert (VEC_empty (ipa_ref_ptr, node->ref_list.refering));
-
-  gcc_assert (node->local.lto_file_data == NULL);
-  bp = pph_in_bitpack (stream);
-  node->local.local = bp_unpack_value (&bp, 1);
-  node->local.externally_visible = bp_unpack_value (&bp, 1);
-  node->local.finalized = bp_unpack_value (&bp, 1);
-  node->local.can_change_signature = bp_unpack_value (&bp, 1);
-  node->local.redefined_extern_inline = bp_unpack_value (&bp, 1);
-
-  node->global.inlined_to = pph_in_cgraph_node (stream);
-
-  node->rtl.preferred_incoming_stack_boundary = pph_in_uint (stream);
-
-  gcc_assert (VEC_empty (ipa_replace_map_p, node->clone.tree_map));
-  node->thunk.fixed_offset = pph_in_uhwi (stream);
-  node->thunk.virtual_value = pph_in_uhwi (stream);
-  node->thunk.alias = pph_in_tree (stream);
-  bp = pph_in_bitpack (stream);
-  node->thunk.this_adjusting = bp_unpack_value (&bp, 1);
-  node->thunk.virtual_offset_p = bp_unpack_value (&bp, 1);
-  node->thunk.thunk_p = bp_unpack_value (&bp, 1);
-
-  node->count = pph_in_uhwi (stream);
-  node->count_materialization_scale = pph_in_uint (stream);
-
-  bp = pph_in_bitpack (stream);
-  node->needed = bp_unpack_value (&bp, 1);
-  node->address_taken = bp_unpack_value (&bp, 1);
-  node->abstract_and_needed = bp_unpack_value (&bp, 1);
-  node->reachable = bp_unpack_value (&bp, 1);
-  node->reachable_from_other_partition = bp_unpack_value (&bp, 1);
-  node->lowered = bp_unpack_value (&bp, 1);
-  node->analyzed = bp_unpack_value (&bp, 1);
-  node->in_other_partition = bp_unpack_value (&bp, 1);
-  node->process = bp_unpack_value (&bp, 1);
-  node->alias = bp_unpack_value (&bp, 1);
-  node->same_body_alias = bp_unpack_value (&bp, 1);
-  node->frequency = (enum node_frequency) bp_unpack_value (&bp, 2);
-  node->only_called_at_startup = bp_unpack_value (&bp, 1);
-  node->only_called_at_exit = bp_unpack_value (&bp, 1);
-
-  return node;
-}
-
-
 /* Have we already emitted this DECL?  */
 
 static bool
@@ -2938,16 +2847,16 @@ pph_decl_already_emitted (tree decl)
 }
 
 
-/* Have we already emitted this cgraph NODE?  */
+/* Have we already expanded this FN?  */
 
 static bool
-pph_node_already_emitted (struct cgraph_node *node)
+pph_fn_already_expanded (tree fn)
 {
-  static struct pointer_set_t *emitted_nodes = NULL;
-  gcc_assert (node != NULL);
-  if (!emitted_nodes)
-    emitted_nodes = pointer_set_create ();
-  return pointer_set_insert (emitted_nodes, node) != 0;
+  static struct pointer_set_t *expanded_fns = NULL;
+  gcc_assert (fn != NULL);
+  if (!expanded_fns)
+    expanded_fns = pointer_set_create ();
+  return pointer_set_insert (expanded_fns, fn) != 0;
 }
 
 
@@ -2969,44 +2878,74 @@ pph_in_symtab (pph_stream *stream)
   num = pph_in_uint (stream);
   for (i = 0; i < num; i++)
     {
-      enum pph_symtab_action action;
-      tree decl;
-      bool top_level, at_end;
-
-      action = pph_in_symtab_action (stream);
-      decl = pph_in_tree (stream);
-      if (action == PPH_SYMTAB_DECLARE)
+      pph_symtab_entry entry;
+      struct bitpack_d bp;
+
+      entry.action = pph_in_symtab_action (stream);
+      entry.decl = pph_in_tree (stream);
+      bp = pph_in_bitpack (stream);
+      entry.top_level = bp_unpack_value (&bp, 1);
+      entry.at_end = bp_unpack_value (&bp, 1);
+      entry.at_eof = bp_unpack_value (&bp, 1);
+      entry.x_processing_template_decl = pph_in_int (stream);
+      entry.function_depth = pph_in_int (stream);
+
+      if (entry.action == PPH_SYMTAB_DECLARE)
 	{
-	  struct bitpack_d bp;
-	  bp = pph_in_bitpack (stream);
-	  top_level = bp_unpack_value (&bp, 1);
-	  at_end = bp_unpack_value (&bp, 1);
-          if (pph_decl_already_emitted (decl))
+          if (pph_decl_already_emitted (entry.decl))
             continue;
-
-	  cp_rest_of_decl_compilation (decl, top_level, at_end);
+	  cp_rest_of_decl_compilation (entry.decl, entry.top_level,
+				       entry.at_end);
 	}
-      else if (action == PPH_SYMTAB_EXPAND)
+      else if (entry.action == PPH_SYMTAB_EXPAND
+	       || entry.action == PPH_SYMTAB_EXPAND_1)
 	{
-	  struct cgraph_node *node;
+	  bool prev_processing_template_decl, prev_at_eof;
+	  int prev_function_depth;
+	  bool need_cgraph_node_p;
+	  tree prev_current_function_decl;
+
+	  pph_in_struct_function (stream, entry.decl);
+	  need_cgraph_node_p = pph_in_bool (stream);
+	  if (pph_fn_already_expanded (entry.decl))
+	    continue;
+
+	  /* ENTRY.DECL was reset to being external by the original
+	     expansion code, so we need to restore its value before
+	     expanding again.  */
+	  DECL_EXTERNAL (entry.decl) = false;
+
+	  /* Re-establish needed global state before calling the
+	     expanders.  FIXME pph, get rid of this by fixing the
+	     expanders.  */
+	  prev_processing_template_decl = processing_template_decl;
+	  prev_at_eof = at_eof;
+	  prev_function_depth = function_depth;
+
+	  processing_template_decl = entry.x_processing_template_decl;
+	  at_eof = entry.at_eof;
+	  function_depth = entry.function_depth;
+
+	  /* Do the expansion.  */
+	  prev_current_function_decl = current_function_decl;
+	  current_function_decl = entry.decl;
+	  push_cfun (DECL_STRUCT_FUNCTION (entry.decl));
+
+	  if (entry.action == PPH_SYMTAB_EXPAND)
+	    expand_or_defer_fn (entry.decl);
+	  else
+	    expand_or_defer_fn_1 (entry.decl);
 
-	  pph_in_struct_function (stream, decl);
-	  node = pph_in_cgraph_node (stream);
-	  if (node && node->local.finalized)
-	    {
-	      if (pph_node_already_emitted (node))
-		continue;
-
-	      /* Since the writer had finalized this cgraph node,
-		 we have to re-play its actions.  To do that, we need
-		 to clear the finalized and reachable bits in the
-		 node, otherwise cgraph_finalize_function will toss
-		 out this node.  */
-	      DECL_EXTERNAL (node->decl) = false;
-	      node->local.finalized = false;
-	      node->reachable = false;
-	      cgraph_finalize_function (node->decl, true);
-	    }
+	  if (need_cgraph_node_p)
+	    cgraph_get_create_node (entry.decl);
+
+	  current_function_decl = prev_current_function_decl;
+	  pop_cfun ();
+
+	  /* Restore global state.  */
+	  processing_template_decl = prev_processing_template_decl;
+	  at_eof = prev_at_eof;
+	  function_depth = prev_function_depth;
 	}
       else
 	gcc_unreachable ();
diff --git a/gcc/cp/pph-out.c b/gcc/cp/pph-out.c
index c817f22..b94cb77 100644
--- a/gcc/cp/pph-out.c
+++ b/gcc/cp/pph-out.c
@@ -1477,15 +1477,6 @@ pph_out_struct_function (pph_stream *stream, struct function *fn)
 }
 
 
-/* Write the struct function instance for DECL to STREAM.  */
-
-static void
-pph_out_struct_function_for_decl (pph_stream *stream, tree decl)
-{
-  pph_out_struct_function (stream, DECL_STRUCT_FUNCTION (decl));
-}
-
-
 /* Write all the fields in lang_decl_base instance LDB to OB.  */
 
 static void
@@ -2437,97 +2428,13 @@ pph_out_tree (pph_stream *stream, tree expr)
 static inline void
 pph_out_symtab_action (pph_stream *stream, enum pph_symtab_action action)
 {
-  gcc_assert (action == (enum pph_symtab_action)(unsigned char) action);
+  gcc_assert ((action == PPH_SYMTAB_DECLARE
+	       || action == PPH_SYMTAB_EXPAND
+	       || action == PPH_SYMTAB_EXPAND_1)
+              && (enum pph_symtab_action)(unsigned char) action);
   pph_out_uchar (stream, action);
 }
 
-
-/* Emit callgraph NODE to STREAM.  */
-
-static void
-pph_out_cgraph_node (pph_stream *stream, struct cgraph_node *node)
-{
-  struct bitpack_d bp;
-  enum pph_record_marker marker;
-
-  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);
-  pph_out_cgraph_node (stream, node->next_nested);
-  pph_out_cgraph_node (stream, node->next_needed);
-  pph_out_cgraph_node (stream, node->next_sibling_clone);
-  pph_out_cgraph_node (stream, node->prev_sibling_clone);
-  pph_out_cgraph_node (stream, node->clones);
-  pph_out_cgraph_node (stream, node->clone_of);
-  pph_out_cgraph_node (stream, node->same_comdat_group);
-  gcc_assert (node->call_site_hash == NULL);
-  pph_out_tree (stream, node->former_clone_of);
-  gcc_assert (node->aux == NULL);
-  gcc_assert (VEC_empty (ipa_opt_pass, node->ipa_transforms_to_apply));
-
-  gcc_assert (VEC_empty (ipa_ref_t, node->ref_list.references));
-  gcc_assert (VEC_empty (ipa_ref_ptr, node->ref_list.refering));
-
-  gcc_assert (node->local.lto_file_data == NULL);
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, node->local.local, 1);
-  bp_pack_value (&bp, node->local.externally_visible, 1);
-  bp_pack_value (&bp, node->local.finalized, 1);
-  bp_pack_value (&bp, node->local.can_change_signature, 1);
-  bp_pack_value (&bp, node->local.redefined_extern_inline, 1);
-  pph_out_bitpack (stream, &bp);
-
-  pph_out_cgraph_node (stream, node->global.inlined_to);
-
-  pph_out_uint (stream, node->rtl.preferred_incoming_stack_boundary);
-
-  gcc_assert (VEC_empty (ipa_replace_map_p, node->clone.tree_map));
-  pph_out_uhwi (stream, node->thunk.fixed_offset);
-  pph_out_uhwi (stream, node->thunk.virtual_value);
-  pph_out_tree (stream, node->thunk.alias);
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, node->thunk.this_adjusting, 1);
-  bp_pack_value (&bp, node->thunk.virtual_offset_p, 1);
-  bp_pack_value (&bp, node->thunk.thunk_p, 1);
-  pph_out_bitpack (stream, &bp);
-
-  pph_out_uhwi (stream, node->count);
-  pph_out_uint (stream, node->count_materialization_scale);
-
-  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-  bp_pack_value (&bp, node->needed, 1);
-  bp_pack_value (&bp, node->address_taken, 1);
-  bp_pack_value (&bp, node->abstract_and_needed, 1);
-  bp_pack_value (&bp, node->reachable, 1);
-  bp_pack_value (&bp, node->reachable_from_other_partition, 1);
-  bp_pack_value (&bp, node->lowered, 1);
-  bp_pack_value (&bp, node->analyzed, 1);
-  bp_pack_value (&bp, node->in_other_partition, 1);
-  bp_pack_value (&bp, node->process, 1);
-  bp_pack_value (&bp, node->alias, 1);
-  bp_pack_value (&bp, node->same_body_alias, 1);
-  bp_pack_value (&bp, node->frequency, 2);
-  bp_pack_value (&bp, node->only_called_at_startup, 1);
-  bp_pack_value (&bp, node->only_called_at_exit, 1);
-  pph_out_bitpack (stream, &bp);
-}
-
-/* Emit callgraph for DECL to STREAM.  */
-
-static void
-pph_out_cgraph_node_for_decl (pph_stream *stream, tree decl)
-{
-  pph_out_cgraph_node (stream, cgraph_get_node (decl));
-}
-
-
 /* Add DECL to the symbol table for pph_out_stream.  ACTION determines
    how DECL should be presented to the middle-end when reading this
    image.  TOP_LEVEL and AT_END are as in rest_of_decl_compilation.  */
@@ -2547,6 +2454,17 @@ pph_add_decl_to_symtab (tree decl, enum pph_symtab_action action,
   entry.decl = decl;
   entry.top_level = top_level;
   entry.at_end = at_end;
+
+  /* Capture some global state that is needed when re-playing this
+     entry.  FIXME pph, this should not be needed.  There is even
+     inconsistencies in the values for AT_END, the values passed on by
+     various callers is not necessarily the same as the value for
+     ENTRY.AT_EOF below (sigh).  */
+  entry.x_processing_template_decl = processing_template_decl;
+  entry.function_depth = function_depth;
+  gcc_assert (at_end == at_eof && (at_eof == 0 || at_eof == 1));
+  entry.at_eof = at_eof;
+
   VEC_safe_push (pph_symtab_entry, heap, pph_out_stream->symtab.v, &entry);
 }
 
@@ -2568,23 +2486,23 @@ pph_out_symtab (pph_stream *stream)
   pph_out_uint (stream, VEC_length (pph_symtab_entry, stream->symtab.v));
   FOR_EACH_VEC_ELT (pph_symtab_entry, stream->symtab.v, i, entry)
     {
+      struct bitpack_d bp;
+
       pph_out_symtab_action (stream, entry->action);
       pph_out_tree (stream, entry->decl);
-      if (entry->action == PPH_SYMTAB_DECLARE)
+      bp = bitpack_create (stream->encoder.w.ob->main_stream);
+      bp_pack_value (&bp, entry->top_level, 1);
+      bp_pack_value (&bp, entry->at_end, 1);
+      bp_pack_value (&bp, entry->at_eof, 1);
+      pph_out_bitpack (stream, &bp);
+      pph_out_int (stream, entry->x_processing_template_decl);
+      pph_out_int (stream, entry->function_depth);
+      if (entry->action == PPH_SYMTAB_EXPAND
+	  || entry->action == PPH_SYMTAB_EXPAND_1)
 	{
-	  struct bitpack_d bp;
-	  bp = bitpack_create (stream->encoder.w.ob->main_stream);
-	  bp_pack_value (&bp, entry->top_level, 1);
-	  bp_pack_value (&bp, entry->at_end, 1);
-	  pph_out_bitpack (stream, &bp);
+	  pph_out_struct_function (stream, DECL_STRUCT_FUNCTION (entry->decl));
+	  pph_out_bool (stream, cgraph_get_node (entry->decl) != NULL);
 	}
-      else if (entry->action == PPH_SYMTAB_EXPAND)
-	{
-	  pph_out_struct_function_for_decl (stream, entry->decl);
-	  pph_out_cgraph_node_for_decl (stream, entry->decl);
-	}
-      else
-	gcc_unreachable ();
     }
 }
 
diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h
index 62cbdbb..78e0d77 100644
--- a/gcc/cp/pph-streamer.h
+++ b/gcc/cp/pph-streamer.h
@@ -141,6 +141,13 @@ typedef struct pph_symtab_entry
   /* Values to be passed to rest_of_decl_compilation.  */
   unsigned int top_level : 1;
   unsigned int at_end : 1;
+
+  /* Values captured from global state used by expand_or_defer_fn and
+     expand_or_defer_fn_1.  FIXME pph, all this global state should
+     disappear.  */
+  unsigned int at_eof : 1;
+  int x_processing_template_decl;
+  int function_depth;
 } pph_symtab_entry;
 
 DEF_VEC_O(pph_symtab_entry);
diff --git a/gcc/cp/pph.h b/gcc/cp/pph.h
index c6ec227..eaae534 100644
--- a/gcc/cp/pph.h
+++ b/gcc/cp/pph.h
@@ -39,7 +39,10 @@ enum pph_symtab_action {
   PPH_SYMTAB_DECLARE = 0x23,
 
   /* Expand this function with expand_or_defer_fn.  */
-  PPH_SYMTAB_EXPAND
+  PPH_SYMTAB_EXPAND,
+
+  /* Expand this function with expand_or_defer_fn_1.  */
+  PPH_SYMTAB_EXPAND_1
 };
 
 /* Record markers.  */
@@ -113,7 +116,6 @@ enum pph_tag {
   /* 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,
@@ -198,22 +200,4 @@ extern void pph_in_canonical_template_parms (pph_stream *);
 /* FIXME pph: These functions should be moved to tree.c on merge.  */
 extern VEC(tree,heap) *chain2vec (tree chain);  /* In pph-out.c.  */
 
-
-/* Inline functions.  */
-
-/* Return true if we are generating a PPH image.  */
-static inline bool
-pph_writer_enabled_p (void)
-{
-  return pph_out_file != NULL;
-}
-
-/* Return true if PPH has been enabled.  */
-static inline bool
-pph_enabled_p (void)
-{
-  return pph_writer_enabled_p () || pph_reader_enabled_p ();
-}
-
-
 #endif  /* GCC_CP_PPH_H  */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 89c23ed..2356b46 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3720,7 +3720,10 @@ expand_or_defer_fn_1 (tree fn)
 {
   /* If we are generating a PPH image, add FN to its symbol table.  */
   if (pph_writer_enabled_p ())
-    pph_add_decl_to_symtab (fn, PPH_SYMTAB_EXPAND, false, at_eof);
+    {
+      pph_add_decl_to_symtab (fn, PPH_SYMTAB_EXPAND_1, false, at_eof);
+      return false;
+    }
 
   /* When the parser calls us after finishing the body of a template
      function, we don't really want to expand the body.  */
@@ -3811,6 +3814,13 @@ expand_or_defer_fn_1 (tree fn)
 void
 expand_or_defer_fn (tree fn)
 {
+  /* If we are generating a PPH image, add FN to its symbol table.  */
+  if (pph_writer_enabled_p ())
+    {
+      pph_add_decl_to_symtab (fn, PPH_SYMTAB_EXPAND, false, at_eof);
+      return;
+    }
+
   if (expand_or_defer_fn_1 (fn))
     {
       function_depth++;
diff --git a/gcc/testsuite/ChangeLog.pph b/gcc/testsuite/ChangeLog.pph
index 916b69c..fd643f6 100644
--- a/gcc/testsuite/ChangeLog.pph
+++ b/gcc/testsuite/ChangeLog.pph
@@ -1,3 +1,15 @@
+2012-03-13   Diego Novillo  <dnovillo@google.com>
+
+	* g++.dg/pph/x2incomplete4.cc: Mark fixed.
+	* g++.dg/pph/x4incomplete4123.cc: Likewise.
+	* g++.dg/pph/x4incomplete4321.cc: Likewise.
+	* g++.dg/pph/x4keyed.cc: Likewise.
+	* g++.dg/pph/x4keyex.cc: Likewise.
+	* g++.dg/pph/x4keyno.cc: Likewise.
+	* g++.dg/pph/x6dynarray5.h: Update expected failure patterns.
+	* g++.dg/pph/x7dynarray6.cc: Likewise.
+	* g++.dg/pph/x7rtti.cc: Likewise.
+
 2012-03-09   Lawrence Crowl  <crowl@google.com>
 
 	* g++.dg/pph/a0neststruct.cci: New.
diff --git a/gcc/testsuite/g++.dg/pph/x2incomplete4.cc b/gcc/testsuite/g++.dg/pph/x2incomplete4.cc
index 1ae17bf..028aa94 100644
--- a/gcc/testsuite/g++.dg/pph/x2incomplete4.cc
+++ b/gcc/testsuite/g++.dg/pph/x2incomplete4.cc
@@ -1,6 +1,2 @@
-// pph asm xdiff 21766
-// xfail-if BOGUS XTRAFUN
-// copies::copies() is wrongly generated
-
 #include "x1incomplete3.h"
 #include "a0incomplete4.cci"
diff --git a/gcc/testsuite/g++.dg/pph/x4incomplete4123.cc b/gcc/testsuite/g++.dg/pph/x4incomplete4123.cc
index 88e9425..4f3168e 100644
--- a/gcc/testsuite/g++.dg/pph/x4incomplete4123.cc
+++ b/gcc/testsuite/g++.dg/pph/x4incomplete4123.cc
@@ -1,6 +1,3 @@
-// pph asm xdiff 21766
-// xfail-if unneeded copy of copies::copies() emitted
-
 #include "x0incomplete1.h"
 #include "x0incomplete2.h"
 #include "x0incomplete3.h"
diff --git a/gcc/testsuite/g++.dg/pph/x4incomplete4321.cc b/gcc/testsuite/g++.dg/pph/x4incomplete4321.cc
index 3152d50..3d6a862 100644
--- a/gcc/testsuite/g++.dg/pph/x4incomplete4321.cc
+++ b/gcc/testsuite/g++.dg/pph/x4incomplete4321.cc
@@ -1,6 +1,3 @@
-// { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "a0incomplete2.hi:7:5: internal compiler error: in gimple_expand_cfg, at cfgexpand.c:4454" "" { xfail *-*-* } 0 }
-
 #include "x0incomplete3.h"
 #include "x0incomplete2.h"
 #include "x0incomplete1.h"
diff --git a/gcc/testsuite/g++.dg/pph/x4keyed.cc b/gcc/testsuite/g++.dg/pph/x4keyed.cc
index 94a72c3..f470785 100644
--- a/gcc/testsuite/g++.dg/pph/x4keyed.cc
+++ b/gcc/testsuite/g++.dg/pph/x4keyed.cc
@@ -1,6 +1,3 @@
-// { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "x4keyed.cc:13:1: internal compiler error: in cgraph_analyze_functions, at cgraphunit.c:1210" "" { xfail *-*-* } 0 }
-
 #include "x0keyed1.h"
 #include "x0keyed2.h"
 
diff --git a/gcc/testsuite/g++.dg/pph/x4keyex.cc b/gcc/testsuite/g++.dg/pph/x4keyex.cc
index ecffabb..d56215f 100644
--- a/gcc/testsuite/g++.dg/pph/x4keyex.cc
+++ b/gcc/testsuite/g++.dg/pph/x4keyex.cc
@@ -1,23 +1,3 @@
-// { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "x4keyex.cc:28:1: internal compiler error: in cgraph_analyze_functions, at cgraphunit.c:1210" "" { xfail *-*-* } 0 }
-
-// formerly was asm xokay 32642
-//
-// This test case fails to compare because LFB/LFE labels are different.
-//
-// 1- Both x0keyno1.h and x0keyno2.h declare exactly the same, as
-//    they both textually include a0keyed.h.
-// 2- When we read x0keyno1.pph, we instantiate all the decls and cgraph
-//    nodes for struct keyed.
-// 3- When we read x0keyno2.pph, we re-instantiate the same decls and
-//    cgraph nodes, which are used instead of the ones in x0keyno1.pph.
-// 4- Since the new decls and nodes have been created later, the functions
-//    have different function numbers (function::funcdef_no field), which
-//    is used to emit the LFB/LFE labels.
-//
-// The future merging process will fix this by choosing the decls and nodes
-// created first by x0keyno1.pph.
-
 #include "x0keyed1.h"
 #include "x0keyed2.h"
 
diff --git a/gcc/testsuite/g++.dg/pph/x4keyno.cc b/gcc/testsuite/g++.dg/pph/x4keyno.cc
index 196cc873e..8de9bd1 100644
--- a/gcc/testsuite/g++.dg/pph/x4keyno.cc
+++ b/gcc/testsuite/g++.dg/pph/x4keyno.cc
@@ -1,8 +1,3 @@
-// { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "x4keyno.cc:13:1: internal compiler error: in cgraph_analyze_functions, at cgraphunit.c:1210" "" { xfail *-*-* } 0 }
-
-// was asm xokay 32642
-
 #include "x0keyno1.h"
 #include "x0keyno2.h"
 
diff --git a/gcc/testsuite/g++.dg/pph/x6dynarray5.h b/gcc/testsuite/g++.dg/pph/x6dynarray5.h
index 130e989..05634c1 100644
--- a/gcc/testsuite/g++.dg/pph/x6dynarray5.h
+++ b/gcc/testsuite/g++.dg/pph/x6dynarray5.h
@@ -1,9 +1,11 @@
 // { dg-xfail-if "UNIMPL TRAIT MANGLING" { "*-*-*" } { "-fpph-map=pph.map" } }
+// { dg-bogus "bits/stl_uninitialized.h:66:12: sorry, unimplemented: mangling trait_expr" "" { xfail *-*-* } 0 }
+// { dg-bogus "bits/stl_uninitialized.h:124:12: sorry, unimplemented: mangling trait_expr" "" { xfail *-*-* } 0 }
 // { dg-bogus "bits/stl_uninitialized.h:178:12: sorry, unimplemented: mangling trait_expr" "" { xfail *-*-* } 0 }
 // { dg-bogus "bits/allocator.h:153:12: sorry, unimplemented: mangling trait_expr" "" { xfail *-*-* } 0 }
 // { dg-bogus "bits/stl_construct.h:98:12: sorry, unimplemented: mangling trait_expr" "" { xfail *-*-* } 0 }
 // { dg-bogus "bits/stl_tempbuf.h:183:12: sorry, unimplemented: mangling trait_expr" "" { xfail *-*-* } 0 }
-// { dg-bogus "bits/cpp_type_traits.h:87:12: internal compiler error: tree check: expected integer_cst, have const_decl in tree_int_cst_sgn, at tree.c:6567" "" { xfail *-*-* } 0 }
+// { dg-bogus "bits/cpp_type_traits.h:87:12: internal compiler error: tree check: expected integer_cst, have const_decl in tree_int_cst_sgn" "" { xfail *-*-* } 0 }
 
 #ifndef X6DYNARRAY5_H
 #define X6DYNARRAY5_H
diff --git a/gcc/testsuite/g++.dg/pph/x7dynarray6.cc b/gcc/testsuite/g++.dg/pph/x7dynarray6.cc
index d80111e..b32780e 100644
--- a/gcc/testsuite/g++.dg/pph/x7dynarray6.cc
+++ b/gcc/testsuite/g++.dg/pph/x7dynarray6.cc
@@ -1,5 +1,4 @@
 // { dg-xfail-if "BOGUS INTRINSIC RETURN" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "ext/atomicity.h:48:61: error: void value not ignored as it ought to be" "" { xfail *-*-* } 0 }
 
 #include <algorithm>
 #include <iostream>
diff --git a/gcc/testsuite/g++.dg/pph/x7rtti.cc b/gcc/testsuite/g++.dg/pph/x7rtti.cc
index 585176d..d7bc164 100644
--- a/gcc/testsuite/g++.dg/pph/x7rtti.cc
+++ b/gcc/testsuite/g++.dg/pph/x7rtti.cc
@@ -1,9 +1,8 @@
-// { dg-xfail-if "UNKNOWN MACRO AND BOGUS RTTI" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "x7rtti.cc:10:0: warning: .__STDC_IEC_559_COMPLEX__. redefined" "" { xfail *-*-* } 0 }
-// { dg-bogus "x7rtti.cc:10:0: warning: .__STDC_ISO_10646__. redefined" "" { xfail *-*-* } 0 }
-// { dg-bogus "x7rtti.cc:10:0: warning: .__STDC_IEC_559__. redefined" "" { xfail *-*-* } 0 }
-// { dg-bogus "x7rtti.cc:22:1: internal compiler error: in cgraph_analyze_functions, at cgraphunit.c:1210" "" { xfail *-*-* } 0 }
 // FIXME pph: This should be a { dg=do run } (with '=' replaced by '-')
+// { xfail-if "UNKNOWN MACRO AND BOGUS RTTI" { "*-*-*" } { "-fpph-map=pph.map" } }
+// { dg-bogus "warning: .__STDC_IEC_559_COMPLEX__. redefined" "" { xfail *-*-* } 0 }
+// { dg-bogus "warning: .__STDC_ISO_10646__. redefined" "" { xfail *-*-* } 0 }
+// { dg-bogus "warning: .__STDC_IEC_559__. redefined" "" { xfail *-*-* } 0 }
 
 #include "x5rtti1.h"
 #include "x5rtti2.h"
diff --git a/gcc/toplev.c b/gcc/toplev.c
index c145af4..e93be1b 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -562,7 +562,7 @@ compile_file (void)
   /* Compilation is now finished except for writing
      what's left of the symbol table output.  */
 
-  if (flag_syntax_only || flag_wpa)
+  if (flag_syntax_only || flag_wpa || flag_pph_gen)
     return;
 
   timevar_start (TV_PHASE_GENERATE);
-- 
1.7.7.3


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]