diff mbox

[pph] Prepare for not streaming identifier bindings. (issue5437095)

Message ID 20111201050228.05B91222595@jade.mtv.corp.google.com
State New
Headers show

Commit Message

Lawrence Crowl Dec. 1, 2011, 5:02 a.m. UTC
The identifier bindings are causing trouble in merging.  This patch is
phase one of getting rid if binding information for identifiers within
pph files.  The bindings will be reconstructed after pph files have
been read in.  The core code enabling this switch has been disabled.

We determine when all pph files are loaded when the parser calls
pph_loaded, which it does when creating the parser.

The identifier bindings are re-assigned in name-lookup.c.

The stream read needs a different code path for merging, so several
routines get factored.



--
This patch is available for review at http://codereview.appspot.com/5437095
diff mbox

Patch

Index: gcc/testsuite/ChangeLog.pph

2011-11-30   Lawrence Crowl  <crowl@google.com>

	* g++.dg/pph/c0anticipated.h: New.
	* g++.dg/pph/c1anticipated.cc: New.
	* g++.dg/pph/x0samename1.h: New.
	* g++.dg/pph/x0samename2.h: New.
	* g++.dg/pph/x4samename.cc: New.

Index: gcc/cp/ChangeLog.pph

2011-11-30   Lawrence Crowl  <crowl@google.com>

	* pph.h (pph_loaded): New.
	(pph_set_global_identifier_bindings): New.
	(pph_out_binding_table): Add extern.
	(pph_in_binding_table): Add extern.
	* pph-core.c (pph_loaded): New.
	* parser.c (c_parse_file): Call pph_loaded.
	* name-lookup.c (pph_set_chain_identifier_bindings): New.
	(pph_set_global_identifier_bindings): New.
	* pph-out.c (pph_out_identifier_bindings): New.
	(pph_out_tree_body): Call above function.
	(pph_out_tree): Call above functions for builtins.
	* pph-in.c (pph_in_merge_ld_base): New.
	(pph_in_ref_lang_specific): Factored from pph_in_lang_specific.
	(pph_in_lang_specific): Call pph_in_ref_lang_specific.
	(pph_in_merge_lang_specific): New.
	(pph_in_tcc_declaration_tail): Factored from pph_in_tcc_declaration.
	(pph_in_tcc_declaration): Call pph_in_tcc_declaration_tail.
	(pph_in_merge_tcc_declaration): New.
	(pph_in_identifier_bindings): New.
	(pph_in_tree_body): Call above function.
        (pph_in_merge_tree_body): New.
        (pph_in_tree): Call pph_in_identifier_bindings functions for builtins.
	Call pph_in_merge_tree_body for merge bodies.


Index: gcc/testsuite/g++.dg/pph/x4samename.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x4samename.cc	(revision 0)
+++ gcc/testsuite/g++.dg/pph/x4samename.cc	(revision 0)
@@ -0,0 +1,13 @@ 
+// { dg-bogus "x4samename.cc:11:18: error: expected unqualified-id before '=' token" "" { xfail *-*-* } 0 }
+// { dg-bogus "x4samename.cc:12:43: error: cannot convert 'const char.' to 'double' for argument '1' to 'int func.double.'" "" { xfail *-*-* } 0 }
+
+#include "x0samename2.h"
+#include "x0samename1.h"
+
+extern struct doppelgaenger out;
+
+int main() {
+   int x = out.field;
+   doppelgaenger = 3;
+   return func(3.14) + func((const char*)0);
+}
Index: gcc/testsuite/g++.dg/pph/c1anticipated.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/c1anticipated.cc	(revision 0)
+++ gcc/testsuite/g++.dg/pph/c1anticipated.cc	(revision 0)
@@ -0,0 +1,12 @@ 
+#include "c0anticipated.h"
+
+int max_solutions;
+int solution_count;
+
+int main(int argc, char **argv) {
+   if(argc > 1)
+      max_solutions = atoi(argv[1]);
+   printf("%d solutions found\n\n", solution_count);
+   pretty('b');
+   return 0;
+}
Index: gcc/testsuite/g++.dg/pph/x0samename1.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x0samename1.h	(revision 0)
+++ gcc/testsuite/g++.dg/pph/x0samename1.h	(revision 0)
@@ -0,0 +1,8 @@ 
+#ifndef X0SAMENAME1
+#define X0SAMENAME1
+
+extern int func(double arg);
+
+struct doppelgaenger { int field; };
+
+#endif
Index: gcc/testsuite/g++.dg/pph/x0samename2.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x0samename2.h	(revision 0)
+++ gcc/testsuite/g++.dg/pph/x0samename2.h	(revision 0)
@@ -0,0 +1,8 @@ 
+#ifndef X0SAMENAME2
+#define X0SAMENAME2
+
+extern int func(const char *arg);
+
+int doppelgaenger;
+
+#endif
Index: gcc/testsuite/g++.dg/pph/c0anticipated.h
===================================================================
--- gcc/testsuite/g++.dg/pph/c0anticipated.h	(revision 0)
+++ gcc/testsuite/g++.dg/pph/c0anticipated.h	(revision 0)
@@ -0,0 +1,18 @@ 
+#ifndef C0ANTICIPATED_H
+#define C0ANTICIPATED_H
+extern  "C" {
+  typedef __SIZE_TYPE__ size_t;
+  void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
+  int printf(const char *, ...);
+  int atoi(const char *);
+}
+
+/* pretty print a board in the specified hexagonal format */
+void pretty(char b) {
+   int i;
+   for(i = 0; i < 1; i += 10) {
+      printf("%c ", b + i);
+   }
+   printf("\n");
+}
+#endif
Index: gcc/cp/pph-core.c
===================================================================
--- gcc/cp/pph-core.c	(revision 181856)
+++ gcc/cp/pph-core.c	(working copy)
@@ -796,6 +796,21 @@  pph_add_include (pph_stream *stream, pph
 }
 
 
