X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=fdb9ee0a896627df2d66d18215eb9671f243d930;hb=f109471af0f1a95e840a66c9e136409d0973021c;hp=3d63d290c21ef61113b16a560e3af1634159889f;hpb=3803edc846afa85c077490e324f4f1a4211121fd;p=cparser diff --git a/parser.c b/parser.c index 3d63d29..fdb9ee0 100644 --- a/parser.c +++ b/parser.c @@ -1550,7 +1550,7 @@ static void check_no_argument(gnu_attribute_t *attribute, const char *name) errorf(HERE, "wrong number of arguments specified for '%s' attribute", name); eat_until_matching_token('('); /* we have already consumed '(', so we stop before ')', eat it */ - eat(')'); + next_token(); attribute->invalid = true; } @@ -1683,6 +1683,7 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes) /* skip possible arguments */ if (token.type == '(') { eat_until_matching_token(')'); + next_token(); /* skip the ')' */ } } else { /* check for arguments */ @@ -3030,6 +3031,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct) parse_compound_type_entries(compound); modifiers |= parse_attributes(&attributes); + /* ISO/IEC 14882:1998(E) §7.1.3:5 */ if (symbol == NULL) { assert(anonymous_entity == NULL); anonymous_entity = (entity_t*)compound; @@ -3144,6 +3146,7 @@ static type_t *parse_enum_specifier(void) parse_enum_entries(type); parse_attributes(&attributes); + /* ISO/IEC 14882:1998(E) §7.1.3:5 */ if (symbol == NULL) { assert(anonymous_entity == NULL); anonymous_entity = entity; @@ -4159,11 +4162,29 @@ static void semantic_parameter_incomplete(const entity_t *entity) type_t *type = skip_typeref(entity->declaration.type); if (is_type_incomplete(type)) { errorf(&entity->base.source_position, - "parameter '%Y' has incomplete type '%T'", entity->base.symbol, - entity->declaration.type); + "parameter '%#T' has incomplete type", + entity->declaration.type, entity->base.symbol); } } +static bool has_parameters(void) +{ + /* func(void) is not a parameter */ + if (token.type == T_IDENTIFIER) { + entity_t const *const entity = get_entity(token.v.symbol, NAMESPACE_NORMAL); + if (entity->kind != ENTITY_TYPEDEF) + return true; + if (skip_typeref(entity->typedefe.type) != type_void) + return true; + } else if (token.type != T_void) { + return true; + } + if (look_ahead(1)->type != ')') + return true; + next_token(); + return false; +} + /** * Parses function type parameters (and optionally creates variable_t entities * for them in a scope) @@ -4192,59 +4213,49 @@ static void parse_parameters(function_type_t *type, scope_t *scope) goto parameters_finished; } - function_parameter_t *last_parameter = NULL; + if (has_parameters()) { + function_parameter_t **anchor = &type->parameters; + for (;;) { + switch (token.type) { + case T_DOTDOTDOT: + next_token(); + type->variadic = true; + goto parameters_finished; - while (true) { - switch (token.type) { - case T_DOTDOTDOT: - next_token(); - type->variadic = true; - goto parameters_finished; + case T_IDENTIFIER: + case T___extension__: + DECLARATION_START + { + entity_t *entity = parse_parameter(); + if (entity->kind == ENTITY_TYPEDEF) { + errorf(&entity->base.source_position, + "typedef not allowed as function parameter"); + break; + } + assert(is_declaration(entity)); - case T_IDENTIFIER: - case T___extension__: - DECLARATION_START - { - entity_t *entity = parse_parameter(); - if (entity->kind == ENTITY_TYPEDEF) { - errorf(&entity->base.source_position, - "typedef not allowed as function parameter"); - break; - } - assert(is_declaration(entity)); + semantic_parameter_incomplete(entity); - /* func(void) is not a parameter */ - if (last_parameter == NULL - && token.type == ')' - && entity->base.symbol == NULL - && skip_typeref(entity->declaration.type) == type_void) { - goto parameters_finished; - } - semantic_parameter_incomplete(entity); + function_parameter_t *const parameter = + allocate_parameter(entity->declaration.type); - function_parameter_t *const parameter = - allocate_parameter(entity->declaration.type); + if (scope != NULL) { + append_entity(scope, entity); + } - if (scope != NULL) { - append_entity(scope, entity); + *anchor = parameter; + anchor = ¶meter->next; + break; } - if (last_parameter != NULL) { - last_parameter->next = parameter; - } else { - type->parameters = parameter; + default: + goto parameters_finished; } - last_parameter = parameter; - break; - } - - default: - goto parameters_finished; - } - if (token.type != ',') { - goto parameters_finished; + if (token.type != ',') { + goto parameters_finished; + } + next_token(); } - next_token(); } @@ -4674,9 +4685,20 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ if (size_expression != NULL) { if (is_constant_expression(size_expression)) { + long const size = fold_constant(size_expression); + array_type->array.size = size; array_type->array.size_constant = true; - array_type->array.size - = fold_constant(size_expression); + /* §6.7.5.2:1 If the expression is a constant expression, it shall + * have a value greater than zero. */ + if (size <= 0) { + if (size < 0 || !GNU_MODE) { + errorf(&size_expression->base.source_position, + "size of array must be greater than zero"); + } else if (warning.other) { + warningf(&size_expression->base.source_position, + "zero length arrays are a GCC extension"); + } + } } else { array_type->array.is_vla = true; } @@ -4715,7 +4737,7 @@ static type_t *semantic_parameter(const source_position_t *pos, type = automatic_type_conversion(type); if (specifiers->is_inline && is_type_valid(type)) { - errorf(pos, "parameter '%Y' declared 'inline'", symbol); + errorf(pos, "parameter '%#T' declared 'inline'", type, symbol); } /* §6.9.1:6 The declarations in the declaration list shall contain @@ -4725,7 +4747,7 @@ static type_t *semantic_parameter(const source_position_t *pos, specifiers->storage_class != STORAGE_CLASS_NONE && specifiers->storage_class != STORAGE_CLASS_REGISTER) ) { - errorf(pos, "invalid storage class for parameter '%Y'", symbol); + errorf(pos, "invalid storage class for parameter '%#T'", type, symbol); } /* delay test for incomplete type, because we might have (void) @@ -5492,8 +5514,8 @@ decl_list_end: /* update function type */ type_t *new_type = duplicate_type(type); - function_parameter_t *parameters = NULL; - function_parameter_t *last_parameter = NULL; + function_parameter_t *parameters = NULL; + function_parameter_t **anchor = ¶meters; parameter = entity->function.parameters.entities; for (; parameter != NULL; parameter = parameter->base.next) { @@ -5526,12 +5548,8 @@ decl_list_end: function_parameter_t *const parameter = allocate_parameter(parameter_type); - if (last_parameter != NULL) { - last_parameter->next = parameter; - } else { - parameters = parameter; - } - last_parameter = parameter; + *anchor = parameter; + anchor = ¶meter->next; } /* §6.9.1.7: A K&R style parameter list does NOT act as a function @@ -8097,18 +8115,13 @@ static expression_t *parse_call_expression(expression_t *expression) add_anchor_token(','); if (token.type != ')') { - call_argument_t *last_argument = NULL; - - while (true) { - call_argument_t *argument = allocate_ast_zero(sizeof(argument[0])); - + call_argument_t **anchor = &call->arguments; + for (;;) { + call_argument_t *argument = allocate_ast_zero(sizeof(*argument)); argument->expression = parse_assignment_expression(); - if (last_argument == NULL) { - call->arguments = argument; - } else { - last_argument->next = argument; - } - last_argument = argument; + + *anchor = argument; + anchor = &argument->next; if (token.type != ',') break;