return true;
}
- /* shortcur, same types are always compatible */
- if(declaration->type == previous->type)
- return true;
-
- if (declaration->type->type == TYPE_FUNCTION &&
- previous->type->type == TYPE_FUNCTION) {
- function_type_t* const prev_func = &previous->type->function;
- function_type_t* const decl_func = &declaration->type->function;
-
- /* 1 of the 2 declarations might have unspecified parameters */
- if(decl_func->unspecified_parameters) {
- return true;
- } else if(prev_func->unspecified_parameters) {
- declaration->type = previous->type;
- return true;
- }
- }
+ type_t *type1 = skip_typeref(declaration->type);
+ type_t *type2 = skip_typeref(previous->type);
- /* TODO: not correct/complete yet */
- return false;
+ return types_compatible(type1, type2);
}
static declaration_t *get_declaration(symbol_t *symbol, namespace_t namespc)
&& previous_declaration->parent_context == context) {
if(!is_compatible_declaration(declaration, previous_declaration)) {
parser_print_error_prefix_pos(declaration->source_position);
- fprintf(stderr, "definition of symbol %s%s with type ",
+ fprintf(stderr, "definition of symbol '%s%s' with type ",
get_namespace_prefix(namespc), symbol->string);
print_type_quoted(declaration->type);
fputc('\n', stderr);
static int get_rank(const type_t *type)
{
+ assert(!is_typeref(type));
/* The C-standard allows promoting to int or unsigned int (see § 7.2.2
* and esp. footnote 108). However we can't fold constants (yet), so we
* can't decide wether unsigned int is possible, while int always works.
points_to_left = skip_typeref(points_to_left);
points_to_right = skip_typeref(points_to_right);
- 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;
- }
-
/* the left type has all qualifiers from the right type */
unsigned missing_qualifiers
= points_to_right->base.qualifiers & ~points_to_left->base.qualifiers;
return;
}
+ points_to_left = get_unqualified_type(points_to_left);
+ points_to_right = get_unqualified_type(points_to_right);
+
+ 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;
+ }
+
*right = create_implicit_cast(*right, type_left);
return;
}
/* TODO check that expression is a constant expression */
/* § 6.7.8.14/15 char array may be initialized by string literals */
- if(type->type == TYPE_ARRAY && expression->type == EXPR_STRING_LITERAL) {
+ if(is_type_array(type) && expression->type == EXPR_STRING_LITERAL) {
array_type_t *array_type = &type->array;
type_t *element_type = array_type->element_type;
}
}
- semantic_assign(type, &expression, "initializer");
+ 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(INITIALIZER_VALUE);
- result->value.value = expression;
+ initializer_t *result = allocate_initializer(INITIALIZER_VALUE);
+ result->value.value = expression;
- return result;
+ return result;
+ }
+
+ return NULL;
}
static initializer_t *parse_sub_initializer(type_t *type,
return initializer_from_expression(type, expression);
}
- /* TODO: ignore qualifiers, comparing pointers is probably
- * not correct */
- if(expression != NULL && expression_type == type) {
- initializer_t *result = allocate_initializer(INITIALIZER_VALUE);
-
- if(type != NULL) {
- semantic_assign(type, &expression, "initializer");
- }
- result->value.value = expression;
-
- return result;
+ /* does the expression match the currently looked at object to initalize */
+ if(expression != NULL) {
+ initializer_t *result = initializer_from_expression(type, expression);
+ if(result != NULL)
+ return result;
}
bool read_paren = false;
/* descend into subtype */
initializer_t *result = NULL;
initializer_t **elems;
- if(type->type == TYPE_ARRAY) {
+ if(is_type_array(type)) {
array_type_t *array_type = &type->array;
type_t *element_type = array_type->element_type;
element_type = skip_typeref(element_type);
if(token.type == '}')
break;
- sub = parse_sub_initializer(element_type, NULL, NULL);
+ sub = parse_sub_initializer_elem(element_type);
if(sub == NULL) {
/* TODO error, do nicer cleanup */
parse_error("member initializer didn't match");
ARR_APP1(initializer_t*, elems, sub);
}
} else {
- assert(type->type == TYPE_COMPOUND_STRUCT
- || type->type == TYPE_COMPOUND_UNION);
+ assert(is_type_compound(type));
compound_type_t *compound_type = &type->compound;
context_t *context = &compound_type->declaration->context;
type_t *iter_type = iter->type;
iter_type = skip_typeref(iter_type);
- sub = parse_sub_initializer(iter_type, NULL, NULL);
+ sub = parse_sub_initializer_elem(iter_type);
if(sub == NULL) {
/* TODO error, do nicer cleanup*/
parse_error("member initializer didn't match");
type = skip_typeref(type);
if(token.type != '{') {
- expression_t *expression = parse_assignment_expression();
- return initializer_from_expression(type, expression);
+ expression_t *expression = parse_assignment_expression();
+ initializer_t *initializer = initializer_from_expression(type, expression);
+ if(initializer == NULL) {
+ parser_print_error_prefix();
+ fprintf(stderr, "initializer expression '");
+ print_expression(expression);
+ fprintf(stderr, "', type ");
+ print_type_quoted(expression->base.datatype);
+ fprintf(stderr, " is incompatible with type ");
+ print_type_quoted(type);
+ fprintf(stderr, "\n");
+ }
+ return initializer;
}
if(is_type_scalar(type)) {
return declarations;
}
+static void semantic_parameter(declaration_t *declaration)
+{
+ /* TODO: improve error messages */
+
+ if(declaration->storage_class == STORAGE_CLASS_TYPEDEF) {
+ parse_error("typedef not allowed in parameter list");
+ } else if(declaration->storage_class != STORAGE_CLASS_NONE
+ && declaration->storage_class != STORAGE_CLASS_REGISTER) {
+ parse_error("parameter may only have none or register storage class");
+ }
+
+ type_t *orig_type = declaration->type;
+ if(orig_type == NULL)
+ return;
+ type_t *type = skip_typeref(orig_type);
+
+ /* Array as last part of a paramter type is just syntactic sugar. Turn it
+ * into a pointer. § 6.7.5.3 (7) */
+ if (is_type_array(type)) {
+ const array_type_t *arr_type = &type->array;
+ type_t *element_type = arr_type->element_type;
+
+ type = make_pointer_type(element_type, type->base.qualifiers);
+
+ declaration->type = type;
+ }
+
+ if(is_type_incomplete(type)) {
+ parser_print_error_prefix();
+ fprintf(stderr, "incomplete type (");
+ print_type_quoted(orig_type);
+ fprintf(stderr, ") not allowed for parameter '%s'\n",
+ declaration->symbol->string);
+ }
+}
+
static declaration_t *parse_parameter(void)
{
declaration_specifiers_t specifiers;
declaration_t *declaration = parse_declarator(&specifiers, true);
- /* TODO check declaration constraints for parameters */
- if(declaration->storage_class == STORAGE_CLASS_TYPEDEF) {
- parse_error("typedef not allowed in parameter list");
- }
-
- /* Array as last part of a paramter type is just syntactic sugar. Turn it
- * into a pointer */
- if (declaration->type->type == TYPE_ARRAY) {
- const array_type_t *const arr_type = &declaration->type->array;
- type_t *element_type = arr_type->element_type;
- declaration->type = make_pointer_type(element_type, TYPE_QUALIFIER_NONE);
- }
+ semantic_parameter(declaration);
return declaration;
}
type_t *function_type = construct_function_type->function_type;
- function_type->function.result_type = type;
+ function_type->function.return_type = type;
type = function_type;
break;
/* § 6.7.5 (22) array intializers for arrays with unknown size determine
* the array type size */
- if(type != NULL && type->type == TYPE_ARRAY && initializer != NULL) {
+ if(type != NULL && is_type_array(type) && initializer != NULL) {
array_type_t *array_type = &type->array;
if(array_type->size == NULL) {
}
}
- if(type != NULL && type->type == TYPE_FUNCTION) {
+ if(type != NULL && is_type_function(type)) {
parser_print_error_prefix_pos(declaration->source_position);
fprintf(stderr, "initializers not allowed for function types at "
"declator '%s' (type ", declaration->symbol->string);
static void parse_kr_declaration_list(declaration_t *declaration)
{
type_t *type = skip_typeref(declaration->type);
- assert(type->type == TYPE_FUNCTION);
+ assert(is_type_function(type));
if(!type->function.kr_style_parameters)
return;
#endif
}
+ semantic_parameter(parameter_declaration);
+ parameter_type = parameter_declaration->type;
+
function_parameter_t *function_parameter
= obstack_alloc(type_obst, sizeof(function_parameter[0]));
memset(function_parameter, 0, sizeof(function_parameter[0]));
return;
}
- type_t *orig_type = ndeclaration->type;
- if(orig_type == NULL) {
+ type_t *type = ndeclaration->type;
+ if(type == NULL) {
eat_block();
return;
}
- type_t *type = skip_typeref(orig_type);
+ /* 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->type != TYPE_FUNCTION) {
parser_print_error_prefix();
fprintf(stderr, "declarator '");
- print_type_ext(orig_type, ndeclaration->symbol, NULL);
+ print_type_ext(type, ndeclaration->symbol, NULL);
fprintf(stderr, "' has a body but is not a function type.\n");
eat_block();
return;
const source_position_t source_position)
{
type_t *ntype = allocate_type_zero(TYPE_FUNCTION);
- ntype->function.result_type = type_int;
+ ntype->function.return_type = type_int;
ntype->function.unspecified_parameters = true;
type_t *type = typehash_insert(ntype);
return declaration;
}
-static type_t *make_function_1_type(type_t *result_type, type_t *argument_type)
+static type_t *make_function_1_type(type_t *return_type, type_t *argument_type)
{
function_parameter_t *parameter
= obstack_alloc(type_obst, sizeof(parameter[0]));
parameter->type = argument_type;
type_t *type = allocate_type_zero(TYPE_FUNCTION);
- type->function.result_type = result_type;
+ type->function.return_type = return_type;
type->function.parameters = parameter;
type_t *result = typehash_insert(type);
/**
* performs automatic type cast as described in § 6.3.2.1
*/
-static type_t *automatic_type_conversion(type_t *type)
+static type_t *automatic_type_conversion(type_t *orig_type)
{
- if(type == NULL)
+ if(orig_type == NULL)
return NULL;
- if(type->type == TYPE_ARRAY) {
+ type_t *type = skip_typeref(orig_type);
+ if(is_type_array(type)) {
array_type_t *array_type = &type->array;
type_t *element_type = array_type->element_type;
unsigned qualifiers = array_type->type.qualifiers;
return make_pointer_type(element_type, qualifiers);
}
- if(type->type == TYPE_FUNCTION) {
- return make_pointer_type(type, TYPE_QUALIFIER_NONE);
+ if(is_type_function(type)) {
+ return make_pointer_type(orig_type, TYPE_QUALIFIER_NONE);
}
- return type;
+ return orig_type;
}
/**
type_t *type_left = left->base.datatype;
type_t *type_inside = inside->base.datatype;
- type_t *result_type = NULL;
+ type_t *return_type = NULL;
if(type_left != NULL && type_inside != NULL) {
type_left = skip_typeref(type_left);
if(is_type_pointer(type_left)) {
pointer_type_t *pointer = &type_left->pointer;
- result_type = pointer->points_to;
+ return_type = pointer->points_to;
array_access->array_ref = left;
array_access->index = inside;
} else if(is_type_pointer(type_inside)) {
pointer_type_t *pointer = &type_inside->pointer;
- result_type = pointer->points_to;
+ return_type = pointer->points_to;
array_access->array_ref = inside;
array_access->index = left;
array_access->flipped = true;
}
next_token();
- result_type = automatic_type_conversion(result_type);
- array_access->expression.datatype = result_type;
+ return_type = automatic_type_conversion(return_type);
+ array_access->expression.datatype = return_type;
return (expression_t*) array_access;
}
type = skip_typeref(pointer_type->points_to);
- if (type->type == TYPE_FUNCTION) {
+ if (is_type_function(type)) {
function_type = &type->function;
- call->expression.datatype = function_type->result_type;
+ call->expression.datatype = function_type->return_type;
}
}
if(function_type == NULL) {
expression->right = create_implicit_cast(right, arithmetic_type);
expression->expression.datatype = arithmetic_type;
return;
- } else if(type_left->type == TYPE_POINTER && is_type_integer(type_right)) {
+ } else if(is_type_pointer(type_left) && is_type_integer(type_right)) {
expression->expression.datatype = type_left;
- } else if(type_left->type == TYPE_POINTER &&
- type_right->type == TYPE_POINTER) {
+ } else if(is_type_pointer(type_left) && is_type_pointer(type_right)) {
if(!pointers_compatible(type_left, type_right)) {
parser_print_error_prefix();
fprintf(stderr, "pointers to incompatible objects to binary - (");
expression->left = create_implicit_cast(left, arithmetic_type);
expression->right = create_implicit_cast(right, arithmetic_type);
expression->expression.datatype = arithmetic_type;
- } else if (type_left->type == TYPE_POINTER &&
- type_right->type == TYPE_POINTER) {
+ } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) {
/* TODO check compatibility */
- } else if (type_left->type == TYPE_POINTER) {
+ } else if (is_type_pointer(type_left)) {
expression->right = create_implicit_cast(right, type_left);
- } else if (type_right->type == TYPE_POINTER) {
+ } else if (is_type_pointer(type_right)) {
expression->left = create_implicit_cast(left, type_right);
} else {
type_error_incompatible("invalid operands in comparison",
type_t *const arithmetic_type = semantic_arithmetic(type_left, type_right);
expression->right = create_implicit_cast(right, arithmetic_type);
expression->expression.datatype = type_left;
- } else if (type_left->type == TYPE_POINTER && is_type_integer(type_right)) {
+ } else if (is_type_pointer(type_left) && is_type_integer(type_right)) {
expression->expression.datatype = type_left;
} else {
parser_print_error_prefix();
return;
type_t *type_left = revert_automatic_type_conversion(left);
- type_left = skip_typeref(orig_type_left);
+ type_left = skip_typeref(orig_type_left);
/* must be a modifiable lvalue */
- if (type_left->type == TYPE_ARRAY) {
+ if (is_type_array(type_left)) {
parser_print_error_prefix();
fprintf(stderr, "Cannot assign to arrays ('");
print_expression(left);
statement->statement.type = STATEMENT_RETURN;
statement->statement.source_position = token.source_position;
- assert(current_function->type->type == TYPE_FUNCTION);
+ assert(is_type_function(current_function->type));
function_type_t *function_type = ¤t_function->type->function;
- type_t *return_type = function_type->result_type;
+ type_t *return_type = function_type->return_type;
expression_t *return_value = NULL;
if(token.type != ';') {