X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=801acc379f0d460b607f92aea32cf4b63a5dd095;hb=3cdead30b5c1d131d5c363188c26255514ea2fc8;hp=88ab74e167d9e83f61746ad1ba5d58e175799305;hpb=73d8bf6a048b2e4a497280f5db29a744385de57f;p=cparser diff --git a/parser.c b/parser.c index 88ab74e..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,11 +4167,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) @@ -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(); } @@ -4271,67 +4280,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 +4350,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 +4382,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 +4407,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 +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->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 +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 '(': { @@ -4538,28 +4541,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 +4624,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: - internal_errorf(HERE, "invalid type construction found"); + 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; @@ -4657,16 +4647,18 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ } } - type = function_type; - break; + /* The function type was constructed earlier. Freeing it here will + * destroy other types. */ + type = typehash_insert(function_type); + continue; } case CONSTRUCT_POINTER: { 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; } @@ -4681,26 +4673,37 @@ 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) { 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; } @@ -4713,18 +4716,11 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ } else if (is_type_function(skipped_type)) { errorf(HERE, "array of functions is not allowed"); } - type = array_type; - break; - } + type = identify_new_type(array_type); + continue; } - - /* The function type was constructed earlier. Freeing it here will - * destroy other types. */ - if (iter->kind == CONSTRUCT_FUNCTION) { - type = typehash_insert(type); - } else { - type = identify_new_type(type); } + internal_errorf(HERE, "invalid type construction found"); } return type; @@ -4746,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 @@ -4756,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) @@ -5523,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) { @@ -5554,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 @@ -6861,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); @@ -6888,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; @@ -8140,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; @@ -11501,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));