Correct wrong positions in error/warning messages.
[cparser] / parser.c
index 4fa91c2..d05f5c2 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1269,24 +1269,25 @@ static attribute_t *parse_attribute_gnu_single(void)
                return NULL;
        }
 
-       const char *name = symbol->string;
-       next_token();
+       attribute_kind_t  kind;
+       char const *const name = symbol->string;
+       for (kind = ATTRIBUTE_GNU_FIRST;; ++kind) {
+               if (kind > ATTRIBUTE_GNU_LAST) {
+                       if (warning.attribute) {
+                               warningf(HERE, "unknown attribute '%s' ignored", name);
+                       }
+                       /* TODO: we should still save the attribute in the list... */
+                       kind = ATTRIBUTE_UNKNOWN;
+                       break;
+               }
 
-       attribute_kind_t kind;
-       for (kind = ATTRIBUTE_GNU_FIRST; kind <= ATTRIBUTE_GNU_LAST; ++kind) {
                const char *attribute_name = get_attribute_name(kind);
                if (attribute_name != NULL
                                && strcmp_underscore(attribute_name, name) == 0)
                        break;
        }
 
-       if (kind >= ATTRIBUTE_GNU_LAST) {
-               if (warning.attribute) {
-                       warningf(HERE, "unknown attribute '%s' ignored", name);
-               }
-               /* TODO: we should still save the attribute in the list... */
-               kind = ATTRIBUTE_UNKNOWN;
-       }
+       next_token();
 
        attribute_t *attribute = allocate_attribute_zero(kind);
 
@@ -1362,10 +1363,10 @@ static attribute_t *parse_attributes(attribute_t *first)
                        break;
 
                case T___thiscall:
-                       next_token();
                        /* TODO record modifier */
                        if (warning.other)
                                warningf(HERE, "Ignoring declaration modifier %K", &token);
+                       eat(T___thiscall);
                        attribute = allocate_attribute_zero(ATTRIBUTE_MS_THISCALL);
                        break;
 
@@ -2201,10 +2202,19 @@ finish_designator:
                                        goto error_parse_next;
                                type_t *const outer_type_skip = skip_typeref(outer_type);
                                if (is_type_compound(outer_type_skip) &&
-                                   !outer_type_skip->compound.compound->complete) {
+                                               !outer_type_skip->compound.compound->complete) {
                                        goto error_parse_next;
                                }
-                               goto error_excess;
+
+                               if (warning.other) {
+                                       source_position_t const* const pos = &expression->base.source_position;
+                                       if (env->entity != NULL) {
+                                               warningf(pos, "excess elements in initializer for '%Y'", env->entity->base.symbol);
+                                       } else {
+                                               warningf(pos, "excess elements in initializer");
+                                       }
+                               }
+                               goto error_parse_next;
                        }
 
                        /* handle { "string" } special case */
@@ -2256,20 +2266,8 @@ finish_designator:
                                path->max_index = index;
                }
 
-               if (type != NULL) {
-                       /* append to initializers list */
-                       ARR_APP1(initializer_t*, initializers, sub);
-               } else {
-error_excess:
-                       if (warning.other) {
-                               if (env->entity != NULL) {
-                                       warningf(HERE, "excess elements in initializer for '%Y'",
-                                                env->entity->base.symbol);
-                               } else {
-                                       warningf(HERE, "excess elements in initializer");
-                               }
-                       }
-               }
+               /* append to initializers list */
+               ARR_APP1(initializer_t*, initializers, sub);
 
 error_parse_next:
                if (token.type == '}') {
@@ -2353,6 +2351,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env)
                DEL_ARR_F(path.path);
 
                expect('}', end_error);
+end_error:;
        } else {
                /* parse_scalar_initializer() also works in this case: we simply
                 * have an expression without {} around it */
@@ -2398,8 +2397,6 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env)
        }
 
        return result;
-end_error:
-       return NULL;
 }
 
 static void append_entity(scope_t *scope, entity_t *entity)
