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? -- >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 -- 2.52.0
