From: Nathaniel Shead Date: Mon, 20 Jan 2025 11:09:22 +0000 (+1100) Subject: c++/modules: Handle mismatching TYPE_CANONICAL when deduping partial specs [PR118101] X-Git-Tag: basepoints/gcc-16~2469 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c0e1879ea639dc527d3928af877d3df985e3f13;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 6fe64bb538c..813c1436141 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 00000000000..cf0411835a1 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-7.h @@ -0,0 +1,5 @@ +// PR c++/118101 +template struct A; +template struct A {}; +template struct B { A f(); }; +B 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 00000000000..6aa7aeebfec --- /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 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 00000000000..1ca391a5ea1 --- /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 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 00000000000..3d2a2873e34 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/partial-7_c.C @@ -0,0 +1,7 @@ +// PR c++/118101 +// { dg-additional-options "-fmodules" } + +template struct A {}; +template struct B { A f(); }; +template struct B; +import B;