X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=fa8ad94f977422dbd48bb2c680b7078d65e83042;hb=11839325c556fdf4b749c536bb0966bb0565c4d7;hp=eedba78d7d57714c81e1fe191d1f899dc614f0bd;hpb=bff9aceb1231eab3e5d18f63270283a337b173a0;p=cparser diff --git a/parser.c b/parser.c index eedba78..fa8ad94 100644 --- a/parser.c +++ b/parser.c @@ -705,6 +705,27 @@ static expression_t *create_implicit_cast(expression_t *expression, panic("casting of non-atomic types not implemented yet"); } +static bool is_atomic_type(const type_t *type, atomic_type_type_t atype) +{ + if(type->type != TYPE_ATOMIC) + return false; + const atomic_type_t *atomic_type = (const atomic_type_t*) type; + + return atomic_type->atype == atype; +} + +static bool is_pointer(const type_t *type) +{ + return type->type == TYPE_POINTER; +} + +static bool is_compound_type(const type_t *type) +{ + return type->type == TYPE_COMPOUND_STRUCT + || type->type == TYPE_COMPOUND_UNION; +} + +/** Implements the rules from § 6.5.16.1 */ static void semantic_assign(type_t *orig_type_left, expression_t **right, const char *context) { @@ -716,40 +737,52 @@ static void semantic_assign(type_t *orig_type_left, expression_t **right, type_t *const type_left = skip_typeref(orig_type_left); type_t *const type_right = skip_typeref(orig_type_right); - if (type_left == type_right) { - return; - } - if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) || - (type_left->type == TYPE_POINTER && is_null_expression(*right)) || - (type_left->type == TYPE_POINTER && type_right->type == TYPE_POINTER)) { + (is_pointer(type_left) && is_null_expression(*right)) || + (is_atomic_type(type_left, ATOMIC_TYPE_BOOL) + && is_pointer(type_right))) { *right = create_implicit_cast(*right, type_left); return; } - if (type_left->type == TYPE_POINTER) { - switch (type_right->type) { - case TYPE_FUNCTION: { - pointer_type_t *const ptr_type = (pointer_type_t*)type_left; - if (ptr_type->points_to == type_right) { - return; - } - break; - } + if (is_pointer(type_left) && is_pointer(type_right)) { + pointer_type_t *pointer_type_left = (pointer_type_t*) type_left; + pointer_type_t *pointer_type_right = (pointer_type_t*) type_right; + type_t *points_to_left = pointer_type_left->points_to; + type_t *points_to_right = pointer_type_right->points_to; - case TYPE_ARRAY: { - pointer_type_t *const ptr_type = (pointer_type_t*)type_left; - array_type_t *const arr_type = (array_type_t*)type_right; - if (ptr_type->points_to == arr_type->element_type) { - return; - } - break; - } + if(!is_atomic_type(points_to_left, ATOMIC_TYPE_VOID) + && !is_atomic_type(points_to_right, ATOMIC_TYPE_VOID) + && !types_compatible(points_to_left, points_to_right)) { + goto incompatible_assign_types; + } - default: break; + /* the left type has all qualifiers from the right type */ + unsigned missing_qualifiers + = points_to_right->qualifiers & ~points_to_left->qualifiers; + if(missing_qualifiers != 0) { + parser_print_error_prefix(); + fprintf(stderr, "destination type "); + print_type_quoted(type_left); + fprintf(stderr, " in %s from type ", context); + print_type_quoted(type_right); + fprintf(stderr, " lacks qualifiers '"); + print_type_qualifiers(missing_qualifiers); + fprintf(stderr, "' in pointed-to type\n"); + return; } + + *right = create_implicit_cast(*right, type_left); + return; } + if (is_compound_type(type_left) + && types_compatible(type_left, type_right)) { + *right = create_implicit_cast(*right, type_left); + return; + } + +incompatible_assign_types: /* TODO: improve error message */ parser_print_error_prefix(); fprintf(stderr, "incompatible types in %s\n", context); @@ -894,10 +927,24 @@ static designator_t *parse_designation(void) } #endif +static initializer_t *initializer_from_string(array_type_t *type, + const char *string) +{ + /* TODO: check len vs. size of array type */ + (void) type; + + initializer_string_t *initializer + = allocate_ast_zero(sizeof(initializer[0])); + + initializer->initializer.type = INITIALIZER_STRING; + initializer->string = string; + + return (initializer_t*) initializer; +} + static initializer_t *initializer_from_expression(type_t *type, expression_t *expression) { - initializer_value_t *result = allocate_ast_zero(sizeof(result[0])); /* TODO check that expression is a constant expression */ @@ -914,15 +961,16 @@ static initializer_t *initializer_from_expression(type_t *type, if(atype == ATOMIC_TYPE_CHAR || atype == ATOMIC_TYPE_SCHAR || atype == ATOMIC_TYPE_UCHAR) { - /* it's fine TODO: check for length of string array... */ - goto initializer_from_expression_finished; + + string_literal_t *literal = (string_literal_t*) expression; + return initializer_from_string(array_type, literal->value); } } } semantic_assign(type, &expression, "initializer"); -initializer_from_expression_finished: + initializer_value_t *result = allocate_ast_zero(sizeof(result[0])); result->initializer.type = INITIALIZER_VALUE; result->value = expression; @@ -1024,6 +1072,8 @@ static initializer_t *parse_sub_initializer(type_t *type, if(token.type == '}') break; expect_block(','); + if(token.type == '}') + break; initializer_t *sub = parse_sub_initializer(element_type, NULL, NULL); @@ -2162,9 +2212,6 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers) initializer_t *initializer = parse_initializer(type); if(type->type == TYPE_ARRAY && initializer != NULL) { - assert(initializer->type == INITIALIZER_LIST); - - initializer_list_t *list = (initializer_list_t*) initializer; array_type_t *array_type = (array_type_t*) type; if(array_type->size == NULL) { @@ -2172,7 +2219,17 @@ static void parse_init_declarators(const declaration_specifiers_t *specifiers) cnst->expression.type = EXPR_CONST; cnst->expression.datatype = type_size_t; - cnst->v.int_value = list->len; + + if(initializer->type == INITIALIZER_LIST) { + initializer_list_t *list + = (initializer_list_t*) initializer; + cnst->v.int_value = list->len; + } else { + assert(initializer->type == INITIALIZER_STRING); + initializer_string_t *string + = (initializer_string_t*) initializer; + cnst->v.int_value = strlen(string->string) + 1; + } array_type->size = (expression_t*) cnst; } @@ -3605,19 +3662,31 @@ static void semantic_logical_op(binary_expression_t *expression) static void semantic_binexpr_assign(binary_expression_t *expression) { - expression_t *left = expression->left; - type_t *type_left = left->datatype; + expression_t *left = expression->left; + type_t *orig_type_left = left->datatype; - if(type_left == NULL) + if(orig_type_left == NULL) return; + type_t *type_left = skip_typeref(orig_type_left); + if (type_left->type == TYPE_ARRAY) { parse_error("Cannot assign to arrays."); - } else if (type_left != NULL) { - semantic_assign(type_left, &expression->right, "assignment"); + return; } - expression->expression.datatype = type_left; + if(type_left->qualifiers & TYPE_QUALIFIER_CONST) { + parser_print_error_prefix(); + fprintf(stderr, "assignment to readonly location '"); + print_expression(left); + fprintf(stderr, "' (type "); + print_type_quoted(orig_type_left); + fprintf(stderr, ")\n"); + } + + semantic_assign(orig_type_left, &expression->right, "assignment"); + + expression->expression.datatype = orig_type_left; } static void semantic_comma(binary_expression_t *expression)