Plug an extension leak on parse error in parse_for().
[cparser] / parser.c
index 386eab2..59417dd 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -9287,6 +9287,23 @@ static statement_t *parse_inner_statement(void)
        return stmt;
 }
 
+/**
+ * Parse an expression in parentheses and mark its variables as read.
+ */
+static expression_t *parse_condition(void)
+{
+       expect('(', end_error0);
+       add_anchor_token(')');
+       expression_t *const expr = parse_expression();
+       mark_vars_read(expr, NULL);
+       rem_anchor_token(')');
+       expect(')', end_error1);
+end_error1:
+       return expr;
+end_error0:
+       return create_error_expression();
+}
+
 /**
  * Parse an if statement.
  */
@@ -9300,18 +9317,12 @@ static statement_t *parse_if(void)
 
        add_anchor_token('{');
 
-       expect('(', end_error);
-       add_anchor_token(')');
-       expression_t *const expr = parse_expression();
+       expression_t *const expr = parse_condition();
        statement->ifs.condition = expr;
        /* §6.8.4.1:1  The controlling expression of an if statement shall have
         *             scalar type. */
        semantic_condition(expr, "condition of 'if'-statment");
-       mark_vars_read(expr, NULL);
-       rem_anchor_token(')');
-       expect(')', end_error);
 
-end_error:
        rem_anchor_token('{');
 
        add_anchor_token(T_else);
@@ -9395,10 +9406,7 @@ static statement_t *parse_switch(void)
 
        PUSH_PARENT(statement);
 
-       expect('(', end_error);
-       add_anchor_token(')');
-       expression_t *const expr = parse_expression();
-       mark_vars_read(expr, NULL);
+       expression_t *const expr = parse_condition();
        type_t       *      type = skip_typeref(expr->base.type);
        if (is_type_integer(type)) {
                type = promote_integer(type);
@@ -9411,8 +9419,6 @@ static statement_t *parse_switch(void)
                type = type_error_type;
        }
        statement->switchs.expression = create_implicit_cast(expr, type);
-       expect(')', end_error);
-       rem_anchor_token(')');
 
        switch_statement_t *rem = current_switch;
        current_switch          = &statement->switchs;
@@ -9426,9 +9432,6 @@ static statement_t *parse_switch(void)
 
        POP_PARENT();
        return statement;
-end_error:
-       POP_PARENT();
-       return create_error_statement();
 }
 
 static statement_t *parse_loop_body(statement_t *const loop)
@@ -9453,24 +9456,16 @@ static statement_t *parse_while(void)
 
        PUSH_PARENT(statement);
 
-       expect('(', end_error);
-       add_anchor_token(')');
-       expression_t *const cond = parse_expression();
+       expression_t *const cond = parse_condition();
        statement->whiles.condition = cond;
        /* §6.8.5:2    The controlling expression of an iteration statement shall
         *             have scalar type. */
        semantic_condition(cond, "condition of 'while'-statement");
-       mark_vars_read(cond, NULL);
-       rem_anchor_token(')');
-       expect(')', end_error);
 
        statement->whiles.body = parse_loop_body(statement);
 
        POP_PARENT();
        return statement;
-end_error:
-       POP_PARENT();
-       return create_error_statement();
 }
 
 /**
@@ -9489,16 +9484,11 @@ static statement_t *parse_do(void)
        rem_anchor_token(T_while);
 
        expect(T_while, end_error);
-       expect('(', end_error);
-       add_anchor_token(')');
-       expression_t *const cond = parse_expression();
+       expression_t *const cond = parse_condition();
        statement->do_while.condition = cond;
        /* §6.8.5:2    The controlling expression of an iteration statement shall
         *             have scalar type. */
        semantic_condition(cond, "condition of 'do-while'-statement");
-       mark_vars_read(cond, NULL);
-       rem_anchor_token(')');
-       expect(')', end_error);
        expect(';', end_error);
 
        POP_PARENT();
@@ -9537,7 +9527,8 @@ static statement_t *parse_for(void)
                        warningf(WARN_UNUSED_VALUE, &init->base.source_position, "initialisation of 'for'-statement has no effect");
                }
                rem_anchor_token(';');
-               expect(';', end_error2);
+               expect(';', end_error3);
+end_error3:;
        }
 
        POP_EXTENSION();
@@ -9625,7 +9616,7 @@ static statement_t *parse_goto(void)
                        else
                                parse_error_expected("while parsing goto", T_IDENTIFIER, NULL);
                        eat_until_anchor();
-                       return create_error_statement();
+                       statement->gotos.label = &allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym_anonymous)->label;
                }
        }
 
@@ -9864,10 +9855,7 @@ static statement_t *parse_ms_try_statment(void)
        POP_PARENT();
 
        if (next_if(T___except)) {
-               expect('(', end_error);
-               add_anchor_token(')');
-               expression_t *const expr = parse_expression();
-               mark_vars_read(expr, NULL);
+               expression_t *const expr = parse_condition();
                type_t       *      type = skip_typeref(expr->base.type);
                if (is_type_integer(type)) {
                        type = promote_integer(type);
@@ -9877,18 +9865,11 @@ static statement_t *parse_ms_try_statment(void)
                        type = type_error_type;
                }
                statement->ms_try.except_expression = create_implicit_cast(expr, type);
-               rem_anchor_token(')');
-               expect(')', end_error);
-               statement->ms_try.final_statement = parse_compound_statement(false);
-       } else if (next_if(T__finally)) {
-               statement->ms_try.final_statement = parse_compound_statement(false);
-       } else {
+       } else if (!next_if(T__finally)) {
                parse_error_expected("while parsing __try statement", T___except, T___finally, NULL);
-               return create_error_statement();
        }
+       statement->ms_try.final_statement = parse_compound_statement(false);
        return statement;
-end_error:
-       return create_error_statement();
 }
 
 static statement_t *parse_empty_statement(void)
@@ -9998,10 +9979,8 @@ end_error:
  */
 static statement_t *intern_parse_statement(void)
 {
-       statement_t *statement = NULL;
-
        /* declaration or statement */
-       add_anchor_token(';');
+       statement_t *statement;
        switch (token.kind) {
        case T_IDENTIFIER: {
                token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind;
@@ -10072,14 +10051,9 @@ static statement_t *intern_parse_statement(void)
        default:
                errorf(HERE, "unexpected token %K while parsing statement", &token);
                statement = create_error_statement();
-               if (!at_anchor())
-                       next_token();
+               eat_until_anchor();
                break;
        }
-       rem_anchor_token(';');
-
-       assert(statement != NULL
-                       && statement->base.source_position.input_name != NULL);
 
        return statement;
 }
@@ -10124,6 +10098,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
        add_anchor_token('*');
        add_anchor_token('+');
        add_anchor_token('-');
+       add_anchor_token(';');
        add_anchor_token('{');
        add_anchor_token('~');
        add_anchor_token(T_CHARACTER_CONSTANT);
@@ -10336,6 +10311,7 @@ end_error:
        rem_anchor_token(T_CHARACTER_CONSTANT);
        rem_anchor_token('~');
        rem_anchor_token('{');
+       rem_anchor_token(';');
        rem_anchor_token('-');
        rem_anchor_token('+');
        rem_anchor_token('*');