@@ -2458,12 +2455,9 @@ static compound_t *parse_compound_type_specifier(bool is_struct)
        }
 
        if (entity == NULL) {
-               entity = allocate_entity_zero(kind);
-
+               entity = allocate_entity_zero(kind, NAMESPACE_TAG, symbol);
                entity->compound.alignment   = 1;
-               entity->base.namespc         = NAMESPACE_TAG;
                entity->base.source_position = pos;
-               entity->base.symbol          = symbol;
                entity->base.parent_scope    = current_scope;
                if (symbol != NULL) {
                        environment_push(entity);
@@ -2507,10 +2501,8 @@ static void parse_enum_entries(type_t *const enum_type)
                        return;
                }
 
-               entity_t *entity             = allocate_entity_zero(ENTITY_ENUM_VALUE);
+               entity_t *const entity = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, token.symbol);
                entity->enum_value.enum_type = enum_type;
-               entity->base.namespc         = NAMESPACE_NORMAL;
-               entity->base.symbol          = token.symbol;
                entity->base.source_position = token.source_position;
                next_token();
 
@@ -2571,10 +2563,8 @@ static type_t *parse_enum_specifier(void)
        }
 
        if (entity == NULL) {
-               entity                       = allocate_entity_zero(ENTITY_ENUM);
-               entity->base.namespc         = NAMESPACE_TAG;
+               entity = allocate_entity_zero(ENTITY_ENUM, NAMESPACE_TAG, symbol);
                entity->base.source_position = pos;
-               entity->base.symbol          = symbol;
                entity->base.parent_scope    = current_scope;
        }
 
@@ -2598,8 +2588,7 @@ static type_t *parse_enum_specifier(void)
                        anonymous_entity = entity;
                }
        } else if (!entity->enume.complete && !(c_mode & _GNUC)) {
-               errorf(HERE, "'enum %Y' used before definition (incomplete enums are a GNU extension)",
-                      symbol);
+               errorf(HERE, "'%T' used before definition (incomplete enums are a GNU extension)", type);
        }
 
        return type;
@@ -2708,28 +2697,25 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute)
                        goto end_error;
                }
 
-               bool is_put;
-               symbol_t *symbol = token.symbol;
-               next_token();
+               symbol_t **prop;
+               symbol_t  *symbol = token.symbol;
                if (strcmp(symbol->string, "put") == 0) {
-                       is_put = true;
+                       prop = &property->put_symbol;
                } else if (strcmp(symbol->string, "get") == 0) {
-                       is_put = false;
+                       prop = &property->get_symbol;
                } else {
                        errorf(HERE, "expected put or get in property declspec");
-                       goto end_error;
+                       prop = NULL;
                }
+               eat(T_IDENTIFIER);
                expect('=', end_error);
                if (token.type != T_IDENTIFIER) {
                        parse_error_expected("while parsing property declspec",
                                             T_IDENTIFIER, NULL);
                        goto end_error;
                }
-               if (is_put) {
-                       property->put_symbol = token.symbol;
-               } else {
-                       property->get_symbol = token.symbol;
-               }
+               if (prop != NULL)
+                       *prop = token.symbol;
                next_token();
        } while (next_if(','));
 