+/* Handle work need after PPH files have been read,
+   but before parsing starts.  */
+
+void
+pph_loaded (void)
+{
+/* FIXME pph: Reconstructing the global binding does not yet work.  */
+#if 0
+  pph_set_global_identifier_bindings();
+#endif
+  if (flag_pph_dump_tree)
+    pph_dump_namespace (pph_logfile, global_namespace);
+}
+
+
 /*********************************************************** stream handling */
 
 
Index: gcc/cp/pph.h
===================================================================
--- gcc/cp/pph.h	(revision 181856)
+++ gcc/cp/pph.h	(working copy)
@@ -139,6 +139,7 @@  extern FILE *pph_logfile;
 
 /* In pph-core.c  */
 extern void pph_init (void);
+extern void pph_loaded (void);
 extern void pph_finish (void);
 extern void pph_dump_location (FILE *file, location_t loc);
 extern void pph_dump_tree_name (FILE *file, tree t, int flags);
@@ -161,8 +162,9 @@  extern enum pph_record_marker pph_in_rec
 
 /* In name-lookup.c.  */
 struct binding_table_s;
-void pph_out_binding_table (pph_stream *, struct binding_table_s *);
-struct binding_table_s *pph_in_binding_table (pph_stream *);
+extern void pph_out_binding_table (pph_stream *, struct binding_table_s *);
+extern struct binding_table_s *pph_in_binding_table (pph_stream *);
+extern void pph_set_global_identifier_bindings ();
 
 /* In pt.c.  */
 extern void pph_out_pending_templates_list (pph_stream *stream);
