Index: gcc/testsuite/g++.dg/template/void3.C =================================================================== --- gcc/testsuite/g++.dg/template/void3.C (revision 116419) +++ gcc/testsuite/g++.dg/template/void3.C (working copy) @@ -1,5 +1,5 @@ //PR c++/28637 template struct A {}; // { dg-error "not a valid type" } -A<0> a; +A<0> a; // { dg-error "type" } Index: gcc/testsuite/g++.dg/template/void10.C =================================================================== --- gcc/testsuite/g++.dg/template/void10.C (revision 0) +++ gcc/testsuite/g++.dg/template/void10.C (revision 0) @@ -0,0 +1,10 @@ +//PR c++/28736 + +template struct A // { dg-error "not a valid type" } +{ + template friend struct B; +}; + +template struct B {}; + +B b; // { dg-error "template argument|invalid type" } Index: gcc/testsuite/g++.dg/template/void4.C =================================================================== --- gcc/testsuite/g++.dg/template/void4.C (revision 116419) +++ gcc/testsuite/g++.dg/template/void4.C (working copy) @@ -4,4 +4,4 @@ template struct A; // { dg-error template class> struct B {}; -B b; +B b; // { dg-error "template|invalid type" } Index: gcc/testsuite/g++.dg/template/crash55.C =================================================================== --- gcc/testsuite/g++.dg/template/crash55.C (revision 116419) +++ gcc/testsuite/g++.dg/template/crash55.C (working copy) @@ -3,4 +3,4 @@ template // { dg-error "nested-name-specifier|two or more|valid type" } struct A {}; // { dg-error "definition" -template void foo(A); // { dg-error "mismatch|constant" } +template void foo(A); // { dg-error "mismatch|constant|template argument" } Index: gcc/testsuite/g++.dg/template/void7.C =================================================================== --- gcc/testsuite/g++.dg/template/void7.C (revision 116419) +++ gcc/testsuite/g++.dg/template/void7.C (working copy) @@ -5,4 +5,4 @@ template struct A // { dg- static int i; }; -A<0> a; +A<0> a; // { dg-error "invalid type|not a valid type" } Index: gcc/testsuite/g++.dg/template/void8.C =================================================================== --- gcc/testsuite/g++.dg/template/void8.C (revision 0) +++ gcc/testsuite/g++.dg/template/void8.C (revision 0) @@ -0,0 +1,7 @@ +//PR c++/28737 + +template struct A; // { dg-error "not a valid type" } + +template struct B; + +template struct B > {}; // { dg-error "not a valid type|declared|invalid" } Index: gcc/testsuite/g++.dg/template/void9.C =================================================================== --- gcc/testsuite/g++.dg/template/void9.C (revision 0) +++ gcc/testsuite/g++.dg/template/void9.C (revision 0) @@ -0,0 +1,4 @@ +//PR c++/28738 + +template struct A {}; // { dg-error "not a valid type" } +template struct A {}; // { dg-error "not a valid type" } Index: gcc/cp/pt.c =================================================================== --- gcc/cp/pt.c (revision 116419) +++ gcc/cp/pt.c (working copy) @@ -336,12 +336,11 @@ push_inline_template_parms_recursive (tr NULL); for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) { - tree parm; + tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); - if (TREE_VEC_ELT (parms, i) == error_mark_node) - continue; + if (parm == error_mark_node) + continue; - parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); gcc_assert (DECL_P (parm)); switch (TREE_CODE (parm)) @@ -2212,15 +2211,13 @@ comp_template_parms (tree parms1, tree p for (i = 0; i < TREE_VEC_LENGTH (t2); ++i) { - tree parm1; - tree parm2; + tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i)); + tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i)); - if (TREE_VEC_ELT (t1, i) == error_mark_node - || TREE_VEC_ELT (t2, i) == error_mark_node) - continue; - - parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i)); - parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i)); + /* If either of the template parameters are invalid, assume + they match for the sake of error recovery. */ + if (parm1 == error_mark_node || parm2 == error_mark_node) + return 1; if (TREE_CODE (parm1) != TREE_CODE (parm2)) return 0; @@ -2352,6 +2349,7 @@ process_template_parm (tree list, tree p { tree decl = 0; tree defval; + tree err_parm_list; int idx = 0; gcc_assert (TREE_CODE (parm) == TREE_LIST); @@ -2361,7 +2359,7 @@ process_template_parm (tree list, tree p { tree p = tree_last (list); - if (p && p != error_mark_node) + if (p && TREE_VALUE (p) != error_mark_node) { p = TREE_VALUE (p); if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL) @@ -2382,7 +2380,11 @@ process_template_parm (tree list, tree p SET_DECL_TEMPLATE_PARM_P (parm); if (TREE_TYPE (parm) == error_mark_node) - return chainon(list, error_mark_node); + { + err_parm_list = build_tree_list (defval, parm); + TREE_VALUE (err_parm_list) = error_mark_node; + return chainon (list, err_parm_list); + } else { /* [temp.param] @@ -2391,7 +2393,11 @@ process_template_parm (tree list, tree p ignored when determining its type. */ TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm)); if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1)) - return chainon(list, error_mark_node); + { + err_parm_list = build_tree_list (defval, parm); + TREE_VALUE (err_parm_list) = error_mark_node; + return chainon (list, err_parm_list); + } } /* A template parameter is not modifiable. */ @@ -2522,11 +2528,15 @@ current_template_args (void) { t = TREE_VALUE (t); - if (TREE_CODE (t) == TYPE_DECL - || TREE_CODE (t) == TEMPLATE_DECL) - t = TREE_TYPE (t); - else - t = DECL_INITIAL (t); + if (t != error_mark_node) + { + if (TREE_CODE (t) == TYPE_DECL + || TREE_CODE (t) == TEMPLATE_DECL) + t = TREE_TYPE (t); + else + t = DECL_INITIAL (t); + } + TREE_VEC_ELT (a, i) = t; } } @@ -3350,9 +3360,10 @@ redeclare_class_template (tree type, tre /* TMPL_PARM and PARM can be either TYPE_DECL, PARM_DECL, or TEMPLATE_DECL. */ - if (TREE_CODE (tmpl_parm) != TREE_CODE (parm) - || (TREE_CODE (tmpl_parm) != TYPE_DECL - && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm)))) + if (tmpl_parm != error_mark_node + && (TREE_CODE (tmpl_parm) != TREE_CODE (parm) + || (TREE_CODE (tmpl_parm) != TYPE_DECL + && !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm))))) { error ("template parameter %q+#D", tmpl_parm); error ("redeclared here as %q#D", parm); @@ -4205,12 +4216,12 @@ mangle_class_name_for_template (const ch tree parm; tree arg; - if (TREE_VEC_ELT (parms, i) == error_mark_node) - continue; - parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); arg = TREE_VEC_ELT (arglist, i); + if (parm == error_mark_node) + continue; + if (i) ccat (',');