https://gcc.gnu.org/g:5c0e1879ea639dc527d3928af877d3df985e3f13
commit r15-7084-g5c0e1879ea639dc527d3928af877d3df985e3f13 Author: Nathaniel Shead <nathanielosh...@gmail.com> Date: Mon Jan 20 22:09:22 2025 +1100 c++/modules: Handle mismatching TYPE_CANONICAL when deduping partial specs [PR118101] In r15-4862 we ensured that merging a partial specialisation would properly update its TYPE_CANONICAL. However, this confuses the deduping mechanism, since the canonical type has updated out from under it, causing is_matching_decl to crash when seeing the equivalent types with different TYPE_CANONICAL. This patch solves the issue by forcing structural equality checking for this case; this way mismatching TYPE_CANONICAL doesn't cause issues, but we still can handle the case that the types are legitimately different. PR c++/118101 gcc/cp/ChangeLog: * module.cc (trees_in::decl_value): Use structural equality when deduping partial specs with mismatching canonical types. gcc/testsuite/ChangeLog: * g++.dg/modules/partial-7.h: New test. * g++.dg/modules/partial-7_a.C: New test. * g++.dg/modules/partial-7_b.C: New test. * g++.dg/modules/partial-7_c.C: New test. Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> Diff: --- gcc/cp/module.cc | 11 ++++++++++- gcc/testsuite/g++.dg/modules/partial-7.h | 5 +++++ gcc/testsuite/g++.dg/modules/partial-7_a.C | 8 ++++++++ gcc/testsuite/g++.dg/modules/partial-7_b.C | 9 +++++++++ gcc/testsuite/g++.dg/modules/partial-7_c.C | 7 +++++++ 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 6fe64bb538c2..813c14361417 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -8650,9 +8650,18 @@ trees_in::decl_value () if (stub_decl) TREE_TYPE (stub_decl) = type; + tree etype = TREE_TYPE (existing); + /* Handle separate declarations with different attributes. */ - tree &eattr = TYPE_ATTRIBUTES (TREE_TYPE (existing)); + tree &eattr = TYPE_ATTRIBUTES (etype); eattr = merge_attributes (eattr, TYPE_ATTRIBUTES (type)); + + /* When merging a partial specialisation, the existing decl may have + had its TYPE_CANONICAL adjusted. If so we should use structural + equality to ensure is_matching_decl doesn't get confused. */ + if ((spec_flags & 2) + && TYPE_CANONICAL (type) != TYPE_CANONICAL (etype)) + SET_TYPE_STRUCTURAL_EQUALITY (type); } if (inner_tag) diff --git a/gcc/testsuite/g++.dg/modules/partial-7.h b/gcc/testsuite/g++.dg/modules/partial-7.h new file mode 100644 index 000000000000..cf0411835a19 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-7.h @@ -0,0 +1,5 @@ +// PR c++/118101 +template <typename> struct A; +template <typename T> struct A<T*> {}; +template <typename T> struct B { A<T*> f(); }; +B<int> inst(); diff --git a/gcc/testsuite/g++.dg/modules/partial-7_a.C b/gcc/testsuite/g++.dg/modules/partial-7_a.C new file mode 100644 index 000000000000..6aa7aeebfec3 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-7_a.C @@ -0,0 +1,8 @@ +// PR c++/118101 +// { dg-additional-options "-fmodules" } +// { dg-module-cmi A } + +module; +#include "partial-7.h" +export module A; +B<int> a; diff --git a/gcc/testsuite/g++.dg/modules/partial-7_b.C b/gcc/testsuite/g++.dg/modules/partial-7_b.C new file mode 100644 index 000000000000..1ca391a5ea15 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-7_b.C @@ -0,0 +1,9 @@ +// PR c++/118101 +// { dg-additional-options "-fmodules" } +// { dg-module-cmi B } + +module; +#include "partial-7.h" +export module B; +import A; +B<int> b; diff --git a/gcc/testsuite/g++.dg/modules/partial-7_c.C b/gcc/testsuite/g++.dg/modules/partial-7_c.C new file mode 100644 index 000000000000..3d2a2873e345 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-7_c.C @@ -0,0 +1,7 @@ +// PR c++/118101 +// { dg-additional-options "-fmodules" } + +template <typename> struct A {}; +template <typename T> struct B { A<T*> f(); }; +template struct B<int>; +import B;