static declaration_t *allocate_declaration_zero(void)
{
- return allocate_ast_zero(sizeof(*allocate_declaration_zero()));
+ declaration_t *declaration = allocate_ast_zero(sizeof(*allocate_declaration_zero()));
+ declaration->type = type_error_type;
+ return declaration;
}
/**
size_t size = get_expression_struct_size(kind);
expression_t *res = allocate_ast_zero(size);
- res->base.kind = kind;
+ res->base.kind = kind;
+ res->base.datatype = type_error_type;
return res;
}
expression->base.source_position, source_type, dest_type);
return expression;
+ case TYPE_COMPOUND_STRUCT:
+ case TYPE_COMPOUND_UNION:
+ case TYPE_ERROR:
+ return expression;
+
default:
panic("casting of non-atomic types not implemented yet");
}
}
/** Implements the rules from § 6.5.16.1 */
-static void semantic_assign(type_t *orig_type_left, expression_t **right,
+static type_t *semantic_assign(type_t *orig_type_left,
+ const expression_t *const right,
const char *context)
{
- type_t *orig_type_right = (*right)->base.datatype;
+ type_t *const orig_type_right = right->base.datatype;
- if(orig_type_right == NULL)
- return;
+ if (!is_type_valid(orig_type_right))
+ return orig_type_right;
type_t *const type_left = skip_typeref(orig_type_left);
type_t *const type_right = skip_typeref(orig_type_right);
if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) ||
- (is_type_pointer(type_left) && is_null_pointer_constant(*right)) ||
+ (is_type_pointer(type_left) && is_null_pointer_constant(right)) ||
(is_type_atomic(type_left, ATOMIC_TYPE_BOOL)
&& is_type_pointer(type_right))) {
- *right = create_implicit_cast(*right, type_left);
- return;
+ return orig_type_left;
}
if (is_type_pointer(type_left) && is_type_pointer(type_right)) {
= points_to_right->base.qualifiers & ~points_to_left->base.qualifiers;
if(missing_qualifiers != 0) {
errorf(HERE, "destination type '%T' in %s from type '%T' lacks qualifiers '%Q' in pointed-to type", type_left, context, type_right, missing_qualifiers);
- return;
+ return orig_type_left;
}
points_to_left = get_unqualified_type(points_to_left);
if(!is_type_atomic(points_to_left, ATOMIC_TYPE_VOID)
&& !is_type_atomic(points_to_right, ATOMIC_TYPE_VOID)
&& !types_compatible(points_to_left, points_to_right)) {
- goto incompatible_assign_types;
+ return NULL;
}
- *right = create_implicit_cast(*right, type_left);
- return;
+ return orig_type_left;
}
- if (is_type_compound(type_left)
- && types_compatible(type_left, type_right)) {
- *right = create_implicit_cast(*right, type_left);
- return;
+ if (is_type_compound(type_left) && is_type_compound(type_right)) {
+ type_t *const unqual_type_left = get_unqualified_type(type_left);
+ type_t *const unqual_type_right = get_unqualified_type(type_right);
+ if (types_compatible(unqual_type_left, unqual_type_right)) {
+ return orig_type_left;
+ }
}
-incompatible_assign_types:
- /* TODO: improve error message */
- errorf(HERE, "incompatible types in %s: '%T' <- '%T'",
- context, orig_type_left, orig_type_right);
+ return NULL;
}
static expression_t *parse_constant_expression(void)
}
}
- type_t *expression_type = skip_typeref(expression->base.datatype);
- if(is_type_scalar(type) || types_compatible(type, expression_type)) {
- semantic_assign(type, &expression, "initializer");
-
- initializer_t *result = allocate_initializer_zero(INITIALIZER_VALUE);
- result->value.value = expression;
+ type_t *const res_type = semantic_assign(type, expression, "initializer");
+ if (res_type == NULL)
+ return NULL;
- return result;
- }
+ initializer_t *const result = allocate_initializer_zero(INITIALIZER_VALUE);
+ result->value.value = create_implicit_cast(expression, res_type);
- return NULL;
+ return result;
}
static initializer_t *parse_sub_initializer(type_t *type,
}
break;
- /* TODO: if type != NULL for the following rules should issue
+ /* TODO: if is_type_valid(type) for the following rules should issue
* an error */
case T_struct: {
type = allocate_type_zero(TYPE_COMPOUND_STRUCT);
errorf(declaration->source_position, "static declaration of '%Y' follows non-static declaration", symbol);
errorf(previous_declaration->source_position, "previous declaration of '%Y' was here", symbol);
} else {
- if (old_storage_class != STORAGE_CLASS_EXTERN) {
+ if (old_storage_class != STORAGE_CLASS_EXTERN && !is_function_definition) {
goto warn_redundant_declaration;
}
if (new_storage_class == STORAGE_CLASS_NONE) {
return append_declaration(declaration);
}
+/**
+ * Check if a given type is a vilid array type.
+ */
+static bool is_valid_array_type(const type_t *type) {
+ if (type->kind == TYPE_ARRAY) {
+ const array_type_t *array = &type->array;
+ const type_t *etype = skip_typeref(array->element_type);
+
+ if (! is_valid_array_type(etype))
+ return false;
+
+ if (etype->kind == TYPE_ATOMIC) {
+ const atomic_type_t *atype = &etype->atomic;
+
+ if (atype->akind == ATOMIC_TYPE_VOID) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
static declaration_t *record_declaration(declaration_t *declaration)
{
- return internal_record_declaration(declaration, false);
+ declaration = internal_record_declaration(declaration, false);
+ const type_t *type = skip_typeref(declaration->type);
+
+ /* check the type here for several not allowed combinations */
+ if (type->kind == TYPE_FUNCTION) {
+ const function_type_t* function_type = &type->function;
+ const type_t* ret_type = skip_typeref(function_type->return_type);
+
+ if (ret_type->kind == TYPE_FUNCTION) {
+ errorf(declaration->source_position, "'%Y' declared as function returning a function",
+ declaration->symbol);
+ declaration->type = type_error_type;
+ } else if (ret_type->kind == TYPE_ARRAY) {
+ errorf(declaration->source_position, "'%Y' declared as function returning an array",
+ declaration->symbol);
+ declaration->type = type_error_type;
+ }
+ }
+ if (! is_valid_array_type(type)) {
+ errorf(declaration->source_position, "declaration of '%Y' as array of voids",
+ declaration->symbol);
+ declaration->type = type_error_type;
+ }
+ return declaration;
}
static declaration_t *record_function_definition(declaration_t *const declaration)
eat('=');
type_t *orig_type = declaration->type;
- type_t *type = NULL;
- if(orig_type != NULL)
- type = skip_typeref(orig_type);
+ type_t *type = type = skip_typeref(orig_type);
if(declaration->init.initializer != NULL) {
parser_error_multiple_definition(declaration, token.source_position);
/* § 6.7.5 (22) array initializers for arrays with unknown size determine
* the array type size */
- if(type != NULL && is_type_array(type) && initializer != NULL) {
+ if(is_type_array(type) && initializer != NULL) {
array_type_t *array_type = &type->array;
if(array_type->size == NULL) {
}
}
- if(type != NULL && is_type_function(type)) {
+ if(is_type_function(type)) {
errorf(declaration->source_position,
"initializers not allowed for function types at declator '%Y' (type '%T')",
declaration->symbol, orig_type);
type_t *orig_type = declaration->type;
type_t *type = skip_typeref(orig_type);
- if(type->kind != TYPE_FUNCTION && declaration->is_inline) {
+ if(is_type_valid(type) &&
+ type->kind != TYPE_FUNCTION && declaration->is_inline) {
warningf(declaration->source_position,
"variable '%Y' declared 'inline'\n", declaration->symbol);
}
type_t *base_type = skip_typeref(type);
if (base_type->base.kind == TYPE_ATOMIC) {
- if (base_type->atomic.akind == ATOMIC_TYPE_CHAR) {
+ switch (base_type->atomic.akind == ATOMIC_TYPE_CHAR) {
warningf(expression->base.source_position,
"array subscript has type '%T'", type);
}
function_type_t *function_type = NULL;
type_t *orig_type = expression->base.datatype;
- if(orig_type != NULL) {
+ if(is_type_valid(orig_type)) {
type_t *type = skip_typeref(orig_type);
if(is_type_pointer(type)) {
/* 6.5.15.2 */
type_t *condition_type_orig = expression->base.datatype;
- if(condition_type_orig != NULL) {
+ if(is_type_valid(condition_type_orig)) {
type_t *condition_type = skip_typeref(condition_type_orig);
- if(condition_type != NULL && !is_type_scalar(condition_type)) {
+ if(condition_type->kind != TYPE_ERROR && !is_type_scalar(condition_type)) {
type_error("expected a scalar type in conditional condition",
expression->base.source_position, condition_type_orig);
}
type_t *orig_true_type = true_expression->base.datatype;
type_t *orig_false_type = false_expression->base.datatype;
- if(orig_true_type == NULL || orig_false_type == NULL)
+ if(!is_type_valid(orig_true_type) || !is_type_valid(orig_false_type))
return result;
type_t *true_type = skip_typeref(orig_true_type);
static void semantic_incdec(unary_expression_t *expression)
{
type_t *orig_type = expression->value->base.datatype;
- if(orig_type == NULL)
+ if(!is_type_valid(orig_type))
return;
type_t *type = skip_typeref(orig_type);
static void semantic_unexpr_arithmetic(unary_expression_t *expression)
{
type_t *orig_type = expression->value->base.datatype;
- if(orig_type == NULL)
+ if(!is_type_valid(orig_type))
return;
type_t *type = skip_typeref(orig_type);
static void semantic_unexpr_scalar(unary_expression_t *expression)
{
type_t *orig_type = expression->value->base.datatype;
- if(orig_type == NULL)
+ if(!is_type_valid(orig_type))
return;
type_t *type = skip_typeref(orig_type);
static void semantic_unexpr_integer(unary_expression_t *expression)
{
type_t *orig_type = expression->value->base.datatype;
- if(orig_type == NULL)
+ if(!is_type_valid(orig_type))
return;
type_t *type = skip_typeref(orig_type);
static void semantic_dereference(unary_expression_t *expression)
{
type_t *orig_type = expression->value->base.datatype;
- if(orig_type == NULL)
+ if(!is_type_valid(orig_type))
return;
type_t *type = skip_typeref(orig_type);
value->base.datatype = revert_automatic_type_conversion(value);
type_t *orig_type = value->base.datatype;
- if(orig_type == NULL)
+ if(!is_type_valid(orig_type))
return;
if(value->kind == EXPR_REFERENCE) {
return;
}
- semantic_assign(orig_type_left, &expression->right, "assignment");
+ type_t *const res_type = semantic_assign(orig_type_left, expression->right,
+ "assignment");
+ if (res_type == NULL) {
+ errorf(expression->expression.source_position,
+ "cannot assign to '%T' from '%T'",
+ orig_type_left, expression->right->base.datatype);
+ } else {
+ expression->right = create_implicit_cast(expression->right, res_type);
+ }
expression->expression.datatype = orig_type_left;
}
"'return' with a value, in function returning void");
return_value = NULL;
} else {
- if(return_type != NULL) {
- semantic_assign(return_type, &return_value, "'return'");
+ if(is_type_valid(return_type)) {
+ if (return_value->base.datatype == NULL)
+ return (statement_t*)statement;
+
+ type_t *const res_type = semantic_assign(return_type,
+ return_value, "'return'");
+ if (res_type == NULL) {
+ errorf(statement->statement.source_position,
+ "cannot assign to '%T' from '%T'",
+ "cannot return something of type '%T' in function returning '%T'",
+ return_value->base.datatype, return_type);
+ } else {
+ return_value = create_implicit_cast(return_value, res_type);
+ }
}
}
/* check for returning address of a local var */