@@ -2748,7 +2734,6 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void)
                kind = ATTRIBUTE_MS_RESTRICT;
        } else if (token.type == T_IDENTIFIER) {
                const char *name = token.symbol->string;
-               next_token();
                for (attribute_kind_t k = ATTRIBUTE_MS_FIRST; k <= ATTRIBUTE_MS_LAST;
                     ++k) {
                        const char *attribute_name = get_attribute_name(k);
@@ -2761,6 +2746,7 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void)
                if (kind == ATTRIBUTE_UNKNOWN && warning.attribute) {
                        warningf(HERE, "unknown __declspec '%s' ignored", name);
                }
+               eat(T_IDENTIFIER);
        } else {
                parse_error_expected("while parsing __declspec", T_IDENTIFIER, NULL);
                return NULL;
@@ -2815,10 +2801,8 @@ end_error:
 
 static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
 {
-       entity_t *entity             = allocate_entity_zero(kind);
-       entity->base.namespc         = NAMESPACE_NORMAL;
+       entity_t *const entity = allocate_entity_zero(kind, NAMESPACE_NORMAL, symbol);
        entity->base.source_position = *HERE;
-       entity->base.symbol          = symbol;
        if (is_declaration(entity)) {
                entity->declaration.type     = type_error_type;
                entity->declaration.implicit = true;
@@ -3206,32 +3190,33 @@ warn_about_long_long:
                case SPECIFIER_LONG | SPECIFIER_DOUBLE | SPECIFIER_IMAGINARY:
                        atomic_type = ATOMIC_TYPE_LONG_DOUBLE;
                        break;
-               default:
+               default: {
                        /* invalid specifier combination, give an error message */
+                       source_position_t const* const pos = &specifiers->source_position;
                        if (type_specifiers == 0) {
-                               if (saw_error)
-                                       goto end_error;
-
-                               /* ISO/IEC 14882:1998(E) §C.1.5:4 */
-                               if (!(c_mode & _CXX) && !strict_mode) {
-                                       if (warning.implicit_int) {
-                                               warningf(HERE, "no type specifiers in declaration, using 'int'");
+                               if (!saw_error) {
+                                       /* ISO/IEC 14882:1998(E) §C.1.5:4 */
+                                       if (!(c_mode & _CXX) && !strict_mode) {
+                                               if (warning.implicit_int) {
+                                                       warningf(pos, "no type specifiers in declaration, using 'int'");
+                                               }
+                                               atomic_type = ATOMIC_TYPE_INT;
+                                               break;
+                                       } else {
+                                               errorf(pos, "no type specifiers given in declaration");
                                        }
-                                       atomic_type = ATOMIC_TYPE_INT;
-                                       break;
-                               } else {
-                                       errorf(HERE, "no type specifiers given in declaration");
                                }
                        } else if ((type_specifiers & SPECIFIER_SIGNED) &&
                                  (type_specifiers & SPECIFIER_UNSIGNED)) {
-                               errorf(HERE, "signed and unsigned specifiers given");
+                               errorf(pos, "signed and unsigned specifiers given");
                        } else if (type_specifiers & (SPECIFIER_SIGNED | SPECIFIER_UNSIGNED)) {
-                               errorf(HERE, "only integer types can be signed or unsigned");
+                               errorf(pos, "only integer types can be signed or unsigned");
                        } else {
-                               errorf(HERE, "multiple datatypes in declaration");
+                               errorf(pos, "multiple datatypes in declaration");
                        }
                        goto end_error;
                }
+               }
 
                if (type_specifiers & SPECIFIER_COMPLEX) {
                        type                = allocate_type_zero(TYPE_COMPLEX);
@@ -3245,7 +3230,7 @@ warn_about_long_long:
                }
                newtype = true;
        } else if (type_specifiers != 0) {
-               errorf(HERE, "multiple datatypes in declaration");
+               errorf(&specifiers->source_position, "multiple datatypes in declaration");
        }
 
        /* FIXME: check type qualifiers here */
@@ -3295,10 +3280,8 @@ static type_qualifiers_t parse_type_qualifiers(void)
 static void parse_identifier_list(scope_t *scope)
 {
        do {
-               entity_t *entity = allocate_entity_zero(ENTITY_PARAMETER);
+               entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.symbol);
                entity->base.source_position = token.source_position;
-               entity->base.namespc         = NAMESPACE_NORMAL;
-               entity->base.symbol          = token.symbol;
                /* a K&R parameter has no type, yet */
                next_token();
 
@@ -3650,7 +3633,6 @@ ptr_operator_end: ;
                                        /* Function declarator. */
                                        if (!env->may_be_abstract) {
                                                errorf(HERE, "function declarator must have a name");
-                                               goto error_out;
                                        }
                                } else {
                        case '&':
@@ -3678,7 +3660,6 @@ ptr_operator_end: ;
                if (env->may_be_abstract)
                        break;
                parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL);
-error_out:
                eat_until_anchor();
                return NULL;
        }
@@ -3896,9 +3877,7 @@ 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);
-               entity->base.namespc         = NAMESPACE_NORMAL;
-               entity->base.symbol          = env.symbol;
+               entity = allocate_entity_zero(ENTITY_TYPEDEF, NAMESPACE_NORMAL, env.symbol);
                entity->base.source_position = env.source_position;
                entity->typedefe.type        = orig_type;
 
@@ -3919,7 +3898,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
        } else {
                /* create a declaration type entity */
                if (flags & DECL_CREATE_COMPOUND_MEMBER) {
-                       entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER);
+                       entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, env.symbol);
 
                        if (env.symbol != NULL) {
                                if (specifiers->is_inline && is_type_valid(type)) {
@@ -3938,10 +3917,9 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                        orig_type = semantic_parameter(&env.source_position, orig_type,
                                                       specifiers, env.symbol);
 
-                       entity = allocate_entity_zero(ENTITY_PARAMETER);
+                       entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, env.symbol);
                } else if (is_type_function(type)) {
-                       entity = allocate_entity_zero(ENTITY_FUNCTION);
-
+                       entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, env.symbol);
                        entity->function.is_inline      = specifiers->is_inline;
                        entity->function.elf_visibility = default_visibility;
                        entity->function.parameters     = env.parameters;
