On Sat, Oct 18, 2025 at 10:35:15AM +0300, Jason Merrill wrote: > On 10/17/25 7:15 PM, Patrick Palka wrote: > > On Fri, 17 Oct 2025, Patrick Palka wrote: > > > > > On Fri, 17 Oct 2025, Jason Merrill wrote: > > > > > > > On 10/16/25 2:58 PM, Nathaniel Shead wrote: > > > > > I'm not 100% sure this is the correct approach, or whether I've picked > > > > > the right sense of "dependent" to check here; any thoughts? > > > > > > > > I think it makes sense to return early in expr_visibility if the > > > > argument is > > > > value-dependent. > > > > > > I believe that'll break g++.dg/abi/no-linkage-expr1.C, the > > > value-dependent ((P)0, N) needs to be walked so that the anon type P > > > within forces specializations of f and g to have internal linkage. > > > > > > This seems similar to PR110323 / r14-9596-g081f8937cb82da except for > > > local variables instead of constexpr variables. So maybe the > > > decl_constant_var_p code path should be used for local vars too? > > > > .. the decl_constant_var_p code path added by r14-9596, to be precise. > > > > Like with constexpr variables, a (non-constexpr) local variable > > within a template argument shouldn't affect linkage because presumably > > it's only used for its value. > > Ah, indeed, the distinction is also between dependent expressions in the > template signature vs those in a template argument. > > Maybe it would be better to check for dependent template arguments in > constrain_visibility_for_template? >
That had actually been my first attempt, to check 'dependent_template_arg_p' in 'constrain_visibility_for_template', but that also caused abi/no-linkage-expr1.C to fail, which is why I went with the approach I did. I'll try just ignoring local variables instead and see how that goes. > Jason > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? > > > > > > > > > > -- >8 -- > > > > > > > > > > When finding the minimal visibility of a template, any reference to a > > > > > dependent local variable will cause the instantiation to be marked as > > > > > internal linkage. However, when processing the template decl we don't > > > > > yet know whether that should actually be the case, as a given > > > > > instantiation may not require referencing the local decl in its > > > > > mangling. So this patch bails on dependent declarations. > > > > > > > > > > PR c++/122253 > > > > > > > > > > gcc/cp/ChangeLog: > > > > > > > > > > * decl2.cc (min_vis_expr_r): Don't mark as VISIBILITY_ANON for a > > > > > !TREE_PUBLIC dependent decl. > > > > > > > > > > gcc/testsuite/ChangeLog: > > > > > > > > > > * g++.dg/modules/internal-16.C: New test. > > > > > > > > > > Signed-off-by: Nathaniel Shead <[email protected]> > > > > > --- > > > > > gcc/cp/decl2.cc | 5 ++++- > > > > > gcc/testsuite/g++.dg/modules/internal-16.C | 23 > > > > > ++++++++++++++++++++++ > > > > > 2 files changed, 27 insertions(+), 1 deletion(-) > > > > > create mode 100644 gcc/testsuite/g++.dg/modules/internal-16.C > > > > > > > > > > diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc > > > > > index 0073f83a10c..572037acd38 100644 > > > > > --- a/gcc/cp/decl2.cc > > > > > +++ b/gcc/cp/decl2.cc > > > > > @@ -2885,7 +2885,10 @@ min_vis_expr_r (tree *tp, int > > > > > */*walk_subtrees*/, > > > > > void *data) > > > > > break; > > > > > } > > > > > addressable: > > > > > - if (! TREE_PUBLIC (t)) > > > > > + if (!TREE_PUBLIC (t) > > > > > + /* We don't really know whether a use of a dependent decl will > > > > > + actually appear in our mangling. */ > > > > > + && !dependent_type_p (TREE_TYPE (t))) > > > > > tpvis = VISIBILITY_ANON; > > > > > else > > > > > tpvis = DECL_VISIBILITY (t); > > > > > diff --git a/gcc/testsuite/g++.dg/modules/internal-16.C > > > > > b/gcc/testsuite/g++.dg/modules/internal-16.C > > > > > new file mode 100644 > > > > > index 00000000000..a891082cc1b > > > > > --- /dev/null > > > > > +++ b/gcc/testsuite/g++.dg/modules/internal-16.C > > > > > @@ -0,0 +1,23 @@ > > > > > +// PR c++/122253 > > > > > +// { dg-additional-options "-fmodules -Wtemplate-names-tu-local" } > > > > > + > > > > > +export module M; > > > > > + > > > > > +template <int> struct ic {}; > > > > > +struct S { constexpr operator int() const { return 42; } }; > > > > > + > > > > > +template <typename T> inline void a(T) { > > > > > + T s; > > > > > + ic<s>{}; > > > > > +} > > > > > + > > > > > +template <typename T> inline auto b(T x) { > > > > > + return [&](auto y) { > > > > > + return [=](auto z) { > > > > > + return ic<(int)x + (int)y + (int)z>{}; > > > > > + }; > > > > > + }; > > > > > +} > > > > > + > > > > > +template void a(S); > > > > > +ic<42 * 3> x = b(S{})(S{})(S{}); > > > > > > > > > > > > > >
