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);
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;
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 */
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 == '}') {
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 */
}
return result;
-end_error:
- return NULL;
}
static void append_entity(scope_t *scope, entity_t *entity)
}
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);
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();
}
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;
}
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;
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(','));
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);
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;
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;
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);
}
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 */
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();
/* Function declarator. */
if (!env->may_be_abstract) {
errorf(HERE, "function declarator must have a name");
- goto error_out;
}
} else {
case '&':
if (env->may_be_abstract)
break;
parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL);
-error_out:
eat_until_anchor();
return NULL;
}
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;
} 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)) {
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;
}
}
} 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;
}
}
- 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;
assert(current_scope != NULL);
entity->base.parent_scope = current_scope;
- entity->base.namespc = NAMESPACE_NORMAL;
environment_push(entity);
append_entity(current_scope, entity);
assert(is_declaration(entity));
orig_type = entity->declaration.type;
}
- eat('=');
type_t *type = skip_typeref(orig_type);
&& entity->variable.initializer != NULL) {
parser_error_multiple_definition(entity, HERE);
}
+ eat('=');
declaration_t *const declaration = &entity->declaration;
bool must_be_constant = false;
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);
type_t *parameter_type = parameter->declaration.type;
if (parameter_type == NULL) {
+ source_position_t const* const pos = ¶meter->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;
}
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,
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,
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;
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;
/* 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);
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) {
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) {
}
/**
- * 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 != ¤t_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 == ¤t_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;
}
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();
}
/**
}
} 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);
}
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;
*/
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;
}
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);
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;
}
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;
}
{
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;
} 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;