@@ -3960,8 +3938,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                                }
                        }
                } else {
-                       entity = allocate_entity_zero(ENTITY_VARIABLE);
-
+                       entity = allocate_entity_zero(ENTITY_VARIABLE, NAMESPACE_NORMAL, env.symbol);
                        entity->variable.elf_visibility = default_visibility;
                        entity->variable.thread_local   = specifiers->thread_local;
 
@@ -3991,13 +3968,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers,
                        }
                }
 
-               if (env.symbol != NULL) {
-                       entity->base.symbol          = env.symbol;
-                       entity->base.source_position = env.source_position;
-               } else {
-                       entity->base.source_position = specifiers->source_position;
-               }
-               entity->base.namespc           = NAMESPACE_NORMAL;
+               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;
@@ -4411,7 +4382,6 @@ finish:
        assert(current_scope != NULL);
 
        entity->base.parent_scope = current_scope;
-       entity->base.namespc      = NAMESPACE_NORMAL;
        environment_push(entity);
        append_entity(current_scope, entity);
 
@@ -4456,7 +4426,6 @@ static void parse_init_declarator_rest(entity_t *entity)
                assert(is_declaration(entity));
                orig_type = entity->declaration.type;
        }
-       eat('=');
 
        type_t *type = skip_typeref(orig_type);
 
@@ -4464,6 +4433,7 @@ static void parse_init_declarator_rest(entity_t *entity)
                        && entity->variable.initializer != NULL) {
                parser_error_multiple_definition(entity, HERE);
        }
+       eat('=');
 
        declaration_t *const declaration = &entity->declaration;
        bool must_be_constant = false;
