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.

> 
> The rest of the patch is OK.
> 
> >     * module.cc (trees_in::is_matching_decl): Only compare types of
> >     inner decls. 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>
> > ---
> >   gcc/cp/decl.cc                          |  6 ------
> >   gcc/cp/module.cc                        |  5 +++--
> >   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, 25 insertions(+), 8 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 febdc89f89d..150d26079a8 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -8921,12 +8921,6 @@ cp_finish_decl (tree decl, tree init, bool
> > init_const_expr_p,
> >         /* Now that we have a type, try these again.  */
> >         layout_decl (decl, 0);
> >         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 (ensure_literal_type_for_constexpr_object (decl) ==
> > error_mark_node)
> > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> > index c99988da05b..606eac77db9 100644
> > --- a/gcc/cp/module.cc
> > +++ b/gcc/cp/module.cc
> > @@ -12193,7 +12193,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);
> >     }
> > @@ -12248,7 +12249,7 @@ trees_in::is_matching_decl (tree existing, tree
> > decl, bool is_typedef)
> >     /* Using cp_tree_equal because we can meet TYPE_ARGUMENT_PACKs
> >        here. I suspect the entities that directly do that are things
> >        that shouldn't go to duplicate_decls (FIELD_DECLs etc).   */
> > -  else if (!cp_tree_equal (TREE_TYPE (decl), TREE_TYPE (existing)))
> > +  else if (!cp_tree_equal (TREE_TYPE (d_inner), TREE_TYPE (e_inner)))
> >       {
> >         mismatch_msg = G_("conflicting type for imported declaration %#qD");
> >       mismatch:
> > 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";
> 
> 

Reply via email to