Remove duplicate word from error message.
[cparser] / parser.c
index d1435c4..d517bd8 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -109,6 +109,12 @@ static declaration_t      **incomplete_arrays;
 static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT;
 
 
+#define PUSH_CURRENT_ENTITY(entity) \
+       entity_t *const new_current_entity = (entity); \
+       entity_t *const old_current_entity = current_entity; \
+       ((void)(current_entity = new_current_entity))
+#define POP_CURRENT_ENTITY() (assert(current_entity == new_current_entity), (void)(current_entity = old_current_entity))
+
 #define PUSH_PARENT(stmt) \
        statement_t *const new_parent = (stmt); \
        statement_t *const old_parent = current_parent; \
@@ -118,8 +124,9 @@ static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT;
 #define PUSH_SCOPE(scope) \
        size_t   const top       = environment_top(); \
        scope_t *const new_scope = (scope); \
-       scope_t *const old_scope = scope_push(new_scope)
-#define POP_SCOPE() (assert(current_scope == new_scope), scope_pop(old_scope), environment_pop_to(top))
+       scope_t *const old_scope = (new_scope ? scope_push(new_scope) : NULL)
+#define PUSH_SCOPE_STATEMENT(scope) PUSH_SCOPE(c_mode & (_C99 | _CXX) ? (scope) : NULL)
+#define POP_SCOPE() (new_scope ? assert(current_scope == new_scope), scope_pop(old_scope), environment_pop_to(top) : (void)0)
 
 #define PUSH_EXTENSION() \
        (void)0; \
@@ -241,10 +248,7 @@ static void semantic_comparison(binary_expression_t *expression);
        case T_ANDAND:                    \
        case T_CHARACTER_CONSTANT:        \
        case T_FLOATINGPOINT:             \
-       case T_FLOATINGPOINT_HEXADECIMAL: \
        case T_INTEGER:                   \
-       case T_INTEGER_HEXADECIMAL:       \
-       case T_INTEGER_OCTAL:             \
        case T_MINUSMINUS:                \
        case T_PLUSPLUS:                  \
        case T_STRING_LITERAL:            \
@@ -323,10 +327,7 @@ static size_t get_expression_struct_size(expression_kind_t kind)
                [EXPR_ENUM_CONSTANT]              = sizeof(reference_expression_t),
                [EXPR_LITERAL_BOOLEAN]            = sizeof(literal_expression_t),
                [EXPR_LITERAL_INTEGER]            = sizeof(literal_expression_t),
-               [EXPR_LITERAL_INTEGER_OCTAL]      = sizeof(literal_expression_t),
-               [EXPR_LITERAL_INTEGER_HEXADECIMAL]= sizeof(literal_expression_t),
                [EXPR_LITERAL_FLOATINGPOINT]      = sizeof(literal_expression_t),
-               [EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL] = sizeof(literal_expression_t),
                [EXPR_LITERAL_CHARACTER]          = sizeof(literal_expression_t),
                [EXPR_LITERAL_WIDE_CHARACTER]     = sizeof(literal_expression_t),
                [EXPR_STRING_LITERAL]             = sizeof(string_literal_expression_t),
@@ -486,7 +487,7 @@ static inline void next_token(void)
 #endif
 }
 
