[18/32] new C++ template bits

Message ID 28707e9f-3d66-9b8b-9341-6110243f3392@acm.org
State New
Headers show
Series
  • C++ 20 Modules
Related show

Commit Message

Nathan Sidwell Nov. 3, 2020, 9:16 p.m.
We also need to manipulate the instantiation tables.  This exposes that 
bit of the template machinery.  (other patches address instantiations 
themselves)

-- 
Nathan Sidwell

Patch

diff --git c/gcc/cp/cp-tree.h w/gcc/cp/cp-tree.h
index fdb8ee57f0b..e8e4d0af2d8 100644
--- c/gcc/cp/cp-tree.h
+++ w/gcc/cp/cp-tree.h
@@ -5386,6 +5563,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;
@@ -6976,6 +7273,16 @@  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 check_mergeable_specialization	(bool, spec_entry *);
+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 c/gcc/cp/pt.c w/gcc/cp/pt.c
index aa162d2a4f9..497ac5aafec 100644
--- c/gcc/cp/pt.c
+++ w/gcc/cp/pt.c
@@ -103,13 +106,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 *);
@@ -29613,6 +29695,104 @@  declare_integer_pack (void)
 			      CP_BUILT_IN_INTEGER_PACK);
 }
 
+/* Collect the specializations and explicit instantitions generated
+   in this module  */
+
+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);
+}
+
+tree
+check_mergeable_specialization (bool decl_p, spec_entry *elt)
+{
+  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, NO_INSERT);
+  return slot ? (*slot)->spec : NULL_TREE;
+}
+
+/* Lookup the specialization of TMPL,ARGS in the decl or type
+   specialization table.  Return what's there, or add SPEC and return
+   NULL.  */
+
+tree
+match_mergeable_specialization (bool decl_p, tree tmpl, tree args, tree spec)
+{
+  gcc_checking_assert (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, INSERT);
+  spec_entry *entry = slot ? *slot: NULL;
+  
+  if (entry)
+    return entry->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;
+}
+
+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)
+    {
+      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