fix incorrect type size for wide string literals
[cparser] / parser.c
index d81e20f..88ad628 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -569,6 +569,16 @@ static inline void next_token(void)
 #endif
 }
 
+static inline bool next_if(int const type)
+{
+       if (token.type == type) {
+               next_token();
+               return true;
+       } else {
+               return false;
+       }
+}
+
 /**
  * Return the next token with a given lookahead.
  */
@@ -702,8 +712,7 @@ static void eat_until_anchor(void)
 static void eat_block(void)
 {
        eat_until_matching_token('{');
-       if (token.type == '}')
-               next_token();
+       next_if('}');
 }
 
 #define eat(token_type) (assert(token.type == (token_type)), next_token())
@@ -747,8 +756,7 @@ static void type_error_incompatible(const char *msg,
                        parse_error_expected(NULL, (expected), NULL); \
                        add_anchor_token(expected);                   \
                        eat_until_anchor();                           \
-                       if (token.type == expected)                   \
-                               next_token();                             \
+                       next_if((expected));                          \
                        rem_anchor_token(expected);                   \
                        goto error_label;                             \
                }                                                 \
@@ -1242,12 +1250,9 @@ static attribute_t *allocate_attribute_zero(attribute_kind_t kind)
  */
 static attribute_argument_t *parse_attribute_arguments(void)
 {
-       if (token.type == ')')
-               return NULL;
-
-       attribute_argument_t *first = NULL;
-       attribute_argument_t *last  = NULL;
-       while (true) {
+       attribute_argument_t  *first  = NULL;
+       attribute_argument_t **anchor = &first;
+       if (token.type != ')') do {
                attribute_argument_t *argument = allocate_ast_zero(sizeof(*argument));
 
                /* is it an identifier */
@@ -1266,20 +1271,10 @@ static attribute_argument_t *parse_attribute_arguments(void)
                }
 
                /* append argument */
-               if (last == NULL) {
-                       first = argument;
-               } else {
-                       last->next = argument;
-               }
-               last = argument;
-
-               if (token.type == ',') {
-                       next_token();
-                       continue;
-               }
-               expect(')', end_error);
-               break;
-       }
+               *anchor = argument;
+               anchor  = &argument->next;
+       } while (next_if(','));
+       expect(')', end_error);
 
        return first;
 
@@ -1373,10 +1368,8 @@ static attribute_t *parse_attribute_gnu_single(void)
        attribute_t *attribute = allocate_attribute_zero(kind);
 
        /* parse arguments */
-       if (token.type == '(') {
-               next_token();
+       if (next_if('('))
                attribute->a.arguments = parse_attribute_arguments();
-       }
 
        return attribute;
 