@@ -4606,10 +4576,8 @@ end_error:
 static entity_t *finished_kr_declaration(entity_t *entity, bool is_definition)
 {
        symbol_t *symbol = entity->base.symbol;
-       if (symbol == NULL) {
-               errorf(HERE, "anonymous declaration not valid as function parameter");
+       if (symbol == NULL)
                return entity;
-       }
 
        assert(entity->base.namespc == NAMESPACE_NORMAL);
        entity_t *previous_entity = get_entity(symbol, NAMESPACE_NORMAL);
@@ -4738,14 +4706,13 @@ decl_list_end:
 
                type_t *parameter_type = parameter->declaration.type;
                if (parameter_type == NULL) {
+                       source_position_t const* const pos = &parameter->base.source_position;
                        if (strict_mode) {
-                               errorf(HERE, "no type specified for function parameter '%Y'",
-                                      parameter->base.symbol);
+                               errorf(pos, "no type specified for function parameter '%Y'", parameter->base.symbol);
                                parameter_type = type_error_type;
                        } else {
                                if (warning.implicit_int) {
-                                       warningf(HERE, "no type specified for function parameter '%Y', using 'int'",
-                                                parameter->base.symbol);
+                                       warningf(pos, "no type specified for function parameter '%Y', using 'int'", parameter->base.symbol);
                                }
                                parameter_type = type_int;
                        }
@@ -4783,7 +4750,7 @@ decl_list_end:
 
        if (warning.other && need_incompatible_warning) {
                type_t *proto_type_type = proto_type->declaration.type;
-               warningf(HERE,
+               warningf(&entity->base.source_position,
                         "declaration '%#T' is incompatible with '%#T' (declared %P)",
                         proto_type_type, proto_type->base.symbol,
                         new_type, entity->base.symbol,
@@ -4825,8 +4792,6 @@ static void check_labels(void)
                        continue;
 
                label_t *label = goto_statement->label;
-
-               label->used = true;
                if (label->base.source_position.input_name == NULL) {
                        print_in_function();
                        errorf(&goto_statement->base.source_position,
@@ -5705,8 +5670,7 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size,
        il_size_t bit_size;
        type_t *skipped_type = skip_typeref(base_type);
        if (!is_type_integer(skipped_type)) {
-               errorf(HERE, "bitfield base type '%T' is not an integer type",
-                      base_type);
+               errorf(source_position, "bitfield base type '%T' is not an integer type", base_type);
                bit_size = 0;
        } else {
                bit_size = get_type_size(base_type) * 8;
@@ -5871,8 +5835,7 @@ static void parse_compound_declarators(compound_t *compound,
                                anchor = &(*anchor)->next;
                        *anchor = specifiers->attributes;
 
-                       entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER);
-                       entity->base.namespc                       = NAMESPACE_NORMAL;
+                       entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, NULL);
                        entity->base.source_position               = source_position;
                        entity->declaration.declared_storage_class = STORAGE_CLASS_NONE;
                        entity->declaration.storage_class          = STORAGE_CLASS_NONE;
@@ -5974,7 +5937,7 @@ static type_t *parse_typename(void)
                /* TODO: improve error message, user does probably not know what a
                 * storage class is...
                 */
-               errorf(HERE, "typename must not have a storage class");
+               errorf(&specifiers.source_position, "typename must not have a storage class");
        }
 
        type_t *result = parse_abstract_declarator(specifiers.type);
@@ -6243,13 +6206,11 @@ static entity_t *create_implicit_function(symbol_t *symbol,
        ntype->function.linkage                = LINKAGE_C;
        type_t *type                           = identify_new_type(ntype);
 
-       entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION);
+       entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol);
        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.namespc                       = NAMESPACE_NORMAL;
-       entity->base.symbol                        = symbol;
        entity->base.source_position               = *source_position;
 
        if (current_scope != NULL) {
@@ -6480,7 +6441,7 @@ static expression_t *parse_reference(void)
                current_function->need_closure = true;
        }
 
-       check_deprecated(HERE, entity);
+       check_deprecated(&pos, entity);
 
        if (warning.init_self && entity == current_init_decl && !in_type_prop
            && entity->kind == ENTITY_VARIABLE) {
@@ -7029,40 +6990,27 @@ end_error:
 }
 
 /**
- * Return the declaration for a given label symbol or create a new one.
- *
- * @param symbol  the symbol of the label
+ * Return the label for the current symbol or create a new one.
  */
-static label_t *get_label(symbol_t *symbol)
+static label_t *get_label(void)
 {
-       entity_t *label;
+       assert(token.type == T_IDENTIFIER);
        assert(current_function != NULL);
 
-       label = get_entity(symbol, NAMESPACE_LABEL);
-       /* if we found a local label, we already created the declaration */
+       entity_t *label = get_entity(token.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) {
                        assert(label->base.parent_scope->depth < current_scope->depth);
                        current_function->goto_to_outer = true;
                }
-               return &label->label;
+       } 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.symbol);
+               label_push(label);
        }
 
-       label = get_entity(symbol, NAMESPACE_LABEL);
-       /* if we found a label in the same function, then we already created the
-        * declaration */
-       if (label != NULL
-                       && label->base.parent_scope == &current_function->parameters) {
-               return &label->label;
-       }
-
-       /* otherwise we need to create a new one */
-       label               = allocate_entity_zero(ENTITY_LABEL);
-       label->base.namespc = NAMESPACE_LABEL;
-       label->base.symbol  = symbol;
-
-       label_push(label);
-
+       eat(T_IDENTIFIER);
        return &label->label;
 }
 
@@ -7075,24 +7023,20 @@ static expression_t *parse_label_address(void)
        eat(T_ANDAND);
        if (token.type != T_IDENTIFIER) {
                parse_error_expected("while parsing label address", T_IDENTIFIER, NULL);
-               goto end_error;
+               return create_invalid_expression();
        }
-       symbol_t *symbol = token.symbol;
-       next_token();
 
-       label_t *label       = get_label(symbol);
+       label_t *const label = get_label();
        label->used          = true;
        label->address_taken = true;
 
        expression_t *expression = allocate_expression_zero(EXPR_LABEL_ADDRESS);
        expression->base.source_position = source_position;
 
-       /* label address is threaten as a void pointer */
+       /* label address is treated as a void pointer */
        expression->base.type           = type_void_ptr;
        expression->label_address.label = label;
        return expression;
-end_error:
-       return create_invalid_expression();
 }
 
 /**
@@ -7232,7 +7176,7 @@ check_idx:
                }
        } else {
                if (is_type_valid(type_left) && is_type_valid(type_inside)) {
-                       errorf(HERE,
+                       errorf(&expr->base.source_position,
                                "array access on object with non-pointer types '%T', '%T'",
                                orig_type_left, orig_type_inside);
                }
@@ -9479,8 +9423,7 @@ end_error:
        if (current_switch != NULL) {
                const case_label_statement_t *def_label = current_switch->default_label;
                if (def_label != NULL) {
-                       errorf(HERE, "multiple default labels in one switch (previous declared %P)",
-                              &def_label->base.source_position);
+                       errorf(&statement->base.source_position, "multiple default labels in one switch (previous declared %P)", &def_label->base.source_position);
                } else {
                        current_switch->default_label = &statement->case_label;
 
@@ -9508,25 +9451,20 @@ end_error:
  */
 static statement_t *parse_label_statement(void)
 {
-       assert(token.type == T_IDENTIFIER);
-       symbol_t *symbol = token.symbol;
-       label_t  *label  = get_label(symbol);
-
        statement_t *const statement = allocate_statement_zero(STATEMENT_LABEL);
-       statement->label.label       = label;
-
-       next_token();
+       label_t     *const label     = get_label();
+       statement->label.label = label;
 
        PUSH_PARENT(statement);
 
        /* if statement is already set then the label is defined twice,
         * otherwise it was just mentioned in a goto/local label declaration so far
         */
+       source_position_t const* const pos = &statement->base.source_position;
        if (label->statement != NULL) {
-               errorf(HERE, "duplicate label '%Y' (declared %P)",
-                      symbol, &label->base.source_position);
+               errorf(pos, "duplicate label '%Y' (declared %P)", label->base.symbol, &label->base.source_position);
        } else {
-               label->base.source_position = token.source_position;
+               label->base.source_position = *pos;
                label->statement            = statement;
        }
 
@@ -9870,9 +9808,9 @@ static statement_t *parse_goto(void)
 
                statement->gotos.expression = expression;
        } else if (token.type == T_IDENTIFIER) {
-               symbol_t *symbol = token.symbol;
-               next_token();
-               statement->gotos.label = get_label(symbol);
+               label_t *const label = get_label();
+               label->used            = true;
+               statement->gotos.label = label;
        } else {
                if (GNU_MODE)
                        parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL);
@@ -10190,12 +10128,9 @@ static statement_t *parse_local_label_declaration(void)
                        errorf(HERE, "multiple definitions of '__label__ %Y' (previous definition %P)",
                               symbol, &entity->base.source_position);
                } else {
-                       entity = allocate_entity_zero(ENTITY_LOCAL_LABEL);
-
+                       entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol);
                        entity->base.parent_scope    = current_scope;
