https://gcc.gnu.org/g:f062a6b7985fcee82e02b626aada4e0824850bd0

commit r16-5024-gf062a6b7985fcee82e02b626aada4e0824850bd0
Author: Nathaniel Shead <[email protected]>
Date:   Thu Oct 16 22:51:23 2025 +1100

    c++: Don't constrain template visibility using no-linkage variables 
[PR122253]
    
    When finding the minimal visibility of a template, any reference to a
    dependent automatic 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.
    
    This patch fixes the issue by checking for no-linkage decls first, in
    which case we just constrain using the type of the entity.  We can't use
    a check for lk_external/lk_internal in the other cases, as
    instantiations referring to internal types can still have external
    linkage as determined by the language, but should still constrain the
    visibility of any declarations that refer to them.
    
            PR c++/122253
    
    gcc/cp/ChangeLog:
    
            * decl2.cc (min_vis_expr_r): Don't mark no-linkage declarations
            as VISIBILITY_ANON.
    
    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]>

Diff:
---
 gcc/cp/decl2.cc                            |  7 ++++++-
 gcc/testsuite/g++.dg/modules/internal-16.C | 30 ++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 0073f83a10ca..9e135af41b34 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 (decl_linkage (t) == lk_none)
+       tpvis = type_visibility (TREE_TYPE (t));
+      /* Decls that have had their visibility constrained will report
+        as external linkage, but we still want to transitively constrain
+        if we refer to them, so just check TREE_PUBLIC instead.  */
+      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 000000000000..4a928ae801bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/internal-16.C
@@ -0,0 +1,30 @@
+// 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 5; }
+  constexpr int operator&() const { return 8; }
+};
+
+template <typename T> inline void a(T) {
+  T a;
+  static T b;
+  ic<a>{};
+  ic<b>{};
+  ic<&a>{};
+  ic<&b>{};
+}
+
+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<5 + 8 + 5> x = b(S{})(S{})(S{});

Reply via email to