From 815e48e3d42231b675bae1dec5fa26890f048ef1 Mon Sep 17 00:00:00 2001 From: Nathaniel Shead Date: Thu, 31 Oct 2024 20:05:16 +1100 Subject: [PATCH] c++/modules: Propagate TYPE_CANONICAL for partial specialisations [PR113814] In some cases, when we go to import a partial specialisation there might already be an incomplete implicit instantiation in the specialisation table. This causes ICEs described in the linked PR as we now have two separate matching specialisations for this same arguments with different TYPE_CANONICAL. We already support multiple specialisations with the same args however, as they may be differently constrained. So we can solve this by simply ensuring that the TYPE_CANONICAL of the new partial specialisation matches the existing specialisation. PR c++/113814 gcc/cp/ChangeLog: * pt.cc (add_mergeable_specialization): Propagate TYPE_CANONICAL. gcc/testsuite/ChangeLog: * g++.dg/modules/partial-6.h: New test. * g++.dg/modules/partial-6_a.H: New test. * g++.dg/modules/partial-6_b.H: New test. * g++.dg/modules/partial-6_c.C: New test. Signed-off-by: Nathaniel Shead Co-authored-by: Jason Merrill --- gcc/cp/pt.cc | 14 +++++++++----- gcc/testsuite/g++.dg/modules/partial-6.h | 7 +++++++ gcc/testsuite/g++.dg/modules/partial-6_a.H | 11 +++++++++++ gcc/testsuite/g++.dg/modules/partial-6_b.H | 21 +++++++++++++++++++++ gcc/testsuite/g++.dg/modules/partial-6_c.C | 12 ++++++++++++ 5 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/partial-6.h create mode 100644 gcc/testsuite/g++.dg/modules/partial-6_a.H create mode 100644 gcc/testsuite/g++.dg/modules/partial-6_b.H create mode 100644 gcc/testsuite/g++.dg/modules/partial-6_c.C diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 334dbb3c39aa..f4213f88b99f 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -31731,12 +31731,16 @@ add_mergeable_specialization (bool decl_p, spec_entry *elt, tree decl, auto *slot = type_specializations->find_slot (elt, INSERT); /* We don't distinguish different constrained partial type - specializations, so there could be duplicates. Everything else - must be new. */ - if (!(flags & 2 && *slot)) + specializations, so there could be duplicates. In that case we + must propagate TYPE_CANONICAL so that they are treated as the + same type. Everything else must be new. */ + if (*slot) + { + gcc_checking_assert (flags & 2); + TYPE_CANONICAL (elt->spec) = TYPE_CANONICAL ((*slot)->spec); + } + else { - gcc_checking_assert (!*slot); - auto entry = ggc_alloc (); *entry = *elt; *slot = entry; diff --git a/gcc/testsuite/g++.dg/modules/partial-6.h b/gcc/testsuite/g++.dg/modules/partial-6.h new file mode 100644 index 000000000000..702c9a1b7ec8 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-6.h @@ -0,0 +1,7 @@ +// PR c++/113814 + +template struct A {}; +template A f(); + +template