On 1/20/26 5:01 AM, Marek Polacek wrote:
On Sat, Jan 17, 2026 at 04:34:11PM +0800, Jason Merrill wrote:
On 1/17/26 8:46 AM, Marek Polacek wrote:
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

Why isn't this line changed with the others?

Ah, presumably we want Z3fooILi140EL to be exported here, so the xfail
can be removed.  Done in this version.  No other change.

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

OK.

-- >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 6dbfdeada20..f29f56f6584 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..e2858c2d4fe 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 
"\t.weak\t_Z3fooILi140EL" } } - fn parm of fn template instantiation
  }
[[=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: 832de2f102fb988ebe4a304635a796854978d880

Reply via email to