Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
This came up during Reflection review:
<https://gcc.gnu.org/pipermail/gcc-patches/2026-January/705175.html>

Certain entities, e.g. vars in public inline functions or template
functions should be exported.  But entities defined within TU-local
should not be exported.

This patch adjusts min_vis_expr_r to that effect as per the Reflection
discussion.

gcc/cp/ChangeLog:

        * decl2.cc (min_vis_expr_r): For _DECLs with no linkage refer to the
        linkage of the containing entity that does have a name with linkage.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/visibility1.C: Adjust dg-final.
---
 gcc/cp/decl2.cc                            | 13 ++++++-------
 gcc/testsuite/g++.dg/reflect/visibility1.C | 18 +++++++++---------
 2 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 4de6345135f..3a2326b4a1d 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -3114,8 +3114,10 @@ min_vis_expr_r (tree *tp, int *walk_subtrees, void *data)
          break;
        }
     addressable:
+      /* For _DECLs with no linkage refer to the linkage of the containing
+        entity that does have a name with linkage.  */
       if (decl_linkage (t) == lk_none)
-       tpvis = type_visibility (TREE_TYPE (t));
+       tpvis = expr_visibility (DECL_CONTEXT (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.  */
@@ -3170,13 +3172,10 @@ min_vis_expr_r (tree *tp, int *walk_subtrees, void 
*data)
              *walk_subtrees = 0;
              break;
            }
-         if ((VAR_P (r) && decl_function_context (r))
-             || TREE_CODE (r) == PARM_DECL)
+         if (VAR_P (r) || TREE_CODE (r) == PARM_DECL)
            {
-             /* Block scope variables are local to the TU.  */
-             tpvis = VISIBILITY_ANON;
-             *walk_subtrees = 0;
-             break;
+             t = r;
+             goto addressable;
            }
          break;
        }
diff --git a/gcc/testsuite/g++.dg/reflect/visibility1.C 
b/gcc/testsuite/g++.dg/reflect/visibility1.C
index c47817b9b4e..738edce5fa8 100644
--- a/gcc/testsuite/g++.dg/reflect/visibility1.C
+++ b/gcc/testsuite/g++.dg/reflect/visibility1.C
@@ -49,8 +49,8 @@ inline void
 qux (int x)
 {
   int v = 42;
-  foo <106, ^^x> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi106EL" } } - var in inline fn - TODO, 
shall this be exported?
-  foo <107, ^^v> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi107EL" } } - var in inline fn - TODO, 
shall this be exported?
+  foo <106, ^^x> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi106EL" } } - var in inline fn
+  foo <107, ^^v> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi107EL" } } - var in inline fn
 }
 
 template <int N>
@@ -58,8 +58,8 @@ void
 plugh (int x)
 {
   int v = 42;
-  foo <132, ^^x> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi132EL" } } - var in public fn template 
instantiation - TODO, shall this be exported?
-  foo <133, ^^v> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi133EL" } } - var in public fn template 
instantiation - TODO, shall this be exported?
+  foo <132, ^^x> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi132EL" } } - var in public fn template instantiation
+  foo <133, ^^v> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi133EL" } } - var in public fn template instantiation
   foo <134, parameters_of (parent_of (^^v))[0]> (); // { dg-final { 
scan-assembler "\t.weak\t_Z3fooILi134EL" { target *-*-linux* } } } - fn parm of 
public fn template instantiation
 }
 
@@ -80,9 +80,9 @@ void
 fred (int x)
 {
   int v = 42;
-  foo <138, ^^x> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi138EL" } } - var in TU-local fn template 
instantiation
-  foo <139, ^^v> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi139EL" } } - var in Tu-local fn template 
instantiation
-  foo <140, parameters_of (parent_of (^^v))[0]> (); // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi140EL" { xfail *-*-* } } } - fn parm of 
TU-local fn template instantiation - TODO, I think this shouldn't be exported 
and the mangling of these 3 doesn't include the template parameter
+  foo <138, ^^x> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi138EL" } } - var in fn template instantiation
+  foo <139, ^^v> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi139EL" } } - var in fn template instantiation
+  foo <140, parameters_of (parent_of (^^v))[0]> (); // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi140EL" { xfail *-*-* } } } - fn parm of 
fn template instantiation - TODO, I think this shouldn't be exported and the 
mangling of these 3 doesn't include the template parameter
 }
 
 [[=1]] void
@@ -108,8 +108,8 @@ xyzzy (int x)
   foo <122, ^^G <int>> ();                     // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi122EL" } } - specialization of TU-local 
template
   foo <123, ^^G <A>> ();                       // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi123EL" } } - specialization of TU-local 
template
   foo <124, ^^G <B>> ();                       // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi124EL" } } - specialization of TU-local 
template
-  foo <125, ^^x> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi125EL" } } - var in public fn but 
non-comdat - TODO, shall this be exported?
-  foo <126, ^^v> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi126EL" } } - var in public fn but 
non-comdat - TODO, shall this be exported?
+  foo <125, ^^x> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi125EL" } } - var in public fn but non-comdat
+  foo <126, ^^v> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi126EL" } } - var in public fn but non-comdat
   foo <127, std::meta::info {}> ();            // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi127EL" { target *-*-linux* } } } - null reflection
   foo <128, ^^b> ();                           // { dg-final { scan-assembler 
"\t.weak\t_Z3fooILi128EL" { target *-*-linux* } } } - public variable
   foo <129, ^^c> ();                           // { dg-final { 
scan-assembler-not "\t.weak\t_Z3fooILi129EL" } } - TU-local variable

base-commit: f0c9201c1f3003f35fa764fa9ebe864f6e123859
-- 
2.52.0

Reply via email to