Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >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
--
2.55.0