X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=b5a0136407c81d61afe77ce1c4ba6c30c96ad739;hb=368123ed15555886729567e502705e73e88d757c;hp=42f74d48ed94cd854cd0d14e4e4e03023f815e83;hpb=1c8bf37c3531502ffef51be54ef2b1af76d1b2db;p=cparser diff --git a/parser.c b/parser.c index 42f74d4..b5a0136 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. */ @@ -539,6 +531,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. * @@ -3442,29 +3442,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 +3469,7 @@ static void parse_microsoft_based(based_spec_t *based_spec) } } next_token(); + return variable; } /** @@ -4169,6 +4164,24 @@ static void semantic_parameter_incomplete(const entity_t *entity) } } +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) @@ -4197,61 +4210,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(); } @@ -4271,67 +4272,69 @@ typedef enum construct_type_kind_t { CONSTRUCT_ARRAY } construct_type_kind_t; -typedef struct construct_type_t construct_type_t; -struct construct_type_t { +typedef union construct_type_t construct_type_t; + +typedef struct construct_type_base_t { construct_type_kind_t kind; construct_type_t *next; -}; - -typedef struct parsed_pointer_t parsed_pointer_t; -struct parsed_pointer_t { - construct_type_t construct_type; - type_qualifiers_t type_qualifiers; - variable_t *base_variable; /**< MS __based extension. */ -}; - -typedef struct parsed_reference_t parsed_reference_t; -struct parsed_reference_t { - construct_type_t construct_type; -}; - -typedef struct construct_function_type_t construct_function_type_t; -struct construct_function_type_t { - construct_type_t construct_type; - type_t *function_type; -}; - -typedef struct parsed_array_t parsed_array_t; -struct parsed_array_t { - construct_type_t construct_type; - type_qualifiers_t type_qualifiers; - bool is_static; - bool is_variable; - expression_t *size; -}; - -typedef struct construct_base_type_t construct_base_type_t; -struct construct_base_type_t { - construct_type_t construct_type; - type_t *type; +} construct_type_base_t; + +typedef struct parsed_pointer_t { + construct_type_base_t base; + type_qualifiers_t type_qualifiers; + variable_t *base_variable; /**< MS __based extension. */ +} parsed_pointer_t; + +typedef struct parsed_reference_t { + construct_type_base_t base; +} parsed_reference_t; + +typedef struct construct_function_type_t { + construct_type_base_t base; + type_t *function_type; +} construct_function_type_t; + +typedef struct parsed_array_t { + construct_type_base_t base; + type_qualifiers_t type_qualifiers; + bool is_static; + bool is_variable; + expression_t *size; +} parsed_array_t; + +union construct_type_t { + construct_type_kind_t kind; + construct_type_base_t base; + parsed_pointer_t pointer; + parsed_reference_t reference; + construct_function_type_t function; + parsed_array_t array; }; static construct_type_t *parse_pointer_declarator(variable_t *base_variable) { eat('*'); - parsed_pointer_t *pointer = obstack_alloc(&temp_obst, sizeof(pointer[0])); - memset(pointer, 0, sizeof(pointer[0])); - pointer->construct_type.kind = CONSTRUCT_POINTER; - pointer->type_qualifiers = parse_type_qualifiers(); - pointer->base_variable = base_variable; + construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->pointer)); + parsed_pointer_t *pointer = &cons->pointer; + memset(pointer, 0, sizeof(*pointer)); + cons->kind = CONSTRUCT_POINTER; + pointer->type_qualifiers = parse_type_qualifiers(); + pointer->base_variable = base_variable; - return &pointer->construct_type; + return cons; } static construct_type_t *parse_reference_declarator(void) { eat('&'); - parsed_reference_t *reference = obstack_alloc(&temp_obst, sizeof(reference[0])); - memset(reference, 0, sizeof(reference[0])); - reference->construct_type.kind = CONSTRUCT_REFERENCE; + construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->reference)); + parsed_reference_t *reference = &cons->reference; + memset(reference, 0, sizeof(*reference)); + cons->kind = CONSTRUCT_REFERENCE; - return (construct_type_t*)reference; + return cons; } static construct_type_t *parse_array_declarator(void) @@ -4339,9 +4342,10 @@ static construct_type_t *parse_array_declarator(void) eat('['); add_anchor_token(']'); - parsed_array_t *array = obstack_alloc(&temp_obst, sizeof(array[0])); - memset(array, 0, sizeof(array[0])); - array->construct_type.kind = CONSTRUCT_ARRAY; + construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->array)); + parsed_array_t *array = &cons->array; + memset(array, 0, sizeof(*array)); + cons->kind = CONSTRUCT_ARRAY; if (token.type == T_static) { array->is_static = true; @@ -4370,7 +4374,7 @@ static construct_type_t *parse_array_declarator(void) expect(']', end_error); end_error: - return &array->construct_type; + return cons; } static construct_type_t *parse_function_declarator(scope_t *scope, @@ -4395,13 +4399,13 @@ static construct_type_t *parse_function_declarator(scope_t *scope, parse_parameters(ftype, scope); - construct_function_type_t *construct_function_type = - obstack_alloc(&temp_obst, sizeof(construct_function_type[0])); - memset(construct_function_type, 0, sizeof(construct_function_type[0])); - construct_function_type->construct_type.kind = CONSTRUCT_FUNCTION; - construct_function_type->function_type = type; + construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->function)); + construct_function_type_t *function = &cons->function; + memset(function, 0, sizeof(*function)); + cons->kind = CONSTRUCT_FUNCTION; + function->function_type = type; - return &construct_function_type->construct_type; + return cons; } typedef struct parse_declarator_env_t { @@ -4416,66 +4420,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->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; @@ -4518,9 +4513,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 '(': { @@ -4538,28 +4533,17 @@ ptr_operator_end: goto declarator_finished; } - /* insert in the middle of the list (behind p) */ - if (p != NULL) { - type->next = p->next; - p->next = type; - } else { - type->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->next = inner_types; - } + *anchor = inner_types; return first; end_error: @@ -4632,15 +4616,13 @@ static void parse_declaration_attributes(entity_t *entity) static type_t *construct_declarator_type(construct_type_t *construct_list, type_t *type) { construct_type_t *iter = construct_list; - for (; iter != NULL; iter = iter->next) { + for (; iter != NULL; iter = iter->base.next) { switch (iter->kind) { case CONSTRUCT_INVALID: break; case CONSTRUCT_FUNCTION: { - construct_function_type_t *construct_function_type - = (construct_function_type_t*) iter; - - type_t *function_type = construct_function_type->function_type; + construct_function_type_t *function = &iter->function; + type_t *function_type = function->function_type; function_type->function.return_type = type; @@ -4667,8 +4649,8 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ if (is_type_reference(skip_typeref(type))) errorf(HERE, "cannot declare a pointer to reference"); - parsed_pointer_t *parsed_pointer = (parsed_pointer_t*) iter; - type = make_based_pointer_type(type, parsed_pointer->type_qualifiers, parsed_pointer->base_variable); + parsed_pointer_t *pointer = &iter->pointer; + type = make_based_pointer_type(type, pointer->type_qualifiers, pointer->base_variable); continue; } @@ -4683,19 +4665,19 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ if (is_type_reference(skip_typeref(type))) errorf(HERE, "cannot declare an array of references"); - parsed_array_t *parsed_array = (parsed_array_t*) iter; - type_t *array_type = allocate_type_zero(TYPE_ARRAY); + parsed_array_t *array = &iter->array; + type_t *array_type = allocate_type_zero(TYPE_ARRAY); - expression_t *size_expression = parsed_array->size; + expression_t *size_expression = array->size; if (size_expression != NULL) { size_expression = create_implicit_cast(size_expression, type_size_t); } - array_type->base.qualifiers = parsed_array->type_qualifiers; + array_type->base.qualifiers = array->type_qualifiers; array_type->array.element_type = type; - array_type->array.is_static = parsed_array->is_static; - array_type->array.is_variable = parsed_array->is_variable; + array_type->array.is_static = array->is_static; + array_type->array.is_variable = array->is_variable; array_type->array.size_expression = size_expression; if (size_expression != NULL) { @@ -5518,8 +5500,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) { @@ -5549,17 +5531,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 @@ -6856,15 +6832,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); @@ -6883,10 +6852,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; @@ -8135,18 +8101,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;