aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c79
1 files changed, 71 insertions, 8 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 82026b1..c481ae3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -8294,10 +8294,13 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
- /* If we're looking at a `}', then we've run out of statements. */
+ /* If we are looking at a `}', then we have run out of
+ statements; the same is true if we have reached the end
+ of file, or have stumbled upon a stray '@end'. */
if (token->type == CPP_CLOSE_BRACE
|| token->type == CPP_EOF
- || token->type == CPP_PRAGMA_EOL)
+ || token->type == CPP_PRAGMA_EOL
+ || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END))
break;
/* If we are in a compound statement and find 'else' then
@@ -21090,6 +21093,12 @@ cp_parser_objc_message_args (cp_parser* parser)
token = cp_lexer_peek_token (parser->lexer);
}
+ if (sel_args == NULL_TREE && addl_args == NULL_TREE)
+ {
+ cp_parser_error (parser, "objective-c++ message argument(s) are expected");
+ return build_tree_list (error_mark_node, error_mark_node);
+ }
+
return build_tree_list (sel_args, addl_args);
}
@@ -21482,7 +21491,12 @@ cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
}
maybe_unary_selector_p = false;
- cp_parser_require (parser, CPP_COLON, RT_COLON);
+ if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+ {
+ /* Something went quite wrong. There should be a colon
+ here, but there is not. Stop parsing parameters. */
+ break;
+ }
type_name = cp_parser_objc_typename (parser);
/* New ObjC allows attributes on parameters too. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
@@ -21517,6 +21531,11 @@ cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
return error_mark_node;
}
+ if (params == NULL_TREE)
+ {
+ cp_parser_error (parser, "objective-c++ method declaration is expected");
+ return error_mark_node;
+ }
return params;
}
@@ -21608,6 +21627,13 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
cp_lexer_consume_token (parser->lexer);
objc_set_method_opt (false);
}
+ /* Other stray characters must generate errors. */
+ else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ error ("stray `%s' between Objective-C++ methods",
+ token->type == CPP_OPEN_BRACE ? "{" : "}");
+ }
/* Finally, try to parse a block-declaration, or a function-definition. */
else
cp_parser_block_declaration (parser, /*statement_p=*/false);
@@ -21670,6 +21696,7 @@ cp_parser_objc_method_prototype_list (cp_parser* parser)
if (sig == error_mark_node)
{
cp_parser_skip_to_end_of_block_or_statement (parser);
+ token = cp_lexer_peek_token (parser->lexer);
continue;
}
objc_add_method_declaration (sig, attributes);
@@ -21687,7 +21714,11 @@ cp_parser_objc_method_prototype_list (cp_parser* parser)
token = cp_lexer_peek_token (parser->lexer);
}
- cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ if (token->type != CPP_EOF)
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ else
+ cp_parser_error (parser, "expected %<@end%>");
+
objc_finish_interface ();
}
@@ -21711,6 +21742,7 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
if (sig == error_mark_node)
{
cp_parser_skip_to_end_of_block_or_statement (parser);
+ token = cp_lexer_peek_token (parser->lexer);
continue;
}
objc_start_method_definition (sig, attribute);
@@ -21726,7 +21758,7 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
perform_deferred_access_checks ();
stop_deferring_access_checks ();
meth = cp_parser_function_definition_after_declarator (parser,
- false);
+ false);
pop_deferring_access_checks ();
objc_finish_method_definition (meth);
}
@@ -21742,7 +21774,11 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
token = cp_lexer_peek_token (parser->lexer);
}
- cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ if (token->type != CPP_EOF)
+ cp_lexer_consume_token (parser->lexer); /* Eat '@end'. */
+ else
+ cp_parser_error (parser, "expected %<@end%>");
+
objc_finish_implementation ();
}
@@ -21759,7 +21795,8 @@ cp_parser_objc_class_ivars (cp_parser* parser)
cp_lexer_consume_token (parser->lexer); /* Eat '{'. */
token = cp_lexer_peek_token (parser->lexer);
- while (token->type != CPP_CLOSE_BRACE)
+ while (token->type != CPP_CLOSE_BRACE
+ && token->keyword != RID_AT_END && token->type != CPP_EOF)
{
cp_decl_specifier_seq declspecs;
int decl_class_or_enum_p;
@@ -21858,7 +21895,14 @@ cp_parser_objc_class_ivars (cp_parser* parser)
token = cp_lexer_peek_token (parser->lexer);
}
- cp_lexer_consume_token (parser->lexer); /* Eat '}'. */
+ if (token->keyword == RID_AT_END)
+ cp_parser_error (parser, "expected %<}%>");
+
+ /* Do not consume the RID_AT_END, so it will be read again as terminating
+ the @interface of @implementation. */
+ if (token->keyword != RID_AT_END && token->type != CPP_EOF)
+ cp_lexer_consume_token (parser->lexer); /* Eat '}'. */
+
/* For historical reasons, we accept an optional semicolon. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
cp_lexer_consume_token (parser->lexer);
@@ -21932,6 +21976,15 @@ cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
cp_lexer_consume_token (parser->lexer); /* Eat '@interface'. */
name = cp_parser_identifier (parser);
+ if (name == error_mark_node)
+ {
+ /* It's hard to recover because even if valid @interface stuff
+ is to follow, we can't compile it (or validate it) if we
+ don't even know which class it refers to. Let's assume this
+ was a stray '@interface' token in the stream and skip it.
+ */
+ return;
+ }
cp_parser_objc_superclass_or_category (parser, &super, &categ);
protos = cp_parser_objc_protocol_refs_opt (parser);
@@ -21958,6 +22011,16 @@ cp_parser_objc_class_implementation (cp_parser* parser)
cp_lexer_consume_token (parser->lexer); /* Eat '@implementation'. */
name = cp_parser_identifier (parser);
+ if (name == error_mark_node)
+ {
+ /* It's hard to recover because even if valid @implementation
+ stuff is to follow, we can't compile it (or validate it) if
+ we don't even know which class it refers to. Let's assume
+ this was a stray '@implementation' token in the stream and
+ skip it.
+ */
+ return;
+ }
cp_parser_objc_superclass_or_category (parser, &super, &categ);
/* We have either a class or a category on our hands. */