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.
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.
===================================================================
@@ -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);
+}
===================================================================
@@ -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;
+}
===================================================================
@@ -0,0 +1,8 @@
+#ifndef X0SAMENAME1
+#define X0SAMENAME1
+
+extern int func(double arg);
+
+struct doppelgaenger { int field; };
+
+#endif
===================================================================
@@ -0,0 +1,8 @@
+#ifndef X0SAMENAME2
+#define X0SAMENAME2
+
+extern int func(const char *arg);
+
+int doppelgaenger;
+
+#endif
===================================================================
@@ -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
===================================================================
@@ -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 */
===================================================================
@@ -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);
===================================================================
@@ -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)
===================================================================
@@ -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);
===================================================================
@@ -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"
===================================================================
@@ -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,