This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[c++ PATCH] PR 29087 (ice on valid code)
- From: Steven Bosscher <stevenb dot gcc at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Mark Mitchell <mark at codesourcery dot com>
- Date: Sat, 16 Sep 2006 19:41:02 +0200
- Subject: [c++ PATCH] PR 29087 (ice on valid code)
:ADDPATCH C++:
Hello,
This patch fixes a C++ regression where we ICE due to too deep recursion
in the parser. Fixed by removing the recursion.
Bootstrapped c,c++,java and tested c++,java on x86_64-suse-linux-gnu.
I don't see much point in adding a test case because failure depends so
much on the machine stack size. But I can put the test case I added in
the audit trail (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29087#c6)
to the test suite if people want me to.
OK for trunk, and for the GCC 4.1 branch?
Gr.
Steven
* parser.c (cp_parser_labeled_statement): Return nothing.
Rename to cp_parser_label_for_labeled_statement. Parse only
the label, not the statement.
(cp_parser_statement): Parse the statement of a labeled-statement
from here, using tail recursion.
Index: parser.c
===================================================================
--- parser.c (revision 116991)
+++ parser.c (working copy)
@@ -1451,8 +1451,8 @@ static tree cp_parser_builtin_offsetof
static void cp_parser_statement
(cp_parser *, tree, bool);
-static tree cp_parser_labeled_statement
- (cp_parser *, tree, bool);
+static void cp_parser_label_for_labeled_statement
+ (cp_parser *);
static tree cp_parser_expression_statement
(cp_parser *, tree);
static tree cp_parser_compound_statement
@@ -6117,9 +6117,11 @@ cp_parser_statement (cp_parser* parser,
{
case RID_CASE:
case RID_DEFAULT:
- statement = cp_parser_labeled_statement (parser, in_statement_expr,
- in_compound);
- break;
+ /* Looks like a labeled-statement with a case label.
+ Parse the label, and then use tail recursion to parse
+ the statement. */
+ cp_parser_label_for_labeled_statement (parser);
+ goto restart;
case RID_IF:
case RID_SWITCH:
@@ -6164,8 +6166,13 @@ cp_parser_statement (cp_parser* parser,
labeled-statement. */
token = cp_lexer_peek_nth_token (parser->lexer, 2);
if (token->type == CPP_COLON)
- statement = cp_parser_labeled_statement (parser, in_statement_expr,
- in_compound);
+ {
+ /* Looks like a labeled-statement with an ordinary label.
+ Parse the label, and then use tail recursion to parse
+ the statement. */
+ cp_parser_label_for_labeled_statement (parser);
+ goto restart;
+ }
}
/* Anything that starts with a `{' must be a compound-statement. */
else if (token->type == CPP_OPEN_BRACE)
@@ -6215,7 +6222,7 @@ cp_parser_statement (cp_parser* parser,
SET_EXPR_LOCATION (statement, statement_location);
}
-/* Parse a labeled-statement.
+/* Parse the label of a labeled-statement.
labeled-statement:
identifier : statement
@@ -6227,18 +6234,25 @@ cp_parser_statement (cp_parser* parser,
labeled-statement:
case constant-expression ... constant-expression : statement
- Returns the new CASE_LABEL_EXPR, for a `case' or `default' label.
- For an ordinary label, returns a LABEL_EXPR.
-
- IN_COMPOUND is as for cp_parser_statement: true when we're nested
- inside a compound. */
+ This function is only called by cp_parser_statement. We can use
+ this to avoid extremely deep recursion (e.g. PR29087): In this
+ function we only parse up to `statement', and then we return to
+ cp_parser_statement to parse `statement' there. So the bits we
+ parse here are:
+
+ identifier :
+ case constant-expression :
+ case constant-expression ... constant-expression :
+ default :
+
+ When a label is parsed without errors, the label is added to the
+ parse tree by the finish_* functions, so this function doesn't
+ have to return the label. */
-static tree
-cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
- bool in_compound)
+static void
+cp_parser_label_for_labeled_statement (cp_parser* parser)
{
cp_token *token;
- tree statement = error_mark_node;
/* The next token should be an identifier. */
token = cp_lexer_peek_token (parser->lexer);
@@ -6246,7 +6260,7 @@ cp_parser_labeled_statement (cp_parser*
&& token->type != CPP_KEYWORD)
{
cp_parser_error (parser, "expected labeled-statement");
- return error_mark_node;
+ return;
}
switch (token->keyword)
@@ -6279,7 +6293,7 @@ cp_parser_labeled_statement (cp_parser*
expr_hi = NULL_TREE;
if (parser->in_switch_statement_p)
- statement = finish_case_label (expr, expr_hi);
+ finish_case_label (expr, expr_hi);
else
error ("case label %qE not within a switch statement", expr);
}
@@ -6290,24 +6304,19 @@ cp_parser_labeled_statement (cp_parser*
cp_lexer_consume_token (parser->lexer);
if (parser->in_switch_statement_p)
- statement = finish_case_label (NULL_TREE, NULL_TREE);
+ finish_case_label (NULL_TREE, NULL_TREE);
else
error ("case label not within a switch statement");
break;
default:
/* Anything else must be an ordinary label. */
- statement = finish_label_stmt (cp_parser_identifier (parser));
+ finish_label_stmt (cp_parser_identifier (parser));
break;
}
/* Require the `:' token. */
cp_parser_require (parser, CPP_COLON, "`:'");
- /* Parse the labeled statement. */
- cp_parser_statement (parser, in_statement_expr, in_compound);
-
- /* Return the label, in the case of a `case' or `default' label. */
- return statement;
}
/* Parse an expression-statement.