On Sat, Oct 18, 2025 at 06:38:57PM +1100, Nathaniel Shead wrote:
> 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.
> 

And here's that patch: Bootstrapped and regtested on
x86_64-pc-linux-gnu, OK for trunk/15?

-- >8 --

Subject: [PATCH] c++: Don't constrain visibility using local variables 
[PR122253]

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 local variables.

        PR c++/122253

gcc/cp/ChangeLog:

        * decl2.cc (min_vis_expr_r): Don't mark as VISIBILITY_ANON for a
        local variable.

gcc/testsuite/ChangeLog:

        * g++.dg/modules/internal-16.C: New test.

Signed-off-by: Nathaniel Shead <[email protected]>
Reviewed-by: Patrick Palka <[email protected]>
Reviewed-by: Jason Merrill <[email protected]>
---
 gcc/cp/decl2.cc                            |  7 ++++++-
 gcc/testsuite/g++.dg/modules/internal-16.C | 23 ++++++++++++++++++++++
 2 files changed, 29 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..5efab46ef91 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2885,7 +2885,12 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void 
*data)
          break;
        }
     addressable:
-      if (! TREE_PUBLIC (t))
+      if (local_variable_p (t))
+       /* Likewise, local variables being used as a template argument are
+          presumably only used for their value, so shouldn't constrain its
+          visibility.  */
+       tpvis = type_visibility (TREE_TYPE (t));
+      else if (!TREE_PUBLIC (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{});
-- 
2.51.0

Reply via email to