assert(type->kind == TYPE_ATOMIC);
const atomic_type_t *atomic_type = &type->atomic;
- atomic_type_type_t atype = atomic_type->atype;
+ atomic_type_kind_t atype = atomic_type->akind;
return atype;
}
if (element_type->kind == TYPE_ATOMIC) {
switch (expression->kind) {
case EXPR_STRING_LITERAL:
- if (element_type->atomic.atype == ATOMIC_TYPE_CHAR) {
+ if (element_type->atomic.akind == ATOMIC_TYPE_CHAR) {
return initializer_from_string(array_type,
expression->string.value);
}
finish_specifiers:
if(type == NULL) {
- atomic_type_type_t atomic_type;
+ atomic_type_kind_t atomic_type;
/* match valid basic types */
switch(type_specifiers) {
}
type = allocate_type_zero(TYPE_ATOMIC);
- type->atomic.atype = atomic_type;
+ type->atomic.akind = atomic_type;
newtype = 1;
} else {
if(type_specifiers != 0) {
assert(declaration != previous_declaration);
if (previous_declaration != NULL
&& previous_declaration->parent_context == context) {
+ /* can happen for K&R style declarations */
+ if(previous_declaration->type == NULL) {
+ previous_declaration->type = declaration->type;
+ }
+
const type_t *const prev_type = skip_typeref(previous_declaration->type);
if (!types_compatible(type, prev_type)) {
errorf(declaration->source_position,
static declaration_t *finished_kr_declaration(declaration_t *declaration)
{
- /* TODO: check that it was actually a parameter that gets a type */
+ symbol_t *symbol = declaration->symbol;
+ if(symbol == NULL) {
+ errorf(HERE, "anonymous declaration not valid as function parameter");
+ return declaration;
+ }
+ namespace_t namespc = (namespace_t) declaration->namespc;
+ if(namespc != NAMESPACE_NORMAL) {
+ return record_declaration(declaration);
+ }
+
+ declaration_t *previous_declaration = get_declaration(symbol, namespc);
+ if(previous_declaration == NULL ||
+ previous_declaration->parent_context != context) {
+ errorf(HERE, "expected declaration of a function parameter, found '%Y'",
+ symbol);
+ return declaration;
+ }
- /* we should have a declaration for the parameter in the current
- * scope */
- return record_declaration(declaration);
+ if(previous_declaration->type == NULL) {
+ previous_declaration->type = declaration->type;
+ previous_declaration->storage_class = declaration->storage_class;
+ previous_declaration->parent_context = context;
+ return previous_declaration;
+ } else {
+ return record_declaration(declaration);
+ }
}
static void parse_declaration(parsed_declaration_func finished_declaration)
/* note that we don't skip typerefs: the standard doesn't allow them here
* (so we can't use is_type_function here) */
if(type->kind != TYPE_FUNCTION) {
- errorf(HERE, "declarator '%#T' has a body but is not a function type", type, ndeclaration->symbol);
+ errorf(HERE, "declarator '%#T' has a body but is not a function type",
+ type, ndeclaration->symbol);
eat_block();
return;
}
declaration_t *parameter = declaration->context.declarations;
for( ; parameter != NULL; parameter = parameter->next) {
- assert(parameter->parent_context == NULL || parameter->parent_context == context);
+ if(parameter->parent_context == &ndeclaration->context) {
+ parameter->parent_context = context;
+ }
+ assert(parameter->parent_context == NULL
+ || parameter->parent_context == context);
parameter->parent_context = context;
environment_push(parameter);
}
declaration->source_position = source_position;
declaration->parent_context = global_context;
+ context_t *old_context = context;
+ set_context(global_context);
+
environment_push(declaration);
+ /* prepend the declaration to the global declarations list */
declaration->next = context->declarations;
context->declarations = declaration;
+ assert(context == global_context);
+ set_context(old_context);
+
return declaration;
}
return create_invalid_expression();
}
+/**
+ * Check if the expression has the character type and issue a warning then.
+ */
+static void check_for_char_index_type(const expression_t *expression) {
+ type_t *type = expression->base.datatype;
+ type_t *base_type = skip_typeref(type);
+
+ if (base_type->base.kind == TYPE_ATOMIC) {
+ if (base_type->atomic.akind == ATOMIC_TYPE_CHAR) {
+ warningf(expression->base.source_position,
+ "array subscript has type '%T'", type);
+ }
+ }
+}
+
static expression_t *parse_array_expression(unsigned precedence,
expression_t *left)
{
return_type = pointer->points_to;
array_access->array_ref = left;
array_access->index = inside;
+ check_for_char_index_type(inside);
} else if(is_type_pointer(type_inside)) {
pointer_type_t *pointer = &type_inside->pointer;
return_type = pointer->points_to;
array_access->array_ref = inside;
array_access->index = left;
array_access->flipped = true;
+ check_for_char_index_type(left);
} else {
errorf(HERE, "array access on object with non-pointer types '%T', '%T'", type_left, type_inside);
}
expect('(');
expression_t *const expr = parse_expression();
- type_t *const type = promote_integer(expr->base.datatype);
+ type_t *const type = promote_integer(skip_typeref(expr->base.datatype));
statement->expression = create_implicit_cast(expr, type);
expect(')');
statement->body = parse_statement();