On Wed, Jun 25, 2025 at 11:52:14AM -0400, Jason Merrill wrote: > On 6/25/25 9:02 AM, Nathaniel Shead wrote: > > On Tue, Jun 24, 2025 at 12:10:09PM -0400, Patrick Palka wrote: > > > On Tue, 24 Jun 2025, Jason Merrill wrote: > > > > > > > On 6/23/25 5:41 PM, Nathaniel Shead wrote: > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk/15? > > > > > > > > > > -- >8 -- > > > > > > > > > > We were erroring because the TEMPLATE_DECL of the existing partial > > > > > specialisation has an undeduced return type, but the imported > > > > > declaration did not. > > > > > > > > > > The root cause is similar to what was fixed in > > > > > r13-2744-g4fac53d6522189, > > > > > where modules streaming code assumes that a TEMPLATE_DECL and its > > > > > DECL_TEMPLATE_RESULT will always have the same TREE_TYPE. That commit > > > > > fixed the issue by ensuring that when the type of a variable is > > > > > deduced > > > > > the TEMPLATE_DECL is updated as well, but this missed handling partial > > > > > specialisations. > > > > > > > > > > However, I don't think we actually care about that, since it seems > > > > > that > > > > > only the type of the inner decl actually matters in practice. > > > > > Instead, > > > > > this patch handles the issue on the modules side when deduping a > > > > > streamed decl, by only comparing the inner type. > > > > > > > > > > PR c++/120644 > > > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > > > * decl.cc (cp_finish_decl): Remove workaround. > > > > > > > > Hmm, if we aren't going to try to keep the type of the TEMPLATE_DECL > > > > correct, > > > > maybe we should always set it to NULL_TREE to make sure we only look at > > > > the > > > > inner type. > > > > > > FWIW cp_finish_decl can get at the TEMPLATE_DECL of a VAR_DECL > > > corresponding to a partial specialization via > > > > > > TI_TEMPLATE (TI_PARTIAL_INFO (DECL_TEMPLATE_INFO (decl))) > > > > > > if we do want to end up keeping the two TREE_TYPEs in sync. > > > > > > > Thanks. On further reflection, maybe the safest approach is to just > > ensure that the types are always consistent (including for partial > > specs); this is what the following patch does. > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? > > > > -- >8 -- > > > > Subject: [PATCH] c++/modules: Ensure type of partial spec VAR_DECL is > > consistent with its template [PR120644] > > > > We were erroring because the TEMPLATE_DECL of the existing partial > > specialisation has an undeduced return type, but the imported > > declaration did not. > > > > The root cause is similar to what was fixed in r13-2744-g4fac53d6522189, > > where modules streaming code assumes that a TEMPLATE_DECL and its > > DECL_TEMPLATE_RESULT will always have the same TREE_TYPE. That commit > > fixed the issue by ensuring that when the type of a variable is deduced > > the TEMPLATE_DECL is updated as well, but missed handling partial > > specialisations. This patch ensures that the same adjustment is made > > there as well. > > > > PR c++/120644 > > > > gcc/cp/ChangeLog: > > > > * decl.cc (cp_finish_decl): Also propagate type to partial > > templates. > > * module.cc (trees_out::decl_value): Add assertion that the > > TREE_TYPE of a streamed template decl matches its inner. > > (trees_in::is_matching_decl): Clarify function return type > > deduction should only occur for non-TEMPLATE_DECL. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/modules/auto-7.h: New test. > > * g++.dg/modules/auto-7_a.H: New test. > > * g++.dg/modules/auto-7_b.C: New test. > > > > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> > > Reviewed-by: Jason Merrill <ja...@redhat.com> > > Reviewed-by: Patrick Palka <ppa...@redhat.com> > > --- > > gcc/cp/decl.cc | 13 +++++++++---- > > gcc/cp/module.cc | 7 ++++++- > > gcc/testsuite/g++.dg/modules/auto-7.h | 12 ++++++++++++ > > gcc/testsuite/g++.dg/modules/auto-7_a.H | 5 +++++ > > gcc/testsuite/g++.dg/modules/auto-7_b.C | 5 +++++ > > 5 files changed, 37 insertions(+), 5 deletions(-) > > create mode 100644 gcc/testsuite/g++.dg/modules/auto-7.h > > create mode 100644 gcc/testsuite/g++.dg/modules/auto-7_a.H > > create mode 100644 gcc/testsuite/g++.dg/modules/auto-7_b.C > > > > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc > > index 4fe97ffbf8f..59701197e16 100644 > > --- a/gcc/cp/decl.cc > > +++ b/gcc/cp/decl.cc > > @@ -8923,10 +8923,15 @@ cp_finish_decl (tree decl, tree init, bool > > init_const_expr_p, > > cp_apply_type_quals_to_decl (cp_type_quals (type), decl); > > /* Update the type of the corresponding TEMPLATE_DECL to match. */ > > - if (DECL_LANG_SPECIFIC (decl) > > - && DECL_TEMPLATE_INFO (decl) > > - && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) == decl) > > - TREE_TYPE (DECL_TI_TEMPLATE (decl)) = type; > > + if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) > > + { > > + tree info = DECL_TEMPLATE_INFO (decl); > > + tree tmpl = TI_TEMPLATE (info); > > + if (DECL_TEMPLATE_RESULT (tmpl) == decl) > > + TREE_TYPE (tmpl) = type; > > + else if (PRIMARY_TEMPLATE_P (tmpl) && TI_PARTIAL_INFO (info)) > > + TREE_TYPE (TI_TEMPLATE (TI_PARTIAL_INFO (info))) = type; > > + } > > Perhaps we should update template_for_substitution to handle partial specs > and then use it here? >
Something like this? Bootstrapped and tested on x86_64-pc-linux-gnu (so far just modules.exp and dg.exp), OK for trunk if full regtest passes? -- >8 -- We were erroring because the TEMPLATE_DECL of the existing partial specialisation has an undeduced return type, but the imported declaration did not. The root cause is similar to what was fixed in r13-2744-g4fac53d6522189, where modules streaming code assumes that a TEMPLATE_DECL and its DECL_TEMPLATE_RESULT will always have the same TREE_TYPE. That commit fixed the issue by ensuring that when the type of a variable is deduced the TEMPLATE_DECL is updated as well, but missed handling partial specialisations. This patch ensures that the same adjustment is made there as well. PR c++/120644 gcc/cp/ChangeLog: * decl.cc (cp_finish_decl): Also propagate type to partial templates. * module.cc (trees_out::decl_value): Add assertion that the TREE_TYPE of a streamed template decl matches its inner. (trees_in::is_matching_decl): Clarify function return type deduction should only occur for non-TEMPLATE_DECL. * pt.cc (template_for_substitution): Handle partial specs. gcc/testsuite/ChangeLog: * g++.dg/modules/auto-7.h: New test. * g++.dg/modules/auto-7_a.H: New test. * g++.dg/modules/auto-7_b.C: New test. Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> Reviewed-by: Jason Merrill <ja...@redhat.com> Reviewed-by: Patrick Palka <ppa...@redhat.com> --- gcc/cp/decl.cc | 10 ++++++---- gcc/cp/module.cc | 7 ++++++- gcc/cp/pt.cc | 4 ++++ gcc/testsuite/g++.dg/modules/auto-7.h | 12 ++++++++++++ gcc/testsuite/g++.dg/modules/auto-7_a.H | 5 +++++ gcc/testsuite/g++.dg/modules/auto-7_b.C | 5 +++++ 6 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/auto-7.h create mode 100644 gcc/testsuite/g++.dg/modules/auto-7_a.H create mode 100644 gcc/testsuite/g++.dg/modules/auto-7_b.C diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 4fe97ffbf8f..83c8e283b56 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -8923,10 +8923,12 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, cp_apply_type_quals_to_decl (cp_type_quals (type), decl); /* Update the type of the corresponding TEMPLATE_DECL to match. */ - if (DECL_LANG_SPECIFIC (decl) - && DECL_TEMPLATE_INFO (decl) - && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) == decl) - TREE_TYPE (DECL_TI_TEMPLATE (decl)) = type; + if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) + { + tree tmpl = template_for_substitution (decl); + if (DECL_TEMPLATE_RESULT (tmpl) == decl) + TREE_TYPE (tmpl) = type; + } } if (ensure_literal_type_for_constexpr_object (decl) == error_mark_node) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index c99988da05b..53edb2ff203 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -8212,6 +8212,10 @@ trees_out::decl_value (tree decl, depset *dep) inner = DECL_TEMPLATE_RESULT (decl); inner_tag = insert (inner, WK_value); + /* On stream-in we assume that a template and its result will + have the same type. */ + gcc_checking_assert (TREE_TYPE (decl) == TREE_TYPE (inner)); + if (streaming_p ()) { int code = TREE_CODE (inner); @@ -12193,7 +12197,8 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef) { dump (dumper::MERGE) && dump ("Propagating deduced return type to %N", existing); - FNDECL_USED_AUTO (e_inner) = true; + gcc_checking_assert (existing == e_inner); + FNDECL_USED_AUTO (existing) = true; DECL_SAVED_AUTO_RETURN_TYPE (existing) = TREE_TYPE (e_type); TREE_TYPE (existing) = change_return_type (TREE_TYPE (d_type), e_type); } diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index deb0106b158..319c733270a 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -27536,6 +27536,10 @@ tree template_for_substitution (tree decl) { tree tmpl = DECL_TI_TEMPLATE (decl); + if (VAR_P (decl) || TYPE_P (decl)) + if (tree partial = most_specialized_partial_spec (decl, tf_none)) + if (partial != error_mark_node) + tmpl = TI_TEMPLATE (partial); /* Set TMPL to the template whose DECL_TEMPLATE_RESULT is the pattern for the instantiation. This is not always the most general diff --git a/gcc/testsuite/g++.dg/modules/auto-7.h b/gcc/testsuite/g++.dg/modules/auto-7.h new file mode 100644 index 00000000000..324b60cfa0a --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-7.h @@ -0,0 +1,12 @@ +// PR c++/120644 + +enum class E { E0, E1 }; + +template <typename T> +constexpr auto fmt_kind = E::E0; + +template <typename T> +class opt{}; + +template <typename T> +constexpr auto fmt_kind<opt<T>> = E::E1; diff --git a/gcc/testsuite/g++.dg/modules/auto-7_a.H b/gcc/testsuite/g++.dg/modules/auto-7_a.H new file mode 100644 index 00000000000..40cb0f886c0 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-7_a.H @@ -0,0 +1,5 @@ +// PR c++/120644 +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +#include "auto-7.h" diff --git a/gcc/testsuite/g++.dg/modules/auto-7_b.C b/gcc/testsuite/g++.dg/modules/auto-7_b.C new file mode 100644 index 00000000000..c6ad37fd828 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/auto-7_b.C @@ -0,0 +1,5 @@ +// PR c++/120644 +// { dg-additional-options "-fmodules -fno-module-lazy" } + +#include "auto-7.h" +import "auto-7_a.H"; -- 2.47.0