2011-01-17 Lawrence Crowl <crowl@google.com>
* g++.dg/pph/x6dynarray3.cc: Add expected overload failures.
* g++.dg/pph/x4namespace.cc: Remove expected failures.
* g++.dg/pph/x4overset1.cc: Add expected overload asm diff failure.
* g++.dg/pph/x4overset2.cc: Likewise.
* g++.dg/pph/x4overset3.cc: Likewise.
* g++.dg/pph/x4overset4.cc: Likewise.
* g++.dg/pph/x0namespace.h: Add spacing.
* g++.dg/pph/x0namespace2.h: Likewise.
2012-01-17 Lawrence Crowl <crowl@google.com>
* pph.h (pph_files_read): New.
(chain2vec): Move from static to global.
* pph-streamer.h (pph_dump_namespace): Add message parameter.
* pph-core.c (pph_dump_namespace): Add message parameter.
(pph_trace_marker): Add PPH: label to debugging output.
(pph_cache_insert_at): Remove non-static aggregate initializer.
(pph_loaded): Enable pph_set_global_identifier_bindings().
* pph-out.c (chain2vec): Move from static to global.
(pph_out_merge_key_namespace_decl): New.
(pph_out_merge_body_namespace_decl): New.
(pph_foreach_out_chain): New.
(pph_out_merge_key_binding_level): Handle namespace keys separately.
(pph_out_merge_key_tree): Likewise.
(pph_out_merge_body_binding_level): Handle namespace bodies separately.
(pph_out_identifier_bindings): No longer emit most binding info.
(pph_out_merge_key_namespace_decl): Output record info.
(pph_out_merge_body_namespace_decl): New.
* pph-in.c (pph_in_merge_body_namespace_decl): New.
(pph_in_merge_key_namespace_decl): New.
(pph_in_merge_key_binding_level): Handle namespace separately.
(pph_in_merge_key_tree): Likewise.
(pph_in_merge_body_binding_level_1): Likewise.
(pph_in_identifier_bindings): No longer emit most binding info.
(pph_ensure_namespace_binding_level): New.
(pph_in_merge_key_namespace_decl): Modify chain as needed.
(pph_in_merge_body_namespace_decl): New.
(bool pph_files_were_read): New.
(pph_files_read): New.
(pph_read_file_1): Set pph_files_were_read.
* pt.c (pph_dump_tinst_level): Add PPH: label to debugging output.
(pph_dump_pending_templates_list): Likewise.
(pph_dump_spec_entry_slot): Likewise.
(pph_dump_spec_entry_htab): Likewise.
* parser.h (cp_debug_parser_where): New.
* parser.c (cp_debug_parser_where): New.
(c_parse_file): Conditionalize call to pph_loaded.
* name-lookup.c (pph_debug_binding_action): New.
(pph_debug_binding_inaction): New.
(pph_foreach_on_chain_bl): New.
(pph_set_identifier_bindings): New.
(pph_set_chain_identifier_bindings): Use pph_set_identifier_bindings.
(pph_set_namespace_bindings): New.
(pph_set_chain_namespace_bindings): New.
(pph_foreach_on_chain): New.
(pph_set_namespace_namespace_binding): New.
(pph_set_namespace_namespace_bindings): New.
(pph_set_global_identifier_bindings): Add call to
pph_set_namespace_namespace_bindings.
2012-01-17 Lawrence Crowl <crowl@google.com>
* langhooks.h (get_lang_hooks): New.
* langhooks.c (get_lang_hooks): New.
===================================================================
@@ -1,6 +1,8 @@
-// pph asm xdiff 18502
-// xfail BOGUS UNKNOWN
-// Some branches seem to be missing.
+// { dg-bogus "a0dynarray-dfn1b.hi:8:13: error: no matching function for call to 'operator new" "" { xfail *-*-* } 0 }
+// { dg-bogus "a0dynarray-dfn1b.hi:22:5: error: no suitable 'operator delete" "" { xfail *-*-* } 0 }
+// { dg-bogus "a0dynarray-dfn2b.hi:8:13: error: no matching function for call to 'operator new" "" { xfail *-*-* } 0 }
+// { dg-bogus "a0dynarray-dfn2b.hi:13:9: error: no suitable 'operator delete" "" { xfail *-*-* } 0 }
+// { dg-bogus "a0dynarray-dcl3.hi:11:60: warning: no corresponding deallocation function for 'void. operator new" "" { xfail *-*-* } 0 }
#include "x5dynarray3.h"
===================================================================
@@ -1,3 +1,5 @@
+// pph asm xdiff 56596
+
#include "x1overset1.h"
#include "x1overset2.h"
===================================================================
@@ -1,4 +1,5 @@
-// pph asm xwant 57625
+// pph asm xdiff 01525
+// wanted 57625
// This test produces overload differences because the declaration and
// call orders are different between pph and textual parsing.
===================================================================
@@ -1,10 +1,8 @@
-// { dg-bogus "x4namespace.cc:11:1: error: 'C' does not name a type" "" { xfail *-*-* } 0 }
-// { dg-bogus "x4namespace.cc:27:5: error: 'z' is not a member of 'A'" "" { xfail *-*-* } 0 }
-
#include "x0namespace.h"
#include "x0namespace2.h"
namespace A {
+
int x = 3;
int x2 = 5;
===================================================================
@@ -1,3 +1,5 @@
+// pph asm xdiff 56596
+
#include "x1overset1.h"
#include "x1overset2.h"
#include "x1overset1.h"
===================================================================
@@ -1,8 +1,11 @@
#ifndef X0NAMESPACE2_H
#define X0NAMESPACE2_H
+
namespace A {
+
extern int x2;
struct B2;
+
template< typename T >
struct C2 {
T* b;
@@ -10,13 +13,17 @@ struct C2 {
int another()
{ return *b; }
};
+
template< typename T >
int C2< T >::method()
{ return x2; }
+
} // namespace A
+
struct D2 : A::C2< int > {
int method();
int another()
{ return *b; }
};
+
#endif
===================================================================
@@ -1,4 +1,5 @@
-// pph asm xwant 57625
+// pph asm xdiff 01525
+// wanted 57625
// This test produces overload differences because the declaration and
// call orders are different between pph and textual parsing.
===================================================================
@@ -1,8 +1,11 @@
#ifndef X0NAMESPACE_H
#define X0NAMESPACE_H
+
namespace A {
+
extern int x;
struct B;
+
template< typename T >
struct C {
T* b;
@@ -10,13 +13,17 @@ struct C {
int another()
{ return *b; }
};
+
template< typename T >
int C< T >::method()
{ return x; }
+
} // namespace A
+
struct D : A::C< int > {
int method();
int another()
{ return *b; }
};
+
#endif
===================================================================
@@ -147,8 +147,10 @@ pph_dump_binding (FILE *file, cp_binding
/* Dump namespace NS for PPH. */
void
-pph_dump_namespace (FILE *file, tree ns)
+pph_dump_namespace (FILE *file, tree ns, const char *msg)
{
+ if (msg)
+ fprintf (file, "\nPPH: %s\n", msg);
fprintf (file, "namespace ");
pph_dump_tree_name (file, ns, 0);
fprintf (file, "{\n");
@@ -183,7 +185,7 @@ pph_dump_binding (FILE *file, cp_binding
{
next = DECL_CHAIN (t);
if (!DECL_IS_BUILTIN (t))
- pph_dump_namespace (file, t);
+ pph_dump_namespace (file, t, (const char *)NULL);
}
}
@@ -227,7 +229,7 @@ static const char *tag_strings[] =
void
pph_trace_marker (enum pph_record_marker marker, enum pph_tag tag)
{
- fprintf (pph_logfile, "marker ");
+ fprintf (pph_logfile, "PPH: marker ");
if (PPH_RECORD_START <= marker && marker <= PPH_RECORD_PREF)
fprintf (pph_logfile, "%s", marker_strings[marker - PPH_RECORD_START]);
else
@@ -401,7 +403,13 @@ pph_cache_insert_at (pph_cache *cache, v
enum pph_tag tag)
{
void **map_slot;
- pph_cache_entry e = { data, tag, false, 0, 0 };
+ pph_cache_entry e;
+
+ e.data = data;
+ e.tag = tag;
+ e.needs_merge_body = false;
+ e.crc = 0;
+ e.crc_nbytes = 0;
map_slot = pointer_map_insert (cache->m, data);
@@ -843,12 +851,9 @@ pph_add_include (pph_stream *stream, pph
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);
+ pph_dump_namespace (pph_logfile, global_namespace, "after all pph read");
}
===================================================================
@@ -159,6 +159,7 @@ extern location_t pph_in_location (pph_s
extern tree pph_in_tree (pph_stream *stream);
extern enum pph_record_marker pph_in_record_marker (pph_stream *stream,
enum pph_tag *tag_p);
+extern bool pph_files_read (void);
/* In name-lookup.c. */
struct binding_table_s;
@@ -172,6 +173,9 @@ extern void pph_out_spec_entry_tables (p
extern void pph_in_pending_templates_list (pph_stream *);
extern void pph_in_spec_entry_tables (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. */
===================================================================
@@ -1087,7 +1087,7 @@ chain2vec_filter (pph_stream *stream, tr
/* Convert a CHAIN to a VEC by copying the nodes. */
-static VEC(tree,heap) *
+VEC(tree,heap) *
chain2vec (tree chain)
{
tree t;
@@ -1160,6 +1160,8 @@ pph_out_merge_body_chain (pph_stream *st
/* Forward declaration to break cyclic dependencies. */
static void pph_out_binding_level (pph_stream *, cp_binding_level *, unsigned);
+static void pph_out_merge_key_namespace_decl (pph_stream *stream, tree ns);
+static void pph_out_merge_body_namespace_decl (pph_stream *stream, tree ns);
/* Helper for pph_out_cxx_binding. STREAM and CB are as in
@@ -1307,31 +1309,54 @@ pph_out_binding_level (pph_stream *strea
}
-/* Write an index of mergeable objects from cp_binding_level BL to STREAM. */
+/* Iterate over a chain FIRST, apply FILTER, and call output FUNCTION. */
+
+static void
+pph_foreach_out_chain (pph_stream *stream, tree first, unsigned filter,
+ void (*function)(pph_stream *, tree))
+{
+ unsigned i;
+ tree ns;
+ VEC(tree,heap) *v;
+ v = chain2vec_filter (stream, first, filter);
+ pph_out_hwi (stream, VEC_length (tree, v));
+ FOR_EACH_VEC_ELT_REVERSE (tree, v, i, ns)
+ (*function) (stream, ns);
+ VEC_free (tree, heap, v);
+}
+
+
+/* Write an index of mergeable namespaces from cp_binding_level BL to
+ STREAM. */
static void
pph_out_merge_key_binding_level (pph_stream *stream, cp_binding_level *bl)
{
- unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
- pph_out_merge_key_chain (stream, bl->names, filter);
- pph_out_merge_key_chain (stream, bl->namespaces, filter);
- pph_out_merge_key_chain (stream, bl->usings, filter);
- pph_out_merge_key_chain (stream, bl->using_directives, filter);
+ unsigned filter1 = PPHF_NO_PREFS | PPHF_NO_BUILTINS;
+ unsigned filter2 = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
+ pph_foreach_out_chain (stream, bl->namespaces, filter1,
+ pph_out_merge_key_namespace_decl);
+ pph_out_merge_key_chain (stream, bl->names, filter2);
+ pph_out_merge_key_chain (stream, bl->usings, filter2);
+ pph_out_merge_key_chain (stream, bl->using_directives, filter2);
}
-/* Write bodies of mergeable objects from cp_binding_level BL to STREAM. */
+/* Write bodies of mergeable namespaces from from cp_binding_level BL
+ to STREAM. */
static void
pph_out_merge_body_binding_level (pph_stream *stream, cp_binding_level *bl)
{
- unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
- pph_out_merge_body_chain (stream, bl->names, filter);
- pph_out_merge_body_chain (stream, bl->namespaces, filter);
- pph_out_merge_body_chain (stream, bl->usings, filter);
- pph_out_merge_body_chain (stream, bl->using_directives, filter);
- pph_out_tree_vec_filtered (stream, bl->static_decls, filter);
- pph_out_binding_level_1 (stream, bl, filter);
+ unsigned filter1 = PPHF_NO_PREFS | PPHF_NO_BUILTINS;
+ unsigned filter2 = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
+ pph_foreach_out_chain (stream, bl->namespaces, filter1,
+ pph_out_merge_body_namespace_decl);
+ pph_out_merge_body_chain (stream, bl->names, filter2);
+ pph_out_merge_body_chain (stream, bl->usings, filter2);
+ pph_out_merge_body_chain (stream, bl->using_directives, filter2);
+ pph_out_tree_vec_filtered (stream, bl->static_decls, filter2);
+ pph_out_binding_level_1 (stream, bl, filter2);
}
@@ -1872,18 +1897,9 @@ pph_out_tcc_declaration (pph_stream *str
/* Emit the bindings for an identifier expr. */
-void
+static 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));
}
@@ -2196,7 +2212,7 @@ pph_out_merge_name (pph_stream *stream,
}
-/* Write merge information for a namespace DECL to STREAM. */
+/* Write merge key information for a namespace DECL to STREAM. */
static void
pph_out_merge_key_namespace_decl (pph_stream *stream, tree decl)
@@ -2205,12 +2221,52 @@ pph_out_merge_key_namespace_decl (pph_st
gcc_assert (TREE_CODE (decl) == NAMESPACE_DECL);
+ pph_out_start_merge_key_tree_record (stream, decl);
+
+ pph_out_tree_header (stream, decl);
+ pph_out_merge_name (stream, decl);
+
+ if (flag_pph_tracer)
+ pph_trace_tree (decl, pph_trace_front, pph_trace_key_out);
+
+ pph_out_tree (stream, DECL_NAME (decl));
+
/* If EXPR is a namespace alias, it will not have an associated
binding. In that case, tell the reader not to bother with it. */
is_namespace_alias = (DECL_NAMESPACE_ALIAS (decl) != NULL_TREE);
pph_out_bool (stream, is_namespace_alias);
if (!is_namespace_alias)
pph_out_merge_key_binding_level (stream, NAMESPACE_LEVEL (decl));
+
+ if (flag_pph_tracer)
+ pph_trace_tree (decl, pph_trace_back, pph_trace_key_out);
+}
+
+
+/* Write merge body information for a namespace DECL to STREAM. */
+
+static void
+pph_out_merge_body_namespace_decl (pph_stream *stream, tree decl)
+{
+ bool is_namespace_alias;
+
+ gcc_assert (TREE_CODE (decl) == NAMESPACE_DECL);
+
+ pph_out_start_tree_record (stream, decl);
+ pph_out_tree_header (stream, decl);
+
+ if (flag_pph_tracer)
+ pph_trace_tree (decl, pph_trace_front, pph_trace_merge_body);
+
+ /* If EXPR is a namespace alias, it will not have an associated
+ binding. In that case, tell the reader not to bother with it. */
+ is_namespace_alias = (DECL_NAMESPACE_ALIAS (decl) != NULL_TREE);
+ pph_out_bool (stream, is_namespace_alias);
+ if (!is_namespace_alias)
+ pph_out_merge_body_binding_level (stream, NAMESPACE_LEVEL (decl));
+
+ if (flag_pph_tracer)
+ pph_trace_tree (decl, pph_trace_back, pph_trace_merge_body);
}
@@ -2234,8 +2290,6 @@ pph_out_merge_key_tree (pph_stream *stre
pph_out_merge_name (stream, expr);
if (DECL_P (expr))
{
- if (TREE_CODE (expr) == NAMESPACE_DECL)
- pph_out_merge_key_namespace_decl (stream, expr);
#if 0
/* FIXME pph: Distable tree merging for the moment. */
else if (TREE_CODE (expr) == TYPE_DECL)
@@ -2589,7 +2643,7 @@ pph_write_file (pph_stream *stream)
cpp_idents_used idents_used;
if (flag_pph_tracer >= 1)
- fprintf (pph_logfile, "PPH: Writing %s\n", pph_out_file);
+ fprintf (pph_logfile, "\nPPH: Writing %s\n", pph_out_file);
/* Emit the line table entries and references to our direct includes. */
pph_out_line_table_and_includes (stream);
@@ -2616,7 +2670,7 @@ pph_write_file (pph_stream *stream)
pph_out_symtab (stream);
if (flag_pph_dump_tree)
- pph_dump_namespace (pph_logfile, global_namespace);
+ pph_dump_namespace (pph_logfile, global_namespace, "after pph write");
}
===================================================================
@@ -20597,11 +20597,13 @@ pph_dump_tinst_level (FILE *stream, stru
++count;
/* Now dump them. */
- fprintf (stream, "%d tinst_levels\n", count);
+ fprintf (stream, "PPH: %d tinst_levels\n", count);
for (cur = tinst; cur != NULL; cur = cur->next)
{
+ fprintf (stream, "PPH: ");
pph_dump_location (stream, cur->locus);
fprintf (stream, "\n");
+ fprintf (stream, "PPH: ");
pph_dump_tree_name (stream, cur->decl, 0);
fprintf (stream, "%d errors, ", cur->errors);
fprintf (stream, "%d in system header\n", cur->in_system_header_p);
@@ -20647,7 +20649,7 @@ pph_dump_pending_templates_list (FILE *s
++count;
/* Now dump them. */
- fprintf (stream, "%d pending templates\n", count );
+ fprintf (stream, "PPH: %d pending templates\n", count );
for (cur = pending_templates; cur != NULL; cur = cur->next )
pph_dump_tinst_level (stream, cur->tinst);
}
@@ -20738,9 +20740,9 @@ pph_dump_spec_entry_slot (void **slot, v
{
FILE *stream = (FILE *)aux;
struct spec_entry *entry = (struct spec_entry *) *slot;
- fprintf (stream, "spec_entry.tmpl: " );
+ fprintf (stream, "PPH: spec_entry.tmpl: " );
pph_dump_tree_name (stream, entry->tmpl, 0);
- fprintf (stream, "spec_entry.spec: " );
+ fprintf (stream, "PPH: spec_entry.spec: " );
pph_dump_tree_name (stream, entry->spec, 0);
return 1;
}
@@ -20752,12 +20754,12 @@ pph_dump_spec_entry_htab (FILE *stream,
{
if (*table)
{
- fprintf (stream, "%d %s spec_entry elements\n",
+ fprintf (stream, "PPH: %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);
+ fprintf (stream, "PPH: NULL %s spec_entry elements\n", name);
}
/* Load and merge a spec_entry TABLE from STREAM. */
===================================================================
@@ -463,6 +463,24 @@ cp_debug_parser_tokens (FILE *file, cp_p
}
+/* Concisely dump the tokens around where the PARSER's current token
+ in a concise manner. If FILE is NULL, the output is printed on
+ stderr. */
+
+void
+cp_debug_parser_where (FILE *file, cp_parser *parser)
+{
+ const size_t window_size = 20;
+ cp_token *token = parser->lexer->next_token;
+ expanded_location eloc = expand_location (token->location);
+
+ if (file == NULL)
+ file = stderr;
+
+ fprintf (file, "%s:%d:%d ", eloc.file, eloc.line, eloc.column);
+ cp_debug_parser_tokens (file, parser, window_size);
+}
+
/* Dump debugging information for the given PARSER. If FILE is NULL,
the output is printed on stderr. */
@@ -27440,7 +27458,8 @@ c_parse_file (void)
the_parser = cp_parser_new ();
- pph_loaded();
+ if (pph_enabled_p () && pph_files_read ())
+ pph_loaded ();
push_deferring_access_checks (flag_access_control
? dk_no_deferred : dk_no_check);
===================================================================
@@ -359,5 +359,6 @@ typedef struct GTY(()) cp_parser {
extern void cp_lexer_debug_tokens (VEC(cp_token,gc) *);
extern cp_token_cache *cp_token_cache_new (cp_token *, cp_token *);
extern void cp_debug_parser (FILE *, cp_parser *);
+extern void cp_debug_parser_where (FILE *, cp_parser *);
#endif /* GCC_CP_PARSER_H */
===================================================================
@@ -249,7 +249,7 @@ enum pph_trace_end
/* In pph-core.c. */
const char *pph_tree_code_text (enum tree_code code);
-void pph_dump_namespace (FILE *, tree ns);
+void pph_dump_namespace (FILE *, tree ns, const char *msg);
pph_stream *pph_stream_registry_lookup (const char *);
void pph_stream_set_header_name (pph_stream *, const char *);
pph_stream *pph_stream_open (const char *, const char *);
===================================================================
@@ -6085,29 +6085,163 @@ pph_in_binding_table (pph_stream *stream
}
+/* Dump a taken binding action. */
+
+static void
+pph_debug_binding_action (const char *action, tree decl)
+{
+ if (flag_pph_debug >= 5 || (flag_pph_debug >= 2 && !DECL_IS_BUILTIN (decl)))
+ {
+ fprintf (pph_logfile, "%s ", action);
+ pph_dump_tree_name (pph_logfile, decl, 0);
+ }
+}
+
+/* Dump a not-taken binding action. */
+
+static void
+pph_debug_binding_inaction (const char *action, tree decl)
+{
+ if (flag_pph_debug >= 5 || (flag_pph_debug >= 3 && !DECL_IS_BUILTIN (decl)))
+ {
+ fprintf (pph_logfile, "not %s ", action);
+ pph_dump_tree_name (pph_logfile, decl, 0);
+ }
+}
+
+
+/* Iterate over chain starting at FIRST and calling FUNCTION for each decl
+ with argument BL. */
+
+static void
+pph_foreach_on_chain_bl (tree first, cp_binding_level *bl,
+ void (*function)(tree, cp_binding_level *))
+{
+ unsigned i;
+ tree decl;
+ VEC(tree,heap) *w = chain2vec (first);
+ FOR_EACH_VEC_ELT_REVERSE (tree, w, i, decl)
+ (*function) (decl, bl);
+ VEC_free (tree, heap, w);
+}
+
+
+/* Set a identifier binding. */
+
+static void
+pph_set_identifier_bindings (tree decl, cp_binding_level *bl)
+{
+ /* Set the identifier binding for a single decl. */
+ tree id = DECL_NAME (decl);
+ if (id)
+ {
+ pph_debug_binding_action ("i-bind", decl);
+ push_binding (id, decl, bl);
+ }
+}
+
+
/* 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))
+ pph_foreach_on_chain_bl (first, bl, pph_set_identifier_bindings);
+}
+
+
+/* Set a namespace identifier binding. */
+
+static void
+pph_set_namespace_bindings (tree decl, cp_binding_level *bl)
+{
+ /* Set the namespace identifier binding for a single decl. */
+ tree id = DECL_NAME (decl);
+ if (id)
{
- /* Set the identifier binding for a single decl. */
- tree id = DECL_NAME (decl);
- if (id)
+ /* This code plagarizes from set_namespace_binding.
+ It has trouble with supplement_binding, methinks. */
+ /* FIXME pph: we should do more merging here. */
+ cxx_binding *b = binding_for_name (bl, id);
+ if (!b->value)
{
- if (flag_pph_debug >=2)
- {
- fprintf (pph_logfile, "binding ");
- pph_dump_tree_name (pph_logfile, id, 0);
- }
- push_binding (id, decl, bl);
+ b->value = decl;
+ pph_debug_binding_action ("v-bind", decl);
+ }
+ else if (TREE_CODE (b->value) == TYPE_DECL &&
+ TREE_CODE (decl) != TYPE_DECL)
+ {
+ b->type = b->value;
+ b->value = decl;
+ pph_debug_binding_action ("p-bind", decl);
+ }
+ else if (TREE_CODE (b->value) != TYPE_DECL &&
+ TREE_CODE (decl) == TYPE_DECL)
+ {
+ b->type = decl;
+ pph_debug_binding_action ("t-bind", decl);
}
+ else
+ pph_debug_binding_inaction ("n-bind", decl);
+ }
+}
+
+
+/* Set the namespace identifier bindings. */
+
+static void
+pph_set_chain_namespace_bindings (tree first, cp_binding_level *bl)
+{
+ pph_foreach_on_chain_bl (first, bl, pph_set_namespace_bindings);
+}
+
+
+static void
+pph_foreach_on_chain (tree first, void (*function)(tree))
+{
+ unsigned i;
+ tree decl;
+ VEC(tree,heap) *w = chain2vec (first);
+ FOR_EACH_VEC_ELT_REVERSE (tree, w, i, decl)
+ (*function) (decl);
+ VEC_free (tree, heap, w);
+}
+
+
+/* Forward declaration. */
+
+static void
+pph_set_namespace_namespace_bindings (cp_binding_level *bl);
+
+
+/* Set a namespace namespace binding. */
+
+static void
+pph_set_namespace_namespace_binding (tree decl)
+{
+ /* Set the namespace identifier binding for a single decl. */
+ tree id = DECL_NAME (decl);
+ if (id)
+ {
+ pph_debug_binding_action ("bind recurse", decl);
+ pph_set_namespace_namespace_bindings (NAMESPACE_LEVEL (decl));
}
}
+/* Set the namespace identifier bindings for a namespace. */
+
+static void
+pph_set_namespace_namespace_bindings (cp_binding_level *bl)
+{
+ pph_set_chain_namespace_bindings (bl->names, bl);
+ pph_set_chain_namespace_bindings (bl->namespaces, bl);
+ pph_set_chain_namespace_bindings (bl->usings, bl);
+ /* FIXME pph: pph_set_chain_namespace_bindings (bl->using_directives, bl); */
+ pph_foreach_on_chain (bl->namespaces, pph_set_namespace_namespace_binding);
+}
+
+
/* Set the identifier bindings for the global namespace
after having read all the PPH files. */
@@ -6119,6 +6253,7 @@ pph_set_global_identifier_bindings (void
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);
+ pph_set_namespace_namespace_bindings (bl);
}
===================================================================
@@ -987,6 +987,8 @@ pph_merge_into_chain (tree expr, const c
/* Forward declaration to break cyclic dependencies. */
static cp_binding_level *pph_in_binding_level (pph_stream *);
+static void pph_in_merge_body_namespace_decl (pph_stream *stream);
+static void pph_in_merge_key_namespace_decl (pph_stream *stream, tree *chain);
/* Helper for pph_in_cxx_binding. Read and return a cxx_binding
instance from STREAM. */
@@ -1203,9 +1205,12 @@ pph_in_binding_level (pph_stream *stream
static void
pph_in_merge_key_binding_level (pph_stream *stream, cp_binding_level *bl)
{
- /* Read all the merge keys and merge into the bindings. */
+ unsigned count, num;
+ num = pph_in_hwi (stream);
+ for (count = 0; count < num; ++count)
+ pph_in_merge_key_namespace_decl (stream, &bl->namespaces);
+ /* FIXME pph: The null check should be unnecessary. */
pph_in_merge_key_chain (stream, (bl) ? &bl->names : NULL);
- pph_in_merge_key_chain (stream, (bl) ? &bl->namespaces : NULL);
pph_in_merge_key_chain (stream, (bl) ? &bl->usings : NULL);
pph_in_merge_key_chain (stream, (bl) ? &bl->using_directives : NULL);
}
@@ -1216,7 +1221,10 @@ pph_in_merge_key_binding_level (pph_stre
static void
pph_in_merge_body_binding_level_1 (pph_stream *stream, cp_binding_level *bl)
{
- pph_in_merge_body_chain (stream);
+ unsigned count, num;
+ num = pph_in_hwi (stream);
+ for (count = 0; count < num; ++count)
+ pph_in_merge_body_namespace_decl (stream);
pph_in_merge_body_chain (stream);
pph_in_merge_body_chain (stream);
pph_in_merge_body_chain (stream);
@@ -1225,7 +1233,6 @@ pph_in_merge_body_binding_level_1 (pph_s
pph_in_binding_level_1 (stream, bl);
}
-
/* Read all the merge bodies from STREAM into the cp_binding_level BL. */
static void
@@ -1964,16 +1971,9 @@ 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));
+ fprintf (pph_logfile, "PPH: 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);
}
@@ -2260,13 +2260,74 @@ pph_in_tree_header (pph_stream *stream,
}
+/* Ensure that a binding level exists for a namespace DECL. */
+
+static void
+pph_ensure_namespace_binding_level (tree decl)
+{
+ if (!DECL_LANG_SPECIFIC (decl))
+ {
+ retrofit_lang_decl (decl);
+ NAMESPACE_LEVEL (decl) = ggc_alloc_cleared_cp_binding_level ();
+ }
+}
+
+
/* Read all the merge keys for the names under namespace DECL from
STREAM. */
static void
-pph_in_merge_key_namespace_decl (pph_stream *stream, tree decl)
+pph_in_merge_key_namespace_decl (pph_stream *stream, tree *chain)
{
+ struct lto_input_block *ib = stream->encoder.r.ib;
bool is_namespace_alias;
+ unsigned image_ix, ix;
+ enum pph_record_marker marker;
+ tree read_decl = NULL, decl = NULL;
+ enum LTO_tags tag;
+ const char *name;
+ tree name_id;
+
+ marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
+ gcc_assert (marker != PPH_RECORD_END);
+ if (pph_is_reference_marker (marker))
+ decl = (tree) pph_cache_find (stream, marker, image_ix, ix, PPH_any_tree);
+ else
+ gcc_assert (marker == PPH_RECORD_START_MERGE_KEY);
+
+ tag = streamer_read_record_start (ib);
+
+ read_decl = pph_in_tree_header (stream, tag);
+ gcc_assert (pph_tree_is_mergeable (read_decl));
+ name = pph_in_string (stream);
+
+ gcc_assert (TREE_CODE (read_decl) == NAMESPACE_DECL);
+
+ if (!decl)
+ {
+ /* The record is new, so we need to link it in. */
+
+ /* If we are merging into an existing CHAIN. Look for a match in
+ CHAIN to READ_DECL's header. If we found a match, DECL will be
+ the existing tree that matches READ_DECL. Otherwise, DECL is the
+ newly allocated READ_DECL. */
+ decl = (chain) ? pph_merge_into_chain (read_decl, name, chain)
+ : read_decl;
+ gcc_assert (decl != NULL);
+
+ pph_cache_insert_at (&stream->cache, decl, ix,
+ pph_tree_code_to_tag (decl));
+ }
+
+ if (flag_pph_tracer)
+ pph_trace_tree (decl, pph_trace_front, pph_trace_unmerged_key);
+
+ name_id = pph_in_tree (stream);
+ if (decl == read_decl)
+ {
+ DECL_NAME (decl) = name_id;
+ TREE_TYPE (decl) = void_type_node;
+ }
/* If EXPR is a namespace alias, we do not need to merge
its binding level (namespaces aliases do not have a
@@ -2275,6 +2336,7 @@ pph_in_merge_key_namespace_decl (pph_str
is_namespace_alias = pph_in_bool (stream);
if (!is_namespace_alias)
{
+ /* FIXME pph this comment is broken. */
/* If this is the first time we see DECL, it will not have
a decl_lang nor a binding level associated with it. This
means that we do not actually need to do any merging, so
@@ -2284,11 +2346,89 @@ pph_in_merge_key_namespace_decl (pph_str
under DECL, but it will not try to attempt any merging.
This is fine. The namespace will be populated once we read
DECL's body. */
- cp_binding_level *bl = DECL_LANG_SPECIFIC (decl)
- ? NAMESPACE_LEVEL (decl)
- : NULL;
- pph_in_merge_key_binding_level (stream, bl);
+ pph_ensure_namespace_binding_level (decl);
+ pph_in_merge_key_binding_level (stream, NAMESPACE_LEVEL (decl));
+ }
+
+ if (flag_pph_tracer)
+ pph_trace_tree (decl, pph_trace_back, pph_trace_unmerged_key);
+}
+
+
+/* Read all the merge bodies for the names under namespace DECL from
+ STREAM. */
+
+static void
+pph_in_merge_body_namespace_decl (pph_stream *stream)
+{
+ bool is_namespace_alias;
+ unsigned image_ix, ix;
+ /* FIXME pph: remove internal cache duplication of external
+ unsigned local_ix;
+ */
+ enum pph_record_marker marker;
+ tree read_decl = NULL, decl = NULL;
+ enum LTO_tags tag;
+ struct lto_input_block *ib = stream->encoder.r.ib;
+
+ marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
+ gcc_assert (marker != PPH_RECORD_END);
+ if (pph_is_reference_marker (marker))
+ decl = (tree) pph_cache_find (stream, marker, image_ix, ix, PPH_any_tree);
+ else if (marker == PPH_RECORD_START_MUTATED)
+ /* FIXME pph: remove internal cache duplication of external
+ local_ix = pph_in_uint (stream);
+ */
+ ;
+ else
+ gcc_assert (marker == PPH_RECORD_START_MERGE_BODY);
+
+ tag = streamer_read_record_start (ib);
+ read_decl = pph_in_tree_header (stream, tag);
+ gcc_assert (TREE_CODE (read_decl) == NAMESPACE_DECL);
+ if (!decl)
+ {
+ if (marker == PPH_RECORD_START_MUTATED)
+ {
+ /* When reading a mutated tree, we only need to re-read its
+ body, the tree itself is already in the cache for another
+ PPH image. */
+ decl = (tree) pph_cache_find (stream, PPH_RECORD_XREF, image_ix, ix,
+ PPH_any_tree);
+
+ /* Read the internal cache slot where EXPR should be stored at. */
+ /* FIXME pph: remove internal cache duplication of external
+ ix = local_ix;
+ */
+ }
+ else if (marker == PPH_RECORD_START_MERGE_BODY)
+ {
+ /* When reading a merge body, the tree has already been allocated
+ and added to STREAM's cache. All we have to do now is read
+ its body. */
+ decl = (tree) pph_cache_get (&stream->cache, ix);
+ }
}
+
+ if (flag_pph_tracer)
+ pph_trace_tree (decl, pph_trace_front, pph_trace_merge_body);
+
+ gcc_assert (DECL_NAME (decl));
+
+ /* If EXPR is a namespace alias, we do not need to merge
+ its binding level (namespaces aliases do not have a
+ binding level, they use the one from the namespace they
+ alias). */
+ is_namespace_alias = pph_in_bool (stream);
+ if (!is_namespace_alias)
+ {
+ gcc_assert (DECL_LANG_SPECIFIC (decl));
+ gcc_assert (NAMESPACE_LEVEL (decl));
+ pph_in_merge_body_binding_level_1 (stream, NAMESPACE_LEVEL (decl));
+ }
+
+ if (flag_pph_tracer)
+ pph_trace_tree (decl, pph_trace_back, pph_trace_merge_body);
}
@@ -2338,8 +2478,6 @@ pph_in_merge_key_tree (pph_stream *strea
if (DECL_P (expr))
{
- if (TREE_CODE (expr) == NAMESPACE_DECL)
- pph_in_merge_key_namespace_decl (stream, expr);
#if 0
/* FIXME pph: Disable type merging for the moment. */
else if (TREE_CODE (expr) == TYPE_DECL)
@@ -2823,6 +2961,20 @@ pph_in_global_binding (pph_stream *strea
}
+/* Keep track of whether or not we actually read any PPH files. */
+
+static bool pph_files_were_read = false;
+
+
+/* Report whether or not we actually read any PPH files. */
+
+bool
+pph_files_read (void)
+{
+ return pph_files_were_read;
+}
+
+
/* Helper for pph_read_file. Read contents of PPH file in STREAM. */
static void
@@ -2848,14 +3000,20 @@ pph_read_file_1 (pph_stream *stream)
(common in system headers). */
stream->in_memory_p = true;
+ pph_files_were_read = true;
+
if (flag_pph_tracer >= 1)
- fprintf (pph_logfile, "PPH: Reading %s\n", stream->name);
+ fprintf (pph_logfile, "\nPPH: Reading Lines and Includes for %s\n",
+ stream->name);
/* Read in STREAM's line table and merge it in the current line table.
At the same time, read in includes in the order they were originally
read. */
cpp_token_replay_loc = pph_in_line_table_and_includes (stream);
+ if (flag_pph_tracer >= 1)
+ fprintf (pph_logfile, "\nPPH: Reading Contents for %s\n", stream->name);
+
/* Read all the identifiers and pre-processor symbols in the global
namespace. */
pph_in_identifiers (stream, &idents_used);
@@ -2895,7 +3053,7 @@ pph_read_file_1 (pph_stream *stream)
pph_in_symtab (stream);
if (flag_pph_dump_tree)
- pph_dump_namespace (pph_logfile, global_namespace);
+ pph_dump_namespace (pph_logfile, global_namespace, "after pph read");
}
===================================================================
@@ -657,3 +657,10 @@ lhd_end_section (void)
saved_section = NULL;
}
}
+
+/* FIXME pph: This is a gdb workaround. Maybe it stays, maybe it does not. */
+struct lang_hooks *
+get_lang_hooks()
+{
+ return &lang_hooks;
+}
===================================================================
@@ -490,4 +490,7 @@ extern tree add_builtin_function_ext_sco
const char *library_name,
tree attrs);
+/* FIXME pph: This is a gdb workaround. Maybe it stays, maybe it does not. */
+extern struct lang_hooks *get_lang_hooks (void);
+
#endif /* GCC_LANG_HOOKS_H */