On 9/30/26 6:12 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.
-- >8 --
This fixes another problem when using namespace splice scopes,
this time in a namespace alias like this:

   template<auto ns> void f () {
     namespace A = [:ns:];
     int i = A::N::x;
   }

where we crash in make_typename_type or make_unbound_class_template
because they expect a type but get a NAMESPACE_DECL built for the
A alias with ORIGINAL_NAMESPACE being a SPLICE_EXPR.  The decl is
coming from cp_parser_namespace_alias_definition -> do_namespace_alias.

We want a SPLICE_SCOPE which is a type, so build one with
make_splice_scope.

I considered changing cp_parser_namespace_alias_definition to build
the SPLICE_SCOPE there but that brought so many other issues that it
wasn't worth it.

        PR c++/127344

gcc/cp/ChangeLog:

        * parser.cc (cp_parser_lookup_name): Call make_splice_scope for
        dependent_namespace_p.  Use the result for make_typename_type
        and make_unbound_class_template.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/ns9.C: New test.
---
  gcc/cp/parser.cc                   | 17 ++++++----
  gcc/testsuite/g++.dg/reflect/ns9.C | 52 ++++++++++++++++++++++++++++++
  2 files changed, 63 insertions(+), 6 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/reflect/ns9.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 373d3358c25..3c84f6e335f 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -35608,15 +35608,21 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
               && dependentish_scope_p (parser->scope))
              || dependent_namespace_p (parser->scope)))
        {
+         tree scope = parser->scope;
+         /* The make_* functions below expect something that's a type.  SCOPE
+            is a NAMESPACE_DECL when we are dealing with a dependent namespace
+            alias like "namespace A = [:ns:];".  */
+         if (dependent_namespace_p (scope))
+           scope = make_splice_scope (ORIGINAL_NAMESPACE (scope),
+                                      /*type_p=*/false);
+
          if (tag_type)
            {
-             tree type;
-
              /* The resolution to Core Issue 180 says that `struct
                 A::B' should be considered a type-name, even if `A'
                 is dependent.  */
-             type = make_typename_type (parser->scope, name, tag_type,
-                                        /*complain=*/tf_error);
+             tree type = make_typename_type (scope, name, tag_type,
+                                             /*complain=*/tf_error);
              if (type != error_mark_node)
                decl = TYPE_NAME (type);
            }
@@ -35624,8 +35630,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                   && (cp_parser_next_token_ends_template_argument_p (parser)
                       || cp_lexer_next_token_is (parser->lexer,
                                                  CPP_CLOSE_PAREN)))
-           decl = make_unbound_class_template (parser->scope,
-                                               name, NULL_TREE,
+           decl = make_unbound_class_template (scope, name, NULL_TREE,
                                                /*complain=*/tf_error);
          else
            decl = build_qualified_name (/*type=*/NULL_TREE,
diff --git a/gcc/testsuite/g++.dg/reflect/ns9.C 
b/gcc/testsuite/g++.dg/reflect/ns9.C
new file mode 100644
index 00000000000..3f2141f6271
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/ns9.C
@@ -0,0 +1,52 @@
+// PR c++/127344
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+template<class, class> struct same_type;
+template<class T> struct same_type<T, T> {};
+
+namespace X { struct N { static constexpr int x = 42; }; }
+
+template<auto ns>
+int
+f ()
+{
+  namespace A = [:ns:];
+  int i = A::N::x;
+  int j = [:ns:]::N::x;
+  return i + j;
+}
+
+namespace N { template<class> struct X {}; }
+template<template<class> class> struct S {};
+
+template<auto ns>
+void
+h ()
+{
+  namespace A = [:ns:];
+  S<A::template X> s;
+}
+
+namespace Y { int y = 1; void fn (); namespace N { int x = 2; } }
+
+template<auto ns>
+int
+k ()
+{
+  namespace A = [:ns:];
+  namespace B = A;
+  auto p = &A::fn;
+  same_type<decltype(p), void (*) ()>();
+  auto q = &[:ns:]::fn;
+  same_type<decltype(q), void (*) ()>();
+  return A::y + B::N::x;
+}
+
+void
+g ()
+{
+  f<^^X>();
+  h<^^N>();
+  k<^^Y>();
+}

base-commit: f4d32f612a3c43e9d0a861b7dae7bb67139c9ab0

Reply via email to