X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=801acc379f0d460b607f92aea32cf4b63a5dd095;hb=c20806e328288d52cc08677c818c23ff2a604aea;hp=357a113b90b1ce56648190a746c52d671f248476;hpb=fbd5cc2831ac4924b74360012b031d4139c0f28e;p=cparser diff --git a/parser.c b/parser.c index 357a113..801acc3 100644 --- a/parser.c +++ b/parser.c @@ -98,14 +98,6 @@ typedef struct parse_initializer_env_t { bool must_be_constant; } parse_initializer_env_t; -/** - * Capture a MS __base extension. - */ -typedef struct based_spec_t { - source_position_t source_position; - variable_t *base_variable; -} based_spec_t; - typedef entity_t* (*parsed_declaration_func) (entity_t *declaration, bool is_definition); /** The current token. */ @@ -351,6 +343,8 @@ static size_t get_entity_struct_size(entity_kind_t kind) /** * Allocate an entity of given kind and initialize all * fields with zero. + * + * @param kind the kind of the entity to allocate */ static entity_t *allocate_entity_zero(entity_kind_t kind) { @@ -458,6 +452,8 @@ static statement_t *allocate_statement_zero(statement_kind_t kind) /** * Allocate an expression node of given kind and initialize all * fields with zero. + * + * @param kind the kind of the expression to allocate */ static expression_t *allocate_expression_zero(expression_kind_t kind) { @@ -539,6 +535,14 @@ static type_t *allocate_type_zero(type_kind_t kind) return res; } +static function_parameter_t *allocate_parameter(type_t *const type) +{ + function_parameter_t *const param = obstack_alloc(type_obst, sizeof(*param)); + memset(param, 0, sizeof(*param)); + param->type = type; + return param; +} + /** * Returns the size of an initializer node. * @@ -1550,7 +1554,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 +1687,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 */ @@ -2975,6 +2980,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct) } if (token.type == T_IDENTIFIER) { + /* the compound has a name, check if we have seen it already */ symbol = token.v.symbol; next_token(); @@ -3030,6 +3036,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 +3151,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; @@ -3442,29 +3450,23 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) return entity; } -static void parse_microsoft_based(based_spec_t *based_spec) +static variable_t *parse_microsoft_based(void) { if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing __based", T_IDENTIFIER, NULL); - return; + return NULL; } symbol_t *symbol = token.v.symbol; entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL); + variable_t *variable; if (entity == NULL || entity->base.kind != ENTITY_VARIABLE) { errorf(HERE, "'%Y' is not a variable name.", symbol); - entity = create_error_entity(symbol, ENTITY_VARIABLE); + variable = &create_error_entity(symbol, ENTITY_VARIABLE)->variable; } else { - variable_t *variable = &entity->variable; - - if (based_spec->base_variable != NULL) { - errorf(HERE, "__based type qualifier specified more than once"); - } - based_spec->source_position = token.source_position; - based_spec->base_variable = variable; + variable = &entity->variable; type_t *const type = variable->base.type; - if (is_type_valid(type)) { if (! is_type_pointer(skip_typeref(type))) { errorf(HERE, "variable in __based modifier must have pointer type instead of '%T'", type); @@ -3475,6 +3477,7 @@ static void parse_microsoft_based(based_spec_t *based_spec) } } next_token(); + return variable; } /** @@ -4164,9 +4167,27 @@ 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; } /** @@ -4197,61 +4218,49 @@ static void parse_parameters(function_type_t *type, scope_t *scope) goto parameters_finished; } - function_parameter_t *parameter; - 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); - parameter = obstack_alloc(type_obst, sizeof(parameter[0])); - memset(parameter, 0, sizeof(parameter[0])); - parameter->type = 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(); } @@ -4419,66 +4428,57 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env, { /* construct a single linked list of construct_type_t's which describe * how to construct the final declarator type */ - construct_type_t *first = NULL; - construct_type_t *last = NULL; - gnu_attribute_t *attributes = NULL; + construct_type_t *first = NULL; + construct_type_t **anchor = &first; + gnu_attribute_t *attributes = NULL; decl_modifiers_t modifiers = parse_attributes(&attributes); - /* MS __based extension */ - based_spec_t base_spec; - base_spec.base_variable = NULL; - for (;;) { construct_type_t *type; + variable_t *based = NULL; /* MS __based extension */ switch (token.type) { case '&': if (!(c_mode & _CXX)) errorf(HERE, "references are only available for C++"); - if (base_spec.base_variable != NULL && warning.other) { - warningf(&base_spec.source_position, - "__based does not precede a pointer operator, ignored"); - } type = parse_reference_declarator(); - /* consumed */ - base_spec.base_variable = NULL; - break; - - case '*': - type = parse_pointer_declarator(base_spec.base_variable); - /* consumed */ - base_spec.base_variable = NULL; break; - case T__based: + case T__based: { + source_position_t const pos = *HERE; next_token(); expect('(', end_error); add_anchor_token(')'); - parse_microsoft_based(&base_spec); + based = parse_microsoft_based(); rem_anchor_token(')'); expect(')', end_error); - continue; + if (token.type != '*') { + if (token.type == T__based) { + errorf(&pos, "__based type modifier specified more than once"); + } else if (warning.other) { + warningf(&pos, + "__based does not precede a pointer declarator, ignored"); + } + continue; + } + /* FALLTHROUGH */ + } + + case '*': + type = parse_pointer_declarator(based); + break; default: goto ptr_operator_end; } - if (last == NULL) { - first = type; - last = type; - } else { - last->base.next = type; - last = type; - } + *anchor = type; + anchor = &type->base.next; /* TODO: find out if this is correct */ modifiers |= parse_attributes(&attributes); } ptr_operator_end: - if (base_spec.base_variable != NULL && warning.other) { - warningf(&base_spec.source_position, - "__based does not precede a pointer operator, ignored"); - } if (env != NULL) { modifiers |= env->modifiers; @@ -4521,9 +4521,9 @@ ptr_operator_end: return NULL; } - construct_type_t *p = last; + construct_type_t **const p = anchor; - while (true) { + for (;;) { construct_type_t *type; switch (token.type) { case '(': { @@ -4541,28 +4541,17 @@ ptr_operator_end: goto declarator_finished; } - /* insert in the middle of the list (behind p) */ - if (p != NULL) { - type->base.next = p->base.next; - p->base.next = type; - } else { - type->base.next = first; - first = type; - } - if (last == p) { - last = type; - } + /* insert in the middle of the list (at p) */ + type->base.next = *p; + *p = type; + if (anchor == p) + anchor = &type->base.next; } declarator_finished: - /* append inner_types at the end of the list, we don't to set last anymore + /* append inner_types at the end of the list, we don't to set anchor anymore * as it's not needed anymore */ - if (last == NULL) { - assert(first == NULL); - first = inner_types; - } else { - last->base.next = inner_types; - } + *anchor = inner_types; return first; end_error: @@ -4701,9 +4690,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; } @@ -4742,7 +4742,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 @@ -4752,7 +4752,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) @@ -5519,8 +5519,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) { @@ -5550,17 +5550,11 @@ decl_list_end: */ parameter_type = get_default_promoted_type(parameter_type); - function_parameter_t *function_parameter - = obstack_alloc(type_obst, sizeof(function_parameter[0])); - memset(function_parameter, 0, sizeof(function_parameter[0])); + function_parameter_t *const parameter = + allocate_parameter(parameter_type); - function_parameter->type = parameter_type; - if (last_parameter != NULL) { - last_parameter->next = function_parameter; - } else { - parameters = function_parameter; - } - last_parameter = function_parameter; + *anchor = parameter; + anchor = ¶meter->next; } /* §6.9.1.7: A K&R style parameter list does NOT act as a function @@ -6857,15 +6851,8 @@ static entity_t *create_implicit_function(symbol_t *symbol, static type_t *make_function_2_type(type_t *return_type, type_t *argument_type1, type_t *argument_type2) { - function_parameter_t *parameter2 - = obstack_alloc(type_obst, sizeof(parameter2[0])); - memset(parameter2, 0, sizeof(parameter2[0])); - parameter2->type = argument_type2; - - function_parameter_t *parameter1 - = obstack_alloc(type_obst, sizeof(parameter1[0])); - memset(parameter1, 0, sizeof(parameter1[0])); - parameter1->type = argument_type1; + function_parameter_t *const parameter2 = allocate_parameter(argument_type2); + function_parameter_t *const parameter1 = allocate_parameter(argument_type1); parameter1->next = parameter2; type_t *type = allocate_type_zero(TYPE_FUNCTION); @@ -6884,10 +6871,7 @@ static type_t *make_function_2_type(type_t *return_type, type_t *argument_type1, */ 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])); - memset(parameter, 0, sizeof(parameter[0])); - parameter->type = argument_type; + function_parameter_t *const parameter = allocate_parameter(argument_type); type_t *type = allocate_type_zero(TYPE_FUNCTION); type->function.return_type = return_type; @@ -8136,18 +8120,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; @@ -11497,9 +11476,10 @@ static void create_microsoft_intrinsics(void) MS_BUILTIN(_byteswap_ulong, make_function_1_type(type_unsigned_long, type_unsigned_long)); MS_BUILTIN(_byteswap_uint64, make_function_1_type(type_unsigned_int64, type_unsigned_int64)); - MS_BUILTIN(__debugbreak, make_function_0_type(type_void)); - MS_BUILTIN(_ReturnAddress, make_function_0_type(type_void_ptr)); - MS_BUILTIN(__popcount, make_function_1_type(type_unsigned_int, type_unsigned_int)); + MS_BUILTIN(__debugbreak, make_function_0_type(type_void)); + MS_BUILTIN(_ReturnAddress, make_function_0_type(type_void_ptr)); + MS_BUILTIN(_AddressOfReturnAddress, make_function_0_type(type_void_ptr)); + MS_BUILTIN(__popcount, make_function_1_type(type_unsigned_int, type_unsigned_int)); /* x86/x64 only */ MS_BUILTIN(_enable, make_function_0_type(type_void));