-static inline bool next_if(int const type)
+static inline bool next_if(token_kind_t const type)
 {
        if (token.kind == type) {
                next_token();
@@ -509,39 +510,18 @@ static inline const token_t *look_ahead(size_t num)
 /**
  * Adds a token type to the token type anchor set (a multi-set).
  */
-static void add_anchor_token(int token_kind)
+static void add_anchor_token(token_kind_t const token_kind)
 {
-       assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
+       assert(token_kind < T_LAST_TOKEN);
        ++token_anchor_set[token_kind];
 }
 
-/**
- * Set the number of tokens types of the given type
- * to zero and return the old count.
- */
-static int save_and_reset_anchor_state(int token_kind)
-{
-       assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
-       int count = token_anchor_set[token_kind];
-       token_anchor_set[token_kind] = 0;
-       return count;
-}
-
-/**
- * Restore the number of token types to the given count.
- */
-static void restore_anchor_state(int token_kind, int count)
-{
-       assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
-       token_anchor_set[token_kind] = count;
-}
-
 /**
  * Remove a token type from the token type anchor set (a multi-set).
  */
-static void rem_anchor_token(int token_kind)
+static void rem_anchor_token(token_kind_t const token_kind)
 {
-       assert(0 <= token_kind && token_kind < T_LAST_TOKEN);
+       assert(token_kind < T_LAST_TOKEN);
        assert(token_anchor_set[token_kind] != 0);
        --token_anchor_set[token_kind];
 }
@@ -549,9 +529,9 @@ static void rem_anchor_token(int token_kind)
 /**
  * Eat tokens until a matching token type is found.
  */
-static void eat_until_matching_token(int type)
+static void eat_until_matching_token(token_kind_t const type)
 {
-       int end_token;
+       token_kind_t end_token;
        switch (type) {
                case '(': end_token = ')';  break;
                case '{': end_token = '}';  break;
@@ -653,21 +633,37 @@ static void type_error_incompatible(const char *msg,
 
 /**
  * Expect the current token is the expected token.
- * If not, generate an error, eat the current statement,
- * and goto the error_label label.
- */
-#define expect(expected, error_label)                     \
-       do {                                                  \
-               if (UNLIKELY(token.kind != (expected))) {         \
-                       parse_error_expected(NULL, (expected), NULL); \
-                       add_anchor_token(expected);                   \
-                       eat_until_anchor();                           \
-                       rem_anchor_token(expected);                   \
-                       if (token.kind != (expected))                 \
-                         goto error_label;                           \
-               }                                                 \
-               next_token();                                     \
-       } while (0)
+ * If not, generate an error and skip until the next anchor.
+ */
+static void expect(token_kind_t const expected)
+{
+       if (UNLIKELY(token.kind != expected)) {
+               parse_error_expected(NULL, expected, NULL);
+               add_anchor_token(expected);
+               eat_until_anchor();
+               rem_anchor_token(expected);
+               if (token.kind != expected)
+                       return;
+       }
+       eat(expected);
+}
+
+static symbol_t *expect_identifier(char const *const context, source_position_t *const pos)
+{
+       if (token.kind != T_IDENTIFIER) {
+               parse_error_expected(context, T_IDENTIFIER, NULL);
+               add_anchor_token(T_IDENTIFIER);
+               eat_until_anchor();
+               rem_anchor_token(T_IDENTIFIER);
+               if (token.kind != T_IDENTIFIER)
+                       return NULL;
+       }
+       symbol_t *const sym = token.base.symbol;
+       if (pos)
+               *pos = *HERE;
+       eat(T_IDENTIFIER);
+       return sym;
+}
 
 /**
  * Push a given scope on the scope stack and make it the
@@ -1108,9 +1104,8 @@ static attribute_argument_t *parse_attribute_arguments(void)
                /* is it an identifier */
                if (token.kind == T_IDENTIFIER
                                && (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) {
-                       symbol_t *symbol   = token.identifier.symbol;
                        argument->kind     = ATTRIBUTE_ARGUMENT_SYMBOL;
-                       argument->v.symbol = symbol;
+                       argument->v.symbol = token.base.symbol;
                        next_token();
                } else {
                        /* must be an expression */
@@ -1124,8 +1119,7 @@ static attribute_argument_t *parse_attribute_arguments(void)
                *anchor = argument;
                anchor  = &argument->next;
        } while (next_if(','));
-       expect(')', end_error);
-end_error:
+       expect(')');
        return first;
 }
 
@@ -1133,59 +1127,15 @@ static attribute_t *parse_attribute_asm(void)
 {
        attribute_t *attribute = allocate_attribute_zero(ATTRIBUTE_GNU_ASM);
        eat(T_asm);
-
-       expect('(', end_error);
+       expect('(');
        attribute->a.arguments = parse_attribute_arguments();
        return attribute;
-
-end_error:
-       return NULL;
-}
-
-static symbol_t *get_symbol_from_token(void)
-{
-       switch(token.kind) {
-       case T_IDENTIFIER:
-               return token.identifier.symbol;
-       case T_auto:
-       case T_char:
-       case T_double:
-       case T_enum:
-       case T_extern:
-       case T_float:
-       case T_int:
-       case T_long:
-       case T_register:
-       case T_short:
-       case T_static:
-       case T_struct:
-       case T_union:
-       case T_unsigned:
-       case T_void:
-       case T_bool:
-       case T__Bool:
-       case T_class:
-       case T_explicit:
-       case T_export:
-       case T_wchar_t:
-       case T_const:
-       case T_signed:
-       case T___real__:
-       case T___imag__:
-       case T_restrict:
-       case T_volatile:
-       case T_inline:
-               /* maybe we need more tokens ... add them on demand */
-               return get_token_kind_symbol(token.kind);
-       default:
-               return NULL;
-       }
 }
 
 static attribute_t *parse_attribute_gnu_single(void)
 {
        /* parse "any-word" */
-       symbol_t *symbol = get_symbol_from_token();
+       symbol_t *const symbol = token.base.symbol;
        if (symbol == NULL) {
                parse_error_expected("while parsing attribute((", T_IDENTIFIER, NULL);
                return NULL;
@@ -1222,21 +1172,23 @@ static attribute_t *parse_attribute_gnu(void)
        attribute_t **anchor = &first;
 
        eat(T___attribute__);
-       expect('(', end_error);
-       expect('(', end_error);
+       expect('(');
+       expect('(');
 
+       add_anchor_token(')');
+       add_anchor_token(',');
        if (token.kind != ')') do {
                attribute_t *attribute = parse_attribute_gnu_single();
-               if (attribute == NULL)
-                       goto end_error;
-
-               *anchor = attribute;
-               anchor  = &attribute->next;
+               if (attribute) {
+                       *anchor = attribute;
+                       anchor  = &attribute->next;
+               }
        } while (next_if(','));
-       expect(')', end_error);
-       expect(')', end_error);
+       rem_anchor_token(',');
+       rem_anchor_token(')');
 
-end_error:
+       expect(')');
+       expect(')');
        return first;
 }
 
@@ -1543,22 +1495,18 @@ static designator_t *parse_designation(void)
                        add_anchor_token(']');
                        designator->array_index = parse_constant_expression();
                        rem_anchor_token(']');
-                       expect(']', end_error);
+                       expect(']');
                        break;
                case '.':
                        designator = allocate_ast_zero(sizeof(designator[0]));
                        designator->source_position = token.base.source_position;
                        next_token();
-                       if (token.kind != T_IDENTIFIER) {
-                               parse_error_expected("while parsing designator",
-                                                    T_IDENTIFIER, NULL);
+                       designator->symbol = expect_identifier("while parsing designator", NULL);
+                       if (!designator->symbol)
                                return NULL;
-                       }
-                       designator->symbol = token.identifier.symbol;
-                       next_token();
                        break;
                default:
-                       expect('=', end_error);
+                       expect('=');
                        return result;
                }
 
@@ -1566,8 +1514,6 @@ static designator_t *parse_designation(void)
                *anchor = designator;
                anchor  = &designator->next;
        }
-end_error:
-       return NULL;
 }
 
 static initializer_t *initializer_from_string(array_type_t *const type,
@@ -2032,7 +1978,7 @@ static initializer_t *parse_sub_initializer(type_path_t *path,
                        /* GNU-style designator ("identifier: value") */
                        designator = allocate_ast_zero(sizeof(designator[0]));
                        designator->source_position = token.base.source_position;
-                       designator->symbol          = token.identifier.symbol;
+                       designator->symbol          = token.base.symbol;
                        eat(T_IDENTIFIER);
                        eat(':');
 
@@ -2061,9 +2007,7 @@ finish_designator:
                        } else {
                                if (type == NULL) {
                                        if (env->entity != NULL) {
-                                               errorf(HERE,
-                                                    "extra brace group at end of initializer for '%Y'",
-                                                    env->entity->base.symbol);
+                                               errorf(HERE, "extra brace group at end of initializer for '%N'", env->entity);
                                        } else {
                                                errorf(HERE, "extra brace group at end of initializer");
                                        }
@@ -2078,13 +2022,12 @@ finish_designator:
                                                            env);
                                rem_anchor_token('}');
 
-                               if (type != NULL) {
-                                       ascend_from_subtype(path);
-                                       expect('}', end_error);
-                               } else {
-                                       expect('}', end_error);
+                               expect('}');
+
+                               if (!type)
                                        goto error_parse_next;
-                               }
+
+                               ascend_from_subtype(path);
                        }
                } else {
                        /* must be an expression */
@@ -2109,7 +2052,7 @@ finish_designator:
 
                                source_position_t const* const pos = &expression->base.source_position;
                                if (env->entity != NULL) {
-                                       warningf(WARN_OTHER, pos, "excess elements in initializer for '%Y'", env->entity->base.symbol);
+                                       warningf(WARN_OTHER, pos, "excess elements in initializer for '%N'", env->entity);
                                } else {
                                        warningf(WARN_OTHER, pos, "excess elements in initializer");
                                }
@@ -2171,7 +2114,9 @@ error_parse_next:
                if (token.kind == '}') {
                        break;
                }
-               expect(',', end_error);
+               add_anchor_token('}');
+               expect(',');
+               rem_anchor_token('}');
                if (token.kind == '}') {
                        break;
                }
@@ -2248,8 +2193,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env)
                max_index = path.max_index;
                DEL_ARR_F(path.path);
 
-               expect('}', end_error);
-end_error:;
+               expect('}');
        } else {
                /* parse_scalar_initializer() also works in this case: we simply
                 * have an expression without {} around it */
@@ -2325,7 +2269,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
        entity_kind_tag_t const kind = is_struct ? ENTITY_STRUCT : ENTITY_UNION;
        if (token.kind == T_IDENTIFIER) {
                /* the compound has a name, check if we have seen it already */
-               symbol = token.identifier.symbol;
+               symbol = token.base.symbol;
                entity = get_tag(symbol, kind);
                next_token();
 
@@ -2352,10 +2296,9 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
        }
 
        if (entity == NULL) {
-               entity = allocate_entity_zero(kind, NAMESPACE_TAG, symbol);
-               entity->compound.alignment   = 1;
-               entity->base.source_position = pos;
-               entity->base.parent_scope    = current_scope;
+               entity = allocate_entity_zero(kind, NAMESPACE_TAG, symbol, &pos);
+               entity->compound.alignment = 1;
+               entity->base.parent_scope  = current_scope;
                if (symbol != NULL) {
                        environment_push(entity);
                }
@@ -2390,20 +2333,14 @@ static void parse_enum_entries(type_t *const enum_type)
        }
 
        add_anchor_token('}');
+       add_anchor_token(',');
        do {
-               if (token.kind != T_IDENTIFIER) {
-                       parse_error_expected("while parsing enum entry", T_IDENTIFIER, NULL);
-                       eat_block();
-                       rem_anchor_token('}');
-                       return;
-               }
-
-               symbol_t *symbol       = token.identifier.symbol;
-               entity_t *const entity
-                       = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, symbol);
+               add_anchor_token('=');
+               source_position_t pos;
+               symbol_t *const symbol = expect_identifier("while parsing enum entry", &pos);
+               entity_t *const entity = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, symbol, &pos);
                entity->enum_value.enum_type = enum_type;
-               entity->base.source_position = token.base.source_position;
-               next_token();
+               rem_anchor_token('=');
 
                if (next_if('=')) {
                        expression_t *value = parse_constant_expression();
@@ -2416,12 +2353,10 @@ static void parse_enum_entries(type_t *const enum_type)
 
                record_entity(entity, false);
        } while (next_if(',') && token.kind != '}');
+       rem_anchor_token(',');
        rem_anchor_token('}');
 
-       expect('}', end_error);
-
-end_error:
-       ;
+       expect('}');
 }
 
 static type_t *parse_enum_specifier(void)
@@ -2433,7 +2368,7 @@ static type_t *parse_enum_specifier(void)
        eat(T_enum);
        switch (token.kind) {
                case T_IDENTIFIER:
-                       symbol = token.identifier.symbol;
+                       symbol = token.base.symbol;
                        entity = get_tag(symbol, ENTITY_ENUM);
                        next_token();
 
@@ -2462,9 +2397,8 @@ static type_t *parse_enum_specifier(void)
        }
 
        if (entity == NULL) {
-               entity = allocate_entity_zero(ENTITY_ENUM, NAMESPACE_TAG, symbol);
-               entity->base.source_position = pos;
-               entity->base.parent_scope    = current_scope;
+               entity = allocate_entity_zero(ENTITY_ENUM, NAMESPACE_TAG, symbol, &pos);
+               entity->base.parent_scope = current_scope;
        }
 
        type_t *const type     = allocate_type_zero(TYPE_ENUM);
@@ -2508,14 +2442,14 @@ static type_t *parse_typeof(void)
 
        type_t *type;
 
-       expect('(', end_error);
+       expect('(');
        add_anchor_token(')');
 
        expression_t *expression  = NULL;
 
        switch (token.kind) {
        case T_IDENTIFIER:
-               if (is_typedef_symbol(token.identifier.symbol)) {
+               if (is_typedef_symbol(token.base.symbol)) {
        DECLARATION_START
                        type = parse_typename();
                } else {
@@ -2527,15 +2461,13 @@ static type_t *parse_typeof(void)
        }
 
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
 
        type_t *typeof_type              = allocate_type_zero(TYPE_TYPEOF);
        typeof_type->typeoft.expression  = expression;
        typeof_type->typeoft.typeof_type = type;
 
        return typeof_type;
-end_error:
-       return NULL;
 }
 
 typedef enum specifiers_t {
@@ -2574,45 +2506,43 @@ static type_t *get_typedef_type(symbol_t *symbol)
 
 static attribute_t *parse_attribute_ms_property(attribute_t *attribute)
 {
-       expect('(', end_error);
+       attribute_property_argument_t *const property = allocate_ast_zero(sizeof(*property));
 
-       attribute_property_argument_t *property
-               = allocate_ast_zero(sizeof(*property));
+       expect('(');
 
+       add_anchor_token(')');
+       add_anchor_token(',');
        do {
-               if (token.kind != T_IDENTIFIER) {
-                       parse_error_expected("while parsing property declspec",
-                                            T_IDENTIFIER, NULL);
-                       goto end_error;
-               }
+               add_anchor_token('=');
+               source_position_t pos;
+               symbol_t *const prop_sym = expect_identifier("while parsing property declspec", &pos);
+               rem_anchor_token('=');
 
-               symbol_t **prop;
-               symbol_t  *symbol = token.identifier.symbol;
-               if (streq(symbol->string, "put")) {
-                       prop = &property->put_symbol;
-               } else if (streq(symbol->string, "get")) {
-                       prop = &property->get_symbol;
-               } else {
-                       errorf(HERE, "expected put or get in property declspec");
-                       prop = NULL;
-               }
-               eat(T_IDENTIFIER);
-               expect('=', end_error);
-               if (token.kind != T_IDENTIFIER) {
-                       parse_error_expected("while parsing property declspec",
-                                            T_IDENTIFIER, NULL);
-                       goto end_error;
+               symbol_t **prop = NULL;
+               if (prop_sym) {
+                       if (streq(prop_sym->string, "put")) {
+                               prop = &property->put_symbol;
+                       } else if (streq(prop_sym->string, "get")) {
+                               prop = &property->get_symbol;
+                       } else {
+                               errorf(&pos, "expected put or get in property declspec, but got '%Y'", prop_sym);
+                       }
                }
+
+               add_anchor_token(T_IDENTIFIER);
+               expect('=');
+               rem_anchor_token(T_IDENTIFIER);
+
+               symbol_t *const sym = expect_identifier("while parsing property declspec", NULL);
                if (prop != NULL)
-                       *prop = token.identifier.symbol;
-               next_token();
+                       *prop = sym ? sym : sym_anonymous;
        } while (next_if(','));
+       rem_anchor_token(',');
+       rem_anchor_token(')');
 
        attribute->a.property = property;
 
-       expect(')', end_error);
-
-end_error:
+       expect(')');
        return attribute;
 }
 
@@ -2622,7 +2552,7 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void)
        if (next_if(T_restrict)) {
                kind = ATTRIBUTE_MS_RESTRICT;
        } else if (token.kind == T_IDENTIFIER) {
-               const char *name = token.identifier.symbol->string;
+               char const *const name = token.base.symbol->string;
                for (attribute_kind_t k = ATTRIBUTE_MS_FIRST; k <= ATTRIBUTE_MS_LAST;
                     ++k) {
                        const char *attribute_name = get_attribute_name(k);
@@ -2658,7 +2588,7 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first)
 {
        eat(T__declspec);
 
-       expect('(', end_error);
+       expect('(');
        if (token.kind != ')') {
                add_anchor_token(')');
 
@@ -2678,15 +2608,13 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first)
 
                rem_anchor_token(')');
        }
-       expect(')', end_error);
-end_error:
+       expect(')');
        return first;
 }
 
 static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
 {
-       entity_t *const entity = allocate_entity_zero(kind, NAMESPACE_NORMAL, symbol);
-       entity->base.source_position = *HERE;
+       entity_t *const entity = allocate_entity_zero(kind, NAMESPACE_NORMAL, symbol, HERE);
        if (is_declaration(entity)) {
                entity->declaration.type     = type_error_type;
                entity->declaration.implicit = true;
@@ -2884,7 +2812,7 @@ wrong_thread_storage_class:
                                }
                        }
 
-                       type_t *const typedef_type = get_typedef_type(token.identifier.symbol);
+                       type_t *const typedef_type = get_typedef_type(token.base.symbol);
                        if (typedef_type == NULL) {
                                /* Be somewhat resilient to typos like 'vodi f()' at the beginning of a
                                 * declaration, so it doesn't generate 'implicit int' followed by more
@@ -2897,9 +2825,7 @@ wrong_thread_storage_class:
                                        case '*': {
                                                errorf(HERE, "%K does not name a type", &token);
 
-                                               symbol_t *symbol = token.identifier.symbol;
-                                               entity_t *entity
-                                                       = create_error_entity(symbol, ENTITY_TYPEDEF);
+                                               entity_t *const entity = create_error_entity(token.base.symbol, ENTITY_TYPEDEF);
 
                                                type = allocate_type_zero(TYPE_TYPEDEF);
                                                type->typedeft.typedefe = &entity->typedefe;
@@ -3150,8 +3076,7 @@ static void parse_identifier_list(scope_t *scope)
 {
        assert(token.kind == T_IDENTIFIER);
        do {
-               entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.identifier.symbol);
-               entity->base.source_position = token.base.source_position;
+               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();
 
@@ -3191,8 +3116,7 @@ static bool has_parameters(void)
        if (look_ahead(1)->kind != ')')
                return true;
        if (token.kind == T_IDENTIFIER) {
-               entity_t const *const entity
-                       = get_entity(token.identifier.symbol, NAMESPACE_NORMAL);
+               entity_t const *const entity = get_entity(token.base.symbol, NAMESPACE_NORMAL);
                if (entity == NULL)
                        return true;
                if (entity->kind != ENTITY_TYPEDEF)
@@ -3223,24 +3147,19 @@ static void parse_parameters(function_type_t *type, scope_t *scope)
 {
        eat('(');
        add_anchor_token(')');
-       int saved_comma_state = save_and_reset_anchor_state(',');
-
-       if (token.kind == T_IDENTIFIER
-           && !is_typedef_symbol(token.identifier.symbol)) {
-               token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind;
-               if (la1_type == ',' || la1_type == ')') {
-                       type->kr_style_parameters = true;
-                       parse_identifier_list(scope);
-                       goto parameters_finished;
-               }
-       }
 
-       if (token.kind == ')') {
+       if (token.kind == T_IDENTIFIER            &&
+           !is_typedef_symbol(token.base.symbol) &&
+           (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) {
+               type->kr_style_parameters = true;
+               parse_identifier_list(scope);
+       } else if (token.kind == ')') {
                /* ISO/IEC 14882:1998(E) ยงC.1.6:1 */
                if (!(c_mode & _CXX))
                        type->unspecified_parameters = true;
        } else if (has_parameters()) {
                function_parameter_t **anchor = &type->parameters;
+               add_anchor_token(',');
                do {
                        switch (token.kind) {
                        case T_DOTDOTDOT:
@@ -3277,14 +3196,12 @@ static void parse_parameters(function_type_t *type, scope_t *scope)
                                goto parameters_finished;
                        }
                } while (next_if(','));
+parameters_finished:
+               rem_anchor_token(',');
        }
 
-parameters_finished:
        rem_anchor_token(')');
-       expect(')', end_error);
-
-end_error:
-       restore_anchor_state(',', saved_comma_state);
+       expect(')');
 }
 
 typedef enum construct_type_kind_t {
@@ -3409,9 +3326,7 @@ static construct_type_t *parse_array_declarator(void)
                errorf(&array->base.pos, "static array parameters require a size");
 
        rem_anchor_token(']');
-       expect(']', end_error);
-
-end_error:
+       expect(']');
        return cons;
 }
 
@@ -3489,7 +3404,7 @@ ptr_operator_end: ;
                if (env->must_be_abstract) {
                        errorf(HERE, "no identifier expected in typename");
                } else {
-                       env->symbol          = token.identifier.symbol;
+                       env->symbol          = token.base.symbol;
                        env->source_position = token.base.source_position;
                }
                next_token();
@@ -3500,7 +3415,7 @@ ptr_operator_end: ;
                token_t const *const la1 = look_ahead(1);
                switch (la1->kind) {
                        case T_IDENTIFIER:
-                               if (is_typedef_symbol(la1->identifier.symbol)) {
+                               if (is_typedef_symbol(la1->base.symbol)) {
                        case ')':
                                        /* ยง6.7.6:2 footnote 126:  Empty parentheses in a type name are
                                         * interpreted as ``function with no parameter specification'', rather
@@ -3525,7 +3440,7 @@ ptr_operator_end: ;
                                                env->must_be_abstract = true;
                                        }
                                        rem_anchor_token(')');
-                                       expect(')', end_error);
+                                       expect(')');
                                }
                                break;
                }
@@ -3574,8 +3489,6 @@ declarator_finished:
        *anchor = inner_types;
 
        return first;
-end_error:
-       return NULL;
 }
 
 static type_t *construct_declarator_type(construct_type_t *construct_list,
@@ -3749,9 +3662,8 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
 
        entity_t *entity;
        if (specifiers->storage_class == STORAGE_CLASS_TYPEDEF) {
-               entity = allocate_entity_zero(ENTITY_TYPEDEF, NAMESPACE_NORMAL, env.symbol);
-               entity->base.source_position = env.source_position;
-               entity->typedefe.type        = orig_type;
+               entity = allocate_entity_zero(ENTITY_TYPEDEF, NAMESPACE_NORMAL, env.symbol, &env.source_position);
+               entity->typedefe.type = orig_type;
 
                if (anonymous_entity != NULL) {
                        if (is_type_compound(type)) {
@@ -3769,27 +3681,25 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                }
        } else {
                /* create a declaration type entity */
+               source_position_t const *const pos = env.symbol ? &env.source_position : &specifiers->source_position;
                if (flags & DECL_CREATE_COMPOUND_MEMBER) {
-                       entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, env.symbol);
+                       entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, env.symbol, pos);
 
                        if (env.symbol != NULL) {
                                if (specifiers->is_inline && is_type_valid(type)) {
-                                       errorf(&env.source_position,
-                                                       "compound member '%Y' declared 'inline'", env.symbol);
+                                       errorf(&env.source_position, "'%N' declared 'inline'", entity);
                                }
 
                                if (specifiers->thread_local ||
                                                specifiers->storage_class != STORAGE_CLASS_NONE) {
-                                       errorf(&env.source_position,
-                                                       "compound member '%Y' must have no storage class",
-                                                       env.symbol);
+                                       errorf(&env.source_position, "'%N' must have no storage class", entity);
                                }
                        }
                } else if (flags & DECL_IS_PARAMETER) {
-                       entity    = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, env.symbol);
+                       entity    = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, env.symbol, pos);
                        orig_type = semantic_parameter(&env.source_position, orig_type, specifiers, entity);
                } else if (is_type_function(type)) {
-                       entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, env.symbol);
+                       entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, env.symbol, pos);
                        entity->function.is_inline      = specifiers->is_inline;
                        entity->function.elf_visibility = default_visibility;
                        entity->function.parameters     = env.parameters;
