From: Matthias Braun Date: Wed, 14 Nov 2007 19:46:41 +0000 (+0000) Subject: do correct semantic check/adjustment for initializers, makes the last fix unnecessary X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=3b491a136d937af49b07f0d46ad0022c37506ecb;p=cparser do correct semantic check/adjustment for initializers, makes the last fix unnecessary [r18397] --- diff --git a/ast2firm.c b/ast2firm.c index dc5d02f..9e27b84 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -1552,8 +1552,6 @@ static void create_initializer(declaration_t *declaration) set_value(declaration->v.value_number, init_node); } else { ir_entity *entity = declaration->v.entity; - ir_mode *mode = get_ir_mode(declaration->type); - init_node = create_conv(NULL, init_node, mode); set_entity_variability(entity, variability_initialized); set_atomic_ent_value(entity, init_node); diff --git a/parser.c b/parser.c index 43b4766..7d21c82 100644 --- a/parser.c +++ b/parser.c @@ -230,6 +230,28 @@ static void parse_error_expected(const char *message, ...) fprintf(stderr, "\n"); } +static void type_error(const char *msg, const source_position_t source_position, + type_t *type) +{ + parser_print_error_prefix_pos(source_position); + fprintf(stderr, "%s, but found type ", msg); + print_type(type); + fputc('\n', stderr); + error(); +} + +static void type_error_incompatible(const char *msg, + const source_position_t source_position, type_t *type1, type_t *type2) +{ + parser_print_error_prefix_pos(source_position); + fprintf(stderr, "%s, incompatible types: ", msg); + print_type(type1); + fprintf(stderr, " - "); + print_type(type2); + fprintf(stderr, ")\n"); + error(); +} + static void eat_block(void) { if(token.type == '{') @@ -465,6 +487,106 @@ static void environment_pop_to(size_t new_top) } +static int get_rank(const type_t *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. + * (unsigned int would be preferable when possible... for stuff like + * struct { enum { ... } bla : 4; } ) */ + if(type->type == TYPE_ENUM) + return ATOMIC_TYPE_INT; + + assert(type->type == TYPE_ATOMIC); + atomic_type_t *atomic_type = (atomic_type_t*) type; + atomic_type_type_t atype = atomic_type->atype; + return atype; +} + +static type_t *promote_integer(type_t *type) +{ + if(get_rank(type) < ATOMIC_TYPE_INT) + type = type_int; + + return type; +} + +static expression_t *create_cast_expression(expression_t *expression, + type_t *dest_type) +{ + unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0])); + + cast->expression.type = EXPR_UNARY; + cast->type = UNEXPR_CAST; + cast->value = expression; + cast->expression.datatype = dest_type; + + return (expression_t*) cast; +} + +static expression_t *create_implicit_cast(expression_t *expression, + type_t *dest_type) +{ + assert(expression->datatype != NULL); + type_t *source_type = expression->datatype; + + if(expression->datatype == dest_type) + return expression; + + if(dest_type->type == TYPE_ATOMIC) { + if(source_type->type != TYPE_ATOMIC) + panic("casting of non-atomic types not implemented yet"); + + if(is_type_floating(dest_type) && !is_type_scalar(source_type)) { + type_error_incompatible("can't cast types", + expression->source_position, + source_type, dest_type); + return expression; + } + + return create_cast_expression(expression, dest_type); + } + if(dest_type->type == TYPE_POINTER) { + if(source_type->type == TYPE_POINTER) { + if(!pointers_compatible(source_type, dest_type)) { + type_error_incompatible("can't implicitely cast types", + expression->source_position, + source_type, dest_type); + } else { + return create_cast_expression(expression, dest_type); + } + } + } + + panic("casting of non-atomic types not implemented yet"); +} + +static void semantic_assign(type_t *orig_type_left, expression_t **right, + const char *context) +{ + type_t *orig_type_right = (*right)->datatype; + type_t *type_left = skip_typeref(orig_type_left); + type_t *type_right = skip_typeref(orig_type_right); + + if(type_left == type_right) { + /* fine */ + } else if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { + *right = create_implicit_cast(*right, type_left); + } else if(type_left->type == TYPE_POINTER + && type_right->type == TYPE_POINTER) { + /* TODO */ + } else { + /* TODO: improve error message */ + parser_print_error_prefix(); + fprintf(stderr, "incompatible types in %s\n", context); + parser_print_error_prefix(); + print_type(type_left); + fputs(" <- ", stderr); + print_type(type_right); + fputs("\n", stderr); + } + +} static expression_t *parse_constant_expression(void) { @@ -596,35 +718,42 @@ static designator_t *parse_designation(void) } } -static initializer_t *parse_initializer_list(void); +static initializer_t *parse_initializer_list(type_t *type); -static initializer_t *parse_initializer(void) +static initializer_t *parse_initializer(type_t *type) { designator_t *designator = parse_designation(); initializer_t *result; if(token.type == '{') { - result = parse_initializer_list(); + result = parse_initializer_list(type); } else { result = allocate_ast_zero(sizeof(result[0])); result->type = INITIALIZER_VALUE; result->v.value = parse_assignment_expression(); + + if(type != NULL) { + semantic_assign(type, &result->v.value, "initializer"); + } } result->designator = designator; return result; } -static initializer_t *parse_initializer_list(void) +static initializer_t *parse_initializer_list(type_t *type) { eat('{'); + /* TODO: semantic */ + (void) type; + initializer_t *result = allocate_ast_zero(sizeof(result[0])); result->type = INITIALIZER_LIST; initializer_t *last = NULL; while(1) { - initializer_t *initializer = parse_initializer(); + initializer_t *initializer = parse_initializer(NULL); if(last != NULL) { last->next = initializer; } else { @@ -748,7 +877,7 @@ static void parse_enum_entries(void) if(token.type == '=') { next_token(); - entry->init.initializer = parse_initializer(); + entry->init.initializer = parse_initializer(type_int); } record_declaration(entry); @@ -1621,7 +1750,7 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers) parser_error_multiple_definition(declaration, ndeclaration); } - ndeclaration->init.initializer = parse_initializer(); + ndeclaration->init.initializer = parse_initializer(declaration->type); } else if(token.type == '{') { if(declaration->type->type != TYPE_FUNCTION) { parser_print_error_prefix(); @@ -2250,102 +2379,6 @@ static expression_t *parse_select_expression(unsigned precedence, return (expression_t*) select; } -static expression_t *create_cast_expression(expression_t *expression, - type_t *dest_type) -{ - unary_expression_t *cast = allocate_ast_zero(sizeof(cast[0])); - - cast->expression.type = EXPR_UNARY; - cast->type = UNEXPR_CAST; - cast->value = expression; - cast->expression.datatype = dest_type; - - return (expression_t*) cast; -} - -static void type_error(const char *msg, const source_position_t source_position, - type_t *type) -{ - parser_print_error_prefix_pos(source_position); - fprintf(stderr, "%s, but found type ", msg); - print_type(type); - fputc('\n', stderr); - error(); -} - -static void type_error_incompatible(const char *msg, - const source_position_t source_position, type_t *type1, type_t *type2) -{ - parser_print_error_prefix_pos(source_position); - fprintf(stderr, "%s, incompatible types: ", msg); - print_type(type1); - fprintf(stderr, " - "); - print_type(type2); - fprintf(stderr, ")\n"); - error(); -} - -static int get_rank(const type_t *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. - * (unsigned int would be preferable when possible... for stuff like - * struct { enum { ... } bla : 4; } ) */ - if(type->type == TYPE_ENUM) - return ATOMIC_TYPE_INT; - - assert(type->type == TYPE_ATOMIC); - atomic_type_t *atomic_type = (atomic_type_t*) type; - atomic_type_type_t atype = atomic_type->atype; - return atype; -} - -static type_t *promote_integer(type_t *type) -{ - if(get_rank(type) < ATOMIC_TYPE_INT) - type = type_int; - - return type; -} - -static expression_t *create_implicit_cast(expression_t *expression, - type_t *dest_type) -{ - assert(expression->datatype != NULL); - type_t *source_type = expression->datatype; - - if(expression->datatype == dest_type) - return expression; - - if(dest_type->type == TYPE_ATOMIC) { - if(source_type->type != TYPE_ATOMIC) - panic("casting of non-atomic types not implemented yet"); - - if(is_type_floating(dest_type) && !is_type_scalar(source_type)) { - type_error_incompatible("can't cast types", - expression->source_position, - source_type, dest_type); - return expression; - } - - return create_cast_expression(expression, dest_type); - } - if(dest_type->type == TYPE_POINTER) { - if(source_type->type == TYPE_POINTER) { - if(!pointers_compatible(source_type, dest_type)) { - type_error_incompatible("can't implicitely cast types", - expression->source_position, - source_type, dest_type); - } else { - return create_cast_expression(expression, dest_type); - } - } - } - - panic("casting of non-atomic types not implemented yet"); -} - static expression_t *parse_call_expression(unsigned precedence, expression_t *expression) { @@ -2761,40 +2794,12 @@ static void semantic_logical_op(binary_expression_t *expression) expression->expression.datatype = type_int; } -static void semantic_assign(type_t *orig_type_left, expression_t **right, - bool is_return) -{ - type_t *orig_type_right = (*right)->datatype; - type_t *type_left = skip_typeref(orig_type_left); - type_t *type_right = skip_typeref(orig_type_right); - - if(type_left == type_right) { - /* fine */ - } else if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { - *right = create_implicit_cast(*right, type_left); - } else if(type_left->type == TYPE_POINTER - && type_right->type == TYPE_POINTER) { - /* TODO */ - } else { - /* TODO: improve error message */ - parser_print_error_prefix(); - fprintf(stderr, "incompatible types in %s\n", - is_return ? "'return'" : "assignment"); - parser_print_error_prefix(); - print_type(type_left); - fputs(" <- ", stderr); - print_type(type_right); - fputs("\n", stderr); - } - -} - static void semantic_binexpr_assign(binary_expression_t *expression) { expression_t *left = expression->left; type_t *type_left = left->datatype; - semantic_assign(type_left, &expression->right, false); + semantic_assign(type_left, &expression->right, "assignment"); expression->expression.datatype = type_left; } @@ -3223,7 +3228,7 @@ static statement_t *parse_return(void) parse_warning("'return' with a value, in function returning void"); return_value = NULL; } else { - semantic_assign(return_type, &return_value, true); + semantic_assign(return_type, &return_value, "'return'"); } } else { return_value = NULL;