This patch saves and restores three template side tables for PPH.  They are
the pending template instantiations list, the template decl specializations
table, and the template type specializations table.

This patch fixes PPH test x1tmplclass.

In the process, I mace lto_output_location and lto_input_location extern in
lto-streamer* and factored cp_debug_parser_tokens out of cp_debug_parser in
cp/parser.c.

Tested on x64.


Index: gcc/testsuite/ChangeLog.pph

2011-07-25  Lawrence Crowl  <cr...@google.com>

        * g++.dg/pph/x1tmplclass.cc: Remove expected failure.

Index: gcc/cp/ChangeLog.pph

2011-07-25   Lawrence Crowl  <cr...@google.com>

        * pph.c (pph_dump_tree_name): Make extern.
        * pph.h (pph_dump_tree_name): Make extern.
        * pph-streamer-in.c (pph_read_file_contents): Load pending templates
        list and tables of decl and type template specializations.
        * pph-streamer.c (enum pph_trace_type): Add PPH_TRACE_LOCATION
        enumeration.
        (pph_trace): Add trace for locations.
        (pph_trace_location): New.
        * pph-streamer.h (pph_trace_location): New.
        (pph_out_pending_templates_list): New.
        (pph_in_pending_templates_list): New.
        (pph_out_spec_entry_tables): New.
        (pph_in_spec_entry_tables): New.
        (pph_out_location): New.
        (pph_in_location): New.
        * pph-streamer-out.c (pph_write_file_contents): Save template pending
        instantiation list, decl specialization table, and type specialization
        table.
        * pt.c (pph_out_tinst_level): New.
        (pph_dump_tinst_level): New.
        (pph_in_tinst_level): New.
        (pph_dump_pending_templates_list): New.
        (pph_out_pending_templates_list): New.
        (pph_in_pending_templates_list): New.
        (pph_out_spec_entry_slot): New.
        (pph_out_spec_entry_htab): New.
        (pph_dump_spec_entry_slot): New.
        (pph_dump_spec_entry_htab): New.
        (pph_in_spec_entry_htab): New.
        (pph_out_spec_entry_tables): New.
        (pph_in_spec_entry_tables): New.
        * parser.c (cp_debug_parser): Factor out printing of token list.
        (cp_debug_parser_tokens): New.

Index: gcc/ChangeLog.pph

2011-07-25  Lawrence Crowl  <cr...@google.com>

        * lto-streamer-out.c (lto_output_location): Make external.
        * lto-streamer-in.c (lto_input_location): Make external.
        * lto-streamer.h (lto_output_location): Make external.
        (lto_input_location): Make external.


Index: gcc/testsuite/g++.dg/pph/x1tmplclass.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x1tmplclass.cc     (revision 176778)
+++ gcc/testsuite/g++.dg/pph/x1tmplclass.cc     (working copy)
@@ -1,5 +1,3 @@
-// { dg-xfail-if "BOGUS" { "*-*-*" } { "-fpph-map=pph.map" } }
-// { dg-bogus "x0tmplclass.h:14:5: error: specializing member 
.wrapper<char>::cache. requires .template<>. syntax" "" { xfail *-*-* } 0 }
 
 #include "x0tmplclass.h"
 
Index: gcc/cp/pph.c
===================================================================
--- gcc/cp/pph.c        (revision 176778)
+++ gcc/cp/pph.c        (working copy)
@@ -46,7 +46,7 @@ FILE *pph_logfile = NULL;
 /* Dump a complicated name for tree T to FILE using FLAGS.
    See TDF_* in tree-pass.h for flags.  */
 
-static void
+void
 pph_dump_tree_name (FILE *file, tree t, int flags)
 {
   enum tree_code code = TREE_CODE (t);
Index: gcc/cp/pph.h
===================================================================
--- gcc/cp/pph.h        (revision 176778)
+++ gcc/cp/pph.h        (working copy)
@@ -52,6 +52,7 @@ extern FILE *pph_logfile;
 /* In pph.c  */
 extern void pph_init (void);
 extern void pph_finish (void);
+extern void pph_dump_tree_name (FILE *file, tree t, int flags);
 extern void pph_dump_namespace (FILE *, tree ns);
 
 #endif  /* GCC_CP_PPH_H  */
Index: gcc/cp/pph-streamer-in.c
===================================================================
--- gcc/cp/pph-streamer-in.c    (revision 176778)
+++ gcc/cp/pph-streamer-in.c    (working copy)
@@ -1448,6 +1448,9 @@ pph_read_file_contents (pph_stream *stre
   FOR_EACH_VEC_ELT (tree, file_unemitted_tinfo_decls, i, t)
     VEC_safe_push (tree, gc, unemitted_tinfo_decls, t);
 
+  pph_in_pending_templates_list (stream);
+  pph_in_spec_entry_tables (stream);
+
   file_static_aggregates = pph_in_tree (stream);
   static_aggregates = chainon (file_static_aggregates, static_aggregates);
 
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 176778)
+++ gcc/cp/pt.c (working copy)
@@ -45,6 +45,8 @@ along with GCC; see the file COPYING3.  
 #include "timevar.h"
 #include "tree-iterator.h"
 #include "vecprim.h"
+#include "pph.h"
+#include "pph-streamer.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -19681,4 +19683,253 @@ print_template_statistics (void)
           htab_collisions (type_specializations));
 }
 
