Do not crash if the expression of an array designator is not constant.
[cparser] / parser.c
index 61d96b5..fc156f4 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -375,7 +375,7 @@ static statement_t *allocate_statement_zero(statement_kind_t kind)
 
        res->base.kind            = kind;
        res->base.parent          = current_parent;
-       res->base.source_position = token.base.source_position;
+       res->base.source_position = *HERE;
        return res;
 }
 
@@ -392,7 +392,7 @@ static expression_t *allocate_expression_zero(expression_kind_t kind)
 
        res->base.kind            = kind;
        res->base.type            = type_error_type;
-       res->base.source_position = token.base.source_position;
+       res->base.source_position = *HERE;
        return res;
 }
 
@@ -487,10 +487,12 @@ static inline void next_token(void)
 #endif
 }
 
+#define eat(token_kind) (assert(token.kind == (token_kind)), next_token())
+
 static inline bool next_if(token_kind_t const type)
 {
        if (token.kind == type) {
-               next_token();
+               eat(type);
                return true;
        } else {
                return false;
@@ -601,8 +603,6 @@ static void eat_block(void)
        next_if('}');
 }
 
-#define eat(token_kind) (assert(token.kind == (token_kind)), next_token())
-
 /**
  * Report a parse error because an expected token was not found.
  */
@@ -1047,12 +1047,12 @@ static string_t parse_string_literals(void)
        assert(token.kind == T_STRING_LITERAL);
        string_t result = token.string.string;
 
-       next_token();
+       eat(T_STRING_LITERAL);
 
        while (token.kind == T_STRING_LITERAL) {
-               warn_string_concat(&token.base.source_position);
+               warn_string_concat(HERE);
                result = concat_strings(&result, &token.string.string);
-               next_token();
+               eat(T_STRING_LITERAL);
        }
 
        return result;
@@ -1106,7 +1106,7 @@ static attribute_argument_t *parse_attribute_arguments(void)
                                && (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) {
                        argument->kind     = ATTRIBUTE_ARGUMENT_SYMBOL;
                        argument->v.symbol = token.base.symbol;
-                       next_token();
+                       eat(T_IDENTIFIER);
                } else {
                        /* must be an expression */
                        expression_t *expression = parse_assignment_expression();
@@ -1172,11 +1172,11 @@ static attribute_t *parse_attribute_gnu(void)
        attribute_t **anchor = &first;
 
        eat(T___attribute__);
+       add_anchor_token(')');
+       add_anchor_token(',');
        expect('(');
        expect('(');
 
-       add_anchor_token(')');
-       add_anchor_token(',');
        if (token.kind != ')') do {
                attribute_t *attribute = parse_attribute_gnu_single();
                if (attribute) {
@@ -1486,8 +1486,8 @@ static designator_t *parse_designation(void)
                switch (token.kind) {
                case '[':
                        designator = allocate_ast_zero(sizeof(designator[0]));
-                       designator->source_position = token.base.source_position;
-                       next_token();
+                       designator->source_position = *HERE;
+                       eat('[');
                        add_anchor_token(']');
                        designator->array_index = parse_constant_expression();
                        rem_anchor_token(']');
@@ -1495,8 +1495,8 @@ static designator_t *parse_designation(void)
                        break;
                case '.':
                        designator = allocate_ast_zero(sizeof(designator[0]));
-                       designator->source_position = token.base.source_position;
-                       next_token();
+                       designator->source_position = *HERE;
+                       eat('.');
                        designator->symbol = expect_identifier("while parsing designator", NULL);
                        if (!designator->symbol)
                                return NULL;
@@ -1829,7 +1829,8 @@ static bool walk_designator(type_path_t *path, const designator_t *designator,
                        }
                } else {
                        expression_t *array_index = designator->array_index;
-                       assert(designator->array_index != NULL);
+                       if (is_constant_expression(array_index) != EXPR_CLASS_CONSTANT)
+                               return true;
 
                        if (!is_type_array(type)) {
                                if (is_type_valid(type)) {
@@ -1973,7 +1974,7 @@ static initializer_t *parse_sub_initializer(type_path_t *path,
                } else if (token.kind == T_IDENTIFIER && look_ahead(1)->kind == ':') {
                        /* GNU-style designator ("identifier: value") */
                        designator = allocate_ast_zero(sizeof(designator[0]));
-                       designator->source_position = token.base.source_position;
+                       designator->source_position = *HERE;
                        designator->symbol          = token.base.symbol;
                        eat(T_IDENTIFIER);
                        eat(':');
@@ -2267,7 +2268,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
                /* the compound has a name, check if we have seen it already */
                symbol = token.base.symbol;
                entity = get_tag(symbol, kind);
-               next_token();
+               eat(T_IDENTIFIER);
 
                if (entity != NULL) {
                        if (entity->base.parent_scope != current_scope &&
@@ -2324,7 +2325,7 @@ static void parse_enum_entries(type_t *const enum_type)
 
        if (token.kind == '}') {
                errorf(HERE, "empty enum not allowed");
-               next_token();
+               eat('}');
                return;
        }
 
@@ -2366,7 +2367,7 @@ static type_t *parse_enum_specifier(void)
                case T_IDENTIFIER:
                        symbol = token.base.symbol;
                        entity = get_tag(symbol, ENTITY_ENUM);
-                       next_token();
+                       eat(T_IDENTIFIER);
 
                        if (entity != NULL) {
                                if (entity->base.parent_scope != current_scope &&
@@ -2438,8 +2439,8 @@ static type_t *parse_typeof(void)
 
        type_t *type;
 
-       expect('(');
        add_anchor_token(')');
+       expect('(');
 
        expression_t *expression  = NULL;
 
@@ -2504,10 +2505,10 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute)
 {
        attribute_property_argument_t *const property = allocate_ast_zero(sizeof(*property));
 
-       expect('(');
-
        add_anchor_token(')');
        add_anchor_token(',');
+       expect('(');
+
        do {
                add_anchor_token('=');
                source_position_t pos;
@@ -2584,10 +2585,9 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first)
 {
        eat(T__declspec);
 
+       add_anchor_token(')');
        expect('(');
        if (token.kind != ')') {
-               add_anchor_token(')');
-
                attribute_t **anchor = &first;
                do {
                        while (*anchor != NULL)
@@ -2601,9 +2601,8 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first)
                        *anchor = attribute;
                        anchor  = &attribute->next;
                } while (next_if(','));
-
-               rem_anchor_token(')');
        }
+       rem_anchor_token(')');
        expect(')');
        return first;
 }
@@ -2632,7 +2631,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
        bool               saw_error       = false;
 
        memset(specifiers, 0, sizeof(*specifiers));
-       specifiers->source_position = token.base.source_position;
+       specifiers->source_position = *HERE;
 
        while (true) {
                specifiers->attributes = parse_attributes(specifiers->attributes);
@@ -2647,7 +2646,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                        specifiers->storage_class = class;                             \
                        if (specifiers->thread_local)                                  \
                                goto check_thread_storage_class;                           \
-                       next_token();                                                  \
+                       eat(token); \
                        break;
 
                MATCH_STORAGE_CLASS(T_typedef,  STORAGE_CLASS_TYPEDEF)
@@ -2689,7 +2688,7 @@ wrong_thread_storage_class:
 #define MATCH_TYPE_QUALIFIER(token, qualifier)                          \
                case token:                                                     \
                        qualifiers |= qualifier;                                    \
-                       next_token();                                               \
+                       eat(token); \
                        break
 
                MATCH_TYPE_QUALIFIER(T_const,    TYPE_QUALIFIER_CONST);
@@ -2709,7 +2708,7 @@ wrong_thread_storage_class:
                        } else {                                                    \
                                type_specifiers |= specifier;                           \
                        }                                                           \
-                       next_token();                                               \
+                       eat(token); \
                        break
 
                MATCH_SPECIFIER(T__Bool,      SPECIFIER_BOOL,      "_Bool");
@@ -2732,13 +2731,13 @@ wrong_thread_storage_class:
                MATCH_SPECIFIER(T_wchar_t,    SPECIFIER_WCHAR_T,   "wchar_t");
 
                case T_inline:
-                       next_token();
+                       eat(T_inline);
                        specifiers->is_inline = true;
                        break;
 
 #if 0
                case T__forceinline:
-                       next_token();
+                       eat(T__forceinline);
                        specifiers->modifiers |= DM_FORCEINLINE;
                        break;
 #endif
@@ -2751,7 +2750,7 @@ wrong_thread_storage_class:
                        } else {
                                type_specifiers |= SPECIFIER_LONG;
                        }
-                       next_token();
+                       eat(T_long);
                        break;
 
 #define CHECK_DOUBLE_TYPE() \
@@ -2779,7 +2778,7 @@ wrong_thread_storage_class:
                case T___builtin_va_list:
                        CHECK_DOUBLE_TYPE();
                        type = duplicate_type(type_valist);
-                       next_token();
+                       eat(T___builtin_va_list);
                        break;
 
                case T_IDENTIFIER: {
@@ -2800,7 +2799,7 @@ wrong_thread_storage_class:
                                        case '&':
                                        case '*':
                                                errorf(HERE, "discarding stray %K in declaration specifier", &token);
-                                               next_token();
+                                               eat(T_IDENTIFIER);
                                                continue;
 
                                        default:
@@ -2826,7 +2825,7 @@ wrong_thread_storage_class:
                                                type = allocate_type_zero(TYPE_TYPEDEF);
                                                type->typedeft.typedefe = &entity->typedefe;
 
-                                               next_token();
+                                               eat(T_IDENTIFIER);
                                                saw_error = true;
                                                continue;
                                        }
@@ -2836,7 +2835,7 @@ wrong_thread_storage_class:
                                }
                        }
 
-                       next_token();
+                       eat(T_IDENTIFIER);
                        type = typedef_type;
                        break;
                }
@@ -3074,7 +3073,7 @@ static void parse_identifier_list(scope_t *scope)
        do {
                entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.base.symbol, HERE);
                /* a K&R parameter has no type, yet */
-               next_token();
+               eat(T_IDENTIFIER);
 
                if (scope != NULL)
                        append_entity(scope, entity);
@@ -3141,8 +3140,8 @@ static bool has_parameters(void)
  */
 static void parse_parameters(function_type_t *type, scope_t *scope)
 {
-       eat('(');
        add_anchor_token(')');
+       eat('(');
 
        if (token.kind == T_IDENTIFIER            &&
            !is_typedef_symbol(token.base.symbol) &&
@@ -3159,7 +3158,7 @@ static void parse_parameters(function_type_t *type, scope_t *scope)
                do {
                        switch (token.kind) {
                        case T_DOTDOTDOT:
-                               next_token();
+                               eat(T_DOTDOTDOT);
                                type->variadic = true;
                                goto parameters_finished;
 
@@ -3301,7 +3300,7 @@ static construct_type_t *parse_array_declarator(void)
        expression_t *size = NULL;
        if (token.kind == '*' && look_ahead(1)->kind == ']') {
                array->is_variable = true;
-               next_token();
+               eat('*');
        } else if (token.kind != ']') {
                size = parse_assignment_expression();
 
@@ -3401,9 +3400,9 @@ ptr_operator_end: ;
                        errorf(HERE, "no identifier expected in typename");
                } else {
                        env->symbol          = token.base.symbol;
-                       env->source_position = token.base.source_position;
+                       env->source_position = *HERE;
                }
-               next_token();
+               eat(T_IDENTIFIER);
                break;
 
        case '(': {
@@ -3428,7 +3427,7 @@ ptr_operator_end: ;
                        case '[':
                        case T___attribute__: /* FIXME __attribute__ might also introduce a parameter of a function declarator. */
                                        /* Paranthesized declarator. */
-                                       next_token();
+                                       eat('(');
                                        add_anchor_token(')');
                                        inner_types = parse_inner_declarator(env);
                                        if (inner_types != NULL) {
@@ -5697,14 +5696,14 @@ static type_t *get_wide_string_type(void)
  */
 static expression_t *parse_string_literal(void)
 {
-       source_position_t begin   = token.base.source_position;
+       source_position_t begin   = *HERE;
        string_t          res     = token.string.string;
        bool              is_wide = (token.kind == T_WIDE_STRING_LITERAL);
 
        next_token();
        while (token.kind == T_STRING_LITERAL
                        || token.kind == T_WIDE_STRING_LITERAL) {
-               warn_string_concat(&token.base.source_position);
+               warn_string_concat(HERE);
                res = concat_strings(&res, &token.string.string);
                next_token();
                is_wide |= token.kind == T_WIDE_STRING_LITERAL;
@@ -5734,7 +5733,7 @@ static expression_t *parse_boolean_literal(bool value)
        literal->literal.value.begin = value ? "true" : "false";
        literal->literal.value.size  = value ? 4 : 5;
 
-       next_token();
+       eat(value ? T_true : T_false);
        return literal;
 }
 
@@ -5775,8 +5774,7 @@ static void check_integer_suffix(void)
                }
        }
        if (*c != '\0') {
-               errorf(&token.base.source_position,
-                      "invalid suffix '%S' on integer constant", suffix);
+               errorf(HERE, "invalid suffix '%S' on integer constant", suffix);
        } else if (not_traditional) {
                warn_traditional_suffix();
        }
@@ -5799,8 +5797,7 @@ static type_t *check_floatingpoint_suffix(void)
                type = type_long_double;
        }
        if (*c != '\0') {
-               errorf(&token.base.source_position,
-                      "invalid suffix '%S' on floatingpoint constant", suffix);
+               errorf(HERE, "invalid suffix '%S' on floatingpoint constant", suffix);
        } else if (not_traditional) {
                warn_traditional_suffix();
        }
@@ -5865,7 +5862,7 @@ static expression_t *parse_character_constant(void)
                }
        }
 
-       next_token();
+       eat(T_CHARACTER_CONSTANT);
        return literal;
 }
 
@@ -5883,7 +5880,7 @@ static expression_t *parse_wide_character_constant(void)
                warningf(WARN_MULTICHAR, HERE, "multi-character character constant");
        }
 
-       next_token();
+       eat(T_WIDE_CHARACTER_CONSTANT);
        return literal;
 }
 
@@ -6071,7 +6068,7 @@ static entity_t *parse_qualified_identifier(void)
 
 static expression_t *parse_reference(void)
 {
-       source_position_t const pos    = token.base.source_position;
+       source_position_t const pos    = *HERE;
        entity_t         *const entity = parse_qualified_identifier();
 
        type_t *orig_type;
@@ -6274,68 +6271,21 @@ static expression_t *parse_parenthesized_expression(void)
        return result;
 }
 
-static expression_t *parse_function_keyword(void)
+static expression_t *parse_function_keyword(funcname_kind_t const kind)
 {
-       /* TODO */
-
        if (current_function == NULL) {
-               errorf(HERE, "'__func__' used outside of a function");
+               errorf(HERE, "'%K' used outside of a function", &token);
        }
 
        expression_t *expression  = allocate_expression_zero(EXPR_FUNCNAME);
        expression->base.type     = type_char_ptr;
-       expression->funcname.kind = FUNCNAME_FUNCTION;
+       expression->funcname.kind = kind;
 
        next_token();
 
        return expression;
 }
 
-static expression_t *parse_pretty_function_keyword(void)
-{
-       if (current_function == NULL) {
-               errorf(HERE, "'__PRETTY_FUNCTION__' used outside of a function");
-       }
-
-       expression_t *expression  = allocate_expression_zero(EXPR_FUNCNAME);
-       expression->base.type     = type_char_ptr;
-       expression->funcname.kind = FUNCNAME_PRETTY_FUNCTION;
-
-       eat(T___PRETTY_FUNCTION__);
-
-       return expression;
-}
-
-static expression_t *parse_funcsig_keyword(void)
-{
-       if (current_function == NULL) {
-               errorf(HERE, "'__FUNCSIG__' used outside of a function");
-       }
-
-       expression_t *expression  = allocate_expression_zero(EXPR_FUNCNAME);
-       expression->base.type     = type_char_ptr;
-       expression->funcname.kind = FUNCNAME_FUNCSIG;
-
-       eat(T___FUNCSIG__);
-
-       return expression;
-}
-
-static expression_t *parse_funcdname_keyword(void)
-{
-       if (current_function == NULL) {
-               errorf(HERE, "'__FUNCDNAME__' used outside of a function");
-       }
-
-       expression_t *expression  = allocate_expression_zero(EXPR_FUNCNAME);
-       expression->base.type     = type_char_ptr;
-       expression->funcname.kind = FUNCNAME_FUNCDNAME;
-
-       eat(T___FUNCDNAME__);
-
-       return expression;
-}
-
 static designator_t *parse_designator(void)
 {
        designator_t *const result = allocate_ast_zero(sizeof(result[0]));
@@ -6386,9 +6336,9 @@ static expression_t *parse_offsetof(void)
 
        eat(T___builtin_offsetof);
 
-       expect('(');
        add_anchor_token(')');
        add_anchor_token(',');
+       expect('(');
        type_t *type = parse_typename();
        rem_anchor_token(',');
        expect(',');
@@ -6441,9 +6391,9 @@ static expression_t *parse_va_start(void)
 
        eat(T___builtin_va_start);
 
-       expect('(');
        add_anchor_token(')');
        add_anchor_token(',');
+       expect('(');
        expression->va_starte.ap = parse_assignment_expression();
        rem_anchor_token(',');
        expect(',');
@@ -6472,9 +6422,9 @@ static expression_t *parse_va_arg(void)
 
        eat(T___builtin_va_arg);
 
-       expect('(');
        add_anchor_token(')');
        add_anchor_token(',');
+       expect('(');
        call_argument_t ap;
        ap.expression = parse_assignment_expression();
        expression->va_arge.ap = ap.expression;
@@ -6498,9 +6448,9 @@ static expression_t *parse_va_copy(void)
 
        eat(T___builtin_va_copy);
 
-       expect('(');
        add_anchor_token(')');
        add_anchor_token(',');
+       expect('(');
        expression_t *dst = parse_assignment_expression();
        assign_error_t error = semantic_assign(type_valist, dst);
        report_assign_error(error, type_valist, dst, "call argument 1",
@@ -6529,8 +6479,8 @@ static expression_t *parse_builtin_constant(void)
 
        eat(T___builtin_constant_p);
 
-       expect('(');
        add_anchor_token(')');
+       expect('(');
        expression->builtin_constant.value = parse_assignment_expression();
        rem_anchor_token(')');
        expect(')');
@@ -6548,9 +6498,9 @@ static expression_t *parse_builtin_types_compatible(void)
 
        eat(T___builtin_types_compatible_p);
 
-       expect('(');
        add_anchor_token(')');
        add_anchor_token(',');
+       expect('(');
        expression->builtin_types_compatible.left = parse_typename();
        rem_anchor_token(',');
        expect(',');
@@ -6567,36 +6517,22 @@ static expression_t *parse_builtin_types_compatible(void)
  */
 static expression_t *parse_compare_builtin(void)
 {
-       expression_t *expression;
-
+       expression_kind_t kind;
        switch (token.kind) {
-       case T___builtin_isgreater:
-               expression = allocate_expression_zero(EXPR_BINARY_ISGREATER);
-               break;
-       case T___builtin_isgreaterequal:
-               expression = allocate_expression_zero(EXPR_BINARY_ISGREATEREQUAL);
-               break;
-       case T___builtin_isless:
-               expression = allocate_expression_zero(EXPR_BINARY_ISLESS);
-               break;
-       case T___builtin_islessequal:
-               expression = allocate_expression_zero(EXPR_BINARY_ISLESSEQUAL);
-               break;
-       case T___builtin_islessgreater:
-               expression = allocate_expression_zero(EXPR_BINARY_ISLESSGREATER);
-               break;
-       case T___builtin_isunordered:
-               expression = allocate_expression_zero(EXPR_BINARY_ISUNORDERED);
-               break;
-       default:
-               internal_errorf(HERE, "invalid compare builtin found");
-       }
-       expression->base.source_position = *HERE;
+       case T___builtin_isgreater:      kind = EXPR_BINARY_ISGREATER;      break;
+       case T___builtin_isgreaterequal: kind = EXPR_BINARY_ISGREATEREQUAL; break;
+       case T___builtin_isless:         kind = EXPR_BINARY_ISLESS;         break;
+       case T___builtin_islessequal:    kind = EXPR_BINARY_ISLESSEQUAL;    break;
+       case T___builtin_islessgreater:  kind = EXPR_BINARY_ISLESSGREATER;  break;
+       case T___builtin_isunordered:    kind = EXPR_BINARY_ISUNORDERED;    break;
+       default: internal_errorf(HERE, "invalid compare builtin found");
+       }
+       expression_t *const expression = allocate_expression_zero(kind);
        next_token();
 
-       expect('(');
        add_anchor_token(')');
        add_anchor_token(',');
+       expect('(');
        expression->binary.left = parse_assignment_expression();
        rem_anchor_token(',');
        expect(',');
@@ -6630,8 +6566,8 @@ static expression_t *parse_assume(void)
 
        eat(T__assume);
 
-       expect('(');
        add_anchor_token(')');
+       expect('(');
        expression->unary.value = parse_assignment_expression();
        rem_anchor_token(')');
        expect(')');
@@ -6643,12 +6579,15 @@ static expression_t *parse_assume(void)
 /**
  * Return the label for the current symbol or create a new one.
  */
-static label_t *get_label(void)
+static label_t *get_label(char const *const context)
 {
-       assert(token.kind == T_IDENTIFIER);
        assert(current_function != NULL);
 
-       entity_t *label = get_entity(token.base.symbol, NAMESPACE_LABEL);
+       symbol_t *const sym = expect_identifier(context, NULL);
+       if (!sym)
+               return NULL;
+
+       entity_t *label = get_entity(sym, NAMESPACE_LABEL);
        /* If we find a local label, we already created the declaration. */
        if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) {
                if (label->base.parent_scope != current_scope) {
@@ -6658,11 +6597,10 @@ static label_t *get_label(void)
        } else if (label == NULL || label->base.parent_scope != &current_function->parameters) {
                /* There is no matching label in the same function, so create a new one. */
                source_position_t const nowhere = { NULL, 0, 0, false };
-               label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.base.symbol, &nowhere);
+               label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym, &nowhere);
                label_push(label);
        }
 
-       eat(T_IDENTIFIER);
        return &label->label;
 }
 
@@ -6671,14 +6609,13 @@ static label_t *get_label(void)
  */
 static expression_t *parse_label_address(void)
 {
-       source_position_t source_position = token.base.source_position;
+       source_position_t const source_position = *HERE;
        eat(T_ANDAND);
-       if (token.kind != T_IDENTIFIER) {
-               parse_error_expected("while parsing label address", T_IDENTIFIER, NULL);
+
+       label_t *const label = get_label("while parsing label address");
+       if (!label)
                return create_error_expression();
-       }
 
-       label_t *const label = get_label();
        label->used          = true;
        label->address_taken = true;
 
@@ -6737,10 +6674,10 @@ static expression_t *parse_primary_expression(void)
        case T_STRING_LITERAL:
        case T_WIDE_STRING_LITERAL:          return parse_string_literal();
        case T___FUNCTION__:
-       case T___func__:                     return parse_function_keyword();
-       case T___PRETTY_FUNCTION__:          return parse_pretty_function_keyword();
-       case T___FUNCSIG__:                  return parse_funcsig_keyword();
-       case T___FUNCDNAME__:                return parse_funcdname_keyword();
+       case T___func__:                     return parse_function_keyword(FUNCNAME_FUNCTION);
+       case T___PRETTY_FUNCTION__:          return parse_function_keyword(FUNCNAME_PRETTY_FUNCTION);
+       case T___FUNCSIG__:                  return parse_function_keyword(FUNCNAME_FUNCSIG);
+       case T___FUNCDNAME__:                return parse_function_keyword(FUNCNAME_FUNCDNAME);
        case T___builtin_offsetof:           return parse_offsetof();
        case T___builtin_va_start:           return parse_va_start();
        case T___builtin_va_arg:             return parse_va_arg();
@@ -6860,7 +6797,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind)
        expression_t *expression;
        if (token.kind == '(' && is_declaration_specifier(look_ahead(1))) {
                source_position_t const pos = *HERE;
-               next_token();
+               eat('(');
                add_anchor_token(')');
                orig_type = parse_typename();
                rem_anchor_token(')');
@@ -7412,8 +7349,8 @@ static expression_t *parse_builtin_classify_type(void)
 
        eat(T___builtin_classify_type);
 
-       expect('(');
        add_anchor_token(')');
+       expect('(');
        expression_t *expression = parse_expression();
        rem_anchor_token(')');
        expect(')');
@@ -8704,8 +8641,8 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
                }
 
                argument->constraints = parse_string_literals();
-               expect('(');
                add_anchor_token(')');
+               expect('(');
                expression_t *expression = parse_expression();
                rem_anchor_token(')');
                if (is_out) {
@@ -8873,7 +8810,7 @@ static statement_t *parse_label_inner_statement(statement_t const *const label,
                                 * statement after a label.  label:; is commonly used to have a label
                                 * before a closing brace. */
                                inner_stmt = create_empty_statement();
-                               next_token();
+                               eat(';');
                                break;
                        }
                        /* FALLTHROUGH */
@@ -9043,7 +8980,7 @@ static statement_t *parse_default_statement(void)
 static statement_t *parse_label_statement(void)
 {
        statement_t *const statement = allocate_statement_zero(STATEMENT_LABEL);
-       label_t     *const label     = get_label();
+       label_t     *const label     = get_label(NULL /* Cannot fail, token is T_IDENTIFIER. */);
        statement->label.label = label;
 
        PUSH_PARENT(statement);
@@ -9091,8 +9028,8 @@ static statement_t *parse_inner_statement(void)
  */
 static expression_t *parse_condition(void)
 {
-       expect('(');
        add_anchor_token(')');
+       expect('(');
        expression_t *const expr = parse_expression();
        mark_vars_read(expr, NULL);
        rem_anchor_token(')');
@@ -9308,8 +9245,8 @@ static statement_t *parse_for(void)
        PUSH_PARENT(statement);
        PUSH_SCOPE_STATEMENT(&statement->fors.scope);
 
-       expect('(');
        add_anchor_token(')');
+       expect('(');
 
        PUSH_EXTENSION();
 
@@ -9390,8 +9327,9 @@ static statement_t *parse_goto(void)
        } else {
                statement = allocate_statement_zero(STATEMENT_GOTO);
                eat(T_goto);
-               if (token.kind == T_IDENTIFIER) {
-                       label_t *const label = get_label();
+
+               label_t *const label = get_label("while parsing goto");
+               if (label) {
                        label->used            = true;
                        statement->gotos.label = label;
 
@@ -9399,11 +9337,6 @@ static statement_t *parse_goto(void)
                        *goto_anchor = &statement->gotos;
                        goto_anchor  = &statement->gotos.next;
                } else {
-                       if (GNU_MODE)
-                               parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL);
-                       else
-                               parse_error_expected("while parsing goto", T_IDENTIFIER, NULL);
-                       eat_until_anchor();
                        statement->gotos.label = &allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym_anonymous, &builtin_source_position)->label;
                }
        }
@@ -9665,29 +9598,31 @@ static statement_t *parse_local_label_declaration(void)
        entity_t *begin   = NULL;
        entity_t *end     = NULL;
        entity_t **anchor = &begin;
+       add_anchor_token(';');
+       add_anchor_token(',');
        do {
                source_position_t pos;
                symbol_t *const symbol = expect_identifier("while parsing local label declaration", &pos);
-               if (!symbol)
-                       goto end_error;
-
-               entity_t *entity = get_entity(symbol, NAMESPACE_LABEL);
-               if (entity != NULL && entity->base.parent_scope == current_scope) {
-                       source_position_t const *const ppos = &entity->base.source_position;
-                       errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos);
-               } else {
-                       entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol, &pos);
-                       entity->base.parent_scope = current_scope;
+               if (symbol) {
+                       entity_t *entity = get_entity(symbol, NAMESPACE_LABEL);
+                       if (entity != NULL && entity->base.parent_scope == current_scope) {
+                               source_position_t const *const ppos = &entity->base.source_position;
+                               errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos);
+                       } else {
+                               entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol, &pos);
+                               entity->base.parent_scope = current_scope;
 
-                       *anchor = entity;
-                       anchor  = &entity->base.next;
-                       end     = entity;
+                               *anchor = entity;
+                               anchor  = &entity->base.next;
+                               end     = entity;
 
-                       environment_push(entity);
+                               environment_push(entity);
+                       }
                }
        } while (next_if(','));
+       rem_anchor_token(',');
+       rem_anchor_token(';');
        expect(';');
-end_error:
        statement->declaration.declarations_begin = begin;
        statement->declaration.declarations_end   = end;
        return statement;
@@ -9702,18 +9637,14 @@ static void parse_namespace_definition(void)
 
        if (token.kind == T_IDENTIFIER) {
                symbol = token.base.symbol;
-               next_token();
-
                entity = get_entity(symbol, NAMESPACE_NORMAL);
-               if (entity != NULL
-                               && entity->kind != ENTITY_NAMESPACE
-                               && entity->base.parent_scope == current_scope) {
-                       if (is_entity_valid(entity)) {
-                               error_redefined_as_different_kind(&token.base.source_position,
-                                               entity, ENTITY_NAMESPACE);
-                       }
+               if (entity && entity->kind != ENTITY_NAMESPACE) {
                        entity = NULL;
+                       if (entity->base.parent_scope == current_scope && is_entity_valid(entity)) {
+                               error_redefined_as_different_kind(HERE, entity, ENTITY_NAMESPACE);
+                       }
                }
+               eat(T_IDENTIFIER);
        }
 
        if (entity == NULL) {
@@ -10203,7 +10134,7 @@ static void parse_external(void)
                case ';':
                        if (!strict_mode) {
                                warningf(WARN_STRAY_SEMICOLON, HERE, "stray ';' outside of function");
-                               next_token();
+                               eat(';');
                                return;
                        }
                        /* FALLTHROUGH */