summaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorNicola Pero <nicola.pero@meta-innovation.com>2010-11-29 03:15:40 +0000
committerNicola Pero <nicola@gcc.gnu.org>2010-11-29 03:15:40 +0000
commit437c23222436111f80b29ec24d2fb863b567e589 (patch)
tree44406a903b8b5e0d042b1c9cd87592f05480f94d /gcc/cp/parser.c
parent45f9cadb2a94bbb57bfd0a3f68afe42346c79c57 (diff)
downloadgcc-437c23222436111f80b29ec24d2fb863b567e589.tar.gz
In gcc/objc/: 2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com>
In gcc/objc/: 2010-11-29 Nicola Pero <nicola.pero@meta-innovation.com> * 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 <nicola.pero@meta-innovation.com> * 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 <nicola.pero@meta-innovation.com> * 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 <nicola.pero@meta-innovation.com> * 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
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c78
1 files changed, 63 insertions, 15 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3ed0579538a..917f75043b3 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);