+
+/* PPH write/read */
+
+
+/* Emit a tinst_level list TINST to STREAM.  */
+
+static void
+pph_out_tinst_level (pph_stream *stream, struct tinst_level *tinst)
+{
+  int count;
+  struct tinst_level *cur;
+
+  /* Count the number of items.  */
+  for (cur = tinst; cur != NULL;  cur = cur->next )
+    ++count;
+
+  /* Now emit them.  */
+  pph_out_uint (stream, count);
+  for (cur = tinst; cur != NULL;  cur = cur->next )
+    {
+      pph_out_tree (stream, cur->decl);
+      pph_out_location (stream, cur->locus);
+      pph_out_uint (stream, cur->errors);
+      pph_out_uint (stream, cur->in_system_header_p);
+    }
+}
+
+/* Dump a tinst_level list TINST to STREAM.  */
+
+static void
+pph_dump_tinst_level (FILE *stream, struct tinst_level *tinst)
+{
+  int count;
+  struct tinst_level *cur;
+
+  /* Count the number of items.  */
+  for (cur = tinst; cur != NULL;  cur = cur->next )
+    ++count;
+
+  /* Now dump them.  */
+  fprintf (stream, "%d tinst_levels\n", count );
+  for (cur = tinst; cur != NULL;  cur = cur->next )
+    {
+      pph_dump_tree_name (stream, cur->decl, 0);
+      /* pph_dump_location (stream, cur->locus); */
+      fprintf (stream, "%d errors, ", cur->errors );
+      fprintf (stream, "%d in system header\n", cur->in_system_header_p );
+    }
+}
+
+/* Load a tinst_level list.  */
+
+static struct tinst_level *
+pph_in_tinst_level (pph_stream *stream)
+{
+  struct tinst_level *last = NULL;
+  unsigned count = pph_in_uint (stream);
+  /* FIXME pph: This leaves the list in reverse order.  Issue?  */
+  for (; count > 0; --count)
+    {
+      struct tinst_level *cur = ggc_alloc_tinst_level ();
+      cur->next = last;
+      cur->decl = pph_in_tree (stream);
+      cur->locus = pph_in_location (stream);
+      cur->errors = pph_in_uint (stream);
+      cur->in_system_header_p = pph_in_uint (stream);
+      last = cur;
+    }
+  return last;
+}
+
+
+/* Dump the pending_templates list to STREAM.  */
+
+static void
+pph_dump_pending_templates_list (FILE *stream)
+{
+  int count = 0;
+  struct pending_template *cur;
+
+  /* Count the number of items.  */
+  for (cur = pending_templates; cur != NULL;  cur = cur->next )
+    ++count;
+
+  /* Now dump them.  */
+  fprintf (stream, "%d pending templates\n", count );
+  for (cur = pending_templates; cur != NULL;  cur = cur->next )
+    pph_dump_tinst_level (stream, cur->tinst);
+}
+
+/* Emit the pending_templates list to STREAM.  */
+
+void
+pph_out_pending_templates_list (pph_stream *stream)
+{
+  int count = 0;
+  struct pending_template *cur;
+
+  if (flag_pph_dump_tree)
+    pph_dump_pending_templates_list (stderr);
+
+  /* Count the number of items.  */
+  for (cur = pending_templates; cur != NULL;  cur = cur->next )
+    ++count;
+
+  /* Now emit them.  */
+  pph_out_uint (stream, count);
+  for (cur = pending_templates; cur != NULL;  cur = cur->next )
+    pph_out_tinst_level (stream, cur->tinst);
+}
+
+/* Load and merge the pending_templates list from STREAM.  */
+
+void
+pph_in_pending_templates_list (pph_stream *stream)
+{ 
+  unsigned count = pph_in_uint (stream);
+  for (; count > 0; --count)
+    {
+      struct pending_template *pt;
+      if (flag_pph_debug >= 2)
+        fprintf (stderr, "loading %d pending templates\n", count );
+      pt = ggc_alloc_pending_template ();
+      pt->next = NULL;
+      pt->tinst = pph_in_tinst_level (stream);
+      /* FIXME pph:  This just appends.  We should merge. */
+      if (last_pending_template)
+        last_pending_template->next = pt;
+      else
+        pending_templates = pt;
+      last_pending_template = pt;
+    }
+
+  if (flag_pph_dump_tree)
+    pph_dump_pending_templates_list (stderr);
+}
+
+
+/* A callback of htab_traverse. Just extracts a (type) tree from SLOT
+   and writes it out for PPH using the AUXillary information. */
+
+static int
+pph_out_spec_entry_slot (void **slot, void *aux)
+{
+  pph_stream *stream = (pph_stream *)aux;
+  struct spec_entry *entry = (struct spec_entry *) *slot;
+  pph_out_tree_or_ref (stream, entry->tmpl);
+  pph_out_tree_or_ref (stream, entry->args);
+  pph_out_tree_or_ref (stream, entry->spec);
+  return 1;
+}
+
+/* Emit a spec_entry TABLE to STREAM.  */
+
+static void
+pph_out_spec_entry_htab (pph_stream *stream, htab_t *table)
+{
+  if (*table)
+    {
+      /*FIXME pph: This write may be unstable.  */
+      pph_out_uint (stream, htab_elements (*table));
+      htab_traverse_noresize (*table, pph_out_spec_entry_slot, stream);
+    }
+  else
+    pph_out_uint (stream, 0);
+}
+
+
+/* A callback of htab_traverse. Just extracts a (type) tree from SLOT
+   and writes it out for PPH using the AUXillary information. */
+
+static int
+pph_dump_spec_entry_slot (void **slot, void *aux)
+{
+  FILE *stream = (FILE *)aux;
+  struct spec_entry *entry = (struct spec_entry *) *slot;
+  fprintf (stream, "dumping a spec_entry\n" );
+  pph_dump_tree_name (stream, entry->tmpl, 0);
+  pph_dump_tree_name (stream, entry->args, 0);
+  pph_dump_tree_name (stream, entry->spec, 0);
+  return 1;
+}
+
+/* Dump a spec_entry TABLE to STREAM.  */
+
+static void
+pph_dump_spec_entry_htab (FILE *stream, const char *name, htab_t *table)
+{
+  if (*table)
+    {
+      fprintf (stream, "%d %s spec_entry elements\n",
+               (int) htab_elements (*table), name);
+      htab_traverse_noresize (*table, pph_dump_spec_entry_slot, stream);
+    }
+  else
+    fprintf (stream, "NULL %s spec_entry elements\n", name);
+}
+
+/* Load and merge a spec_entry TABLE from STREAM.  */
+
+static void
+pph_in_spec_entry_htab (pph_stream *stream, htab_t *table)
+{
+  spec_entry **slot = NULL;
+  unsigned count = pph_in_uint (stream);
+  if (flag_pph_debug >= 2)
+    fprintf (stderr, "loading %d spec_entries\n", count );
+  for (; count > 0; --count)
+    {
+      hashval_t hash;
+      spec_entry **slot;
+      struct spec_entry *se = ggc_alloc_spec_entry ();
+      se->tmpl = pph_in_tree (stream);
+      se->args = pph_in_tree (stream);
+      se->spec = pph_in_tree (stream);
+      hash = hash_specialization (se);
+      slot = htab_find_slot_with_hash (*table, se, hash, INSERT);
+      *slot = se;
+    }
+}
+
+
+/* Emit all spec_entry tables to STREAM. */
+
+void
+pph_out_spec_entry_tables (pph_stream *stream)
+{
+  pph_out_spec_entry_htab (stream, &decl_specializations);
+  if (flag_pph_dump_tree)
+    pph_dump_spec_entry_htab (stderr, "decl", &decl_specializations);
+  pph_out_spec_entry_htab (stream, &type_specializations);
+  if (flag_pph_dump_tree)
+    pph_dump_spec_entry_htab (stderr, "type", &type_specializations);
+}
+
+/* Load and merge all spec_entry tables from STREAM.  */
+
+void
+pph_in_spec_entry_tables (pph_stream *stream)
+{
+  pph_in_spec_entry_htab (stream, &decl_specializations);
+  if (flag_pph_dump_tree)
+    pph_dump_spec_entry_htab (stderr, "decl", &decl_specializations);
+  pph_in_spec_entry_htab (stream, &type_specializations);
+  if (flag_pph_dump_tree)
+    pph_dump_spec_entry_htab (stderr, "type", &type_specializations);
+}
+
+
 #include "gt-cp-pt.h"
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c     (revision 176778)
+++ gcc/cp/parser.c     (working copy)
@@ -435,13 +435,33 @@ cp_debug_print_unparsed_queues (FILE *fi
 }
 
 
