From 5fde62e29930ccf09c647c47db77894ff046b0ac Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Thu, 4 Jul 2013 21:58:35 +0000 Subject: [PATCH] re PR c++/38634 (ICE with wrong number of template parameters) /cp 2013-07-04 Paolo Carlini PR c++/38634 * decl.c (start_preparsed_function): Return a bool, false if push_template_decl fails. (start_function): Adjust. * cp-tree.h: Update. /testsuite 2013-07-04 Paolo Carlini PR c++/38634 * g++.dg/template/crash116.C: New. From-SVN: r200682 --- gcc/cp/ChangeLog | 8 ++++++ gcc/cp/cp-tree.h | 5 ++-- gcc/cp/decl.c | 32 +++++++++++++----------- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/template/crash116.C | 13 ++++++++++ 5 files changed, 47 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/crash116.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 92fefea845c..3a0ba58f743 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2013-07-04 Paolo Carlini + + PR c++/38634 + * decl.c (start_preparsed_function): Return a bool, false if + push_template_decl fails. + (start_function): Adjust. + * cp-tree.h: Update. + 2013-07-03 Jakub Jelinek PR c++/57771 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3e8043a4162..1b0b2435c53 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5206,8 +5206,9 @@ extern void finish_enum_value_list (tree); extern void finish_enum (tree); extern void build_enumerator (tree, tree, tree, location_t); extern tree lookup_enumerator (tree, tree); -extern void start_preparsed_function (tree, tree, int); -extern int start_function (cp_decl_specifier_seq *, const cp_declarator *, tree); +extern bool start_preparsed_function (tree, tree, int); +extern bool start_function (cp_decl_specifier_seq *, + const cp_declarator *, tree); extern tree begin_function_body (void); extern void finish_function_body (tree); extern tree outer_curly_brace_block (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 047fd77fd74..54bede00bb1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -12993,7 +12993,7 @@ check_function_type (tree decl, tree current_function_parms) error_mark_node if the function has never been defined, or a BLOCK if the function has been defined somewhere. */ -void +bool start_preparsed_function (tree decl1, tree attrs, int flags) { tree ctype = NULL_TREE; @@ -13090,10 +13090,14 @@ start_preparsed_function (tree decl1, tree attrs, int flags) by push_nested_class.) */ if (processing_template_decl) { - /* FIXME: Handle error_mark_node more gracefully. */ tree newdecl1 = push_template_decl (decl1); - if (newdecl1 != error_mark_node) - decl1 = newdecl1; + if (newdecl1 == error_mark_node) + { + if (ctype || DECL_STATIC_FUNCTION_P (decl1)) + pop_nested_class (); + return false; + } + decl1 = newdecl1; } /* We are now in the scope of the function being defined. */ @@ -13204,7 +13208,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) /* This function may already have been parsed, in which case just return; our caller will skip over the body without parsing. */ if (DECL_INITIAL (decl1) != error_mark_node) - return; + return true; /* Initialize RTL machinery. We cannot do this until CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this @@ -13366,17 +13370,19 @@ start_preparsed_function (tree decl1, tree attrs, int flags) start_fname_decls (); store_parm_decls (current_function_parms); + + return true; } /* Like start_preparsed_function, except that instead of a FUNCTION_DECL, this function takes DECLSPECS and DECLARATOR. - Returns 1 on success. If the DECLARATOR is not suitable for a function - (it defines a datum instead), we return 0, which tells - yyparse to report a parse error. */ + Returns true on success. If the DECLARATOR is not suitable + for a function, we return false, which tells the parser to + skip the entire function. */ -int +bool start_function (cp_decl_specifier_seq *declspecs, const cp_declarator *declarator, tree attrs) @@ -13385,13 +13391,13 @@ start_function (cp_decl_specifier_seq *declspecs, decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs); if (decl1 == error_mark_node) - return 0; + return false; /* If the declarator is not suitable for a function definition, cause a syntax error. */ if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) { error ("invalid function declaration"); - return 0; + return false; } if (DECL_MAIN_P (decl1)) @@ -13400,9 +13406,7 @@ start_function (cp_decl_specifier_seq *declspecs, gcc_assert (same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node)); - start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT); - - return 1; + return start_preparsed_function (decl1, attrs, /*flags=*/SF_DEFAULT); } /* Returns true iff an EH_SPEC_BLOCK should be created in the body of diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7e72edf668f..09599ffb5de 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-07-04 Paolo Carlini + + PR c++/38634 + * g++.dg/template/crash116.C: New. + 2013-07-04 Joern Rennecke * gcc.dg/tree-ssa/vrp66.c: Make conditional on { target { ! int16 } } . diff --git a/gcc/testsuite/g++.dg/template/crash116.C b/gcc/testsuite/g++.dg/template/crash116.C new file mode 100644 index 00000000000..d26c591ef43 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash116.C @@ -0,0 +1,13 @@ +// PR c++/38634 + +template struct A +{ + A(); +}; + +template A::A() // { dg-error "template|required" } +{ + struct B {}; +} + +A<0> a; -- 2.30.2