X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=a6430d247340d0a31811deb0b4dd5ae975622c5a;hb=fee559c8e58c8c01b85e20dac7d2010939c88d1a;hp=ca0e03e0ca1b7c478da27cafa6bb5b4f7416947d;hpb=334d6479c8e1a963d8b9736b82e678017f03018f;p=cparser diff --git a/parser.c b/parser.c index ca0e03e..a6430d2 100644 --- a/parser.c +++ b/parser.c @@ -84,7 +84,6 @@ struct declaration_specifiers_t { symbol_t *get_property_sym; /**< the name of the get property if set. */ symbol_t *put_property_sym; /**< the name of the put property if set. */ type_t *type; - variable_t *based_variable; /**< Microsoft __based variable. */ }; /** @@ -98,6 +97,14 @@ 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. */ @@ -737,15 +744,6 @@ void parse_error_expected(const char *message, ...) va_end(ap); } -/** - * Report a type error. - */ -static void type_error(const char *msg, const source_position_t *source_position, - type_t *type) -{ - errorf(source_position, "%s, but found type '%T'", msg, type); -} - /** * Report an incompatible type. */ @@ -3414,7 +3412,7 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) return entity; } -static void parse_microsoft_based(declaration_specifiers_t *specifiers) +static void parse_microsoft_based(based_spec_t *based_spec) { if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing __based", T_IDENTIFIER, NULL); @@ -3429,10 +3427,11 @@ static void parse_microsoft_based(declaration_specifiers_t *specifiers) } else { variable_t *variable = &entity->variable; - if (specifiers->based_variable != NULL) { + if (based_spec->base_variable != NULL) { errorf(HERE, "__based type qualifier specified more than once"); } - specifiers->based_variable = variable; + based_spec->source_position = token.source_position; + based_spec->base_variable = variable; type_t *const type = variable->base.type; @@ -3591,15 +3590,6 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) expect(')'); break; - case T__based: - next_token(); - expect('('); - add_anchor_token(')'); - parse_microsoft_based(specifiers); - rem_anchor_token(')'); - expect(')'); - break; - case T___thread: switch (specifiers->storage_class) { case STORAGE_CLASS_NONE: @@ -4036,7 +4026,9 @@ static void semantic_parameter(declaration_t *declaration) /* TODO: improve error messages */ source_position_t const* const pos = &declaration->base.source_position; - /* §6.9.1:6 */ + /* §6.9.1:6 The declarations in the declaration list shall contain no + * storage-class specifier other than register and no + * initializations. */ switch (declaration->declared_storage_class) { /* Allowed storage classes */ case STORAGE_CLASS_NONE: @@ -4049,16 +4041,20 @@ static void semantic_parameter(declaration_t *declaration) } type_t *const orig_type = declaration->type; - /* §6.7.5.3(7): Array as last part of a parameter type is just syntactic - * sugar. Turn it into a pointer. - * §6.7.5.3(8): A declaration of a parameter as ``function returning type'' - * shall be adjusted to ``pointer to function returning type'', as in 6.3.2.1. + /* §6.7.5.3:7 A declaration of a parameter as ``array of type'' shall be + * adjusted to ``qualified pointer to type'', [...] + * §6.7.5.3:8 A declaration of a parameter as ``function returning type'' + * shall be adjusted to ``pointer to function returning type'', + * as in 6.3.2.1. */ type_t *const type = automatic_type_conversion(orig_type); declaration->type = type; + /* §6.7.5.3:4 After adjustment, the parameters in a parameter type list in + * a function declarator that is part of a definition of that + * function shall not have incomplete type. */ if (is_type_incomplete(skip_typeref(type))) { - errorf(pos, "parameter '%#T' is of incomplete type", + errorf(pos, "parameter '%#T' has incomplete type", orig_type, declaration->base.symbol); } } @@ -4186,6 +4182,7 @@ 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; @@ -4214,7 +4211,7 @@ struct construct_base_type_t { type_t *type; }; -static construct_type_t *parse_pointer_declarator(void) +static construct_type_t *parse_pointer_declarator(variable_t *base_variable) { eat('*'); @@ -4222,8 +4219,9 @@ static construct_type_t *parse_pointer_declarator(void) memset(pointer, 0, sizeof(pointer[0])); pointer->construct_type.kind = CONSTRUCT_POINTER; pointer->type_qualifiers = parse_type_qualifiers(); + pointer->base_variable = base_variable; - return (construct_type_t*) pointer; + return &pointer->construct_type; } static construct_type_t *parse_reference_declarator(void) @@ -4271,7 +4269,7 @@ static construct_type_t *parse_array_declarator(void) expect(']'); end_error: - return (construct_type_t*) array; + return &array->construct_type; } static construct_type_t *parse_function_declarator(scope_t *scope, @@ -4323,19 +4321,39 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env, 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; switch (token.type) { case '&': if (!(c_mode & _CXX)) errorf(HERE, "references are only available for C++"); + if (base_spec.base_variable != NULL) + 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(); + type = parse_pointer_declarator(base_spec.base_variable); + /* consumed */ + base_spec.base_variable = NULL; break; + case T__based: + next_token(); + expect('('); + add_anchor_token(')'); + parse_microsoft_based(&base_spec); + rem_anchor_token(')'); + expect(')'); + continue; + default: goto ptr_operator_end; } @@ -4352,6 +4370,9 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env, modifiers |= parse_attributes(&attributes); } ptr_operator_end: + if (base_spec.base_variable != NULL) + warningf(&base_spec.source_position, + "__based does not precede a pointer operator, ignored"); if (env != NULL) { modifiers |= env->modifiers; @@ -4510,8 +4531,7 @@ static void parse_declaration_attributes(entity_t *entity) } } -static type_t *construct_declarator_type(construct_type_t *construct_list, - type_t *type, variable_t *variable) +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) { @@ -4548,7 +4568,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, 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, variable); + type = make_based_pointer_type(type, parsed_pointer->type_qualifiers, parsed_pointer->base_variable); continue; } @@ -4624,7 +4644,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, construct_type_t *construct_type = parse_inner_declarator(&env, may_be_abstract); - type_t *type = construct_declarator_type(construct_type, specifiers->type, specifiers->based_variable); + type_t *type = construct_declarator_type(construct_type, specifiers->type); if (construct_type != NULL) { obstack_free(&temp_obst, construct_type); @@ -4701,7 +4721,7 @@ static type_t *parse_abstract_declarator(type_t *base_type) { construct_type_t *construct_type = parse_inner_declarator(NULL, 1); - type_t *result = construct_declarator_type(construct_type, base_type, NULL); + type_t *result = construct_declarator_type(construct_type, base_type); if (construct_type != NULL) { obstack_free(&temp_obst, construct_type); } @@ -5121,6 +5141,7 @@ static void parse_anonymous_declaration_rest( const declaration_specifiers_t *specifiers) { eat(';'); + anonymous_entity = NULL; if (warning.other) { if (specifiers->storage_class != STORAGE_CLASS_NONE) { @@ -5154,16 +5175,18 @@ static void check_variable_type_complete(entity_t *ent) if (ent->kind != ENTITY_VARIABLE) return; + /* §6.7:7 If an identifier for an object is declared with no linkage, the + * type for the object shall be complete [...] */ declaration_t *decl = &ent->declaration; - if (decl->storage_class == STORAGE_CLASS_EXTERN) + if (decl->storage_class != STORAGE_CLASS_NONE) return; type_t *type = decl->type; if (!is_type_incomplete(skip_typeref(type))) return; - errorf(&ent->base.source_position, - "variable '%#T' is of incomplete type", type, ent->base.symbol); + errorf(&ent->base.source_position, "variable '%#T' has incomplete type", + type, ent->base.symbol); } @@ -7891,6 +7914,18 @@ static void warn_reference_address_as_bool(expression_t const* expr) } } +static void semantic_condition(expression_t const *const expr, + char const *const context) +{ + type_t *const type = skip_typeref(expr->base.type); + if (is_type_scalar(type)) { + warn_reference_address_as_bool(expr); + } else if (is_type_valid(type)) { + errorf(&expr->base.source_position, + "%s must have scalar type", context); + } +} + /** * Parse a conditional expression, ie. 'expression ? ... : ...'. * @@ -7903,18 +7938,11 @@ static expression_t *parse_conditional_expression(expression_t *expression) conditional_expression_t *conditional = &result->conditional; conditional->condition = expression; - warn_reference_address_as_bool(expression); - eat('?'); add_anchor_token(':'); - /* 6.5.15.2 */ - type_t *const condition_type_orig = expression->base.type; - type_t *const condition_type = skip_typeref(condition_type_orig); - if (!is_type_scalar(condition_type) && is_type_valid(condition_type)) { - type_error("expected a scalar type in conditional condition", - &expression->base.source_position, condition_type_orig); - } + /* §6.5.15:2 The first operand shall have scalar type. */ + semantic_condition(expression, "condition of conditional operator"); expression_t *true_expression = expression; bool gnu_cond = false; @@ -8245,15 +8273,8 @@ static void semantic_unexpr_plus(unary_expression_t *expression) static void semantic_not(unary_expression_t *expression) { - type_t *const orig_type = expression->value->base.type; - type_t *const type = skip_typeref(orig_type); - if (!is_type_scalar(type) && is_type_valid(type)) { - errorf(&expression->base.source_position, - "operand of ! must be of scalar type"); - } - - warn_reference_address_as_bool(expression->value); - + /* §6.5.3.3:1 The operand [...] of the ! operator, scalar type. */ + semantic_condition(expression->value, "operand of !"); expression->base.type = c_mode & _CXX ? type_bool : type_int; } @@ -8842,25 +8863,10 @@ static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression) */ static void semantic_logical_op(binary_expression_t *expression) { - expression_t *const left = expression->left; - expression_t *const right = expression->right; - type_t *const orig_type_left = left->base.type; - type_t *const orig_type_right = right->base.type; - type_t *const type_left = skip_typeref(orig_type_left); - type_t *const type_right = skip_typeref(orig_type_right); - - warn_reference_address_as_bool(left); - warn_reference_address_as_bool(right); - - if (!is_type_scalar(type_left) || !is_type_scalar(type_right)) { - /* TODO: improve error message */ - if (is_type_valid(type_left) && is_type_valid(type_right)) { - errorf(&expression->base.source_position, - "operation needs scalar types"); - } - return; - } - + /* §6.5.13:2 Each of the operands shall have scalar type. + * §6.5.14:2 Each of the operands shall have scalar type. */ + semantic_condition(expression->left, "left operand of logical operator"); + semantic_condition(expression->right, "right operand of logical operator"); expression->base.type = c_mode & _CXX ? type_bool : type_int; } @@ -9635,7 +9641,9 @@ static statement_t *parse_if(void) add_anchor_token(')'); expression_t *const expr = parse_expression(); statement->ifs.condition = expr; - warn_reference_address_as_bool(expr); + /* §6.8.4.1:1 The controlling expression of an if statement shall have + * scalar type. */ + semantic_condition(expr, "condition of 'if'-statment"); mark_vars_read(expr, NULL); rem_anchor_token(')'); expect(')'); @@ -9776,7 +9784,9 @@ static statement_t *parse_while(void) add_anchor_token(')'); expression_t *const cond = parse_expression(); statement->whiles.condition = cond; - warn_reference_address_as_bool(cond); + /* §6.8.5:2 The controlling expression of an iteration statement shall + * have scalar type. */ + semantic_condition(cond, "condition of 'while'-statement"); mark_vars_read(cond, NULL); rem_anchor_token(')'); expect(')'); @@ -9810,7 +9820,9 @@ static statement_t *parse_do(void) add_anchor_token(')'); expression_t *const cond = parse_expression(); statement->do_while.condition = cond; - warn_reference_address_as_bool(cond); + /* §6.8.5:2 The controlling expression of an iteration statement shall + * have scalar type. */ + semantic_condition(cond, "condition of 'do-while'-statement"); mark_vars_read(cond, NULL); rem_anchor_token(')'); expect(')'); @@ -9840,22 +9852,20 @@ static statement_t *parse_for(void) expect('('); add_anchor_token(')'); - if (token.type != ';') { - if (is_declaration_specifier(&token, false)) { - parse_declaration(record_entity); - } else { - add_anchor_token(';'); - expression_t *const init = parse_expression(); - statement->fors.initialisation = init; - mark_vars_read(init, VAR_ANY); - if (warning.unused_value && !expression_has_effect(init)) { - warningf(&init->base.source_position, - "initialisation of 'for'-statement has no effect"); - } - rem_anchor_token(';'); - expect(';'); - } + if (token.type == ';') { + next_token(); + } else if (is_declaration_specifier(&token, false)) { + parse_declaration(record_entity); } else { + add_anchor_token(';'); + expression_t *const init = parse_expression(); + statement->fors.initialisation = init; + mark_vars_read(init, VAR_ANY); + if (warning.unused_value && !expression_has_effect(init)) { + warningf(&init->base.source_position, + "initialisation of 'for'-statement has no effect"); + } + rem_anchor_token(';'); expect(';'); } @@ -9863,7 +9873,9 @@ static statement_t *parse_for(void) add_anchor_token(';'); expression_t *const cond = parse_expression(); statement->fors.condition = cond; - warn_reference_address_as_bool(cond); + /* §6.8.5:2 The controlling expression of an iteration statement shall + * have scalar type. */ + semantic_condition(cond, "condition of 'for'-statement"); mark_vars_read(cond, NULL); rem_anchor_token(';'); }