@@ -3807,7 +3717,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                                }
                        }
                } else {
-                       entity = allocate_entity_zero(ENTITY_VARIABLE, NAMESPACE_NORMAL, env.symbol);
+                       entity = allocate_entity_zero(ENTITY_VARIABLE, NAMESPACE_NORMAL, env.symbol, pos);
                        entity->variable.elf_visibility = default_visibility;
                        entity->variable.thread_local   = specifiers->thread_local;
 
@@ -3830,12 +3740,11 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                                        }
                                }
                                if (invalid_storage_class) {
-                                       errorf(&env.source_position, "invalid storage class for variable '%N'", entity);
+                                       errorf(&env.source_position, "invalid storage class for '%N'", entity);
                                }
                        }
                }
 
-               entity->base.source_position   = env.symbol != NULL ? env.source_position : specifiers->source_position;
                entity->declaration.type       = orig_type;
                entity->declaration.alignment  = get_type_alignment(orig_type);
                entity->declaration.modifiers  = env.modifiers;
@@ -3942,14 +3851,6 @@ warn_arg_count:
        }
 }
 
-/**
- * Check if a symbol is the equal to "main".
- */
-static bool is_sym_main(const symbol_t *const sym)
-{
-       return streq(sym->string, "main");
-}
-
 static void error_redefined_as_different_kind(const source_position_t *pos,
                const entity_t *old, entity_kind_t new_kind)
 {
@@ -4009,6 +3910,8 @@ static void merge_in_attributes(declaration_t *decl, attribute_t *attributes)
        }
 }
 