-                       entity->base.namespc         = NAMESPACE_LABEL;
                        entity->base.source_position = token.source_position;
-                       entity->base.symbol          = symbol;
 
                        *anchor = entity;
                        anchor  = &entity->base.next;
@@ -10236,10 +10171,8 @@ static void parse_namespace_definition(void)
        }
 
        if (entity == NULL) {
-               entity                       = allocate_entity_zero(ENTITY_NAMESPACE);
-               entity->base.symbol          = symbol;
+               entity = allocate_entity_zero(ENTITY_NAMESPACE, NAMESPACE_NORMAL, symbol);
                entity->base.source_position = token.source_position;
-               entity->base.namespc         = NAMESPACE_NORMAL;
                entity->base.parent_scope    = current_scope;
        }
 
@@ -10694,7 +10627,8 @@ static void parse_linkage_specification(void)
 {
        eat(T_extern);
 
-       const char *linkage = parse_string_literals().begin;
+       source_position_t const pos     = *HERE;
+       char const       *const linkage = parse_string_literals().begin;
 
        linkage_kind_t old_linkage = current_linkage;
        linkage_kind_t new_linkage;
@@ -10703,7 +10637,7 @@ static void parse_linkage_specification(void)
        } else if (strcmp(linkage, "C++") == 0) {
                new_linkage = LINKAGE_CXX;
        } else {
-               errorf(HERE, "linkage string \"%s\" not recognized", linkage);
+               errorf(&pos, "linkage string \"%s\" not recognized", linkage);
                new_linkage = LINKAGE_INVALID;
        }
        current_linkage = new_linkage;