Index: gcc/cp/pph-out.c
===================================================================
--- gcc/cp/pph-out.c	(revision 181856)
+++ gcc/cp/pph-out.c	(working copy)
@@ -1797,6 +1797,24 @@  pph_out_tcc_declaration (pph_stream *str
 /******************************************************** tree head and body */
 
 
+/* Emit the bindings for an identifier expr. */
+
+void
+pph_out_identifier_bindings (pph_stream *stream, tree expr)
+{
+/* FIXME pph: Writing bindings is causing trouble,
+   but not writing them is not yet working.  */
+#if 0
+#else
+  pph_out_cxx_binding (stream, IDENTIFIER_NAMESPACE_BINDINGS (expr));
+  pph_out_cxx_binding (stream, IDENTIFIER_BINDING (expr));
+  pph_out_tree (stream, IDENTIFIER_TEMPLATE (expr));
+  pph_out_tree (stream, IDENTIFIER_LABEL_VALUE (expr));
+#endif
+  pph_out_tree (stream, REAL_IDENTIFIER_TYPE_VALUE (expr));
+}
+
+
 /* Write the body of EXPR to STREAM.  This writes out all fields not
    written by the generic tree streaming routines.  */
 
@@ -1875,11 +1893,7 @@  pph_out_tree_body (pph_stream *stream, t
       break;
 
     case IDENTIFIER_NODE:
-      pph_out_cxx_binding (stream, IDENTIFIER_NAMESPACE_BINDINGS (expr));
-      pph_out_cxx_binding (stream, IDENTIFIER_BINDING (expr));
-      pph_out_tree (stream, IDENTIFIER_TEMPLATE (expr));
-      pph_out_tree (stream, IDENTIFIER_LABEL_VALUE (expr));
-      pph_out_tree (stream, REAL_IDENTIFIER_TYPE_VALUE (expr));
+      pph_out_identifier_bindings (stream, expr);
       break;
 
     case BASELINK:
@@ -2176,6 +2190,8 @@  pph_out_tree (pph_stream *stream, tree e
          the class and code.  */
       gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
       streamer_write_builtin (stream->encoder.w.ob, expr);
+      if (TREE_CODE (expr) == IDENTIFIER_NODE)
+        pph_out_identifier_bindings (stream, expr);
       return;
     }
   else if (TREE_CODE (expr) == INTEGER_CST)
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 181856)
+++ gcc/cp/parser.c	(working copy)
@@ -27241,6 +27241,9 @@  c_parse_file (void)
     pph_init_include_tree ();
 
   the_parser = cp_parser_new ();
+
+  pph_loaded();
+
   push_deferring_access_checks (flag_access_control
 				? dk_no_deferred : dk_no_check);
   cp_parser_translation_unit (the_parser);
Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c	(revision 181856)
+++ gcc/cp/name-lookup.c	(working copy)
@@ -6083,4 +6083,42 @@  pph_in_binding_table (pph_stream *stream
   return bt;
 }
 
+
+/*  Set the identifier bindings for an individual chain.  */
+
+static void
+pph_set_chain_identifier_bindings (tree first, cp_binding_level *bl)
+{
+  tree decl;
+  for (decl = first; decl; decl = TREE_CHAIN (decl))
+    {
+      /* Set the identifier binding for a single decl.  */
+      tree id = DECL_NAME (decl);
+      if (id)
+	{
+	  if (flag_pph_debug >=2)
+	    {
+	     fprintf (pph_logfile, "binding ");
+	     pph_dump_tree_name (pph_logfile, id, 0);
+	   }
+	  push_binding (id, decl, bl);
+	}
+    }
+}
+
+
+/* Set the identifier bindings for the global namespace
+   after having read all the PPH files.  */
+
+void
+pph_set_global_identifier_bindings ()
+{
+  cp_binding_level *bl = scope_chain->bindings;
+  pph_set_chain_identifier_bindings (bl->names, bl);
+  pph_set_chain_identifier_bindings (bl->namespaces, bl);
+  pph_set_chain_identifier_bindings (bl->usings, bl);
+  pph_set_chain_identifier_bindings (bl->using_directives, bl);
+}
+
+
 #include "gt-cp-name-lookup.h"
Index: gcc/cp/pph-in.c
===================================================================
--- gcc/cp/pph-in.c	(revision 181856)
+++ gcc/cp/pph-in.c	(working copy)
@@ -1389,6 +1389,31 @@  pph_in_ld_base (pph_stream *stream, stru
 }
 
 
+/* Merge all fields into lang_decl_base instance LDB from STREAM.  */
+
+static void
+pph_in_merge_ld_base (pph_stream *stream, struct lang_decl_base *ldb)
+{
+  struct bitpack_d bp;
+
+  bp = pph_in_bitpack (stream);
+  /* FIXME pph: At present, we are only merging the anticipated bit.
+     The rest are simply overwritten.  */
+  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->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);
+  ldb->anticipated_p &= bp_unpack_value (&bp, 1);
+  ldb->friend_attr = bp_unpack_value (&bp, 1);
+  ldb->template_conv_p = bp_unpack_value (&bp, 1);
+  ldb->odr_used = bp_unpack_value (&bp, 1);
+  ldb->u2sel = bp_unpack_value (&bp, 1);
+}
+
+
 /* Read all the fields in lang_decl_min instance LDM from STREAM.  */
 
 static void
@@ -1471,25 +1496,26 @@  pph_in_ld_parm (pph_stream *stream, stru
 }
 
 
-/* Read language specific data in DECL from STREAM.  */
+/* Read potential reference to a lang decl specific.  Return null when
+   either the read pointer is null, or it is already in the cache.
+   Otherwise, return the pointer to the lang decl specific.  */
 