+static bool is_main(entity_t*);
+
 /**
  * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings
  * for various problems that occur for multiple definitions
@@ -4023,6 +3926,10 @@ entity_t *record_entity(entity_t *entity, const bool is_definition)
        if (symbol == NULL)
                return entity;
 
+       assert(!entity->base.parent_scope);
+       assert(current_scope);
+       entity->base.parent_scope = current_scope;
+
        entity_t *const previous_entity = get_entity(symbol, namespc);
        /* pushing the same entity twice will break the stack structure */
        assert(previous_entity != entity);
@@ -4038,7 +3945,7 @@ entity_t *record_entity(entity_t *entity, const bool is_definition)
                        warningf(WARN_STRICT_PROTOTYPES, pos, "function declaration '%#N' is not a prototype", entity);
                }
 
-               if (current_scope == file_scope && is_sym_main(symbol)) {
+               if (is_main(entity)) {
                        check_main(entity);
                }
        }
@@ -4142,7 +4049,7 @@ entity_t *record_entity(entity_t *entity, const bool is_definition)
 
                                                case STORAGE_CLASS_EXTERN:
                                                        if (is_definition) {
-                                                               if (prev_type->function.unspecified_parameters && !is_sym_main(symbol)) {
+                                                               if (prev_type->function.unspecified_parameters && !is_main(entity)) {
                                                                        warningf(WARN_MISSING_PROTOTYPES, pos, "no previous prototype for '%#N'", entity);
                                                                }
                                                        } else if (new_storage_class == STORAGE_CLASS_NONE) {
@@ -4169,12 +4076,12 @@ warn_redundant_declaration: ;
                                        } else if (!is_definition        &&
                                                        is_type_valid(prev_type) &&
                                                        !pos->is_system_header) {
-                                               warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%Y' (declared %P)", symbol, ppos);
+                                               warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%N' (declared %P)", entity, ppos);
                                        }
                                } else if (current_function == NULL) {
                                        if (old_storage_class != STORAGE_CLASS_STATIC &&
                                                        new_storage_class == STORAGE_CLASS_STATIC) {
-                                               errorf(pos, "static declaration of '%Y' follows non-static declaration (declared %P)", symbol, ppos);
+                                               errorf(pos, "static declaration of '%N' follows non-static declaration (declared %P)", entity, ppos);
                                        } else if (old_storage_class == STORAGE_CLASS_EXTERN) {
                                                prev_decl->storage_class          = STORAGE_CLASS_NONE;
                                                prev_decl->declared_storage_class = STORAGE_CLASS_NONE;
@@ -4187,9 +4094,9 @@ warn_redundant_declaration: ;
                                } else if (is_type_valid(prev_type)) {
                                        if (old_storage_class == new_storage_class) {
 error_redeclaration:
-                                               errorf(pos, "redeclaration of '%Y' (declared %P)", symbol, ppos);
+                                               errorf(pos, "redeclaration of '%N' (declared %P)", entity, ppos);
                                        } else {
-                                               errorf(pos, "redeclaration of '%Y' with different linkage (declared %P)", symbol, ppos);
+                                               errorf(pos, "redeclaration of '%N' with different linkage (declared %P)", entity, ppos);
                                        }
                                }
                        }
@@ -4212,7 +4119,7 @@ error_redeclaration:
        if (entity->kind == ENTITY_FUNCTION) {
                if (is_definition &&
                                entity->declaration.storage_class != STORAGE_CLASS_STATIC &&
-                               !is_sym_main(symbol)) {
+                               !is_main(entity)) {
                        if (is_warn_on(WARN_MISSING_PROTOTYPES)) {
                                warningf(WARN_MISSING_PROTOTYPES, pos, "no previous prototype for '%#N'", entity);
                        } else {
@@ -4229,10 +4136,6 @@ warn_missing_declaration:
        }
 
 finish:
-       assert(entity->base.parent_scope == NULL);
-       assert(current_scope != NULL);
-
-       entity->base.parent_scope = current_scope;
        environment_push(entity);
        append_entity(current_scope, entity);
 
@@ -4242,8 +4145,7 @@ finish:
 static void parser_error_multiple_definition(entity_t *entity,
                const source_position_t *source_position)
 {
-       errorf(source_position, "multiple definition of '%Y' (declared %P)",
-              entity->base.symbol, &entity->base.source_position);
+       errorf(source_position, "redefinition of '%N' (declared %P)", entity, &entity->base.source_position);
 }
 
 static bool is_declaration_specifier(const token_t *token)
@@ -4252,7 +4154,7 @@ static bool is_declaration_specifier(const token_t *token)
                DECLARATION_START
                        return true;
                case T_IDENTIFIER:
-                       return is_typedef_symbol(token->identifier.symbol);
+                       return is_typedef_symbol(token->base.symbol);
 
                default:
                        return false;
@@ -4400,9 +4302,8 @@ static void parse_declaration_rest(entity_t *ndeclaration,
        }
        rem_anchor_token(',');
        rem_anchor_token(';');
-       expect(';', end_error);
+       expect(';');
 
-end_error:
        anonymous_entity = NULL;
 }
 
@@ -4679,11 +4580,7 @@ static void check_declarations(void)
 {
        if (is_warn_on(WARN_UNUSED_PARAMETER)) {
                const scope_t *scope = &current_function->parameters;
-
-               /* do not issue unused warnings for main */
-               if (!is_sym_main(current_function->base.base.symbol)) {
-                       warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL);
-               }
+               warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL);
        }
        if (is_warn_on(WARN_UNUSED_VARIABLE)) {
                walk_statements(current_function->statement, check_unused_variables,
@@ -5100,7 +4997,7 @@ found_break_parent:
                        type_t *const ret  = skip_typeref(type->function.return_type);
                        if (!is_type_void(ret) &&
                            is_type_valid(ret) &&
-                           !is_sym_main(current_function->base.base.symbol)) {
+                           !is_main(current_entity)) {
                                source_position_t const *const pos = &stmt->base.source_position;
                                warningf(WARN_RETURN_TYPE, pos, "control reaches end of non-void function");
                        }
@@ -5316,6 +5213,8 @@ static bool is_main(entity_t *entity)
        return true;
 }
 
+static void prepare_main_collect2(entity_t*);
+
 static void parse_external_declaration(void)
 {
        /* function-definitions and declarations both start with declaration
@@ -5409,8 +5308,6 @@ static void parse_external_declaration(void)
        if (ndeclaration != entity) {
                function->parameters = ndeclaration->function.parameters;
        }
-       assert(is_declaration(entity));
-       type = skip_typeref(entity->declaration.type);
 
        PUSH_SCOPE(&function->parameters);
 
@@ -5436,9 +5333,8 @@ static void parse_external_declaration(void)
                /* parse function body */
                int         label_stack_top      = label_top();
                function_t *old_current_function = current_function;
-               entity_t   *old_current_entity   = current_entity;
                current_function                 = function;
-               current_entity                   = entity;
+               PUSH_CURRENT_ENTITY(entity);
                PUSH_PARENT(NULL);
 
                goto_first   = NULL;
@@ -5465,13 +5361,23 @@ static void parse_external_declaration(void)
                        }
                }
 
