if (closure && DECL_IOBJ_MEMBER_FUNCTION_P (t))
parms = DECL_CHAIN (parms);
parms = tsubst (parms, args, complain, t);
+ if (parms == error_mark_node)
+ return error_mark_node;
for (tree parm = parms; parm; parm = DECL_CHAIN (parm))
DECL_CONTEXT (parm) = r;
if (closure && DECL_IOBJ_MEMBER_FUNCTION_P (t))
/* We're dealing with a normal parameter. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ if (type == error_mark_node && !(complain & tf_error))
+ RETURN (error_mark_node);
+
type = type_decays_to (type);
TREE_TYPE (r) = type;
cp_apply_type_quals_to_decl (cp_type_quals (type), r);
/* If cp_unevaluated_operand is set, we're just looking for a
single dummy parameter, so don't keep going. */
if (DECL_CHAIN (t) && !cp_unevaluated_operand)
- DECL_CHAIN (r) = tsubst (DECL_CHAIN (t), args,
- complain, DECL_CHAIN (t));
+ {
+ tree chain = tsubst (DECL_CHAIN (t), args,
+ complain, DECL_CHAIN (t));
+ if (chain == error_mark_node)
+ RETURN (error_mark_node);
+ DECL_CHAIN (r) = chain;
+ }
/* FIRST_R contains the start of the chain we've built. */
r = first_r;
--- /dev/null
+// 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" } defn of #1
+
+template<class T>
+void g(int, void*); // #2
+
+template<class T>
+void g(int, void_t<typename T::type>*) { } // { dg-error "not a class" } defn of #2
+
+int main() {
+ f<int>(0); // { dg-error "no match" }
+ g<int>(0, 0); // { dg-error "no match" }
+}