+/* Dump the tokens in a window of size WINDOW_SIZE around the next_token for
+   the given PARSER.  If FILE is NULL, the output is printed on stderr. */
+
+void
+cp_debug_parser_tokens (FILE *file, cp_parser *parser, int window_size)
+{
+  cp_token *next_token, *first_token, *start_token;
+
+  if (file == NULL)
+    file = stderr;
+
+  next_token = parser->lexer->next_token;
+  first_token = VEC_address (cp_token, parser->lexer->buffer);
+  start_token = (next_token > first_token + window_size / 2)
+               ? next_token - window_size / 2
+               : first_token;
+  cp_lexer_dump_tokens (file, parser->lexer->buffer, start_token, window_size,
+                       next_token);
+}
+
+
 /* Dump debugging information for the given PARSER.  If FILE is NULL,
    the output is printed on stderr.  */
 
 void
 cp_debug_parser (FILE *file, cp_parser *parser)
 {
-  cp_token *start_token, *first_token, *next_token;
   const size_t window_size = 200;
 
   if (file == NULL)
@@ -507,14 +527,7 @@ cp_debug_parser (FILE *file, cp_parser *
           parser->num_classes_being_defined);
   fprintf (file, "Number of template parameter lists for the current "
           "declaration: %u\n", parser->num_template_parameter_lists);
-
-  next_token = parser->lexer->next_token;
-  first_token = VEC_address (cp_token, parser->lexer->buffer);
-  start_token = (next_token > first_token + window_size / 2)
-               ? next_token - window_size / 2
-               : first_token;
-  cp_lexer_dump_tokens (file, parser->lexer->buffer, start_token, window_size,
-                       next_token);
+  cp_debug_parser_tokens (file, parser, window_size);
 }
 
 