-               if (is_main(entity) && enable_main_collect2_hack)
-                       prepare_main_collect2(entity);
+               if (is_main(entity)) {
+                       /* Force main to C linkage. */
+                       type_t *const type = entity->declaration.type;
+                       assert(is_type_function(type));
+                       if (type->function.linkage != LINKAGE_C) {
+                               type_t *new_type           = duplicate_type(type);
+                               new_type->function.linkage = LINKAGE_C;
+                               entity->declaration.type   = identify_new_type(new_type);
+                       }
+
+                       if (enable_main_collect2_hack)
+                               prepare_main_collect2(entity);
+               }
 
+               POP_CURRENT_ENTITY();
                POP_PARENT();
                assert(current_function == function);
-               assert(current_entity   == entity);
-               current_entity   = old_current_entity;
                current_function = old_current_function;
                label_pop_to(label_stack_top);
        }
@@ -5642,15 +5548,15 @@ static void parse_bitfield_member(entity_t *entity)
 static void parse_compound_declarators(compound_t *compound,
                const declaration_specifiers_t *specifiers)
 {
+       add_anchor_token(';');
+       add_anchor_token(',');
        do {
                entity_t *entity;
 
                if (token.kind == ':') {
                        /* anonymous bitfield */
                        type_t *type = specifiers->type;
-                       entity_t *entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER,
-                                                               NAMESPACE_NORMAL, NULL);
-                       entity->base.source_position               = *HERE;
+                       entity_t *const entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, NULL, HERE);
                        entity->declaration.declared_storage_class = STORAGE_CLASS_NONE;
                        entity->declaration.storage_class          = STORAGE_CLASS_NONE;
                        entity->declaration.type                   = type;
@@ -5683,7 +5589,7 @@ static void parse_compound_declarators(compound_t *compound,
                                        entity_t *prev = find_compound_entry(compound, symbol);
                                        if (prev != NULL) {
                                                source_position_t const *const ppos = &prev->base.source_position;
-                                               errorf(pos, "multiple declarations of symbol '%Y' (declared %P)", symbol, ppos);
+                                               errorf(pos, "multiple declarations of '%N' (declared %P)", entity, ppos);
                                        }
                                }
 
@@ -5713,9 +5619,10 @@ static void parse_compound_declarators(compound_t *compound,
                        }
                }
        } while (next_if(','));
-       expect(';', end_error);
+       rem_anchor_token(',');
+       rem_anchor_token(';');
+       expect(';');
 
-end_error:
        anonymous_entity = NULL;
 }
 
@@ -5739,8 +5646,7 @@ static void parse_compound_type_entries(compound_t *compound)
 
                        default:
                                rem_anchor_token('}');
-                               expect('}', end_error);
-end_error:
+                               expect('}');
                                /* ยง6.7.2.1:7 */
                                compound->complete = true;
                                return;
@@ -5780,20 +5686,6 @@ struct expression_parser_function_t {
 
 static expression_parser_function_t expression_parsers[T_LAST_TOKEN];
 
-/**
- * Prints an error message if an expression was expected but not read
- */
-static expression_t *expected_expression_error(void)
-{
-       /* skip the error message if the error token was read */
-       if (token.kind != T_ERROR) {
-               errorf(HERE, "expected expression, got token %K", &token);
-       }
-       next_token();
-
-       return create_error_expression();
-}
-
 static type_t *get_string_type(void)
 {
        return is_warn_on(WARN_WRITE_STRINGS) ? type_const_char_ptr : type_char_ptr;
@@ -5934,24 +5826,12 @@ static expression_t *parse_number_literal(void)
                check_integer_suffix();
                type = type_int;
                break;
-       case T_INTEGER_OCTAL:
-               kind = EXPR_LITERAL_INTEGER_OCTAL;
-               check_integer_suffix();
-               type = type_int;
-               break;
-       case T_INTEGER_HEXADECIMAL:
-               kind = EXPR_LITERAL_INTEGER_HEXADECIMAL;
-               check_integer_suffix();
-               type = type_int;
-               break;
+
        case T_FLOATINGPOINT:
                kind = EXPR_LITERAL_FLOATINGPOINT;
                type = check_floatingpoint_suffix();
                break;
-       case T_FLOATINGPOINT_HEXADECIMAL:
-               kind = EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL;
-               type = check_floatingpoint_suffix();
-               break;
+
        default:
                panic("unexpected token type in parse_number_literal");
        }
@@ -6011,8 +5891,7 @@ static expression_t *parse_wide_character_constant(void)
        return literal;
 }
 
