From: Jason Merrill Date: Fri, 9 Mar 2018 23:03:06 +0000 (-0500) Subject: re PR c++/71169 (ICE on invalid C++ code in pop_nested_class (cp/class.c:7785)) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=be977d080fd58b54984bb487b0acaf0739a26899;p=gcc.git re PR c++/71169 (ICE on invalid C++ code in pop_nested_class (cp/class.c:7785)) /cp 2018-03-09 Jason Merrill Paolo Carlini PR c++/71169 PR c++/71832 * pt.c (any_erroneous_template_args_p): New. * cp-tree.h (any_erroneous_template_args_p): Declare it. * parser.c (cp_parser_class_specifier_1): Use it. /testsuite 2018-03-09 Jason Merrill Paolo Carlini PR c++/71169 PR c++/71832 * g++.dg/cpp0x/pr71169.C: New. * g++.dg/cpp0x/pr71169-2.C: Likewise. * g++.dg/cpp0x/pr71832.C: Likewise. Co-Authored-By: Paolo Carlini From-SVN: r258401 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 09bd3318482..c287232d4d2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2018-03-10 Jason Merrill + Paolo Carlini + + PR c++/71169 + PR c++/71832 + * pt.c (any_erroneous_template_args_p): New. + * cp-tree.h (any_erroneous_template_args_p): Declare it. + * parser.c (cp_parser_class_specifier_1): Use it. + 2018-03-09 Jason Merrill PR c++/84726 - unnecessary capture of constant vars. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4a406d2e9f5..186a37eea6b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6569,6 +6569,7 @@ extern int processing_template_parmlist; extern bool dependent_type_p (tree); extern bool dependent_scope_p (tree); extern bool any_dependent_template_arguments_p (const_tree); +extern bool any_erroneous_template_args_p (const_tree); extern bool dependent_template_p (tree); extern bool dependent_template_id_p (tree, tree); extern bool type_dependent_expression_p (tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a19bbe1e1d0..cdc62388973 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -22669,6 +22669,16 @@ cp_parser_class_specifier_1 (cp_parser* parser) cp_default_arg_entry *e; tree save_ccp, save_ccr; + if (any_erroneous_template_args_p (type)) + { + /* Skip default arguments, NSDMIs, etc, in order to improve + error recovery (c++/71169, c++/71832). */ + vec_safe_truncate (unparsed_funs_with_default_args, 0); + vec_safe_truncate (unparsed_nsdmis, 0); + vec_safe_truncate (unparsed_classes, 0); + vec_safe_truncate (unparsed_funs_with_definitions, 0); + } + /* In a first pass, parse default arguments to the functions. Then, in a second pass, parse the bodies of the functions. This two-phased approach handles cases like: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 89024c10fe2..bc815d29764 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -25048,6 +25048,39 @@ any_dependent_template_arguments_p (const_tree args) return false; } +/* Returns true if ARGS contains any errors. */ + +bool +any_erroneous_template_args_p (const_tree args) +{ + int i; + int j; + + if (args == error_mark_node) + return true; + + if (args && TREE_CODE (args) != TREE_VEC) + { + if (tree ti = get_template_info (args)) + args = TI_ARGS (ti); + else + args = NULL_TREE; + } + + if (!args) + return false; + + for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i) + { + const_tree level = TMPL_ARGS_LEVEL (args, i + 1); + for (j = 0; j < TREE_VEC_LENGTH (level); ++j) + if (error_operand_p (TREE_VEC_ELT (level, j))) + return true; + } + + return false; +} + /* Returns TRUE if the template TMPL is type-dependent. */ bool diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1e99bc3139e..2c07f6a11ca 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2018-03-09 Jason Merrill + Paolo Carlini + + PR c++/71169 + PR c++/71832 + * g++.dg/cpp0x/pr71169.C: New. + * g++.dg/cpp0x/pr71169-2.C: Likewise. + * g++.dg/cpp0x/pr71832.C: Likewise. + 2018-03-09 Peter Bergner PR target/83969 diff --git a/gcc/testsuite/g++.dg/cpp0x/pr71169-2.C b/gcc/testsuite/g++.dg/cpp0x/pr71169-2.C new file mode 100644 index 00000000000..fa29e95d5d2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr71169-2.C @@ -0,0 +1,19 @@ +// { dg-do compile { target c++11 } } + +template class A { // { dg-error "declared" } + template void m_fn1() { + m_fn1(); + } +}; + +template +struct B +{ + int f(int = 0) { return 0; } +}; + +int main() +{ + B b; + return b.f(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/pr71169.C b/gcc/testsuite/g++.dg/cpp0x/pr71169.C new file mode 100644 index 00000000000..44690a917e1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr71169.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++11 } } + +template class A { // { dg-error "declared" } + template void m_fn1() { + m_fn1(); + } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr71832.C b/gcc/testsuite/g++.dg/cpp0x/pr71832.C new file mode 100644 index 00000000000..3b851110f3c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr71832.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++11 } } + +template < typename decltype (0) > struct A // { dg-error "expected|two or more" } +{ + void foo () { baz (); } + template < typename ... S > void baz () {} +};