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?
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{});