-static entity_t *create_implicit_function(symbol_t *symbol,
-               const source_position_t *source_position)
+static entity_t *create_implicit_function(symbol_t *symbol, source_position_t const *const pos)
 {
        type_t *ntype                          = allocate_type_zero(TYPE_FUNCTION);
        ntype->function.return_type            = type_int;
@@ -6020,12 +5899,11 @@ static entity_t *create_implicit_function(symbol_t *symbol,
        ntype->function.linkage                = LINKAGE_C;
        type_t *type                           = identify_new_type(ntype);
 
-       entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
+       entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol, pos);
        entity->declaration.storage_class          = STORAGE_CLASS_EXTERN;
        entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
        entity->declaration.type                   = type;
        entity->declaration.implicit               = true;
-       entity->base.source_position               = *source_position;
 
        if (current_scope != NULL)
                record_entity(entity, false);
@@ -6151,13 +6029,9 @@ static entity_t *parse_qualified_identifier(void)
 
        entity_t *entity;
        while (true) {
-               if (token.kind != T_IDENTIFIER) {
-                       parse_error_expected("while parsing identifier", T_IDENTIFIER, NULL);
+               symbol = expect_identifier("while parsing identifier", &pos);
+               if (!symbol)
                        return create_error_entity(sym_anonymous, ENTITY_VARIABLE);
-               }
-               symbol = token.identifier.symbol;
-               pos    = *HERE;
-               next_token();
 
                /* lookup entity */
                entity = lookup_entity(lookup_scope, symbol, NAMESPACE_NORMAL);
@@ -6188,9 +6062,8 @@ static entity_t *parse_qualified_identifier(void)
        if (entity == NULL) {
                if (!strict_mode && token.kind == '(') {
                        /* an implicitly declared function */
-                       warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos,
-                                "implicit declaration of function '%Y'", symbol);
                        entity = create_implicit_function(symbol, &pos);
+                       warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, "implicit declaration of '%N'", entity);
                } else {
                        errorf(&pos, "unknown identifier '%Y' found.", symbol);
                        entity = create_error_entity(symbol, ENTITY_VARIABLE);
@@ -6326,7 +6199,7 @@ static expression_t *parse_cast(void)
        type_t *type = parse_typename();
 
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
 
        if (token.kind == '{') {
                return parse_compound_literal(&pos, type);
@@ -6344,8 +6217,6 @@ static expression_t *parse_cast(void)
        }
 
        return cast;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -6379,9 +6250,7 @@ static expression_t *parse_statement_expression(void)
        expression->base.type = type;
 
        rem_anchor_token(')');
-       expect(')', end_error);
-
-end_error:
+       expect(')');
        return expression;
 }
 
@@ -6397,7 +6266,7 @@ static expression_t *parse_parenthesized_expression(void)
                return parse_statement_expression();
 
        case T_IDENTIFIER:
-               if (is_typedef_symbol(la1->identifier.symbol)) {
+               if (is_typedef_symbol(la1->base.symbol)) {
        DECLARATION_START
                        return parse_cast();
                }
@@ -6408,9 +6277,8 @@ static expression_t *parse_parenthesized_expression(void)
        expression_t *result = parse_expression();
        result->base.parenthesized = true;
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
 
-end_error:
        return result;
 }
 
@@ -6478,29 +6346,18 @@ static expression_t *parse_funcdname_keyword(void)
 
 static designator_t *parse_designator(void)
 {
-       designator_t *result    = allocate_ast_zero(sizeof(result[0]));
-       result->source_position = *HERE;
-
-       if (token.kind != T_IDENTIFIER) {
-               parse_error_expected("while parsing member designator",
-                                    T_IDENTIFIER, NULL);
+       designator_t *const result = allocate_ast_zero(sizeof(result[0]));
+       result->symbol = expect_identifier("while parsing member designator", &result->source_position);
+       if (!result->symbol)
                return NULL;
-       }
-       result->symbol = token.identifier.symbol;
-       next_token();
 
        designator_t *last_designator = result;
        while (true) {
                if (next_if('.')) {
-                       if (token.kind != T_IDENTIFIER) {
-                               parse_error_expected("while parsing member designator",
-                                                    T_IDENTIFIER, NULL);
+                       designator_t *const designator = allocate_ast_zero(sizeof(result[0]));
+                       designator->symbol = expect_identifier("while parsing member designator", &designator->source_position);
+                       if (!designator->symbol)
                                return NULL;
-                       }
-                       designator_t *designator    = allocate_ast_zero(sizeof(result[0]));
-                       designator->source_position = *HERE;
-                       designator->symbol          = token.identifier.symbol;
-                       next_token();
 
                        last_designator->next = designator;
                        last_designator       = designator;
@@ -6512,7 +6369,7 @@ static designator_t *parse_designator(void)
                        designator->source_position = *HERE;
                        designator->array_index     = parse_expression();
                        rem_anchor_token(']');
-                       expect(']', end_error);
+                       expect(']');
                        if (designator->array_index == NULL) {
                                return NULL;
                        }
@@ -6525,8 +6382,6 @@ static designator_t *parse_designator(void)
        }
 
        return result;
-end_error:
-       return NULL;
 }
 
 /**
@@ -6539,15 +6394,15 @@ static expression_t *parse_offsetof(void)
 
        eat(T___builtin_offsetof);
 
-       expect('(', end_error);
+       expect('(');
+       add_anchor_token(')');
        add_anchor_token(',');
        type_t *type = parse_typename();
        rem_anchor_token(',');
-       expect(',', end_error);
-       add_anchor_token(')');
+       expect(',');
        designator_t *designator = parse_designator();
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
 
        expression->offsetofe.type       = type;
        expression->offsetofe.designator = designator;
@@ -6566,8 +6421,6 @@ static expression_t *parse_offsetof(void)
        DEL_ARR_F(path.path);
 
        return expression;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -6579,11 +6432,12 @@ static expression_t *parse_va_start(void)
 
        eat(T___builtin_va_start);
 
-       expect('(', end_error);
+       expect('(');
+       add_anchor_token(')');
        add_anchor_token(',');
        expression->va_starte.ap = parse_assignment_expression();
        rem_anchor_token(',');
-       expect(',', end_error);
+       expect(',');
        expression_t *const expr = parse_assignment_expression();
        if (expr->kind == EXPR_REFERENCE) {
                entity_t *const entity = expr->reference.entity;
@@ -6598,12 +6452,12 @@ static expression_t *parse_va_start(void)
                } else {
                        expression->va_starte.parameter = &entity->variable;
                }
-               expect(')', end_error);
-               return expression;
+       } else {
+               expression = create_error_expression();
        }
-       expect(')', end_error);
-end_error:
-       return create_error_expression();
+       rem_anchor_token(')');
+       expect(')');
+       return expression;
 }
 
 /**
@@ -6615,19 +6469,21 @@ static expression_t *parse_va_arg(void)
 
        eat(T___builtin_va_arg);
 
-       expect('(', end_error);
+       expect('(');
+       add_anchor_token(')');
+       add_anchor_token(',');
        call_argument_t ap;
        ap.expression = parse_assignment_expression();
        expression->va_arge.ap = ap.expression;
        check_call_argument(type_valist, &ap, 1);
 
-       expect(',', end_error);
+       rem_anchor_token(',');
+       expect(',');
        expression->base.type = parse_typename();
-       expect(')', end_error);
+       rem_anchor_token(')');
+       expect(')');
 
        return expression;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -6639,24 +6495,26 @@ static expression_t *parse_va_copy(void)
 
        eat(T___builtin_va_copy);
 
-       expect('(', end_error);
+       expect('(');
+       add_anchor_token(')');
+       add_anchor_token(',');
        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",
                            &dst->base.source_position);
        expression->va_copye.dst = dst;
 
-       expect(',', end_error);
+       rem_anchor_token(',');
+       expect(',');
 
        call_argument_t src;
        src.expression = parse_assignment_expression();
        check_call_argument(type_valist, &src, 2);
        expression->va_copye.src = src.expression;
-       expect(')', end_error);
+       rem_anchor_token(')');
+       expect(')');
 
        return expression;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -6668,16 +6526,14 @@ static expression_t *parse_builtin_constant(void)
 
        eat(T___builtin_constant_p);
 
-       expect('(', end_error);
+       expect('(');
        add_anchor_token(')');
        expression->builtin_constant.value = parse_assignment_expression();
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
        expression->base.type = type_int;
 
        return expression;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -6689,20 +6545,18 @@ static expression_t *parse_builtin_types_compatible(void)
 
        eat(T___builtin_types_compatible_p);
 
-       expect('(', end_error);
+       expect('(');
        add_anchor_token(')');
        add_anchor_token(',');
        expression->builtin_types_compatible.left = parse_typename();
        rem_anchor_token(',');
-       expect(',', end_error);
+       expect(',');
        expression->builtin_types_compatible.right = parse_typename();
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
        expression->base.type = type_int;
 
        return expression;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -6737,11 +6591,15 @@ static expression_t *parse_compare_builtin(void)
        expression->base.source_position = *HERE;
        next_token();
 
-       expect('(', end_error);
+       expect('(');
+       add_anchor_token(')');
+       add_anchor_token(',');
        expression->binary.left = parse_assignment_expression();
-       expect(',', end_error);
+       rem_anchor_token(',');
+       expect(',');
        expression->binary.right = parse_assignment_expression();
-       expect(')', end_error);
+       rem_anchor_token(')');
+       expect(')');
 
        type_t *const orig_type_left  = expression->binary.left->base.type;
        type_t *const orig_type_right = expression->binary.right->base.type;
@@ -6758,8 +6616,6 @@ static expression_t *parse_compare_builtin(void)
        }
 
        return expression;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -6771,16 +6627,14 @@ static expression_t *parse_assume(void)
 
        eat(T__assume);
 
-       expect('(', end_error);
+       expect('(');
        add_anchor_token(')');
        expression->unary.value = parse_assignment_expression();
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
 
        expression->base.type = type_void;
        return expression;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -6791,7 +6645,7 @@ static label_t *get_label(void)
        assert(token.kind == T_IDENTIFIER);
        assert(current_function != NULL);
 
-       entity_t *label = get_entity(token.identifier.symbol, NAMESPACE_LABEL);
+       entity_t *label = get_entity(token.base.symbol, 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) {
@@ -6800,7 +6654,8 @@ 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. */
-               label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.identifier.symbol);
+               source_position_t const nowhere = { NULL, 0, 0, false };
+               label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.base.symbol, &nowhere);
                label_push(label);
        }
 
@@ -6859,9 +6714,8 @@ static expression_t *parse_noop_expression(void)
                rem_anchor_token(',');
                rem_anchor_token(')');
        }
-       expect(')', end_error);
+       expect(')');
 
-end_error:
        return literal;
 }
 
@@ -6874,10 +6728,7 @@ static expression_t *parse_primary_expression(void)
        case T_false:                        return parse_boolean_literal(false);
        case T_true:                         return parse_boolean_literal(true);
        case T_INTEGER:
-       case T_INTEGER_OCTAL:
-       case T_INTEGER_HEXADECIMAL:
-       case T_FLOATINGPOINT:
-       case T_FLOATINGPOINT_HEXADECIMAL:    return parse_number_literal();
+       case T_FLOATINGPOINT:                return parse_number_literal();
        case T_CHARACTER_CONSTANT:           return parse_character_constant();
        case T_WIDE_CHARACTER_CONSTANT:      return parse_wide_character_constant();
        case T_STRING_LITERAL:
@@ -6912,7 +6763,7 @@ static expression_t *parse_primary_expression(void)
        case T_COLONCOLON:
                return parse_reference();
        case T_IDENTIFIER:
-               if (!is_typedef_symbol(token.identifier.symbol)) {
+               if (!is_typedef_symbol(token.base.symbol)) {
                        return parse_reference();
                }
                /* FALLTHROUGH */
@@ -6985,8 +6836,7 @@ check_idx:
        arr->base.type = res_type;
 
        rem_anchor_token(']');
-       expect(']', end_error);
-end_error:
+       expect(']');
        return expr;
 }
 
@@ -7011,7 +6861,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind)
                add_anchor_token(')');
                orig_type = parse_typename();
                rem_anchor_token(')');
