On 9/13/26 3:27 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.
-- >8 --
In

   template<class> struct Y {};
   namespace N { }

   template<auto ns>
   void f () {
     typename [:ns:]::template Y<int> b;   // #1
   }
   void g () { f<^^N>(); }

no error is given for #1.  The problem is that we do lookup_template_class
first which does:

       push_decl_namespace (context);
       templ = lookup_name (d1, LOOK_where::NAMESPACE, LOOK_want::NORMAL);
       pop_decl_namespace ();

which is an unqualified lookup that goes out through the enclosing
namespaces.  We should do a qualified lookup in N only.  This patch
makes us use lookup_qualified_name to find the TEMPLATE_DECL and then
pass that to lookup_template_class with a null context.

We already have a call to lookup_qualified_name so I just shuffled
the code a bit.  Also guard the qualified_name_lookup_error call
with a complain check.  And give an error if we didn't get a type
for the cp_build_qualified_type call.

Note that the UNBOUND_CLASS_TEMPLATE case will also need something
similar.

The diagnostic for t9 is currently technically imprecise because
fn is a function template; we should say that it isn't a type template
instead.

        PR c++/127349

gcc/cp/ChangeLog:

        * pt.cc (lookup_template_class): Print %qE if d1 is not a type.
        (tsubst) <case TYPENAME_TYPE>: Do lookup_qualified_name first
        before lookup_template_class.  Guard qualified_name_lookup_error
        with a complain check.  Use gcc_checking_assert instead of
        gcc_assert.  Use identifier_p.  Give an error if we didn't get
        a type.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/ns7.C: New test.
---
  gcc/cp/pt.cc                       | 51 +++++++++++++++++++-----------
  gcc/testsuite/g++.dg/reflect/ns7.C | 38 ++++++++++++++++++++++
  2 files changed, 71 insertions(+), 18 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/reflect/ns7.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 53e81d8006c..527e2b25b56 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -10399,7 +10399,12 @@ lookup_template_class (tree d1, tree arglist, tree 
in_decl, tree context,
    if (! templ)
      {
        if (complain & tf_error)
-       error ("%qT is not a template", d1);
+       {
+         if (TYPE_P (d1))
+           error ("%qT is not a template", d1);
+         else
+           error ("%qE is not a template", d1);
+       }
        return error_mark_node;
      }
@@ -17935,30 +17940,40 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
           a type.  */
        if (TREE_CODE (ctx) == NAMESPACE_DECL)
          {
+           tree id;
+           tree targs = NULL_TREE;
            if (TREE_CODE (f) == TEMPLATE_ID_EXPR)
              {
-               tree d = TREE_OPERAND (f, 0);
-               tree n = TREE_OPERAND (f, 1);
-               f = lookup_template_class (d, n, in_decl, ctx, complain);
+               id = TREE_OPERAND (f, 0);
+               targs = TREE_OPERAND (f, 1);
+             }
+           else
+             id = f;
+
+           gcc_checking_assert (identifier_p (id));
+           tree decl = lookup_qualified_name (ctx, id);
+           if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
+             {
+               if (complain & tf_error)
+                 qualified_name_lookup_error (ctx, id, decl, input_location);
+               return error_mark_node;
+             }
+           if (targs)
+             {
+               f = lookup_template_class (decl, targs, in_decl, NULL_TREE,
+                                          complain);
                if (f == error_mark_node)
                  return error_mark_node;
              }
+           else if (TREE_CODE (decl) == NAMESPACE_DECL)
+             return decl;
+           else if (TREE_CODE (decl) == TYPE_DECL)
+             f = TREE_TYPE (decl);
            else
              {
-               gcc_assert (TREE_CODE (f) == IDENTIFIER_NODE);
-               tree decl = lookup_qualified_name (ctx, f);
-               if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
-                 {
-                   qualified_name_lookup_error (ctx, f, decl, input_location);
-                   return error_mark_node;
-                 }
-               if (TREE_CODE (decl) == NAMESPACE_DECL)
-                 return decl;
-               else
-                 {
-                   gcc_checking_assert (TREE_CODE (decl) == TYPE_DECL);
-                   f = TREE_TYPE (decl);
-                 }
+               if (complain & tf_error)
+                 error ("%qD is not a type", decl);
+               return error_mark_node;
              }
            return cp_build_qualified_type
                    (f, cp_type_quals (f) | cp_type_quals (t), complain);
diff --git a/gcc/testsuite/g++.dg/reflect/ns7.C 
b/gcc/testsuite/g++.dg/reflect/ns7.C
new file mode 100644
index 00000000000..a9ba862d77b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/ns7.C
@@ -0,0 +1,38 @@
+// PR c++/127349
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+template<class> struct Y {};
+namespace M { template<class> struct W {}; }
+namespace N {
+  template<class> struct X {};
+  template<class T> using A = X<T>;
+  inline namespace I { template<class> struct V {}; }
+  using namespace M;
+  template<class, class> struct Z {};
+  int v;
+  template<class T> void fn ();
+}
+
+template<template<class> class> struct S {};
+
+template<auto ns>
+void
+f ()
+{
+  typename [:ns:]::template X<int> t1;
+  typename [:ns:]::template A<int> t2;
+  typename [:ns:]::template V<int> t3;
+  typename [:ns:]::template W<int> t4;
+  typename [:ns:]::template Y<int> t5; // { dg-error "'Y' is not a member of 
'N'" }
+  typename [:ns:]::template v<int> t6; // { dg-error "'N::v' is not a 
template" }
+  typename [:ns:]::v t7;               // { dg-error "'N::v' is not a type" }
+  typename [:ns:]::X t8;               // { dg-error "is not a type" }
+  typename [:ns:]::template fn<int> t9;  // { dg-error "not a template" }
+}
+
+void
+h ()
+{
+  f<^^N>();
+}

base-commit: 6e6249fc9e9932909089bc5b8cb3618650c9e662

Reply via email to