public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-7557] c++: Incorrect specialization hash table [PR 99285]
@ 2021-03-08 18:08 Nathan Sidwell
0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2021-03-08 18:08 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:ded6a1953dd7f43229c44e5d0d17c264338a3f4c
commit r11-7557-gded6a1953dd7f43229c44e5d0d17c264338a3f4c
Author: Nathan Sidwell <nathan@acm.org>
Date: Mon Mar 8 10:01:21 2021 -0800
c++: Incorrect specialization hash table [PR 99285]
Class template partial specializations need to be in the
specialization hash, but not all of them. This defers adding
streamed-in entities to the hash table, in the same way I deferred
adding the instantiation and specialization lists for 99170.
PR c++/99285
gcc/cp/
* cp-tree.h (match_mergeable_specialization)
(add_mergeable_specialization): Adjust parms.
* module.cc (trees_in::decl_value): Adjust
add_mergeable_specialization calls.
(trees_out::key_mergeable): Adjust match_mergeable_specialization
calls.
(specialization_add): Likewise.
* pt.c (match_mergeable_specialization): Do not insert.
(add_mergeable_specialization): Add to hash table here.
gcc/testsuite/
* g++.dg/modules/pr99285_a.H: New.
* g++.dg/modules/pr99285_b.H: New.
Diff:
---
gcc/cp/cp-tree.h | 7 ++--
gcc/cp/module.cc | 23 +++++++++----
gcc/cp/pt.c | 57 +++++++++++++++++++-------------
gcc/testsuite/g++.dg/modules/pr99285_a.H | 11 ++++++
gcc/testsuite/g++.dg/modules/pr99285_b.H | 7 ++++
5 files changed, 71 insertions(+), 34 deletions(-)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 39e2ad83abd..81ff375f8a5 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7239,11 +7239,10 @@ extern void walk_specializations (bool,
void (*)(bool, spec_entry *,
void *),
void *);
-extern tree match_mergeable_specialization (bool is_decl, spec_entry *,
- bool insert = true);
+extern tree match_mergeable_specialization (bool is_decl, spec_entry *);
extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec);
-extern void add_mergeable_specialization (tree tmpl, tree args,
- tree spec, unsigned);
+extern void add_mergeable_specialization (bool is_decl, spec_entry *,
+ tree outer, 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/module.cc b/gcc/cp/module.cc
index 48862dd9bbc..2518d73c220 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -8059,9 +8059,14 @@ trees_in::decl_value ()
set_constraints (decl, spec.spec);
if (mk & MK_template_mask
|| mk == MK_partial)
- /* Add to specialization tables now that constraints etc are
- added. */
- add_mergeable_specialization (spec.tmpl, spec.args, decl, spec_flags);
+ {
+ /* Add to specialization tables now that constraints etc are
+ added. */
+ bool is_decl = (mk & MK_template_mask) && (mk & MK_tmpl_decl_mask);
+
+ spec.spec = is_decl ? inner : type;
+ add_mergeable_specialization (is_decl, &spec, decl, spec_flags);
+ }
if (TREE_CODE (decl) == INTEGER_CST && !TREE_OVERFLOW (decl))
{
@@ -8154,7 +8159,10 @@ trees_in::decl_value ()
{
tree e = match_mergeable_specialization (true, &spec);
if (!e)
- add_mergeable_specialization (spec.tmpl, spec.args, decl, spec_flags);
+ {
+ spec.spec = inner;
+ add_mergeable_specialization (true, &spec, decl, spec_flags);
+ }
else if (e != existing)
set_overrun ();
}
@@ -10344,14 +10352,14 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
{
/* Make sure we can locate the decl. */
tree existing = match_mergeable_specialization
- (bool (mk & MK_tmpl_decl_mask), entry, false);
+ (bool (mk & MK_tmpl_decl_mask), entry);
gcc_assert (existing);
if (mk & MK_tmpl_decl_mask)
{
if (mk & MK_tmpl_alias_mask)
/* It should be in both tables. */
- gcc_assert (match_mergeable_specialization (false, entry, false)
+ gcc_assert (match_mergeable_specialization (false, entry)
== TREE_TYPE (existing));
else if (mk & MK_tmpl_tmpl_mask)
if (tree ti = DECL_TEMPLATE_INFO (existing))
@@ -10659,6 +10667,7 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
if (mk & MK_template_mask)
{
+ // FIXME: We could stream the specialization hash?
spec_entry spec;
spec.tmpl = tree_node ();
spec.args = tree_node ();
@@ -12869,7 +12878,7 @@ specialization_add (bool decl_p, spec_entry *entry, void *data_)
/* Only alias templates can appear in both tables (and
if they're in the type table they must also be in the decl table). */
gcc_checking_assert
- (!match_mergeable_specialization (true, entry, false)
+ (!match_mergeable_specialization (true, entry)
== (decl_p || !DECL_ALIAS_TEMPLATE_P (entry->tmpl)));
}
else if (VAR_OR_FUNCTION_DECL_P (entry->spec))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 81df8c88ccd..5e485f10d19 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29955,28 +29955,19 @@ walk_specializations (bool decls_p,
}
/* Lookup the specialization of *ELT, in the decl or type
- specialization table. Return the SPEC that's already there (NULL if
- nothing). If INSERT is true, and there was nothing, add the new
- spec. */
+ specialization table. Return the SPEC that's already there, or
+ NULL if nothing. */
tree
-match_mergeable_specialization (bool decl_p, spec_entry *elt, bool insert)
+match_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,
- insert ? INSERT : NO_INSERT);
- if (slot && *slot)
- return (*slot)->spec;
+ auto *slot = specializations->find_slot_with_hash (elt, hash, NO_INSERT);
- if (insert)
- {
- auto entry = ggc_alloc<spec_entry> ();
- *entry = *elt;
- *slot = entry;
- }
+ if (slot)
+ return (*slot)->spec;
return NULL_TREE;
}
@@ -30012,23 +30003,43 @@ get_mergeable_specialization_flags (tree tmpl, tree decl)
return flags;
}
-/* Add a new specialization of TMPL. FLAGS is as returned from
+/* Add a new specialization described by SPEC. DECL is the
+ maybe-template decl and FLAGS is as returned from
get_mergeable_specialization_flags. */
void
-add_mergeable_specialization (tree tmpl, tree args, tree decl, unsigned flags)
+add_mergeable_specialization (bool decl_p, spec_entry *elt,
+ tree decl, unsigned flags)
{
+ hash_table<spec_hasher> *specializations
+ = decl_p ? decl_specializations : type_specializations;
+
+ hashval_t hash = spec_hasher::hash (elt);
+ auto *slot = specializations->find_slot_with_hash (elt, hash, INSERT);
+
+ /* We don't distinguish different constrained partial type
+ specializations, so there could be duplicates. Everything else
+ must be new. */
+ if (!(flags & 2 && *slot))
+ {
+ gcc_checking_assert (!*slot);
+
+ auto entry = ggc_alloc<spec_entry> ();
+ *entry = *elt;
+ *slot = entry;
+ }
+
if (flags & 1)
- DECL_TEMPLATE_INSTANTIATIONS (tmpl)
- = tree_cons (args, decl, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
+ DECL_TEMPLATE_INSTANTIATIONS (elt->tmpl)
+ = tree_cons (elt->args, decl, DECL_TEMPLATE_INSTANTIATIONS (elt->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));
+ tree cons = tree_cons (elt->args, decl,
+ DECL_TEMPLATE_SPECIALIZATIONS (elt->tmpl));
+ TREE_TYPE (cons) = elt->spec;
+ DECL_TEMPLATE_SPECIALIZATIONS (elt->tmpl) = cons;
}
}
diff --git a/gcc/testsuite/g++.dg/modules/pr99285_a.H b/gcc/testsuite/g++.dg/modules/pr99285_a.H
new file mode 100644
index 00000000000..14d0aa06c03
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99285_a.H
@@ -0,0 +1,11 @@
+// PR 99285 ICE with template-template-parm
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename... _Tp> struct common_type;
+
+template<> struct common_type<> {};
+
+template<typename _Tp0> struct common_type<_Tp0> {};
+
+template<typename _Tp1, typename _Tp2> struct common_type<_Tp1, _Tp2> {};
diff --git a/gcc/testsuite/g++.dg/modules/pr99285_b.H b/gcc/testsuite/g++.dg/modules/pr99285_b.H
new file mode 100644
index 00000000000..01a8eaf6228
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99285_b.H
@@ -0,0 +1,7 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+import "pr99285_a.H";
+
+template<typename _Rep1, typename _Rep2,
+ typename _CRep = typename common_type<_Rep1, _Rep2>::type>
+struct X;
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2021-03-08 18:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-08 18:08 [gcc r11-7557] c++: Incorrect specialization hash table [PR 99285] Nathan Sidwell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).