On Tue, Dec 09, 2025 at 12:05:43AM +0800, Jason Merrill wrote:
> On 12/8/25 3:50 AM, Nathaniel Shead wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> > 
> > -- >8 --
> > 
> > Modules allow temploid friends to no longer be implicitly inline, as
> > functions defined in a class body will not be implicitly inline if
> > attached to a named module.
> > 
> > This requires us to clean up linkage handling a little bit, mostly by
> > replacing usages of 'DECL_TEMPLATE_INSTANTIATION' with
> > 'DECL_TEMPLOID_INSTANTIATION' when determining if an entity has vague
> > linkage.
> 
> These changes are OK.
> 

Thanks, I'll push these adjustments now.

> > As a drive-by cleanup, the check for DECL_TEMPLATE_INSTANTIATION in
> > check_module_decl_linkage is never getting hit because it's covered by
> > the processing_template_decl check anyway, so remove it.
> 
> That doesn't sound right to me; processing_template_decl checks for
> templates, while DECL_TEMPLATE_INSTANTIATION checks for instantiations?
> 

Took a closer look, this function is never called during instantiation
to begin with actually, it's only ever called during parsing when
linkage is first determined.  We may as well keep the hunk in case that
ever changes I suppose for clarity (though I'm not sure why we ever
would need to actually).

