-- >8 --
This fixes a bogus error for
namespace N { struct S {}; }
template<auto ns> void f () {
using typename [:ns:]::S;
S s;
}
It is a failure to propagate USING_DECL_TYPENAME_P to the USING_DECL
in case we are not at_class_scope_p. With that flag set, the dependent
USING_DECL will be treated as naming a type.
PR c++/127707
gcc/cp/ChangeLog:
* name-lookup.cc (finish_nonmember_using_decl): New bool
parameter. Set USING_DECL_TYPENAME_P if it's true.
* name-lookup.h (finish_nonmember_using_decl): Adjust
declaration.
* parser.cc (finish_using_decl): Pass typename_p to
finish_nonmember_using_decl.
* pt.cc (tsubst_stmt) <case DECL_EXPR>: Pass
USING_DECL_TYPENAME_P to finish_nonmember_using_decl.
gcc/testsuite/ChangeLog:
* g++.dg/reflect/ns12.C: New test.
---
gcc/cp/name-lookup.cc | 9 ++++-
gcc/cp/name-lookup.h | 3 +-
gcc/cp/parser.cc | 2 +-
gcc/cp/pt.cc | 3 +-
gcc/testsuite/g++.dg/reflect/ns12.C | 63 +++++++++++++++++++++++++++++
5 files changed, 75 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/reflect/ns12.C
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 41453110047..f89f5643d86 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -6988,10 +6988,12 @@ push_using_decl_bindings (tree name, tree value)
push_using_decl_bindings (nullptr, name, value);
}
-/* Process a using declaration in non-class scope. */
+/* Process a using declaration in non-class scope. TYPENAME_P is true if
+ the using decl had the typename keyword; this is important to record for
+ a block-scope using declaration with a dependent scope (using a splice). */
void
-finish_nonmember_using_decl (tree scope, tree name)
+finish_nonmember_using_decl (tree scope, tree name, bool typename_p/*=false*/)
{
gcc_checking_assert (current_binding_level->kind != sk_class);
@@ -7004,6 +7006,9 @@ finish_nonmember_using_decl (tree scope, tree name)
if (!using_decl)
return;
+ if (typename_p)
+ USING_DECL_TYPENAME_P (using_decl) = true;
+
/* Emit debug info. */
if (!processing_template_decl)
cp_emit_debug_info_for_using (lookup.value,
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index af3fd927f3d..3737ae0ebac 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -505,7 +505,8 @@ extern bool decl_in_scope_p (tree);
extern cxx_binding *outer_binding (tree, cxx_binding *, bool);
extern void cp_emit_debug_info_for_using (tree, tree);
-extern void finish_nonmember_using_decl (tree scope, tree name);
+extern void finish_nonmember_using_decl (tree scope, tree name,
+ bool typename_p = false);
extern void finish_using_directive (tree target, tree attribs);
void push_local_extern_decl_alias (tree decl);
extern tree pushdecl (tree, bool hiding = false);
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3c84f6e335f..23017857277 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -24696,7 +24696,7 @@ finish_using_decl (tree qscope, tree identifier, bool
typename_p = false)
finish_member_declaration (decl);
}
else
- finish_nonmember_using_decl (qscope, identifier);
+ finish_nonmember_using_decl (qscope, identifier, typename_p);
return decl;
}
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 2b68ceb0cd2..c7f5d55b14f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -19919,7 +19919,8 @@ tsubst_stmt (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
"class, namespace, or enumeration", scope);
return error_mark_node;
}
- finish_nonmember_using_decl (scope, DECL_NAME (decl));
+ finish_nonmember_using_decl (scope, DECL_NAME (decl),
+ USING_DECL_TYPENAME_P (decl));
}
else
{
diff --git a/gcc/testsuite/g++.dg/reflect/ns12.C
b/gcc/testsuite/g++.dg/reflect/ns12.C
new file mode 100644
index 00000000000..fcb06eb33a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/ns12.C
@@ -0,0 +1,63 @@
+// PR c++/127707
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+namespace N {
+ struct S {};
+ struct R {};
+}
+namespace A = N;
+struct S {};
+
+using typename [:^^N:]::R;
+R r;
+
+template<auto ns>
+void
+f ()
+{
+ using typename [:ns:]::S;
+ S s;
+}
+
+template<auto ns>
+void
+f2 ()
+{
+ [] (auto) {
+ using typename [:ns:]::S;
+ S s;
+ } (0);
+}
+
+template<auto ns>
+void
+f3 ()
+{
+ [] <auto ns2> () {
+ using typename [:ns2:]::S;
+ S s;
+ }.template operator()<ns>();
+}
+
+template<auto ns>
+void
+fbad ()
+{
+ using [:ns:]::S;
+ S s; // { dg-error "expected" }
+}
+
+void
+g ()
+{
+ f<^^::>();
+ f<^^N>();
+ f<^^A>();
+ f2<^^::>();
+ f2<^^N>();
+ f2<^^A>();
+ f3<^^::>();
+ f3<^^N>();
+ f3<^^A>();
+}
base-commit: 189b0202e2664ea06e17c5424d2d17151607ee2d