X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=6715131f79afd944860711dd2154b88daf3f99ea;hb=f017f4f5080052f95185056b3af472ab737bc64a;hp=bb29247588f80303994e006e5fbc0ec8fbdd4e4d;hpb=09527515b3f2d630abff8304689f98dc82d128f5;p=cparser diff --git a/parser.c b/parser.c index bb29247..6715131 100644 --- a/parser.c +++ b/parser.c @@ -31,7 +31,7 @@ typedef struct { typedef struct declaration_specifiers_t declaration_specifiers_t; struct declaration_specifiers_t { source_position_t source_position; - unsigned char storage_class; + unsigned char declared_storage_class; bool is_inline; decl_modifiers_t decl_modifiers; type_t *type; @@ -809,11 +809,12 @@ static type_t *make_global_typedef(const char *name, type_t *type) symbol_t *const symbol = symbol_table_insert(name); declaration_t *const declaration = allocate_declaration_zero(); - declaration->namespc = NAMESPACE_NORMAL; - declaration->storage_class = STORAGE_CLASS_TYPEDEF; - declaration->type = type; - declaration->symbol = symbol; - declaration->source_position = builtin_source_position; + declaration->namespc = NAMESPACE_NORMAL; + declaration->storage_class = STORAGE_CLASS_TYPEDEF; + declaration->declared_storage_class = STORAGE_CLASS_TYPEDEF; + declaration->type = type; + declaration->symbol = symbol; + declaration->source_position = builtin_source_position; record_declaration(declaration); @@ -1003,7 +1004,14 @@ static initializer_t *initializer_from_expression(type_t *orig_type, return result; } -static initializer_t *parse_scalar_initializer(type_t *type) +static bool is_initializer_constant(const expression_t *expression) +{ + return is_constant_expression(expression) + || is_address_constant(expression); +} + +static initializer_t *parse_scalar_initializer(type_t *type, + bool must_be_constant) { /* there might be extra {} hierarchies */ int braces = 0; @@ -1015,7 +1023,13 @@ static initializer_t *parse_scalar_initializer(type_t *type) braces++; } - expression_t *expression = parse_assignment_expression(); + expression_t *expression = parse_assignment_expression(); + if(must_be_constant && !is_initializer_constant(expression)) { + errorf(expression->base.source_position, + "Initialisation expression '%E' is not constant\n", + expression); + } + initializer_t *initializer = initializer_from_expression(type, expression); if(initializer == NULL) { @@ -1056,11 +1070,13 @@ struct type_path_entry_t { typedef struct type_path_t type_path_t; struct type_path_t { type_path_entry_t *path; - type_t *top_type; + type_t *top_type; /**< type of the element the path points */ + size_t max_index; /**< largest index in outermost array */ bool invalid; }; -static __attribute__((unused)) void debug_print_type_path(const type_path_t *path) +static __attribute__((unused)) void debug_print_type_path( + const type_path_t *path) { size_t len = ARR_LEN(path->path); @@ -1304,7 +1320,7 @@ static void skip_initializers(void) } static initializer_t *parse_sub_initializer(type_path_t *path, - type_t *outer_type, size_t top_path_level) + type_t *outer_type, size_t top_path_level, bool must_be_constant) { type_t *orig_type = path->top_type; type_t *type = skip_typeref(orig_type); @@ -1340,12 +1356,13 @@ static initializer_t *parse_sub_initializer(type_path_t *path, if(token.type == '{') { if(is_type_scalar(type)) { - sub = parse_scalar_initializer(type); + sub = parse_scalar_initializer(type, must_be_constant); } else { eat('{'); descend_into_subtype(path); - sub = parse_sub_initializer(path, orig_type, top_path_level+1); + sub = parse_sub_initializer(path, orig_type, top_path_level+1, + must_be_constant); ascend_from_subtype(path); @@ -1355,6 +1372,12 @@ static initializer_t *parse_sub_initializer(type_path_t *path, /* must be an expression */ expression_t *expression = parse_assignment_expression(); + if(must_be_constant && !is_initializer_constant(expression)) { + errorf(expression->base.source_position, + "Initialisation expression '%E' is not constant\n", + expression); + } + /* handle { "string" } special case */ if((expression->kind == EXPR_STRING_LITERAL || expression->kind == EXPR_WIDE_STRING_LITERAL) @@ -1395,6 +1418,18 @@ static initializer_t *parse_sub_initializer(type_path_t *path, descend_into_subtype(path); } } + + /* update largest index of top array */ + const type_path_entry_t *first = &path->path[0]; + type_t *first_type = first->type; + first_type = skip_typeref(first_type); + if(is_type_array(first_type)) { + size_t index = first->v.index; + if(index > path->max_index) + path->max_index = index; + } + + /* append to initializers list */ ARR_APP1(initializer_t*, initializers, sub); if(token.type == '}') { @@ -1404,7 +1439,10 @@ static initializer_t *parse_sub_initializer(type_path_t *path, if(token.type == '}') { break; } + advance_current_object(path, top_path_level); + orig_type = path->top_type; + type = skip_typeref(orig_type); } size_t len = ARR_LEN(initializers); @@ -1417,8 +1455,6 @@ static initializer_t *parse_sub_initializer(type_path_t *path, ascend_to(path, top_path_level); - /* TODO: if(is_global && !is_constant(...)) { error } */ - return result; end_error: @@ -1428,52 +1464,81 @@ end_error: return NULL; } -static initializer_t *parse_initializer(type_t *const orig_type) -{ - initializer_t *result; - - type_t *const type = skip_typeref(orig_type); +typedef struct parse_initializer_env_t { + type_t *type; /* the type of the initializer. In case of an + array type with unspecified size this gets + adjusted to the actual size. */ + initializer_t *initializer; /* initializer will be filled in here */ + bool must_be_constant; +} parse_initializer_env_t; - if(token.type != '{') { - expression_t *expression = parse_assignment_expression(); - initializer_t *initializer = initializer_from_expression(type, expression); - if(initializer == NULL) { - errorf(HERE, - "initializer expression '%E' of type '%T' is incompatible with type '%T'", - expression, expression->base.type, orig_type); - } - return initializer; - } +static void parse_initializer(parse_initializer_env_t *env) +{ + type_t *type = skip_typeref(env->type); + initializer_t *result = NULL; + size_t max_index; if(is_type_scalar(type)) { /* TODO: § 6.7.8.11; eat {} without warning */ - - result = parse_scalar_initializer(type); - - if(token.type == ',') - next_token(); - - return result; + result = parse_scalar_initializer(type, env->must_be_constant); } else if(token.type == '{') { - next_token(); + eat('{'); type_path_t path; memset(&path, 0, sizeof(path)); - path.top_type = orig_type; + path.top_type = env->type; path.path = NEW_ARR_F(type_path_entry_t, 0); descend_into_subtype(&path); - result = parse_sub_initializer(&path, orig_type, 1); + result = parse_sub_initializer(&path, env->type, 1, + env->must_be_constant); + max_index = path.max_index; DEL_ARR_F(path.path); - expect('}'); + expect_void('}'); } else { - /* TODO ... */ + /* parse_scalar_initializer also works in this case: we simply + * have an expression without {} around it */ + result = parse_scalar_initializer(type, env->must_be_constant); } - return result; + /* § 6.7.5 (22) array initializers for arrays with unknown size determine + * the array type size */ + if(is_type_array(type) && type->array.size_expression == NULL + && result != NULL) { + size_t size; + switch (result->kind) { + case INITIALIZER_LIST: + size = max_index + 1; + break; + + case INITIALIZER_STRING: + size = result->string.string.size; + break; + + case INITIALIZER_WIDE_STRING: + size = result->wide_string.string.size; + break; + + default: + panic("invalid initializer type"); + } + + expression_t *cnst = allocate_expression_zero(EXPR_CONST); + cnst->base.type = type_size_t; + cnst->conste.v.int_value = size; + + type_t *new_type = duplicate_type(type); + + new_type->array.size_expression = cnst; + new_type->array.size_constant = true; + new_type->array.size = size; + env->type = new_type; + } + + env->initializer = result; } static declaration_t *append_declaration(declaration_t *declaration); @@ -1570,7 +1635,10 @@ static void parse_enum_entries(type_t *const enum_type) if(token.type == '=') { next_token(); - entry->init.enum_value = parse_constant_expression(); + expression_t *value = parse_constant_expression(); + + value = create_implicit_cast(value, enum_type); + entry->init.enum_value = value; /* TODO semantic */ } @@ -1753,13 +1821,13 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) switch(token.type) { /* storage class */ -#define MATCH_STORAGE_CLASS(token, class) \ - case token: \ - if(specifiers->storage_class != STORAGE_CLASS_NONE) { \ +#define MATCH_STORAGE_CLASS(token, class) \ + case token: \ + if(specifiers->declared_storage_class != STORAGE_CLASS_NONE) { \ errorf(HERE, "multiple storage classes in declaration specifiers"); \ - } \ - specifiers->storage_class = class; \ - next_token(); \ + } \ + specifiers->declared_storage_class = class; \ + next_token(); \ break; MATCH_STORAGE_CLASS(T_typedef, STORAGE_CLASS_TYPEDEF) @@ -1769,22 +1837,22 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) MATCH_STORAGE_CLASS(T_register, STORAGE_CLASS_REGISTER) case T___thread: - switch (specifiers->storage_class) { - case STORAGE_CLASS_NONE: - specifiers->storage_class = STORAGE_CLASS_THREAD; - break; + switch (specifiers->declared_storage_class) { + case STORAGE_CLASS_NONE: + specifiers->declared_storage_class = STORAGE_CLASS_THREAD; + break; - case STORAGE_CLASS_EXTERN: - specifiers->storage_class = STORAGE_CLASS_THREAD_EXTERN; - break; + case STORAGE_CLASS_EXTERN: + specifiers->declared_storage_class = STORAGE_CLASS_THREAD_EXTERN; + break; - case STORAGE_CLASS_STATIC: - specifiers->storage_class = STORAGE_CLASS_THREAD_STATIC; - break; + case STORAGE_CLASS_STATIC: + specifiers->declared_storage_class = STORAGE_CLASS_THREAD_STATIC; + break; - default: - errorf(HERE, "multiple storage classes in declaration specifiers"); - break; + default: + errorf(HERE, "multiple storage classes in declaration specifiers"); + break; } next_token(); break; @@ -2078,10 +2146,10 @@ static void semantic_parameter(declaration_t *declaration) { /* TODO: improve error messages */ - if(declaration->storage_class == STORAGE_CLASS_TYPEDEF) { + if(declaration->declared_storage_class == STORAGE_CLASS_TYPEDEF) { errorf(HERE, "typedef not allowed in parameter list"); - } else if(declaration->storage_class != STORAGE_CLASS_NONE - && declaration->storage_class != STORAGE_CLASS_REGISTER) { + } else if(declaration->declared_storage_class != STORAGE_CLASS_NONE + && declaration->declared_storage_class != STORAGE_CLASS_REGISTER) { errorf(HERE, "parameter may only have none or register storage class"); } @@ -2476,10 +2544,16 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, static declaration_t *parse_declarator( const declaration_specifiers_t *specifiers, bool may_be_abstract) { - declaration_t *const declaration = allocate_declaration_zero(); - declaration->storage_class = specifiers->storage_class; - declaration->modifiers = specifiers->decl_modifiers; - declaration->is_inline = specifiers->is_inline; + declaration_t *const declaration = allocate_declaration_zero(); + declaration->declared_storage_class = specifiers->declared_storage_class; + declaration->modifiers = specifiers->decl_modifiers; + declaration->is_inline = specifiers->is_inline; + + declaration->storage_class = specifiers->declared_storage_class; + if(declaration->storage_class == STORAGE_CLASS_NONE + && scope != global_scope) { + declaration->storage_class = STORAGE_CLASS_AUTO; + } construct_type_t *construct_type = parse_inner_declarator(declaration, may_be_abstract); @@ -2671,6 +2745,7 @@ warn_redundant_declaration: } if (new_storage_class == STORAGE_CLASS_NONE) { previous_declaration->storage_class = STORAGE_CLASS_NONE; + previous_declaration->declared_storage_class = STORAGE_CLASS_NONE; } } } else { @@ -2761,52 +2836,28 @@ static void parse_init_declarator_rest(declaration_t *declaration) eat('='); type_t *orig_type = declaration->type; - type_t *type = type = skip_typeref(orig_type); + type_t *type = skip_typeref(orig_type); if(declaration->init.initializer != NULL) { parser_error_multiple_definition(declaration, token.source_position); } - initializer_t *initializer = parse_initializer(type); - - /* § 6.7.5 (22) array initializers for arrays with unknown size determine - * the array type size */ - if(is_type_array(type) && initializer != NULL) { - array_type_t *array_type = &type->array; - - if(array_type->size_expression == NULL) { - size_t size; - switch (initializer->kind) { - case INITIALIZER_LIST: { - /* TODO */ - size = initializer->list.len; - break; - } - - case INITIALIZER_STRING: { - size = initializer->string.string.size; - break; - } - - case INITIALIZER_WIDE_STRING: { - size = initializer->wide_string.string.size; - break; - } - - default: { - panic("invalid initializer type"); - break; - } - } + bool must_be_constant = false; + if(declaration->storage_class == STORAGE_CLASS_STATIC + || declaration->storage_class == STORAGE_CLASS_THREAD_STATIC + || declaration->parent_scope == global_scope) { + must_be_constant = true; + } - expression_t *cnst = allocate_expression_zero(EXPR_CONST); - cnst->base.type = type_size_t; - cnst->conste.v.int_value = size; + parse_initializer_env_t env; + env.type = orig_type; + env.must_be_constant = must_be_constant; + parse_initializer(&env); - array_type->size_expression = cnst; - array_type->size_constant = true; - array_type->size = size; - } + if(env.type != orig_type) { + orig_type = env.type; + type = skip_typeref(orig_type); + declaration->type = env.type; } if(is_type_function(type)) { @@ -2814,7 +2865,7 @@ static void parse_init_declarator_rest(declaration_t *declaration) "initializers not allowed for function types at declator '%Y' (type '%T')", declaration->symbol, orig_type); } else { - declaration->init.initializer = initializer; + declaration->init.initializer = env.initializer; } } @@ -2825,14 +2876,15 @@ static void parse_anonymous_declaration_rest( { eat(';'); - declaration_t *const declaration = allocate_declaration_zero(); - declaration->type = specifiers->type; - declaration->storage_class = specifiers->storage_class; - declaration->source_position = specifiers->source_position; + declaration_t *const declaration = allocate_declaration_zero(); + declaration->type = specifiers->type; + declaration->declared_storage_class = specifiers->declared_storage_class; + declaration->source_position = specifiers->source_position; - if (declaration->storage_class != STORAGE_CLASS_NONE) { + if (declaration->declared_storage_class != STORAGE_CLASS_NONE) { warningf(declaration->source_position, "useless storage class in empty declaration"); } + declaration->storage_class = STORAGE_CLASS_NONE; type_t *type = declaration->type; switch (type->kind) { @@ -2907,6 +2959,7 @@ static declaration_t *finished_kr_declaration(declaration_t *declaration) if(previous_declaration->type == NULL) { previous_declaration->type = declaration->type; + previous_declaration->declared_storage_class = declaration->declared_storage_class; previous_declaration->storage_class = declaration->storage_class; previous_declaration->parent_scope = scope; return previous_declaration; @@ -3252,12 +3305,13 @@ static void parse_compound_declarators(declaration_t *struct_declaration, type_t *type = make_bitfield_type(base_type, size, source_position); - declaration = allocate_declaration_zero(); - declaration->namespc = NAMESPACE_NORMAL; - declaration->storage_class = STORAGE_CLASS_NONE; - declaration->source_position = source_position; - declaration->modifiers = specifiers->decl_modifiers; - declaration->type = type; + declaration = allocate_declaration_zero(); + declaration->namespc = NAMESPACE_NORMAL; + declaration->declared_storage_class = STORAGE_CLASS_NONE; + declaration->storage_class = STORAGE_CLASS_NONE; + declaration->source_position = source_position; + declaration->modifiers = specifiers->decl_modifiers; + declaration->type = type; } else { declaration = parse_declarator(specifiers,/*may_be_abstract=*/true); @@ -3342,7 +3396,7 @@ static type_t *parse_typename(void) declaration_specifiers_t specifiers; memset(&specifiers, 0, sizeof(specifiers)); parse_declaration_specifiers(&specifiers); - if(specifiers.storage_class != STORAGE_CLASS_NONE) { + if(specifiers.declared_storage_class != STORAGE_CLASS_NONE) { /* TODO: improve error message, user does probably not know what a * storage class is... */ @@ -3410,6 +3464,9 @@ static expression_t *parse_string_const(void) } if (token.type != T_WIDE_STRING_LITERAL) { expression_t *const cnst = allocate_expression_zero(EXPR_STRING_LITERAL); + /* note: that we use type_char_ptr here, which is already the + * automatic converted type. revert_automatic_type_conversion + * will construct the array type */ cnst->base.type = type_char_ptr; cnst->string.value = res; return cnst; @@ -3507,12 +3564,13 @@ static declaration_t *create_implicit_function(symbol_t *symbol, free_type(ntype); } - declaration_t *const declaration = allocate_declaration_zero(); - declaration->storage_class = STORAGE_CLASS_EXTERN; - declaration->type = type; - declaration->symbol = symbol; - declaration->source_position = source_position; - declaration->parent_scope = global_scope; + declaration_t *const declaration = allocate_declaration_zero(); + declaration->storage_class = STORAGE_CLASS_EXTERN; + declaration->declared_storage_class = STORAGE_CLASS_EXTERN; + declaration->type = type; + declaration->symbol = symbol; + declaration->source_position = source_position; + declaration->parent_scope = global_scope; scope_t *old_scope = scope; set_scope(global_scope); @@ -3629,6 +3687,19 @@ type_t *revert_automatic_type_conversion(const expression_t *expression) return type_left->pointer.points_to; } + case EXPR_STRING_LITERAL: { + size_t size = expression->string.value.size; + return make_array_type(type_char, size, TYPE_QUALIFIER_NONE); + } + + case EXPR_WIDE_STRING_LITERAL: { + size_t size = expression->wide_string.value.size; + return make_array_type(type_wchar_t, size, TYPE_QUALIFIER_NONE); + } + + case EXPR_COMPOUND_LITERAL: + return expression->compound_literal.type; + default: break; } @@ -3689,8 +3760,14 @@ static expression_t *parse_compound_literal(type_t *type) { expression_t *expression = allocate_expression_zero(EXPR_COMPOUND_LITERAL); + parse_initializer_env_t env; + env.type = type; + env.must_be_constant = false; + parse_initializer(&env); + type = env.type; + expression->compound_literal.type = type; - expression->compound_literal.initializer = parse_initializer(type); + expression->compound_literal.initializer = env.initializer; expression->base.type = automatic_type_conversion(type); return expression; @@ -5878,7 +5955,6 @@ static statement_t *parse_break(void) */ static bool is_local_var_declaration(const declaration_t *declaration) { switch ((storage_class_tag_t) declaration->storage_class) { - case STORAGE_CLASS_NONE: case STORAGE_CLASS_AUTO: case STORAGE_CLASS_REGISTER: { const type_t *type = skip_typeref(declaration->type); @@ -5897,25 +5973,11 @@ static bool is_local_var_declaration(const declaration_t *declaration) { * Check if a given declaration represents a variable. */ static bool is_var_declaration(const declaration_t *declaration) { - switch ((storage_class_tag_t) declaration->storage_class) { - case STORAGE_CLASS_NONE: - case STORAGE_CLASS_EXTERN: - case STORAGE_CLASS_STATIC: - case STORAGE_CLASS_AUTO: - case STORAGE_CLASS_REGISTER: - case STORAGE_CLASS_THREAD: - case STORAGE_CLASS_THREAD_EXTERN: - case STORAGE_CLASS_THREAD_STATIC: { - const type_t *type = skip_typeref(declaration->type); - if(is_type_function(type)) { - return false; - } else { - return true; - } - } - default: + if(declaration->storage_class == STORAGE_CLASS_TYPEDEF) return false; - } + + const type_t *type = skip_typeref(declaration->type); + return !is_type_function(type); } /**