> >     PR c++/122819
> > 
> > gcc/cp/ChangeLog:
> > 
> >     * decl.cc (start_preparsed_function): Use
> >     DECL_TEMPLOID_INSTANTIATION instead of
> >     DECL_TEMPLATE_INSTANTIATION to check vague linkage.
> >     * decl2.cc (vague_linkage_p): Likewise.
> >     (c_parse_final_cleanups): Simplify condition.
> >     * module.cc (check_module_decl_linkage): Remove unnecessary
> >     condition.
> >     * semantics.cc (expand_or_defer_fn_1): Also check for temploid
> >     friend functions.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> >     * g++.dg/modules/tpl-friend-22.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead <[email protected]>
> > ---
> >   gcc/cp/decl.cc                               |  6 ++---
> >   gcc/cp/decl2.cc                              |  5 ++--
> >   gcc/cp/module.cc                             |  2 --
> >   gcc/cp/semantics.cc                          |  4 +++-
> >   gcc/testsuite/g++.dg/modules/tpl-friend-22.C | 24 ++++++++++++++++++++
> >   5 files changed, 32 insertions(+), 9 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/modules/tpl-friend-22.C
> > 
> > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > index 74c862ec1c7..31081b390fa 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -19750,7 +19750,7 @@ start_preparsed_function (tree decl1, tree attrs, 
> > int flags)
> >     }
> >       }
> > -  bool honor_interface = (!DECL_TEMPLATE_INSTANTIATION (decl1)
> > +  bool honor_interface = (!DECL_TEMPLOID_INSTANTIATION (decl1)
> >                       /* Implicitly-defined methods (like the
> >                          destructor for a class in which no destructor
> >                          is explicitly declared) must not be defined
> > @@ -19781,7 +19781,7 @@ start_preparsed_function (tree decl1, tree attrs, 
> > int flags)
> >     else if (!finfo->interface_unknown && honor_interface)
> >       {
> >         if (DECL_DECLARED_INLINE_P (decl1)
> > -     || DECL_TEMPLATE_INSTANTIATION (decl1))
> > +     || DECL_TEMPLOID_INSTANTIATION (decl1))
> >     {
> >       DECL_EXTERNAL (decl1)
> >         = (finfo->interface_only
> > @@ -19823,7 +19823,7 @@ start_preparsed_function (tree decl1, tree attrs, 
> > int flags)
> >     DECL_EXTERNAL (decl1) = 0;
> >         if ((DECL_DECLARED_INLINE_P (decl1)
> > -      || DECL_TEMPLATE_INSTANTIATION (decl1))
> > +      || DECL_TEMPLOID_INSTANTIATION (decl1))
> >       && ! DECL_INTERFACE_KNOWN (decl1))
> >     DECL_DEFER_OUTPUT (decl1) = 1;
> >         else
> > diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
> > index 8ec9740c8a9..01bf26b1e4f 100644
> > --- a/gcc/cp/decl2.cc
> > +++ b/gcc/cp/decl2.cc
> > @@ -2510,7 +2510,7 @@ vague_linkage_p (tree decl)
> >         || (TREE_CODE (decl) == FUNCTION_DECL
> >       && DECL_DECLARED_INLINE_P (decl))
> >         || (DECL_LANG_SPECIFIC (decl)
> > -     && DECL_TEMPLATE_INSTANTIATION (decl))
> > +     && DECL_TEMPLOID_INSTANTIATION (decl))
> >         || (VAR_P (decl) && DECL_INLINE_VAR_P (decl)))
> >       return true;
> >     else if (DECL_FUNCTION_SCOPE_P (decl))
> > @@ -5850,8 +5850,7 @@ c_parse_final_cleanups (void)
> >       && !(header_module_p ()
> >            && (DECL_DEFAULTED_FN (decl) || decl_tls_wrapper_p (decl)))
> >       /* Don't complain if the template was defined.  */
> > -     && !((DECL_TEMPLATE_INSTANTIATION (decl)
> > -           || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
> > +     && !(DECL_TEMPLOID_INSTANTIATION (decl)
> >            && DECL_INITIAL (DECL_TEMPLATE_RESULT
> >                             (template_for_substitution (decl))))
> >       && warning_at (DECL_SOURCE_LOCATION (decl), 0,
> > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> > index 5c70e9bb469..1d8ca71b7da 100644
> > --- a/gcc/cp/module.cc
> > +++ b/gcc/cp/module.cc
> > @@ -21717,8 +21717,6 @@ check_module_decl_linkage (tree decl)
> >       || (TREE_CODE (decl) == VAR_DECL
> >           && !DECL_INLINE_VAR_P (decl)))
> >         && decl_defined_p (decl)
> > -      && !(DECL_LANG_SPECIFIC (decl)
> > -      && DECL_TEMPLATE_INSTANTIATION (decl))
> >         && decl_linkage (decl) == lk_external)
> >       error_at (DECL_SOURCE_LOCATION (decl),
> >           "external linkage definition of %qD in header module must "
> > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > index 331db16f76d..b32ab2f0d2b 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -5537,7 +5537,9 @@ expand_or_defer_fn_1 (tree fn)
> >        of the compilation.  Until that point, we do not want the back
> >        end to output them -- but we do want it to see the bodies of
> >        these functions so that it can inline them as appropriate.  */
> > -  if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn))
> > +  if (DECL_DECLARED_INLINE_P (fn)
> > +      || DECL_IMPLICIT_INSTANTIATION (fn)
> > +      || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (fn))
> >       {
> >         if (DECL_INTERFACE_KNOWN (fn))
> >     /* We've already made a decision as to how this function will
> > diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-22.C 
> > b/gcc/testsuite/g++.dg/modules/tpl-friend-22.C
> > new file mode 100644
> > index 00000000000..a77d1cbecad
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/modules/tpl-friend-22.C
> > @@ -0,0 +1,24 @@
> > +// PR c++/122819
> > +// { dg-do compile { target *-*-*gnu* } }
> > +// { dg-additional-options "-fmodules" }
> > +
> > +export module M;
> > +
> > +template <typename T> struct S;
> > +void foo(S<float>);
> > +
> > +template <typename T> struct S {
> > +  friend void foo(S) {}
> > +};
> > +
> > +void foo(S<double>);
> > +
> > +void use() {
> > +  foo(S<int>{});
> > +  foo(S<float>{});
> > +  foo(S<double>{});
> > +}
> > +
> > +// { dg-final { scan-assembler "_ZW1M3fooS_1SIiE,comdat" } }
> > +// { dg-final { scan-assembler "_ZW1M3fooS_1SIfE,comdat" } }
> > +// { dg-final { scan-assembler "_ZW1M3fooS_1SIdE,comdat" } }
> 

Reply via email to