-               expect(')', end_error);
+               expect(')');
 
                if (token.kind == '{') {
                        /* It was not sizeof(type) after all.  It is sizeof of an expression
@@ -7059,7 +6909,6 @@ typeprop_expression:
                                what, wrong_type, orig_type);
        }
 
-end_error:
        return tp_expression;
 }
 
@@ -7080,12 +6929,9 @@ static expression_t *parse_select_expression(expression_t *addr)
        source_position_t const pos = *HERE;
        next_token();
 
-       if (token.kind != T_IDENTIFIER) {
-               parse_error_expected("while parsing select", T_IDENTIFIER, NULL);
+       symbol_t *const symbol = expect_identifier("while parsing select", NULL);
+       if (!symbol)
                return create_error_expression();
-       }
-       symbol_t *symbol = token.identifier.symbol;
-       next_token();
 
        type_t *const orig_type = addr->base.type;
        type_t *const type      = skip_typeref(orig_type);
@@ -7305,7 +7151,7 @@ static expression_t *parse_call_expression(expression_t *expression)
        }
        rem_anchor_token(',');
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
 
        if (function_type == NULL)
                return result;
@@ -7354,7 +7200,6 @@ static expression_t *parse_call_expression(expression_t *expression)
                        handle_builtin_argument_restrictions(call);
        }
 
-end_error:
        return result;
 }
 
@@ -7456,8 +7301,7 @@ static expression_t *parse_conditional_expression(expression_t *expression)
                true_expression = parse_expression();
        }
        rem_anchor_token(':');
-       expect(':', end_error);
-end_error:;
+       expect(':');
        expression_t *false_expression =
                parse_subexpression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL);
 
@@ -7565,16 +7409,14 @@ static expression_t *parse_builtin_classify_type(void)
 
        eat(T___builtin_classify_type);
 
-       expect('(', end_error);
+       expect('(');
        add_anchor_token(')');
        expression_t *expression = parse_expression();
        rem_anchor_token(')');
-       expect(')', end_error);
+       expect(')');
        result->classify_type.type_expression = expression;
 
        return result;
-end_error:
-       return create_error_expression();
 }
 
 /**
@@ -7590,8 +7432,7 @@ static expression_t *parse_delete(void)
 
        if (next_if('[')) {
                result->kind = EXPR_UNARY_DELETE_ARRAY;
-               expect(']', end_error);
-end_error:;
+               expect(']');
        }
 
        expression_t *const value = parse_subexpression(PREC_CAST);
@@ -8535,10 +8376,7 @@ static bool expression_has_effect(const expression_t *const expr)
                case EXPR_LITERAL_CHARACTER:
                case EXPR_LITERAL_WIDE_CHARACTER:
                case EXPR_LITERAL_INTEGER:
-               case EXPR_LITERAL_INTEGER_OCTAL:
-               case EXPR_LITERAL_INTEGER_HEXADECIMAL:
                case EXPR_LITERAL_FLOATINGPOINT:
-               case EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL: return false;
                case EXPR_STRING_LITERAL:             return false;
                case EXPR_WIDE_STRING_LITERAL:        return false;
 
@@ -8713,10 +8551,6 @@ CREATE_BINEXPR_PARSER(',',                    EXPR_BINARY_COMMA,              PR
 
 static expression_t *parse_subexpression(precedence_t precedence)
 {
-       if (token.kind < 0) {
-               return expected_expression_error();
-       }
-
        expression_parser_function_t *parser
                = &expression_parsers[token.kind];
        expression_t                 *left;
@@ -8729,10 +8563,6 @@ static expression_t *parse_subexpression(precedence_t precedence)
        assert(left != NULL);
 
        while (true) {
-               if (token.kind < 0) {
-                       return expected_expression_error();
-               }
-
                parser = &expression_parsers[token.kind];
                if (parser->infix_parser == NULL)
                        break;
@@ -8867,18 +8697,16 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
                asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0]));
 
                if (next_if('[')) {
-                       if (token.kind != T_IDENTIFIER) {
-                               parse_error_expected("while parsing asm argument",
-                                                    T_IDENTIFIER, NULL);
+                       add_anchor_token(']');
+                       argument->symbol = expect_identifier("while parsing asm argument", NULL);
+                       rem_anchor_token(']');
+                       expect(']');
+                       if (!argument->symbol)
                                return NULL;
-                       }
-                       argument->symbol = token.identifier.symbol;
-
-                       expect(']', end_error);
                }
 
                argument->constraints = parse_string_literals();
-               expect('(', end_error);
+               expect('(');
                add_anchor_token(')');
                expression_t *expression = parse_expression();
                rem_anchor_token(')');
@@ -8940,7 +8768,7 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
                        mark_vars_read(expression, NULL);
                }
                argument->expression = expression;
-               expect(')', end_error);
+               expect(')');
 
                set_address_taken(expression, true);
 
@@ -8952,8 +8780,6 @@ static asm_argument_t *parse_asm_arguments(bool is_out)
        }
 
        return result;
-end_error:
-       return NULL;
 }
 
 /**
@@ -8991,7 +8817,7 @@ static statement_t *parse_asm_statement(void)
        if (next_if(T_volatile))
                asm_statement->is_volatile = true;
 
-       expect('(', end_error);
+       expect('(');
        add_anchor_token(')');
        if (token.kind != T_STRING_LITERAL) {
                parse_error_expected("after asm(", T_STRING_LITERAL, NULL);
@@ -9022,10 +8848,9 @@ static statement_t *parse_asm_statement(void)
 
 end_of_asm:
        rem_anchor_token(')');
-       expect(')', end_error);
-       expect(';', end_error);
+       expect(')');
+       expect(';');
 
-end_error:
        if (asm_statement->outputs == NULL) {
                /* GCC: An 'asm' instruction without any output operands will be treated
                 * identically to a volatile 'asm' instruction. */
@@ -9076,6 +8901,7 @@ static statement_t *parse_case_statement(void)
        source_position_t *const pos       = &statement->base.source_position;
 
        eat(T_case);
+       add_anchor_token(':');
 
        expression_t *expression = parse_expression();
        type_t *expression_type = expression->base.type;
@@ -9138,8 +8964,8 @@ static statement_t *parse_case_statement(void)
 
        PUSH_PARENT(statement);
 
-       expect(':', end_error);
-end_error:
+       rem_anchor_token(':');
+       expect(':');
 
        if (current_switch != NULL) {
                if (! statement->case_label.is_bad) {
@@ -9185,8 +9011,7 @@ static statement_t *parse_default_statement(void)
 
        PUSH_PARENT(statement);
 
-       expect(':', end_error);
-end_error:
+       expect(':');
 
        if (current_switch != NULL) {
                const case_label_statement_t *def_label = current_switch->default_label;
@@ -9268,16 +9093,13 @@ static statement_t *parse_inner_statement(void)
  */
 static expression_t *parse_condition(void)
 {
-       expect('(', end_error0);
+       expect('(');
        add_anchor_token(')');
        expression_t *const expr = parse_expression();
        mark_vars_read(expr, NULL);
        rem_anchor_token(')');
-       expect(')', end_error1);
-end_error1:
+       expect(')');
        return expr;
-end_error0:
-       return create_error_expression();
 }
 
 /**
@@ -9290,8 +9112,9 @@ static statement_t *parse_if(void)
        eat(T_if);
 
        PUSH_PARENT(statement);
+       PUSH_SCOPE_STATEMENT(&statement->ifs.scope);
 
-       add_anchor_token('{');
+       add_anchor_token(T_else);
 
        expression_t *const expr = parse_condition();
        statement->ifs.condition = expr;
@@ -9299,9 +9122,6 @@ static statement_t *parse_if(void)
         *             scalar type. */
        semantic_condition(expr, "condition of 'if'-statment");
 
-       rem_anchor_token('{');
-
-       add_anchor_token(T_else);
        statement_t *const true_stmt = parse_inner_statement();
        statement->ifs.true_statement = true_stmt;
        rem_anchor_token(T_else);
@@ -9324,6 +9144,7 @@ static statement_t *parse_if(void)
                warningf(WARN_PARENTHESES, pos, "suggest explicit braces to avoid ambiguous 'else'");
        }
 
+       POP_SCOPE();
        POP_PARENT();
        return statement;
 }
@@ -9381,6 +9202,7 @@ static statement_t *parse_switch(void)
        eat(T_switch);
 
        PUSH_PARENT(statement);
+       PUSH_SCOPE_STATEMENT(&statement->switchs.scope);
 
        expression_t *const expr = parse_condition();
        type_t       *      type = skip_typeref(expr->base.type);
@@ -9406,6 +9228,7 @@ static statement_t *parse_switch(void)
        }
        check_enum_cases(&statement->switchs);
 
+       POP_SCOPE();
        POP_PARENT();
        return statement;
 }
@@ -9431,6 +9254,7 @@ static statement_t *parse_while(void)
        eat(T_while);
 
        PUSH_PARENT(statement);
+       PUSH_SCOPE_STATEMENT(&statement->whiles.scope);
 
        expression_t *const cond = parse_condition();
        statement->whiles.condition = cond;
