diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d7c952dd8804352bad65eae25554acc110847914..e219547c545c0f4c553cbe62d4a7efbc9d61cdd4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2006-08-26 Lee Millward <lee.millward@codesourcery.com> + + PR c++/28736 + PR c++/28737 + PR c++/28738 + * pt.c (process_template_parm): Store invalid template + parameters as a TREE_LIST with a TREE_VALUE of error_mark_node. + (push_inline_template_parms_recursive): Check for template + parameters having a TREE_VALUE of error_mark_node rather than + check the parameter itself. + (mangle_class_name_for_template): Likewise. + (comp_template_parms): When comparing the individual template + parameters, return 1 if either is error_mark_node. + (current_template_args): Robustify. + (redeclare_class_template): Likewise. + 2006-08-26 Mark Mitchell <mark@codesourcery.com> PR c++/28588 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e078149fa770fd91aa6af355bff1ed9f556ddee5..5e0c9541b9a7194f1cc58d2f40c291e0fedf69b3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -336,12 +336,11 @@ push_inline_template_parms_recursive (tree parmlist, int levels) 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 parms2) 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 parm, bool is_non_type) { 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 parm, bool is_non_type) { 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 parm, bool is_non_type) 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 parm, bool is_non_type) 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, tree parms) /* 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); @@ -4207,12 +4218,12 @@ mangle_class_name_for_template (const char* name, tree parms, tree arglist) 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 (','); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 017de891864a60557eb002ced2671f41e68ebe8b..1df799676b4b389198df2e2c352424960accd95f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2006-08-26 Lee Millward <lee.millward@codesourcery.com> + + PR c++/28736 + * g++.dg/template/void10.C: New test. + + PR c++/28737 + * g++.dg/template/void8.C: New test. + + PR c+_+/28738 + * g++.dg/template/void9.C: New test. + + * g++.dg/template/void3.C: Adjust error markers. + * g++.dg/template/void4.C: Likewise. + * g++.dg/template/crash55.C: Likewise. + * g++.dg/template/void7.C: Likewise + 2006-08-26 Mark Mitchell <mark@codesourcery.com> PR c++/28588 diff --git a/gcc/testsuite/g++.dg/template/crash55.C b/gcc/testsuite/g++.dg/template/crash55.C index 7e15b66ee75b0e28b81bb36233b932989bbeb111..0e3fe4c3a5939b8e1a314d9d719ab0bceb995ae9 100644 --- a/gcc/testsuite/g++.dg/template/crash55.C +++ b/gcc/testsuite/g++.dg/template/crash55.C @@ -3,4 +3,4 @@ template<typename class T, T = T()> // { dg-error "nested-name-specifier|two or more|valid type" } struct A {}; // { dg-error "definition" -template<int> void foo(A<int>); // { dg-error "mismatch|constant" } +template<int> void foo(A<int>); // { dg-error "mismatch|constant|template argument" } diff --git a/gcc/testsuite/g++.dg/template/void10.C b/gcc/testsuite/g++.dg/template/void10.C new file mode 100644 index 0000000000000000000000000000000000000000..56e0b6d2e5b88f606f7832f1fb4b1e391d7d96c0 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/void10.C @@ -0,0 +1,10 @@ +//PR c++/28736 + +template<void> struct A // { dg-error "not a valid type" } +{ + template<typename> friend struct B; +}; + +template<typename> struct B {}; + +B<int> b; // { dg-error "template argument|invalid type" } diff --git a/gcc/testsuite/g++.dg/template/void3.C b/gcc/testsuite/g++.dg/template/void3.C index 6526a2a47be1db3ebe1421a8e70457a8bad4b7e8..bb59934ffe4f7703b28e9ed153c8e71e443d59a1 100644 --- a/gcc/testsuite/g++.dg/template/void3.C +++ b/gcc/testsuite/g++.dg/template/void3.C @@ -1,5 +1,5 @@ //PR c++/28637 template<void> struct A {}; // { dg-error "not a valid type" } -A<0> a; +A<0> a; // { dg-error "type" } diff --git a/gcc/testsuite/g++.dg/template/void4.C b/gcc/testsuite/g++.dg/template/void4.C index 7d264fbf10bc47670d38aa04d23284f61bc2f171..fe30b2e3736bcdb76dac9fc82b771760de39b4ab 100644 --- a/gcc/testsuite/g++.dg/template/void4.C +++ b/gcc/testsuite/g++.dg/template/void4.C @@ -4,4 +4,4 @@ template<void> struct A; // { dg-error "not a valid type" } template<template<int> class> struct B {}; -B<A> b; +B<A> b; // { dg-error "template|invalid type" } diff --git a/gcc/testsuite/g++.dg/template/void7.C b/gcc/testsuite/g++.dg/template/void7.C index 2c464b3a055cfb27870d120e244240e9722c4e3d..95d87a2073220dbcd608dcb6a38fa7cbcf9ea8bd 100644 --- a/gcc/testsuite/g++.dg/template/void7.C +++ b/gcc/testsuite/g++.dg/template/void7.C @@ -5,4 +5,4 @@ template<void> struct A // { dg-error "not a valid type" } static int i; }; -A<0> a; +A<0> a; // { dg-error "invalid type|not a valid type" } diff --git a/gcc/testsuite/g++.dg/template/void8.C b/gcc/testsuite/g++.dg/template/void8.C new file mode 100644 index 0000000000000000000000000000000000000000..e45c91c044c2021497a34c92f7558db45f84643b --- /dev/null +++ b/gcc/testsuite/g++.dg/template/void8.C @@ -0,0 +1,7 @@ +//PR c++/28737 + +template<void> struct A; // { dg-error "not a valid type" } + +template<typename> struct B; + +template<void N> struct B<A<N> > {}; // { dg-error "not a valid type|declared|invalid" } diff --git a/gcc/testsuite/g++.dg/template/void9.C b/gcc/testsuite/g++.dg/template/void9.C new file mode 100644 index 0000000000000000000000000000000000000000..bb2ed66ff381614bf6d7ba51b6a8bf32c618ef98 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/void9.C @@ -0,0 +1,4 @@ +//PR c++/28738 + +template<int,void> struct A {}; // { dg-error "not a valid type" } +template<int N> struct A<N,0> {}; // { dg-error "not a valid type" }