-static void
-pph_in_lang_specific (pph_stream *stream, tree decl)
+static struct lang_decl *
+pph_in_ref_lang_specific (pph_stream *stream, tree decl)
 {
   struct lang_decl *ld;
-  struct lang_decl_base *ldb;
   enum pph_record_marker marker;
   unsigned image_ix, ix;
 
   marker = pph_in_start_record (stream, &image_ix, &ix, PPH_lang_decl);
   if (marker == PPH_RECORD_END)
-    return;
+    return NULL;
   else if (pph_is_reference_marker (marker))
     {
       DECL_LANG_SPECIFIC (decl) =
 	(struct lang_decl *) pph_cache_find (stream, marker, image_ix, ix,
 					     PPH_lang_decl);
-      return;
+      return NULL;
     }
 
   /* Allocate a lang_decl structure for DECL, if not already present.
@@ -1504,6 +1530,21 @@  pph_in_lang_specific (pph_stream *stream
   /* 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_lang_decl);
+  return ld;
+}
+
+
+/* Read language specific data in DECL from STREAM.  */
+
+static void
+pph_in_lang_specific (pph_stream *stream, tree decl)
+{
+  struct lang_decl *ld;
+  struct lang_decl_base *ldb;
+
+  ld = pph_in_ref_lang_specific (stream, decl);
+  if (!ld)
+    return;
 
   /* Read all the fields in lang_decl_base.  */
   ldb = &ld->u.base;
@@ -1534,6 +1575,48 @@  pph_in_lang_specific (pph_stream *stream
 }
 
 
+/* Read language specific data in DECL from STREAM.  */
+
+static void
+pph_in_merge_lang_specific (pph_stream *stream, tree decl)
+{
+  struct lang_decl *ld;
+  struct lang_decl_base *ldb;
+
+  ld = pph_in_ref_lang_specific (stream, decl);
+  if (!ld)
+    return;
+
+  /* Read all the fields in lang_decl_base.  */
+  ldb = &ld->u.base;
+  pph_in_merge_ld_base (stream, ldb);
+
+  /* FIXME pph: We probably should not be merging some of these selectors.  */
+  if (ldb->selector == 0)
+    {
+      /* Read all the fields in lang_decl_min.  */
+      pph_in_ld_min (stream, &ld->u.min);
+    }
+  else if (ldb->selector == 1)
+    {
+      /* Read all the fields in lang_decl_fn.  */
+      pph_in_ld_fn (stream, &ld->u.fn);
+    }
+  else if (ldb->selector == 2)
+    {
+      /* Read all the fields in lang_decl_ns.  */
+      pph_in_ld_ns (stream, &ld->u.ns);
+    }
+  else if (ldb->selector == 3)
+    {
+      /* Read all the fields in lang_decl_parm.  */
+      pph_in_ld_parm (stream, &ld->u.parm);
+    }
+  else
+    gcc_unreachable ();
+}
+
+
 /********************************************************* tree base classes */
 
 
@@ -1765,9 +1848,8 @@  pph_in_tcc_type (pph_stream *stream, tre
 /* Read from STREAM the body of tcc_declaration tree DECL.  */
 
 static void
-pph_in_tcc_declaration (pph_stream *stream, tree decl)
+pph_in_tcc_declaration_tail (pph_stream *stream, tree decl)
 {
-  pph_in_lang_specific (stream, decl);
   DECL_INITIAL (decl) = pph_in_tree (stream);
 
   /* The tree streamer only writes DECL_CHAIN for PARM_DECL nodes.
@@ -1815,9 +1897,50 @@  pph_in_tcc_declaration (pph_stream *stre
 }
 
 
+/* Read from STREAM the body of tcc_declaration tree DECL.  */
+
+static void
+pph_in_tcc_declaration (pph_stream *stream, tree decl)
+{
+  pph_in_lang_specific (stream, decl);
+  pph_in_tcc_declaration_tail (stream, decl);
+}
+
+
+/* Read from STREAM and merge the body of tcc_declaration tree DECL.  */
+
+static void
+pph_in_merge_tcc_declaration (pph_stream *stream, tree decl)
+{
+  pph_in_merge_lang_specific (stream, decl);
+  /* FIXME pph: Some of the tail may not be necessary.  */
+  pph_in_tcc_declaration_tail (stream, decl);
+}
+
+
 /******************************************************** tree head and body */
 
 
+/* Stream in identifier bindings.  */
+
+static void
+pph_in_identifier_bindings (pph_stream *stream, tree expr)
+{
+  if (flag_pph_debug >= 3)
+    fprintf (pph_logfile, "in identifier %s\n", IDENTIFIER_POINTER (expr));
+/* FIXME pph: Writing bindings is causing trouble,
+   but not writing them is not yet working.  */
+#if 0
+#else
+  IDENTIFIER_NAMESPACE_BINDINGS (expr) = pph_in_cxx_binding (stream);
+  IDENTIFIER_BINDING (expr) = pph_in_cxx_binding (stream);
+  IDENTIFIER_TEMPLATE (expr) = pph_in_tree (stream);
+  IDENTIFIER_LABEL_VALUE (expr) = pph_in_tree (stream);
+#endif
+  REAL_IDENTIFIER_TYPE_VALUE (expr) = pph_in_tree (stream);
+}
+
+
 /* Read the body fields of EXPR from STREAM.  */
 
 static void
@@ -1891,13 +2014,7 @@  pph_in_tree_body (pph_stream *stream, tr
       break;
 
     case IDENTIFIER_NODE:
-      if (flag_pph_debug >= 3)
-	fprintf (pph_logfile, "in identifier %s\n", IDENTIFIER_POINTER (expr));
-      IDENTIFIER_NAMESPACE_BINDINGS (expr) = pph_in_cxx_binding (stream);
-      IDENTIFIER_BINDING (expr) = pph_in_cxx_binding (stream);
-      IDENTIFIER_TEMPLATE (expr) = pph_in_tree (stream);
-      IDENTIFIER_LABEL_VALUE (expr) = pph_in_tree (stream);
-      REAL_IDENTIFIER_TYPE_VALUE (expr) = pph_in_tree (stream);
+      pph_in_identifier_bindings (stream, expr);
       break;
 
     case BASELINK:
@@ -1997,6 +2114,45 @@  pph_in_tree_body (pph_stream *stream, tr
 }
 
 
+/* Read the body fields of EXPR for merging from STREAM.  */
+
+static void
+pph_in_merge_tree_body (pph_stream *stream, tree expr)
+{
+  struct lto_input_block *ib = stream->encoder.r.ib;
+  struct data_in *data_in = stream->encoder.r.data_in;
+
+  /* If we are reading a merge body, it means that EXPR is already in
+     some chain.  Given that EXPR may now be in a different location
+     in the chain, we need to make sure we do not lose it.  */
+  tree saved_expr_chain = TREE_CHAIN (expr);
+
+  /* Read the language-independent parts of EXPR's body.  */
+  streamer_read_tree_body (ib, data_in, expr);
+
+  /* Handle common tree code classes first.  */
+  switch (TREE_CODE_CLASS (TREE_CODE (expr)))
+    {
+      case tcc_declaration:
+       pph_in_merge_tcc_declaration (stream, expr);
+       break;
+
+      case tcc_type:
+       pph_in_tcc_type (stream, expr);
+       break;
+
+      default:
+       fatal_error ("PPH: unrecognized tree node '%s'",
+                    pph_tree_code_text (TREE_CODE (expr)));
+       break;
+    }
+
+  /* Restore TREE_CHAIN if necessary.  FIXME pph, we should just not
+     save TREE_CHAIN for merge bodies.  */
+  TREE_CHAIN (expr) = saved_expr_chain;
+}
+
+
 /* Unpack language-dependent bitfields from BP into EXPR.  */
 
 static void
@@ -2163,7 +2319,6 @@  pph_in_tree (pph_stream *stream)
   enum pph_record_marker marker;
   unsigned image_ix, ix;
   enum LTO_tags tag;
-  tree saved_expr_chain = NULL;
 
   /* Read record start and test cache.  */
   marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
@@ -2184,7 +2339,10 @@  pph_in_tree (pph_stream *stream)
           /* If we are going to read a built-in function, all we need is
              the code and class.  */
           gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
-          return streamer_get_builtin_tree (ib, data_in);
+          expr = streamer_get_builtin_tree (ib, data_in);
+	  if (TREE_CODE (expr) == IDENTIFIER_NODE)
+	    pph_in_identifier_bindings (stream, expr);
+	  return expr;
         }
       else if (tag == lto_tree_code_to_tag (INTEGER_CST))
         {
@@ -2237,18 +2395,10 @@  pph_in_tree (pph_stream *stream)
 	: marker == PPH_RECORD_START_MUTATED ? pph_trace_mutate
 	: pph_trace_normal );
 
-  /* If we are reading a merge body, it means that EXPR is already in
-     some chain.  Given that EXPR may now be in a different location
-     in the chain, we need to make sure we do not lose it.  */
-  if (marker == PPH_RECORD_START_MERGE_BODY)
-    saved_expr_chain = TREE_CHAIN (expr);
-
-  pph_in_tree_body (stream, expr);
-
-  /* Restore TREE_CHAIN if necessary.  FIXME pph, we should just not
-     save TREE_CHAIN for merge bodies.  */
   if (marker == PPH_RECORD_START_MERGE_BODY)
-    TREE_CHAIN (expr) = saved_expr_chain;
+    pph_in_merge_tree_body (stream, expr);
+  else
+    pph_in_tree_body (stream, expr);
 
   if (flag_pph_tracer)
     pph_trace_tree (expr, pph_trace_back,