Index: gcc/cp/pph-streamer.c
===================================================================
--- gcc/cp/pph-streamer.c       (revision 176778)
+++ gcc/cp/pph-streamer.c       (working copy)
@@ -169,6 +169,7 @@ enum pph_trace_type
     PPH_TRACE_UINT,
     PPH_TRACE_BYTES,
     PPH_TRACE_STRING,
+    PPH_TRACE_LOCATION,
     PPH_TRACE_CHAIN,
     PPH_TRACE_BITPACK
 };
@@ -244,6 +245,14 @@ pph_trace (pph_stream *stream, const voi
        fprintf (pph_logfile, ", NULL_STRING");
       break;
 
+    case PPH_TRACE_LOCATION:
+      if (data)
+       fprintf (pph_logfile, ", value=%.*s",
+                              (int) nbytes, (const char *) data);
+      else
+       fprintf (pph_logfile, ", NULL_LOCATION");
+      break;
+
     case PPH_TRACE_CHAIN:
       {
        const_tree t = (const_tree) data;
@@ -316,6 +325,26 @@ pph_trace_string_with_length (pph_stream
 }
 
 
+/* Show tracing information for location_t LOC on STREAM.  */
+
+void
+pph_trace_location (pph_stream *stream, location_t loc)
+{
+  char dec[10]; /* ten digits per file line number */
+  expanded_location xloc = expand_location (loc);
+  size_t flen = strlen (xloc.file);
+  size_t mlen = flen + 12; /* for : and 10 digits and \n */
+  size_t llen;
+  char *str = xmalloc (mlen);
+
+  strcpy (str, xloc.file);
+  str[flen] = ':';
+  sprintf (str + flen + 1, "%d", xloc.line);
+  llen = strlen (str);
+  pph_trace (stream, str, llen, PPH_TRACE_LOCATION);
+}
+
+
 /* Show tracing information for a tree chain starting with T on STREAM.  */
 
 void
Index: gcc/cp/pph-streamer.h
===================================================================
--- gcc/cp/pph-streamer.h       (revision 176778)
+++ gcc/cp/pph-streamer.h       (working copy)
@@ -142,6 +142,7 @@ void pph_trace_uint (pph_stream *, unsig
 void pph_trace_bytes (pph_stream *, const void *, size_t);
 void pph_trace_string (pph_stream *, const char *);
 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_stream *, void *, unsigned);
@@ -170,6 +171,13 @@ tree pph_alloc_tree (enum tree_code, str
                     struct data_in *);
 void pph_read_file (const char *);
 
+/* In pt.c.  */
+extern void pph_out_pending_templates_list (pph_stream *stream);
+extern void pph_in_pending_templates_list (pph_stream *stream);
+extern void pph_out_spec_entry_tables (pph_stream *stream);
+extern void pph_in_spec_entry_tables (pph_stream *stream);
+
+
 /* Inline functions.  */
 
 /* Output AST T to STREAM.  This function is the primary interface.  */
@@ -280,6 +288,15 @@ pph_out_tree_VEC (pph_stream *stream, VE
 }
 #endif
 
+/* Write location LOC of length to STREAM.  */
+static inline void
+pph_out_location (pph_stream *stream, location_t loc)
+{
+  if (flag_pph_tracer >= 4)
+    pph_trace_location (stream, loc);
+  lto_output_location (stream->ob, loc);
+}
+
 /* Write a chain of ASTs to STREAM starting with FIRST.  */
 static inline void
 pph_out_chain (pph_stream *stream, tree first)
@@ -341,6 +358,16 @@ pph_in_string (pph_stream *stream)
   return s;
 }
 
+/* Read and return a location_t from STREAM.  */
+static inline location_t
+pph_in_location (pph_stream *stream)
+{
+  location_t loc = lto_input_location (stream->ib, stream->data_in);
+  if (flag_pph_tracer >= 4)
+    pph_trace_location (stream, loc);
+  return loc;
+}
+
 /* Load an AST from STREAM.  Return the corresponding tree.  */
 static inline tree
 pph_in_tree (pph_stream *stream)
Index: gcc/cp/pph-streamer-out.c
===================================================================
--- gcc/cp/pph-streamer-out.c   (revision 176778)
+++ gcc/cp/pph-streamer-out.c   (working copy)
@@ -1245,6 +1245,10 @@ pph_write_file_contents (pph_stream *str
      globals should be fields in struct cp_parser.  */
   pph_out_tree (stream, keyed_classes);
   pph_out_tree_vec (stream, unemitted_tinfo_decls);
+
+  pph_out_pending_templates_list (stream);
+  pph_out_spec_entry_tables (stream);
+
   pph_out_tree (stream, static_aggregates);
 
   /* Emit the symbol table.  */
Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c      (revision 176778)
+++ gcc/lto-streamer-out.c      (working copy)
@@ -644,7 +644,7 @@ lto_output_location_bitpack (struct bitp
    When bitpack is handy, it is more space effecient to call
    lto_output_location_bitpack with existing bitpack.  */
 
-static void
+void
 lto_output_location (struct output_block *ob, location_t loc)
 {
   struct bitpack_d bp = bitpack_create (ob->main_stream);
Index: gcc/lto-streamer-in.c
===================================================================
--- gcc/lto-streamer-in.c       (revision 176778)
+++ gcc/lto-streamer-in.c       (working copy)
@@ -333,7 +333,7 @@ lto_input_location_bitpack (struct data_
 
 /* Read a location from input block IB.  */
 
-static location_t
+location_t
 lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
 {
   struct bitpack_d bp;
Index: gcc/lto-streamer.h
===================================================================
--- gcc/lto-streamer.h  (revision 176778)
+++ gcc/lto-streamer.h  (working copy)
@@ -977,6 +977,9 @@ extern void lto_data_in_delete (struct d
 extern const char *lto_input_string (struct data_in *,
                                     struct lto_input_block *);
 extern void lto_input_data_block (struct lto_input_block *, void *, size_t);
+extern location_t lto_input_location (struct lto_input_block *ib,
+                                      struct data_in *data_in);
+
 extern void gimple_streamer_reader_init (void);
 
 
@@ -1001,6 +1004,7 @@ void lto_output_string (struct output_bl
 void lto_output_string_with_length (struct output_block *,
                                    struct lto_output_stream *, const char *,
                                    unsigned int, bool);
+extern void lto_output_location (struct output_block *ob, location_t loc);
 
 
 /* In lto-cgraph.c  */

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

Reply via email to