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;
 }

Reply via email to