@@ -9440,6 +9264,7 @@ static statement_t *parse_while(void)
 
        statement->whiles.body = parse_loop_body(statement);
 
+       POP_SCOPE();
        POP_PARENT();
        return statement;
 }
@@ -9454,21 +9279,21 @@ static statement_t *parse_do(void)
        eat(T_do);
 
        PUSH_PARENT(statement);
+       PUSH_SCOPE_STATEMENT(&statement->do_while.scope);
 
        add_anchor_token(T_while);
        statement->do_while.body = parse_loop_body(statement);
        rem_anchor_token(T_while);
 
-       expect(T_while, end_error0);
-end_error0:;
+       expect(T_while);
        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");
-       expect(';', end_error1);
-end_error1:
+       expect(';');
 
+       POP_SCOPE();
        POP_PARENT();
        return statement;
 }
@@ -9483,9 +9308,9 @@ static statement_t *parse_for(void)
        eat(T_for);
 
        PUSH_PARENT(statement);
-       PUSH_SCOPE(&statement->fors.scope);
+       PUSH_SCOPE_STATEMENT(&statement->fors.scope);
 
-       expect('(', end_error1);
+       expect('(');
        add_anchor_token(')');
 
        PUSH_EXTENSION();
@@ -9502,8 +9327,7 @@ 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_error3);
-end_error3:;
+               expect(';');
        }
 
        POP_EXTENSION();
@@ -9518,8 +9342,7 @@ end_error3:;
                mark_vars_read(cond, NULL);
                rem_anchor_token(';');
        }
-       expect(';', end_error2);
-end_error2:
+       expect(';');
        if (token.kind != ')') {
                expression_t *const step = parse_expression();
                statement->fors.step = step;
@@ -9529,8 +9352,7 @@ end_error2:
                }
        }
        rem_anchor_token(')');
-       expect(')', end_error1);
-end_error1:
+       expect(')');
        statement->fors.body = parse_loop_body(statement);
 
        POP_SCOPE();
@@ -9584,13 +9406,11 @@ static statement_t *parse_goto(void)
                        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)->label;
+                       statement->gotos.label = &allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym_anonymous, &builtin_source_position)->label;
                }
        }
 
-       expect(';', end_error);
-
-end_error:
+       expect(';');
        return statement;
 }
 
@@ -9606,9 +9426,7 @@ static statement_t *parse_continue(void)
        statement_t *statement = allocate_statement_zero(STATEMENT_CONTINUE);
 
        eat(T_continue);
-       expect(';', end_error);
-
-end_error:
+       expect(';');
        return statement;
 }
 
@@ -9624,9 +9442,7 @@ static statement_t *parse_break(void)
        statement_t *statement = allocate_statement_zero(STATEMENT_BREAK);
 
        eat(T_break);
-       expect(';', end_error);
-
-end_error:
+       expect(';');
        return statement;
 }
 
@@ -9642,9 +9458,7 @@ static statement_t *parse_leave_statement(void)
        statement_t *statement = allocate_statement_zero(STATEMENT_LEAVE);
 
        eat(T___leave);
-       expect(';', end_error);
-
-end_error:
+       expect(';');
        return statement;
 }
 
@@ -9758,9 +9572,7 @@ static statement_t *parse_return(void)
        }
        statement->returns.value = return_value;
 
-       expect(';', end_error);
-
-end_error:
+       expect(';');
        return statement;
 }
 
@@ -9798,9 +9610,7 @@ static statement_t *parse_expression_statement(void)
        statement->expression.expression = expr;
        mark_vars_read(expr, ENT_ANY);
 
-       expect(';', end_error);
-
-end_error:
+       expect(';');
        return statement;
 }
 
@@ -9858,20 +9668,18 @@ static statement_t *parse_local_label_declaration(void)
        entity_t *end     = NULL;
        entity_t **anchor = &begin;
        do {
-               if (token.kind != T_IDENTIFIER) {
-                       parse_error_expected("while parsing local label declaration",
-                               T_IDENTIFIER, NULL);
+               source_position_t pos;
+               symbol_t *const symbol = expect_identifier("while parsing local label declaration", &pos);
+               if (!symbol)
                        goto end_error;
-               }
-               symbol_t *symbol = token.identifier.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(HERE, "multiple definitions of '%N' (previous definition %P)", entity, ppos);
+                       errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos);
                } else {
-                       entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol);
-                       entity->base.parent_scope    = current_scope;
-                       entity->base.source_position = token.base.source_position;
+                       entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol, &pos);
+                       entity->base.parent_scope = current_scope;
 
                        *anchor = entity;
                        anchor  = &entity->base.next;
@@ -9879,9 +9687,8 @@ static statement_t *parse_local_label_declaration(void)
 
                        environment_push(entity);
                }
-               next_token();
        } while (next_if(','));
-       expect(';', end_error);
+       expect(';');
 end_error:
        statement->declaration.declarations_begin = begin;
        statement->declaration.declarations_end   = end;
@@ -9896,7 +9703,7 @@ static void parse_namespace_definition(void)
        symbol_t *symbol = NULL;
 
        if (token.kind == T_IDENTIFIER) {
-               symbol = token.identifier.symbol;
+               symbol = token.base.symbol;
                next_token();
 
                entity = get_entity(symbol, NAMESPACE_NORMAL);
@@ -9912,9 +9719,8 @@ static void parse_namespace_definition(void)
        }
 
        if (entity == NULL) {
-               entity = allocate_entity_zero(ENTITY_NAMESPACE, NAMESPACE_NORMAL, symbol);
-               entity->base.source_position = token.base.source_position;
-               entity->base.parent_scope    = current_scope;
+               entity = allocate_entity_zero(ENTITY_NAMESPACE, NAMESPACE_NORMAL, symbol, HERE);
+               entity->base.parent_scope = current_scope;
        }
 
        if (token.kind == '=') {
@@ -9926,17 +9732,15 @@ static void parse_namespace_definition(void)
        append_entity(current_scope, entity);
 
        PUSH_SCOPE(&entity->namespacee.members);
+       PUSH_CURRENT_ENTITY(entity);
 
-       entity_t     *old_current_entity = current_entity;
-       current_entity = entity;
-
-       expect('{', end_error);
+       add_anchor_token('}');
+       expect('{');
        parse_externals();
-       expect('}', end_error);
+       rem_anchor_token('}');
+       expect('}');
 
-end_error:
-       assert(current_entity == entity);
-       current_entity = old_current_entity;
+       POP_CURRENT_ENTITY();
        POP_SCOPE();
 }
 
@@ -9954,7 +9758,7 @@ static statement_t *intern_parse_statement(void)
                token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind;
                if (la1_type == ':') {
                        statement = parse_label_statement();
-               } else if (is_typedef_symbol(token.identifier.symbol)) {
+               } else if (is_typedef_symbol(token.base.symbol)) {
                        statement = parse_declaration_statement();
                } else {
                        /* it's an identifier, the grammar says this must be an
@@ -9964,7 +9768,7 @@ static statement_t *intern_parse_statement(void)
                        switch (la1_type) {
                        case '&':
                        case '*':
-                               if (get_entity(token.identifier.symbol, NAMESPACE_NORMAL) != NULL) {
+                               if (get_entity(token.base.symbol, NAMESPACE_NORMAL) != NULL) {
                        default:
                                        statement = parse_expression_statement();
                                } else {
@@ -10166,8 +9970,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement)
                *anchor = sub_statement;
                anchor  = &sub_statement->base.next;
        }
-       expect('}', end_error);
-end_error:
+       expect('}');
 
        /* look over all statements again to produce no effect warnings */
        if (is_warn_on(WARN_UNUSED_VALUE)) {
@@ -10324,16 +10127,20 @@ static void parse_global_asm(void)
        statement_t *statement = allocate_statement_zero(STATEMENT_ASM);
 
        eat(T_asm);
-       expect('(', end_error);
+       add_anchor_token(';');
+       add_anchor_token(')');
+       add_anchor_token(T_STRING_LITERAL);
+       expect('(');
 
+       rem_anchor_token(T_STRING_LITERAL);
        statement->asms.asm_text = parse_string_literals();
        statement->base.next     = unit->global_asm;
        unit->global_asm         = statement;
 
-       expect(')', end_error);
-       expect(';', end_error);
-
-end_error:;
+       rem_anchor_token(')');
+       expect(')');
+       rem_anchor_token(';');
+       expect(';');
 }
 
 static void parse_linkage_specification(void)
@@ -10357,12 +10164,11 @@ static void parse_linkage_specification(void)
 
        if (next_if('{')) {
                parse_externals();
-               expect('}', end_error);
+               expect('}');
        } else {
                parse_external();
        }
 
-end_error:
        assert(current_linkage == new_linkage);
        current_linkage = old_linkage;
 }
@@ -10543,7 +10349,7 @@ static void complete_incomplete_arrays(void)
        }
 }
 
-void prepare_main_collect2(entity_t *entity)
+static void prepare_main_collect2(entity_t *const entity)
 {
        PUSH_SCOPE(&entity->function.statement->compound.scope);