From 437c23222436111f80b29ec24d2fb863b567e589 Mon Sep 17 00:00:00 2001 From: Nicola Pero Date: Mon, 29 Nov 2010 03:15:40 +0000 Subject: In gcc/objc/: 2010-11-29 Nicola Pero In gcc/objc/: 2010-11-29 Nicola Pero * objc-act.c (objc_eh_runtime_type): Avoid ICE if error_mark_node is passed as argument. (objc_begin_catch_clause): Added code to deal with an error_mark_node or NULL_TREE argument. Improved checks for invalid arguments. Added code to traverse typedefs. In gcc/testsuite/: 2010-11-29 Nicola Pero * objc.dg/exceptions-1.m: New. * objc.dg/exceptions-2.m: New. * objc.dg/exceptions-3.m: New. * objc.dg/exceptions-4.m: New. * objc.dg/exceptions-5.m: New. * obj-c++.dg/exceptions-1.mm: New. * obj-c++.dg/exceptions-2.mm: New. * obj-c++.dg/exceptions-3.mm: New. * obj-c++.dg/exceptions-4.mm: New. * obj-c++.dg/exceptions-5.mm: New. In gcc/cp/: 2010-11-29 Nicola Pero * parser.c (cp_parser_objc_try_catch_finally_statement): Parse @catch(...) and pass NULL_TREE to objc_begin_catch_clause() in that case. Improved error recovery. Reorganized code to be almost identical to c_parser_objc_try_catch_finally_statement. In gcc/: 2010-11-29 Nicola Pero * c-parser.c (c_parser_objc_try_catch_statement): Renamed to c_parser_objc_try_catch_finally_statement for consistency with the C++ parser. Parse @catch(...) and pass NULL_TREE to objc_begin_catch_clause() in that case. Improved error recovery. Reorganized code to be almost identical to cp_parser_objc_try_catch_finally_statement. From-SVN: r167233 --- gcc/cp/parser.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 63 insertions(+), 15 deletions(-) (limited to 'gcc/cp/parser.c') diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3ed0579..917f750 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -22598,15 +22598,25 @@ cp_parser_objc_declaration (cp_parser* parser, tree attributes) objc-catch-clause objc-catch-clause-seq [opt] objc-catch-clause: - @catch ( exception-declaration ) compound-statement + @catch ( objc-exception-declaration ) compound-statement - objc-finally-clause + objc-finally-clause: @finally compound-statement - Returns NULL_TREE. */ + objc-exception-declaration: + parameter-declaration + '...' + + where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS. + + Returns NULL_TREE. + + PS: This function is identical to c_parser_objc_try_catch_finally_statement + for C. Keep them in sync. */ static tree -cp_parser_objc_try_catch_finally_statement (cp_parser *parser) { +cp_parser_objc_try_catch_finally_statement (cp_parser *parser) +{ location_t location; tree stmt; @@ -22620,22 +22630,60 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) { while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH)) { - cp_parameter_declarator *parmdecl; - tree parm; + cp_parameter_declarator *parm; + tree parameter_declaration = error_mark_node; + bool seen_open_paren = false; cp_lexer_consume_token (parser->lexer); - cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); - parmdecl = cp_parser_parameter_declaration (parser, false, NULL); - parm = grokdeclarator (parmdecl->declarator, - &parmdecl->decl_specifiers, - PARM, /*initialized=*/0, - /*attrlist=*/NULL); - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); - objc_begin_catch_clause (parm); + if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + seen_open_paren = true; + if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) + { + /* We have "@catch (...)" (where the '...' are literally + what is in the code). Skip the '...'. + parameter_declaration is set to NULL_TREE, and + objc_being_catch_clauses() knows that that means + '...'. */ + cp_lexer_consume_token (parser->lexer); + parameter_declaration = NULL_TREE; + } + else + { + /* We have "@catch (NSException *exception)" or something + like that. Parse the parameter declaration. */ + parm = cp_parser_parameter_declaration (parser, false, NULL); + if (parm == NULL) + parameter_declaration = error_mark_node; + else + parameter_declaration = grokdeclarator (parm->declarator, + &parm->decl_specifiers, + PARM, /*initialized=*/0, + /*attrlist=*/NULL); + } + if (seen_open_paren) + cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + else + { + /* If there was no open parenthesis, we are recovering from + an error, and we are trying to figure out what mistake + the user has made. */ + + /* If there is an immediate closing parenthesis, the user + probably forgot the opening one (ie, they typed "@catch + NSException *e)". Parse the closing parenthesis and keep + going. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) + cp_lexer_consume_token (parser->lexer); + + /* If these is no immediate closing parenthesis, the user + probably doesn't know that parenthesis are required at + all (ie, they typed "@catch NSException *e"). So, just + forget about the closing parenthesis and keep going. */ + } + objc_begin_catch_clause (parameter_declaration); cp_parser_compound_statement (parser, NULL, false); objc_finish_catch_clause (); } - if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY)) { cp_lexer_consume_token (parser->lexer); -- cgit v1.1