https://gcc.gnu.org/g:eaa6998e9367345605a46c30fb2df9b19789d10e
commit r16-8373-geaa6998e9367345605a46c30fb2df9b19789d10e Author: Jakub Jelinek <[email protected]> Date: Wed Apr 1 00:22:46 2026 +0200 c++: Fix up access_context::current and current_namespace On Mon, Mar 30, 2026 at 01:15:07PM +0200, Tomasz Kaminski wrote: > > auto > > Q::baz () -> typename [: current_namespace () == ^^Q ? ^^int : ^^:: :] > > { > > return 0; > > } > > part also fails, there I don't know what's right but possibly it should > > be in Q; in that case it would be a pre-existing bug already for > > std::meta::access_context::current () too. > > > My reading of the standard may be wrong here. I think you're right, but because it is a preexisting bug on access_context, sending this as a separate patch rather than updating the current_* patch. 2026-04-01 Jakub Jelinek <[email protected]> * reflect.cc (reflect_current_scope): Use decl_namespace_list->last () in preference to current_namespace. * g++.dg/reflect/access_context1.C: Add new tests. * g++.dg/reflect/current_function1.C: Likewise. * g++.dg/reflect/current_class1.C: Likewise. * g++.dg/reflect/current_class2.C: Likewise. * g++.dg/reflect/current_namespace1.C: Likewise. Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/reflect.cc | 3 +++ gcc/testsuite/g++.dg/reflect/access_context1.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/reflect/current_class1.C | 13 +++++++++++++ gcc/testsuite/g++.dg/reflect/current_class2.C | 12 ++++++++++++ gcc/testsuite/g++.dg/reflect/current_function1.C | 17 +++++++++++++++++ gcc/testsuite/g++.dg/reflect/current_namespace1.C | 15 +++++++++++++++ 6 files changed, 74 insertions(+) diff --git a/gcc/cp/reflect.cc b/gcc/cp/reflect.cc index 69b236659d89..b30b4b82087e 100644 --- a/gcc/cp/reflect.cc +++ b/gcc/cp/reflect.cc @@ -6356,6 +6356,9 @@ reflect_current_scope (location_t loc, const constexpr_ctx *ctx, tree call, } if (current_class_type) scope = current_class_type; + /* If we have been pushed into a different namespace, use it. */ + else if (!vec_safe_is_empty (decl_namespace_list)) + scope = decl_namespace_list->last (); else if (current_namespace) scope = current_namespace; else diff --git a/gcc/testsuite/g++.dg/reflect/access_context1.C b/gcc/testsuite/g++.dg/reflect/access_context1.C index c0ec0d3fa805..ac8661d4f1a8 100644 --- a/gcc/testsuite/g++.dg/reflect/access_context1.C +++ b/gcc/testsuite/g++.dg/reflect/access_context1.C @@ -146,6 +146,8 @@ namespace O { return a; } + int bar (); + int baz (); } consteval bool @@ -156,6 +158,18 @@ can_do_via (info r) return true; } +typename [: access_context::current ().scope () == ^^:: ? ^^int : ^^:: :] +O::bar () +{ + return 0; +} + +auto +O::baz () -> typename [: access_context::current ().scope () == ^^O ? ^^int : ^^:: :] +{ + return 0; +} + struct W; static_assert (can_do_via (^^S)); diff --git a/gcc/testsuite/g++.dg/reflect/current_class1.C b/gcc/testsuite/g++.dg/reflect/current_class1.C index 4b0c17d47461..cb6223ec45bb 100644 --- a/gcc/testsuite/g++.dg/reflect/current_class1.C +++ b/gcc/testsuite/g++.dg/reflect/current_class1.C @@ -68,3 +68,16 @@ bar () static_assert (parent_of (current_class ()) == ^^bar); }; } + +struct X { + struct Y { + int foo (); + }; +}; + +auto +X::Y::foo () +-> typename [: current_class () == ^^Y ? ^^int : ^^:: :] +{ + return 0; +} diff --git a/gcc/testsuite/g++.dg/reflect/current_class2.C b/gcc/testsuite/g++.dg/reflect/current_class2.C index e7c2e3370836..de277757ab3e 100644 --- a/gcc/testsuite/g++.dg/reflect/current_class2.C +++ b/gcc/testsuite/g++.dg/reflect/current_class2.C @@ -71,3 +71,15 @@ namespace O return a; // { dg-error "invalid initialization of reference of type" } } } + +struct X { + struct Y { + int foo (); + }; +}; + +typename [: current_class () == ^^X ? ^^int : ^^:: :] // { dg-error "uncaught exception of type 'std::meta::exception'; 'what\\\(\\\)': 'current scope does not represent a class nor a member function'" } +X::Y::foo () // { dg-error "expected unqualified-id before 'typename'" "" { target *-*-* } .-1 } +{ + return 0; +} diff --git a/gcc/testsuite/g++.dg/reflect/current_function1.C b/gcc/testsuite/g++.dg/reflect/current_function1.C index c7d2ee4deb5f..71faf8b7c145 100644 --- a/gcc/testsuite/g++.dg/reflect/current_function1.C +++ b/gcc/testsuite/g++.dg/reflect/current_function1.C @@ -38,6 +38,11 @@ struct V : U info v = current_function (); }; +struct W : T +{ + info w = current_function (); +}; + void bar () { @@ -45,6 +50,7 @@ bar () static_assert (foo (^^foo) == ^^foo); static_assert (foo () == ^^bar); static_assert (T {}.t == ^^bar); + static_assert (is_constructor (T ().t) && parent_of (T ().t) == ^^T); consteval { static_assert (current_function () == ^^bar); consteval { @@ -74,3 +80,14 @@ baz () } static_assert (baz ()); + +consteval void +fred () +{ + constexpr W w; + static_assert (is_constructor (w.t) && parent_of (w.t) == ^^T); + static_assert (is_constructor (w.w) && parent_of (w.w) == ^^W); + constexpr W wb {}; + static_assert (wb.t == ^^fred); + static_assert (wb.w == ^^fred); +} diff --git a/gcc/testsuite/g++.dg/reflect/current_namespace1.C b/gcc/testsuite/g++.dg/reflect/current_namespace1.C index e56425fa602b..d42ac1c6bc0b 100644 --- a/gcc/testsuite/g++.dg/reflect/current_namespace1.C +++ b/gcc/testsuite/g++.dg/reflect/current_namespace1.C @@ -90,4 +90,19 @@ namespace Q { return a; } + + int bar (); + int baz (); +} + +typename [: current_namespace () == ^^:: ? ^^int : ^^:: :] +Q::bar () +{ + return 0; +} + +auto +Q::baz () -> typename [: current_namespace () == ^^Q ? ^^int : ^^:: :] +{ + return 0; }
