https://gcc.gnu.org/g:e65b3092ce078418632186b7d67c3e443f6657fd

commit r17-4860-ge65b3092ce078418632186b7d67c3e443f6657fd
Author: Marek Polacek <[email protected]>
Date:   Fri Sep 11 15:40:37 2026 -0400

    c++/reflection: ICE with ns splice scope in ns alias [PR127344]
    
    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.
    
    Reviewed-by: Jason Merrill <[email protected]>

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

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 373d3358c25f..3c84f6e335fc 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 000000000000..3f2141f6271f
--- /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>();
+}

Reply via email to