@@ -1386,37 +1379,22 @@ end_error:
 
 static attribute_t *parse_attribute_gnu(void)
 {
-       attribute_t *first = NULL;
-       attribute_t *last  = NULL;
+       attribute_t  *first  = NULL;
+       attribute_t **anchor = &first;
 
        eat(T___attribute__);
        expect('(', end_error);
        expect('(', end_error);
 
-       if (token.type == ')') {
-               next_token();
-               expect(')', end_error);
-               return first;
-       }
-
-       while (true) {
+       if (token.type != ')') do {
                attribute_t *attribute = parse_attribute_gnu_single();
                if (attribute == NULL)
                        goto end_error;
 
-               if (last == NULL) {
-                       first = attribute;
-               } else {
-                       last->next = attribute;
-               }
-               last = attribute;
-
-               if (token.type == ')') {
-                       next_token();
-                       break;
-               }
-               expect(',', end_error);
-       }
+               *anchor = attribute;
+               anchor  = &attribute->next;
+       } while (next_if(','));
+       expect(')', end_error);
        expect(')', end_error);
 
 end_error:
@@ -1426,12 +1404,10 @@ end_error:
 /** Parse attributes. */
 static attribute_t *parse_attributes(attribute_t *first)
 {
-       attribute_t *last = first;
-       while (true) {
-               if (last != NULL) {
-                       while (last->next != NULL)
-                               last = last->next;
-               }
+       attribute_t **anchor = &first;
+       for (;;) {
+               while (*anchor != NULL)
+                       anchor = &(*anchor)->next;
 
                attribute_t *attribute;
                switch (token.type) {
@@ -1475,12 +1451,8 @@ static attribute_t *parse_attributes(attribute_t *first)
                        return first;
                }
 
-               if (last == NULL) {
-                       first = attribute;
-               } else {
-                       last->next = attribute;
-               }
-               last = attribute;
+               *anchor = attribute;
+               anchor  = &attribute->next;
        }
 }
 
@@ -1721,10 +1693,10 @@ unary:
 
 static designator_t *parse_designation(void)
 {
-       designator_t *result = NULL;
-       designator_t *last   = NULL;
+       designator_t  *result = NULL;
+       designator_t **anchor = &result;
 
-       while (true) {
+       for (;;) {
                designator_t *designator;
                switch (token.type) {
                case '[':
@@ -1754,12 +1726,8 @@ static designator_t *parse_designation(void)
                }
 
                assert(designator != NULL);
-               if (last != NULL) {
-                       last->next = designator;
-               } else {
-                       result = designator;
-               }
-               last = designator;
+               *anchor = designator;
+               anchor  = &designator->next;
        }
 end_error:
        return NULL;
@@ -1864,13 +1832,12 @@ static initializer_t *parse_scalar_initializer(type_t *type,
 {
        /* there might be extra {} hierarchies */
        int braces = 0;
-       if (token.type == '{') {
+       if (next_if('{')) {
                if (warning.other)
                        warningf(HERE, "extra curly braces around scalar initializer");
                do {
                        ++braces;
-                       next_token();
-               } while (token.type == '{');
+               } while (next_if('{'));
        }
 
        expression_t *expression = parse_assignment_expression();
@@ -1893,9 +1860,7 @@ static initializer_t *parse_scalar_initializer(type_t *type,
 
        bool additional_warning_displayed = false;
        while (braces > 0) {
-               if (token.type == ',') {
-                       next_token();
-               }
+               next_if(',');
                if (token.type != '}') {
                        if (!additional_warning_displayed && warning.other) {
                                warningf(HERE, "additional elements in scalar initializer");
@@ -2193,8 +2158,7 @@ static void advance_current_object(type_path_t *path, size_t top_path_level)
  */
 static void skip_initializers(void)
 {
-       if (token.type == '{')
-               next_token();
+       next_if('{');
 
        while (token.type != '}') {
                if (token.type == T_EOF)
@@ -2327,9 +2291,7 @@ finish_designator:
                                        && outer_type != NULL) {
                                sub = initializer_from_expression(outer_type, expression);
                                if (sub != NULL) {
-                                       if (token.type == ',') {
-                                               next_token();
-                                       }
+                                       next_if(',');
                                        if (token.type != '}' && warning.other) {
                                                warningf(HERE, "excessive elements in initializer for type '%T'",
                                                                 orig_type);
@@ -2625,8 +2587,7 @@ static void parse_enum_entries(type_t *const enum_type)
                entity->base.source_position = token.source_position;
                next_token();
 
-               if (token.type == '=') {
-                       next_token();
+               if (next_if('=')) {
                        expression_t *value = parse_constant_expression();
 
                        value = create_implicit_cast(value, enum_type);
@@ -2636,11 +2597,7 @@ static void parse_enum_entries(type_t *const enum_type)
                }
 
                record_entity(entity, false);
-
-               if (token.type != ',')
-                       break;
-               next_token();
-       } while (token.type != '}');
+       } while (next_if(',') && token.type != '}');
        rem_anchor_token('}');
 
        expect('}', end_error);
@@ -2651,33 +2608,38 @@ end_error:
 
 static type_t *parse_enum_specifier(void)
 {
-       entity_t        *entity;
-       symbol_t        *symbol;
+       entity_t *entity;
+       symbol_t *symbol;
 
        eat(T_enum);
-       if (token.type == T_IDENTIFIER) {
-               symbol = token.v.symbol;
-               next_token();
+       switch (token.type) {
+               case T_IDENTIFIER:
+                       symbol = token.v.symbol;
+                       next_token();
 
-               entity = get_tag(symbol, ENTITY_ENUM);
-               if (entity != NULL) {
-                       if (entity->base.parent_scope != current_scope &&
-                                       (token.type == '{' || token.type == ';')) {
-                               /* we're in an inner scope and have a definition. Shadow
-                                * existing definition in outer scope */
-                               entity = NULL;
-                       } else if (entity->enume.complete && token.type == '{') {
-                               errorf(HERE, "multiple definitions of 'enum %Y' (previous definition %P)",
-                                               symbol, &entity->base.source_position);
+                       entity = get_tag(symbol, ENTITY_ENUM);
+                       if (entity != NULL) {
+                               if (entity->base.parent_scope != current_scope &&
+                                               (token.type == '{' || token.type == ';')) {
+                                       /* we're in an inner scope and have a definition. Shadow
+                                        * existing definition in outer scope */
+                                       entity = NULL;
+                               } else if (entity->enume.complete && token.type == '{') {
+                                       errorf(HERE, "multiple definitions of 'enum %Y' (previous definition %P)",
+                                                       symbol, &entity->base.source_position);
+                               }
                        }
-               }
-       } else if (token.type != '{') {
-               parse_error_expected("while parsing enum type specifier",
-                                    T_IDENTIFIER, '{', NULL);
-               return NULL;
-       } else {
-               entity  = NULL;
-               symbol  = NULL;
+                       break;
+
+               case '{':
+                       entity = NULL;
+                       symbol = NULL;
+                       break;
+
+               default:
+                       parse_error_expected("while parsing enum type specifier",
+                                       T_IDENTIFIER, '{', NULL);
+                       return NULL;
        }
 
        if (entity == NULL) {
@@ -2739,9 +2701,8 @@ static type_t *parse_typeof(void)
        bool old_gcc_extension = in_gcc_extension;
        in_type_prop           = true;
 
-       while (token.type == T___extension__) {
+       while (next_if(T___extension__)) {
                /* This can be a prefix to a typename or an expression. */
-               next_token();
                in_gcc_extension = true;
        }
        switch (token.type) {
@@ -2828,7 +2789,7 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute)
        attribute_property_argument_t *property
                = allocate_ast_zero(sizeof(*property));
 
-       while (true) {
+       do {
                if (token.type != T_IDENTIFIER) {
                        parse_error_expected("while parsing property declspec",
                                             T_IDENTIFIER, NULL);
@@ -2858,10 +2819,7 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute)
                        property->get_symbol = token.v.symbol;
                }
                next_token();
-               if (token.type == ')')
-                       break;
-               expect(',', end_error);
-       }
+       } while (next_if(','));
 
        attribute->a.property = property;
 
@@ -2874,9 +2832,8 @@ end_error:
 static attribute_t *parse_microsoft_extended_decl_modifier_single(void)
 {
        attribute_kind_t kind = ATTRIBUTE_UNKNOWN;
-       if (token.type == T_restrict) {
+       if (next_if(T_restrict)) {
                kind = ATTRIBUTE_MS_RESTRICT;
-               next_token();
        } else if (token.type == T_IDENTIFIER) {
                const char *name = token.v.symbol->string;
                next_token();
@@ -2904,10 +2861,8 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void)
        }
 
        /* parse arguments */
-       if (token.type == '(') {
-               next_token();
+       if (next_if('('))
                attribute->a.arguments = parse_attribute_arguments();
-       }
 
        return attribute;
 }
@@ -2918,37 +2873,24 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first)
 
        expect('(', end_error);
 
-       if (token.type == ')') {
-               next_token();
+       if (next_if(')'))
                return NULL;
-       }
 
        add_anchor_token(')');
 
-       attribute_t *last = first;
-       while (true) {
-               if (last != NULL) {
-                       while (last->next != NULL)
-                               last = last->next;
-               }
+       attribute_t **anchor = &first;
+       do {
+               while (*anchor != NULL)
+                       anchor = &(*anchor)->next;
 
                attribute_t *attribute
                        = parse_microsoft_extended_decl_modifier_single();
                if (attribute == NULL)
                        goto end_error;
 
-               if (last == NULL) {
-                       first = attribute;
-               } else {
-                       last->next = attribute;
-               }
-               last = attribute;
-
-               if (token.type == ')') {
-                       break;
-               }
-               expect(',', end_error);
-       }
+               *anchor = attribute;
+               anchor  = &attribute->next;
+       } while (next_if(','));
 
        rem_anchor_token(')');
        expect(')', end_error);
@@ -3450,12 +3392,7 @@ static void parse_identifier_list(scope_t *scope)
 
                if (scope != NULL)
                        append_entity(scope, entity);
-
-               if (token.type != ',') {
-                       break;
-               }
-               next_token();
-       } while (token.type == T_IDENTIFIER);
+       } while (next_if(',') && token.type == T_IDENTIFIER);
 }
 
 static entity_t *parse_parameter(void)
@@ -3536,7 +3473,7 @@ static void parse_parameters(function_type_t *type, scope_t *scope)
 
        if (has_parameters()) {
                function_parameter_t **anchor = &type->parameters;
-               for (;;) {
+               do {
                        switch (token.type) {
                        case T_DOTDOTDOT:
                                next_token();
@@ -3572,11 +3509,7 @@ static void parse_parameters(function_type_t *type, scope_t *scope)
                        default:
                                goto parameters_finished;
                        }
-                       if (token.type != ',') {
-                               goto parameters_finished;
-                       }
-                       next_token();
-               }
+               } while (next_if(','));
        }
 
 
@@ -3670,18 +3603,12 @@ static construct_type_t *parse_array_declarator(void)
        memset(array, 0, sizeof(*array));
        cons->kind = CONSTRUCT_ARRAY;
 
-       if (token.type == T_static) {
+       if (next_if(T_static))
                array->is_static = true;
-               next_token();
-       }
 
        type_qualifiers_t type_qualifiers = parse_type_qualifiers();
-       if (type_qualifiers != 0) {
-               if (token.type == T_static) {
+       if (type_qualifiers != 0 && next_if(T_static))
                        array->is_static = true;
-                       next_token();
-               }
-       }
        array->type_qualifiers = type_qualifiers;
 
        if (token.type == '*' && look_ahead(1)->type == ']') {
@@ -4036,15 +3963,11 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
 
        attribute_t *attributes = parse_attributes(env.attributes);
        /* append (shared) specifier attribute behind attributes of this
-          declarator */
-       if (attributes != NULL) {
-               attribute_t *last = attributes;
-               while (last->next != NULL)
-                       last = last->next;
-               last->next = specifiers->attributes;
-       } else {
-               attributes = specifiers->attributes;
-       }
+        * declarator */
+       attribute_t **anchor = &attributes;
+       while (*anchor != NULL)
+               anchor = &(*anchor)->next;
+       *anchor = specifiers->attributes;
 
        entity_t *entity;
        if (specifiers->storage_class == STORAGE_CLASS_TYPEDEF) {
@@ -4722,9 +4645,8 @@ static void parse_declaration_rest(entity_t *ndeclaration,
 
                check_variable_type_complete(entity);
 
-               if (token.type != ',')
+               if (!next_if(','))
                        break;
-               eat(',');
 
                add_anchor_token('=');
                ndeclaration = parse_declarator(specifiers, flags);
@@ -5313,9 +5235,8 @@ static void check_reachable(statement_t *const stmt)
                        break;
                }
 
-               case STATEMENT_CONTINUE: {
-                       statement_t *parent = stmt;
-                       for (;;) {
+               case STATEMENT_CONTINUE:
+                       for (statement_t *parent = stmt;;) {
                                parent = parent->base.parent;
                                if (parent == NULL) /* continue not within loop */
                                        return;
@@ -5329,11 +5250,9 @@ static void check_reachable(statement_t *const stmt)
                                        default: break;
                                }
                        }
-               }
 
-               case STATEMENT_BREAK: {
-                       statement_t *parent = stmt;
-                       for (;;) {
+               case STATEMENT_BREAK:
+                       for (statement_t *parent = stmt;;) {
                                parent = parent->base.parent;
                                if (parent == NULL) /* break not within loop/switch */
                                        return;
@@ -5352,7 +5271,6 @@ static void check_reachable(statement_t *const stmt)
                        }
 found_break_parent:
                        break;
-               }
 
                case STATEMENT_GOTO:
                        if (stmt->gotos.expression) {
@@ -5993,7 +5911,7 @@ static expression_t *find_create_select(const source_position_t *pos,
 static void parse_compound_declarators(compound_t *compound,
                const declaration_specifiers_t *specifiers)
 {
-       while (true) {
+       do {
                entity_t *entity;
 
                if (token.type == ':') {
@@ -6006,15 +5924,11 @@ static void parse_compound_declarators(compound_t *compound,
                        type_t *type = make_bitfield_type(base_type, size,
                                        &source_position, NULL);
 
-                       attribute_t *attributes = parse_attributes(NULL);
-                       if (attributes != NULL) {
-                               attribute_t *last = attributes;
-                               while (last->next != NULL)
-                                       last = last->next;
-                               last->next = specifiers->attributes;
-                       } else {
-                               attributes = specifiers->attributes;
-                       }
+                       attribute_t  *attributes = parse_attributes(NULL);
+                       attribute_t **anchor     = &attributes;
+                       while (*anchor != NULL)
+                               anchor = &(*anchor)->next;
+                       *anchor = specifiers->attributes;
 
                        entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER);
                        entity->base.namespc                       = NAMESPACE_NORMAL;
@@ -6082,11 +5996,7 @@ static void parse_compound_declarators(compound_t *compound,
                                append_entity(&compound->members, entity);
                        }
                }
-
-               if (token.type != ',')
-                       break;
-               next_token();
-       }
+       } while (next_if(','));
        expect(';', end_error);
 
 end_error:
@@ -6517,13 +6427,12 @@ static entity_t *lookup_entity(const scope_t *scope, symbol_t *symbol,
 static entity_t *parse_qualified_identifier(void)
 {
        /* namespace containing the symbol */
-       symbol_t      *symbol;
-       const scope_t *lookup_scope = NULL;
+       symbol_t          *symbol;
+       source_position_t  pos;
+       const scope_t     *lookup_scope = NULL;
 
-       if (token.type == T_COLONCOLON) {
-               next_token();
+       if (next_if(T_COLONCOLON))
                lookup_scope = &unit->scope;
-       }
 
        entity_t *entity;
        while (true) {
@@ -6532,14 +6441,14 @@ static entity_t *parse_qualified_identifier(void)
                        return create_error_entity(sym_anonymous, ENTITY_VARIABLE);
                }
                symbol = token.v.symbol;
+               pos    = *HERE;
                next_token();
 
                /* lookup entity */
                entity = lookup_entity(lookup_scope, symbol, NAMESPACE_NORMAL);
 
-               if (token.type != T_COLONCOLON)
+               if (!next_if(T_COLONCOLON))
                        break;
-               next_token();
 
                switch (entity->kind) {
                case ENTITY_NAMESPACE:
@@ -6551,7 +6460,7 @@ static entity_t *parse_qualified_identifier(void)
                        lookup_scope = &entity->compound.members;
                        break;
                default:
-                       errorf(HERE, "'%Y' must be a namespace, class, struct or union (but is a %s)",
+                       errorf(&pos, "'%Y' must be a namespace, class, struct or union (but is a %s)",
                               symbol, get_entity_kind_name(entity->kind));
                        goto end_error;
                }
@@ -6561,14 +6470,14 @@ static entity_t *parse_qualified_identifier(void)
                if (!strict_mode && token.type == '(') {
                        /* an implicitly declared function */
                        if (warning.error_implicit_function_declaration) {
-                               errorf(HERE, "implicit declaration of function '%Y'", symbol);
+                               errorf(&pos, "implicit declaration of function '%Y'", symbol);
                        } else if (warning.implicit_function_declaration) {
-                               warningf(HERE, "implicit declaration of function '%Y'", symbol);
+                               warningf(&pos, "implicit declaration of function '%Y'", symbol);
                        }
 
-                       entity = create_implicit_function(symbol, HERE);
+                       entity = create_implicit_function(symbol, &pos);
                } else {
-                       errorf(HERE, "unknown identifier '%Y' found.", symbol);
+                       errorf(&pos, "unknown identifier '%Y' found.", symbol);
                        entity = create_error_entity(symbol, ENTITY_VARIABLE);
                }
        }
@@ -6577,12 +6486,7 @@ static entity_t *parse_qualified_identifier(void)
 
 end_error:
        /* skip further qualifications */
-       while (token.type == T_IDENTIFIER) {
-               next_token();
-               if (token.type != T_COLONCOLON)
-                       break;
-               next_token();
-       }
+       while (next_if(T_IDENTIFIER) && next_if(T_COLONCOLON)) {}
 
        return create_error_entity(sym_anonymous, ENTITY_VARIABLE);
 }
@@ -6885,8 +6789,7 @@ static designator_t *parse_designator(void)
 
        designator_t *last_designator = result;
        while (true) {
-               if (token.type == '.') {
-                       next_token();
+               if (next_if('.')) {
                        if (token.type != T_IDENTIFIER) {
                                parse_error_expected("while parsing member designator",
                                                     T_IDENTIFIER, NULL);
@@ -6901,8 +6804,7 @@ static designator_t *parse_designator(void)
                        last_designator       = designator;
                        continue;
                }
-               if (token.type == '[') {
-                       next_token();
+               if (next_if('[')) {
                        add_anchor_token(']');
                        designator_t *designator    = allocate_ast_zero(sizeof(result[0]));
                        designator->source_position = *HERE;
@@ -7265,14 +7167,9 @@ static expression_t *parse_noop_expression(void)
                add_anchor_token(')');
                add_anchor_token(',');
 
-               if (token.type != ')') {
-                       while (true) {
-                               (void)parse_assignment_expression();
-                               if (token.type != ',')
-                                       break;
-                               next_token();
-                       }
-               }
+               if (token.type != ')') do {
+                       (void)parse_assignment_expression();
+               } while (next_if(','));
        }
        rem_anchor_token(',');
        rem_anchor_token(')');
@@ -7672,17 +7569,13 @@ static expression_t *parse_call_expression(expression_t *expression)
 
        if (token.type != ')') {
                call_argument_t **anchor = &call->arguments;
-               for (;;) {
+               do {
                        call_argument_t *argument = allocate_ast_zero(sizeof(*argument));
                        argument->expression = parse_assignment_expression();
 
                        *anchor = argument;
                        anchor  = &argument->next;
-
-                       if (token.type != ',')
-                               break;
-                       next_token();
-               }
+               } while (next_if(','));
        }
        rem_anchor_token(',');
        rem_anchor_token(')');
@@ -7998,8 +7891,7 @@ static expression_t *parse_delete(void)
 
        eat(T_delete);
 
-       if (token.type == '[') {
-               next_token();
+       if (next_if('[')) {
                result->kind = EXPR_UNARY_DELETE_ARRAY;
                expect(']', end_error);
 end_error:;
@@ -8107,14 +7999,14 @@ static bool is_lvalue(const expression_t *expression)
                return true;
 
        default: {
-         type_t *type = skip_typeref(expression->base.type);
-         return
-               /* ISO/IEC 14882:1998(E) §3.10:3 */
-               is_type_reference(type) ||
-               /* Claim it is an lvalue, if the type is invalid.  There was a parse
-                * error before, which maybe prevented properly recognizing it as
-                * lvalue. */
-               !is_type_valid(type);
+               type_t *type = skip_typeref(expression->base.type);
+               return
+                       /* ISO/IEC 14882:1998(E) §3.10:3 */
+                       is_type_reference(type) ||
+                       /* Claim it is an lvalue, if the type is invalid.  There was a parse
+                        * error before, which maybe prevented properly recognizing it as
+                        * lvalue. */
+                       !is_type_valid(type);
        }
        }
 }
@@ -9276,8 +9168,7 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
                asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
                memset(argument, 0, sizeof(argument[0]));
 
-               if (token.type == '[') {
-                       eat('[');
+               if (next_if('[')) {
                        if (token.type != T_IDENTIFIER) {
                                parse_error_expected("while parsing asm argument",
                                                     T_IDENTIFIER, NULL);
@@ -9356,9 +9247,8 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
                *anchor = argument;
                anchor  = &argument->next;
 
-               if (token.type != ',')
+               if (!next_if(','))
                        break;
-               eat(',');
        }
 
        return result;
@@ -9371,23 +9261,18 @@ end_error:
  */
 static asm_clobber_t *parse_asm_clobbers(void)
 {
-       asm_clobber_t *result = NULL;
-       asm_clobber_t *last   = NULL;
+       asm_clobber_t *result  = NULL;
+       asm_clobber_t **anchor = &result;
 
        while (token.type == T_STRING_LITERAL) {
                asm_clobber_t *clobber = allocate_ast_zero(sizeof(clobber[0]));
                clobber->clobber       = parse_string_literals();
 
-               if (last != NULL) {
-                       last->next = clobber;
-               } else {
-                       result = clobber;
-               }
-               last = clobber;
+               *anchor = clobber;
+               anchor  = &clobber->next;
 
-               if (token.type != ',')
+               if (!next_if(','))
                        break;
-               eat(',');
        }
 
        return result;
@@ -9403,36 +9288,31 @@ static statement_t *parse_asm_statement(void)
 
        eat(T_asm);
 
-       if (token.type == T_volatile) {
-               next_token();
+       if (next_if(T_volatile))
                asm_statement->is_volatile = true;
-       }
 
        expect('(', end_error);
        add_anchor_token(')');
        add_anchor_token(':');
        asm_statement->asm_text = parse_string_literals();
 
-       if (token.type != ':') {
+       if (!next_if(':')) {
                rem_anchor_token(':');
                goto end_of_asm;
        }
-       eat(':');
 
        asm_statement->outputs = parse_asm_arguments(true);
-       if (token.type != ':') {
+       if (!next_if(':')) {
                rem_anchor_token(':');
                goto end_of_asm;
        }
-       eat(':');
 
        asm_statement->inputs = parse_asm_arguments(false);
-       if (token.type != ':') {
+       if (!next_if(':')) {
                rem_anchor_token(':');
                goto end_of_asm;
        }
        rem_anchor_token(':');
-       eat(':');
 
        asm_statement->clobbers = parse_asm_clobbers();
 
@@ -9479,8 +9359,7 @@ static statement_t *parse_case_statement(void)
        }
 
        if (GNU_MODE) {
-               if (token.type == T_DOTDOTDOT) {
-                       next_token();
+               if (next_if(T_DOTDOTDOT)) {
                        expression_t *const end_range   = parse_expression();
                        statement->case_label.end_range = end_range;
                        if (!is_constant_expression(end_range)) {
@@ -9683,8 +9562,7 @@ end_error:
        statement->ifs.true_statement = true_stmt;
        rem_anchor_token(T_else);
 
-       if (token.type == T_else) {
-               next_token();
+       if (next_if(T_else)) {
                statement->ifs.false_statement = parse_statement();
        } else if (warning.parentheses &&
                        true_stmt->kind == STATEMENT_IF &&
@@ -9887,13 +9765,11 @@ static statement_t *parse_for(void)
        scope_t      *old_scope = scope_push(&statement->fors.scope);
 
        bool old_gcc_extension = in_gcc_extension;
-       while (token.type == T___extension__) {
-               next_token();
+       while (next_if(T___extension__)) {
                in_gcc_extension = true;
        }
 
-       if (token.type == ';') {
-               next_token();
+       if (next_if(';')) {
        } else if (is_declaration_specifier(&token, false)) {
                parse_declaration(record_entity, DECL_FLAGS_NONE);
        } else {
@@ -9961,8 +9837,7 @@ static statement_t *parse_goto(void)
        statement_t *statement = allocate_statement_zero(STATEMENT_GOTO);
        eat(T_goto);
 
-       if (GNU_MODE && token.type == '*') {
-               next_token();
+       if (GNU_MODE && next_if('*')) {
                expression_t *expression = parse_expression();
                mark_vars_read(expression, NULL);
 
@@ -10245,8 +10120,7 @@ static statement_t *parse_ms_try_statment(void)
 
        POP_PARENT;
 
-       if (token.type == T___except) {
-               eat(T___except);
+       if (next_if(T___except)) {
                expect('(', end_error);
                add_anchor_token(')');
                expression_t *const expr = parse_expression();
@@ -10263,8 +10137,7 @@ static statement_t *parse_ms_try_statment(void)
                rem_anchor_token(')');
                expect(')', end_error);
                statement->ms_try.final_statement = parse_compound_statement(false);
-       } else if (token.type == T__finally) {
-               eat(T___finally);
+       } else if (next_if(T__finally)) {
                statement->ms_try.final_statement = parse_compound_statement(false);
        } else {
                parse_error_expected("while parsing __try statement", T___except, T___finally, NULL);
@@ -10293,7 +10166,7 @@ static statement_t *parse_local_label_declaration(void)
 
        entity_t *begin = NULL, *end = NULL;
 
-       while (true) {
+       do {
                if (token.type != T_IDENTIFIER) {
                        parse_error_expected("while parsing local label declaration",
                                T_IDENTIFIER, NULL);
@@ -10321,11 +10194,7 @@ static statement_t *parse_local_label_declaration(void)
                        environment_push(entity);
                }
                next_token();
-
-               if (token.type != ',')
-                       break;
-               next_token();
-       }
+       } while (next_if(','));
        eat(';');
 end_error:
        statement->declaration.declarations_begin = begin;
@@ -10432,9 +10301,7 @@ expression_statment:
        case T___extension__:
                /* This can be a prefix to a declaration or an expression statement.
                 * We simply eat it now and parse the rest with tail recursion. */
-               do {
-                       next_token();
-               } while (token.type == T___extension__);
+               while (next_if(T___extension__)) {}
                bool old_gcc_extension = in_gcc_extension;
                in_gcc_extension       = true;
                statement = intern_parse_statement();
@@ -10831,8 +10698,7 @@ static void parse_linkage_specification(void)
        }
        current_linkage = new_linkage;
 
-       if (token.type == '{') {
-               next_token();
+       if (next_if('{')) {
                parse_externals();
                expect('}', end_error);
        } else {