From 5bba2215c23d71ea08fb81656d93041229f7ea9c Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 19 Nov 2020 13:18:09 -0800 Subject: [PATCH] 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. --- gcc/cp/cp-tree.h | 17 ++++++++++ gcc/cp/pt.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 112 insertions(+), 7 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0c4b74a..021de76 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5403,6 +5403,14 @@ public: hash_map *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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a1b6631..463b1c3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 { 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 *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 (); + *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 -- 2.7.4