Jason, We are having several issues re-instantiating symbols and namespaces from a pph image. We are not handling all the cases and the contortions we are going through are getting increasingly bizarre. Perhaps you could give us a few pointers?
When we write the contents of a header file into an image, we do the following in pph_write_file_contents (http://gcc.gnu.org/viewcvs/branches/pph/gcc/cp/pph-streamer-out.c?view=markup): static void pph_write_file_contents (pph_stream *stream, cpp_idents_used *idents_used) { pph_out_identifiers (stream, idents_used); pph_out_scope_chain (stream, scope_chain, false); if (flag_pph_dump_tree) pph_dump_namespace (pph_logfile, global_namespace); pph_out_tree (stream, keyed_classes, false); pph_out_tree_vec (stream, unemitted_tinfo_decls, false); pph_out_tree (stream, static_aggregates, false); } In pph_out_scope_chain, we simply pickle out the contents of scope_chain->bindings. When compiling the translation unit, we read and merge a pph image in pph_read_file_contents (http://gcc.gnu.org/viewcvs/branches/pph/gcc/cp/pph-streamer-in.c?view=markup). When re-building scope_chain->bindings, we call pph_add_bindings, which will add everything under the file's scope_chain->bindings into the current translation unit global_namespace. This is currently pretty hacky, we are calling some symbol registration functions that I'm not sure are completely right. So we have various assembly miscomparisons, strange duplicate declaration errors and outright ICEs. The code currently does: static void pph_add_bindings_to_namespace (struct cp_binding_level *bl, tree ns) { tree t, chain; /* The chains are built backwards (ref: add_decl_to_level), reverse them before putting them back in. */ bl->names = nreverse (bl->names); bl->namespaces = nreverse (bl->namespaces); for (t = bl->names; t; t = chain) { /* Pushing a decl into a scope clobbers its DECL_CHAIN. Preserve it. */ chain = DECL_CHAIN (t); pushdecl_into_namespace (t, ns); if (TREE_CODE (t) == VAR_DECL && TREE_STATIC (t) && !DECL_EXTERNAL (t)) varpool_finalize_decl (t); } for (t = bl->namespaces; t; t = chain) { /* Pushing a decl into a scope clobbers its DECL_CHAIN. Preserve it. */ chain = DECL_CHAIN (t); pushdecl_into_namespace (t, ns); if (NAMESPACE_LEVEL (t)) pph_add_bindings_to_namespace (NAMESPACE_LEVEL (t), t); } } and we call it with global_namespace the first time. The call to pushdecl_into_namespace is mostly a wrapper around pushdecl_with_scope: tree pushdecl_into_namespace (tree dcl, tree nsp) { tree ret; /* FIXME pph: There might be a better way to do this... */ struct cp_binding_level *level = NAMESPACE_LEVEL (nsp); tree saved = current_namespace; current_namespace = nsp; #if 0 ret = pushdecl_maybe_friend (dcl, /*is_friend=*/false); #else ret = pushdecl_with_scope (dcl, level, /*is_friend=*/false); #endif current_namespace = saved; return ret; } I've been looking around in the parser, and it seems to use a variety of different symbol registration routines. I think all this reconstruction we are doing needs to be re-written, it is quite hacky and incomplete. Is there a canonical way that we should use to rebuild the elements from scope_chain->bindings? Could we not simply add them to the current translation unit's scope_chain->bindings as-is, instead of doing all these pushdecl calls? When we read the PPH file back in we do need to create varpool entries for some symbols so they get processed by the callgraph, but I'm not sure what's the best way to go about that. Thanks. Diego.