Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/15/14?
-- >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 that added in r14-6343-g0c018a74eb1aff. Before r14-6343, we would reject the testcase 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/cpp0x/alias-decl-80.C: New test. --- gcc/cp/pt.cc | 9 ++++++++- gcc/testsuite/g++.dg/cpp0x/alias-decl-80.C | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) 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" } +} -- 2.49.0.608.gcb96e1697a