On Mon, 19 May 2025, Patrick Palka wrote:

> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk/15/14?

Whoops, CI reports I missed a testsuite adjustment expecting an
additional error in other/default13.C, which seems reasonable.  Here's
an updated patch.

-- >8 --

Here we declare f twice, first ordinarily and then using a dependent
alias template.  Due to alias template transparency these logically
declare the same overload.  But now the function type of f, which was
produced from the first declaration, diverges from the type of its
formal parameter, which is produced from the subsequent redefinition,
in that substituting T=int succeeds for the function type but not for
the formal parameter type.  This eventually causes us to produce an
undiagnosed error_mark_node in the AST of function call, leading to
a sanity check failure added in r14-6343-g0c018a74eb1aff.

Before r14-6343, we would later reject the testcase albeit from
regenerate_decl_from_template when instantiating the definition of f,
making this a regression.

To fix this, it seems we just need to check for errors when substituting
the type of a PARM_DECL, since that could still fail despite substitution
into the function type succeeding.

        PR c++/120224

gcc/cp/ChangeLog:

        * pt.cc (tsubst_function_decl): Return error_mark_node if any
        of the substituted function parameters are erroneous.
        (tsubst_decl) <case PARM_DECL>: Return error_mark_node if
        the substituted function parameter type is erroneous.

gcc/testsuite/ChangeLog:

        * g++.dg/other/default13.C: Expect additional overload
        resolution failure diagnostic.
        * g++.dg/cpp0x/alias-decl-80.C: New test.
---
 gcc/cp/pt.cc                               |  9 ++++++++-
 gcc/testsuite/g++.dg/cpp0x/alias-decl-80.C | 14 ++++++++++++++
 gcc/testsuite/g++.dg/other/default13.C     |  2 +-
 3 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-80.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1973d25b61a0..df6d7bb136ea 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -14903,7 +14903,11 @@ tsubst_function_decl (tree t, tree args, 
tsubst_flags_t complain,
     parms = DECL_CHAIN (parms);
   parms = tsubst (parms, args, complain, t);
   for (tree parm = parms; parm; parm = DECL_CHAIN (parm))
-    DECL_CONTEXT (parm) = r;
+    {
+      if (parm == error_mark_node)
+       return error_mark_node;
+      DECL_CONTEXT (parm) = r;
+    }
   if (closure && DECL_IOBJ_MEMBER_FUNCTION_P (t))
     {
       tree tparm = build_this_parm (r, closure, type_memfn_quals (type));
@@ -15474,6 +15478,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain,
               /* We're dealing with a normal parameter.  */
               type = tsubst (TREE_TYPE (t), args, complain, in_decl);
 
+           if (type == error_mark_node)
+             RETURN (error_mark_node);
+
             type = type_decays_to (type);
             TREE_TYPE (r) = type;
             cp_apply_type_quals_to_decl (cp_type_quals (type), r);
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-80.C 
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-80.C
new file mode 100644
index 000000000000..e2ff663843de
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-80.C
@@ -0,0 +1,14 @@
+// PR c++/120224
+// { dg-do compile { target c++11 } }
+
+template<class> using void_t = void;
+
+template<class T>
+void f(void*); // #1
+
+template<class T>
+void f(void_t<typename T::type>*) { } // { dg-error "not a class" } #2
+
+int main() {
+  f<int>(0); // { dg-error "no match" }
+}
diff --git a/gcc/testsuite/g++.dg/other/default13.C 
b/gcc/testsuite/g++.dg/other/default13.C
index eae23ffdf2d1..381aee78ea2c 100644
--- a/gcc/testsuite/g++.dg/other/default13.C
+++ b/gcc/testsuite/g++.dg/other/default13.C
@@ -8,4 +8,4 @@ template < typename > struct B
   int f;
 };
 
-B < int > b (0);
+B < int > b (0); // { dg-error "no match" }
-- 
2.49.0.608.gcb96e1697a

Reply via email to