c++: Template hash access

This exposes the template specialization table, so the modules
machinery may access it.  The hashed entity (tmpl, args & spec) is
available, along with a hash table walker.  We also need a way of
finding or inserting entries, along with some bookkeeping fns to deal
with the instantiation and (partial) specialization lists.

	gcc/cp/
	* cp-tree.h (struct spec_entry): Moved from pt.c.
	(walk_specializations, match_mergeable_specialization)
	(get_mergeable_specialization_flags)
	(add_mergeable_specialization): Declare.
	* pt.c (struct spec_entry): Moved to cp-tree.h.
	(walk_specializations, match_mergeable_specialization)
	(get_mergeable_specialization_flags)
	(add_mergeable_specialization): New.
This commit is contained in:
Nathan Sidwell 2020-11-19 13:18:09 -08:00
parent 08b4d32571
commit 5bba2215c2
2 changed files with 112 additions and 7 deletions

View File

@ -5403,6 +5403,14 @@ public:
hash_map<tree, tree> *saved;
};
/* Entry in the specialization hash table. */
struct GTY((for_user)) spec_entry
{
tree tmpl; /* The general template this is a specialization of. */
tree args; /* The args for this (maybe-partial) specialization. */
tree spec; /* The specialization itself. */
};
/* in class.c */
extern int current_class_depth;
@ -6994,6 +7002,15 @@ extern bool copy_guide_p (const_tree);
extern bool template_guide_p (const_tree);
extern bool builtin_guide_p (const_tree);
extern void store_explicit_specifier (tree, tree);
extern void walk_specializations (bool,
void (*)(bool, spec_entry *,
void *),
void *);
extern tree match_mergeable_specialization (bool is_decl, tree tmpl,
tree args, tree spec);
extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec);
extern void add_mergeable_specialization (tree tmpl, tree args,
tree spec, unsigned);
extern tree add_outermost_template_args (tree, tree);
extern tree add_extra_args (tree, tree);
extern tree build_extra_args (tree, tree, tsubst_flags_t);

View File

@ -103,13 +103,6 @@ local_specialization_stack::~local_specialization_stack ()
/* True if we've recursed into fn_type_unification too many times. */
static bool excessive_deduction_depth;
struct GTY((for_user)) spec_entry
{
tree tmpl;
tree args;
tree spec;
};
struct spec_hasher : ggc_ptr_hash<spec_entry>
{
static hashval_t hash (spec_entry *);
@ -29625,6 +29618,101 @@ declare_integer_pack (void)
CP_BUILT_IN_INTEGER_PACK);
}
/* Walk the decl or type specialization table calling FN on each
entry. */
void
walk_specializations (bool decls_p,
void (*fn) (bool decls_p, spec_entry *entry, void *data),
void *data)
{
spec_hash_table *table = decls_p ? decl_specializations
: type_specializations;
spec_hash_table::iterator end (table->end ());
for (spec_hash_table::iterator iter (table->begin ()); iter != end; ++iter)
fn (decls_p, *iter, data);
}
/* Lookup the specialization of TMPL, ARGS in the decl or type
specialization table. Return what's there, or if SPEC is non-null,
add it and return NULL. */
tree
match_mergeable_specialization (bool decl_p, tree tmpl, tree args, tree spec)
{
spec_entry elt = {tmpl, args, spec};
hash_table<spec_hasher> *specializations
= decl_p ? decl_specializations : type_specializations;
hashval_t hash = spec_hasher::hash (&elt);
spec_entry **slot
= specializations->find_slot_with_hash (&elt, hash,
spec ? INSERT : NO_INSERT);
spec_entry *entry = slot ? *slot: NULL;
if (entry)
return entry->spec;
if (spec)
{
entry = ggc_alloc<spec_entry> ();
*entry = elt;
*slot = entry;
}
return NULL_TREE;
}
/* Return flags encoding whether SPEC is on the instantiation and/or
specialization lists of TMPL. */
unsigned
get_mergeable_specialization_flags (tree tmpl, tree decl)
{
unsigned flags = 0;
for (tree inst = DECL_TEMPLATE_INSTANTIATIONS (tmpl);
inst; inst = TREE_CHAIN (inst))
if (TREE_VALUE (inst) == decl)
{
flags |= 1;
break;
}
if (CLASS_TYPE_P (TREE_TYPE (decl))
&& CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl))
&& CLASSTYPE_USE_TEMPLATE (TREE_TYPE (decl)) == 2)
/* Only need to search if DECL is a partial specialization. */
for (tree part = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
part; part = TREE_CHAIN (part))
if (TREE_VALUE (part) == decl)
{
flags |= 2;
break;
}
return flags;
}
/* Add a new specialization of TMPL. FLAGS is as returned from
get_mergeable_specialization_flags. */
void
add_mergeable_specialization (tree tmpl, tree args, tree decl, unsigned flags)
{
if (flags & 1)
DECL_TEMPLATE_INSTANTIATIONS (tmpl)
= tree_cons (args, decl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
if (flags & 2)
{
/* A partial specialization. */
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
= tree_cons (args, decl, DECL_TEMPLATE_SPECIALIZATIONS (tmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (tmpl))
= TREE_TYPE (DECL_TEMPLATE_RESULT (decl));
}
}
/* Set up the hash tables for template instantiations. */
void