This routine patch fixes PR objc/48187. The problem is that the following code
@interface A { ] } @end would cause the ObjC parser to enter into an infinite loop. The parser fails to parse ] as an instance variable, but then when it tries to skip to the next semicolon to resume parsing from the next instance variable, the standard c_parser_skip_until_found() doesn't skip the ] because it's a special token that reduces the nesting level. So, the parser tries to parse ] again as an instance variable, and then again and again, failing to ever make any progress ;-) The fix adds an explicit branch to deal with the parsing failure, and carefully skips to the next semicolon (or '}) even in the case of ']' or ')'. -- As I was looking at that chunk of code, I also noticed the error message saying "extra semicolon in struct or union specified" for an extra semicolon found in a list of ObjC instance variables. I think it's incorrect or at least confusing as a list of ObjC instance variables isn't a "struct or union". ;-) I changed it to simply say "extra semicolon" as I like short and clear error messages. But I'm happy to change it to something else (eg, "extra semicolon specified in list of Objective-C instance variables") if other people disagree. -- I added testcases. -- Finally, I also updated the ObjC++ parser so that it would survive the same testcases (previously they would crash the compiler). Ok to commit ? Thanks Index: ChangeLog =================================================================== --- ChangeLog (revision 174112) +++ ChangeLog (working copy) @@ -1,3 +1,11 @@ +2011-05-24 Nicola Pero <nicola.p...@meta-innovation.com> + + PR objc/48187 + * c-parser.c (c_parser_objc_class_instance_variables): More robust + parsing of syntax error in ObjC instance variable lists. In + particular, avoid an infinite loop if there is a stray ']'. + Updated error message. + 2011-05-24 Joseph Myers <jos...@codesourcery.com> * Makefile.in (GCC_OBJS): Remove opts-common.o and options.o. Index: testsuite/ChangeLog =================================================================== --- testsuite/ChangeLog (revision 174112) +++ testsuite/ChangeLog (working copy) @@ -1,3 +1,10 @@ +2011-05-24 Nicola Pero <nicola.p...@meta-innovation.com> + + PR objc/48187 + * objc.dg/pr48187.m: New testcase. + * obj-c++.dg/pr48187.mm: New testcase. + * objc.dg/ivar-extra-semicolon.m: New testcase. + 2011-05-24 Tom de Vries <t...@codesourcery.com> PR tree-optimization/49121 Index: testsuite/objc.dg/ivar-extra-semicolon.m =================================================================== --- testsuite/objc.dg/ivar-extra-semicolon.m (revision 0) +++ testsuite/objc.dg/ivar-extra-semicolon.m (revision 0) @@ -0,0 +1,15 @@ +/* Contributed by Nicola Pero <nicola.p...@meta-innovation.com>, May 2011. */ +/* { dg-do compile } */ +/* { dg-options "-pedantic" } */ + +#include <objc/objc.h> + +@interface MyClass +{ + ; /* { dg-warning "extra semicolon" } */ + int a; + ; /* { dg-warning "extra semicolon" } */ + int b; + ; /* { dg-warning "extra semicolon" } */ +} +@end Index: testsuite/objc.dg/pr48187.m =================================================================== --- testsuite/objc.dg/pr48187.m (revision 0) +++ testsuite/objc.dg/pr48187.m (revision 0) @@ -0,0 +1,39 @@ +/* { dg-do compile } */ + +@interface A +{ + ] /* { dg-error "xpected" } */ +} +@end + +@interface B +{ + ]; /* { dg-error "xpected" } */ +} +@end + +@interface C +{ + ]; /* { dg-error "xpected" } */ + int x; +} +@end + +@interface D +{ + ) /* { dg-error "xpected" } */ +} +@end + +@interface E +{ + ); /* { dg-error "xpected" } */ +} +@end + +@interface F +{ + ); /* { dg-error "xpected" } */ + int x; +} +@end Index: testsuite/obj-c++.dg/pr48187.mm =================================================================== --- testsuite/obj-c++.dg/pr48187.mm (revision 0) +++ testsuite/obj-c++.dg/pr48187.mm (revision 0) @@ -0,0 +1,39 @@ +/* { dg-do compile } */ + +@interface A +{ + ] /* { dg-error "xpected" } */ +} +@end + +@interface B +{ + ]; /* { dg-error "xpected" } */ +} +@end + +@interface C +{ + ]; /* { dg-error "xpected" } */ + int x; +} +@end + +@interface D +{ + ( +} /* { dg-error "xpected" } */ +@end + +@interface E +{ + (; /* { dg-error "xpected" } */ +} +@end + +@interface F +{ + (; /* { dg-error "xpected" } */ + int x; +} +@end Index: cp/ChangeLog =================================================================== --- cp/ChangeLog (revision 174112) +++ cp/ChangeLog (working copy) @@ -1,3 +1,8 @@ +2011-05-24 Nicola Pero <nicola.p...@meta-innovation.com>, + + * parser.c (cp_parser_objc_class_ivars): Deal gracefully with a + syntax error in declaring an ObjC instance variable. + 2011-05-24 Joseph Myers <jos...@codesourcery.com> * Make-lang.in (GXX_OBJS): Remove prefix.o. Index: cp/parser.c =================================================================== --- cp/parser.c (revision 174112) +++ cp/parser.c (working copy) @@ -22494,7 +22494,8 @@ cp_parser_objc_class_ivars (cp_parser* parser) NULL_TREE, attributes); /* Add the instance variable. */ - objc_add_instance_variable (decl); + if (decl != error_mark_node && decl != NULL_TREE) + objc_add_instance_variable (decl); /* Reset PREFIX_ATTRIBUTES. */ while (attributes && TREE_CHAIN (attributes) != first_attribute) Index: c-parser.c =================================================================== --- c-parser.c (revision 174112) +++ c-parser.c (working copy) @@ -6945,7 +6945,7 @@ c_parser_objc_class_instance_variables (c_parser * if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { pedwarn (c_parser_peek_token (parser)->location, OPT_pedantic, - "extra semicolon in struct or union specified"); + "extra semicolon"); c_parser_consume_token (parser); continue; } @@ -6988,13 +6988,34 @@ c_parser_objc_class_instance_variables (c_parser * /* Parse some comma-separated declarations. */ decls = c_parser_struct_declaration (parser); - { - /* Comma-separated instance variables are chained together in - reverse order; add them one by one. */ - tree ivar = nreverse (decls); - for (; ivar; ivar = DECL_CHAIN (ivar)) - objc_add_instance_variable (copy_node (ivar)); - } + if (decls == NULL) + { + /* There is a syntax error. We want to skip the offending + tokens up to the next ';' (included) or '}' + (excluded). */ + + /* First, skip manually a ')' or ']'. This is because they + reduce the nesting level, so c_parser_skip_until_found() + wouldn't be able to skip past them. */ + c_token *token = c_parser_peek_token (parser); + if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE) + c_parser_consume_token (parser); + + /* Then, do the standard skipping. */ + c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL); + + /* We hopefully recovered. Start normal parsing again. */ + parser->error = false; + continue; + } + else + { + /* Comma-separated instance variables are chained together + in reverse order; add them one by one. */ + tree ivar = nreverse (decls); + for (; ivar; ivar = DECL_CHAIN (ivar)) + objc_add_instance_variable (copy_node (ivar)); + } c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } }