Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?

-- >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
-- 
2.55.0

Reply via email to