X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=parser.c;h=59417dd90865c950574f7b223181aaf69ce5d58d;hb=6e71c889a8a04df82310c2503a272229e7a1f84f;hp=4784f8a5a170fbd897ba5b59be405b6699981f2e;hpb=f181ba24df15120ce46e9a23d9466e6177de3473;p=cparser diff --git a/parser.c b/parser.c index 4784f8a..59417dd 100644 --- a/parser.c +++ b/parser.c @@ -320,7 +320,7 @@ static size_t get_expression_struct_size(expression_kind_t kind) static const size_t sizes[] = { [EXPR_ERROR] = sizeof(expression_base_t), [EXPR_REFERENCE] = sizeof(reference_expression_t), - [EXPR_REFERENCE_ENUM_VALUE] = sizeof(reference_expression_t), + [EXPR_ENUM_CONSTANT] = sizeof(reference_expression_t), [EXPR_LITERAL_BOOLEAN] = sizeof(literal_expression_t), [EXPR_LITERAL_INTEGER] = sizeof(literal_expression_t), [EXPR_LITERAL_INTEGER_OCTAL] = sizeof(literal_expression_t), @@ -999,10 +999,10 @@ static assign_error_t semantic_assign(type_t *orig_type_left, points_to_left = get_unqualified_type(points_to_left); points_to_right = get_unqualified_type(points_to_right); - if (is_type_atomic(points_to_left, ATOMIC_TYPE_VOID)) + if (is_type_void(points_to_left)) return res; - if (is_type_atomic(points_to_right, ATOMIC_TYPE_VOID)) { + if (is_type_void(points_to_right)) { /* ISO/IEC 14882:1998(E) §C.1.2:6 */ return c_mode & _CXX ? ASSIGN_ERROR_INCOMPATIBLE : res; } @@ -1441,7 +1441,7 @@ static void mark_vars_read(expression_t *const expr, entity_t *lhs_ent) case EXPR_UNARY_CAST: /* Special case: Use void cast to mark a variable as "read" */ - if (is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_VOID)) + if (is_type_void(skip_typeref(expr->base.type))) lhs_ent = NULL; goto unary; @@ -1536,7 +1536,7 @@ unary: case EXPR_OFFSETOF: case EXPR_STATEMENT: // TODO case EXPR_LABEL_ADDRESS: - case EXPR_REFERENCE_ENUM_VALUE: + case EXPR_ENUM_CONSTANT: return; } @@ -3208,6 +3208,8 @@ static void semantic_parameter_incomplete(const entity_t *entity) static bool has_parameters(void) { /* func(void) is not a parameter */ + if (look_ahead(1)->kind != ')') + return true; if (token.kind == T_IDENTIFIER) { entity_t const *const entity = get_entity(token.identifier.symbol, NAMESPACE_NORMAL); @@ -3215,13 +3217,20 @@ static bool has_parameters(void) return true; if (entity->kind != ENTITY_TYPEDEF) return true; - if (skip_typeref(entity->typedefe.type) != type_void) + type_t const *const type = skip_typeref(entity->typedefe.type); + if (!is_type_void(type)) return true; + if (c_mode & _CXX) { + /* ISO/IEC 14882:1998(E) §8.3.5:2 It must be literally (void). A typedef + * is not allowed. */ + errorf(HERE, "empty parameter list defined with a typedef of 'void' not allowed in C++"); + } else if (type->base.qualifiers != TYPE_QUALIFIER_NONE) { + /* §6.7.5.3:10 Qualification is not allowed here. */ + errorf(HERE, "'void' as parameter must not have type qualifiers"); + } } else if (token.kind != T_void) { return true; } - if (look_ahead(1)->kind != ')') - return true; next_token(); return false; } @@ -4741,7 +4750,7 @@ static bool expression_returns(expression_t const *const expr) } case EXPR_REFERENCE: - case EXPR_REFERENCE_ENUM_VALUE: + case EXPR_ENUM_CONSTANT: case EXPR_LITERAL_CASES: case EXPR_STRING_LITERAL: case EXPR_WIDE_STRING_LITERAL: @@ -5111,8 +5120,8 @@ found_break_parent: type_t *const type = skip_typeref(current_function->base.type); assert(is_type_function(type)); type_t *const ret = skip_typeref(type->function.return_type); - if (!is_type_atomic(ret, ATOMIC_TYPE_VOID) && - is_type_valid(ret) && + if (!is_type_void(ret) && + is_type_valid(ret) && !is_sym_main(current_function->base.base.symbol)) { source_position_t const *const pos = &stmt->base.source_position; warningf(WARN_RETURN_TYPE, pos, "control reaches end of non-void function"); @@ -6233,7 +6242,7 @@ static expression_t *parse_reference(void) expression_kind_t kind = EXPR_REFERENCE; if (entity->kind == ENTITY_ENUM_VALUE) - kind = EXPR_REFERENCE_ENUM_VALUE; + kind = EXPR_ENUM_CONSTANT; expression_t *expression = allocate_expression_zero(kind); expression->base.source_position = pos; @@ -6273,7 +6282,7 @@ static bool semantic_cast(expression_t *cast) source_position_t const *pos = &cast->base.source_position; /* §6.5.4 A (void) cast is explicitly permitted, more for documentation than for utility. */ - if (dst_type == type_void) + if (is_type_void(dst_type)) return true; /* only integer and pointer can be casted to pointer */ @@ -6868,9 +6877,10 @@ static expression_t *parse_noop_expression(void) if (token.kind != ')') do { (void)parse_assignment_expression(); } while (next_if(',')); + + rem_anchor_token(','); + rem_anchor_token(')'); } - rem_anchor_token(','); - rem_anchor_token(')'); expect(')', end_error); end_error: @@ -7051,7 +7061,7 @@ typeprop_expression: type_t const* const type = skip_typeref(orig_type); char const* wrong_type = NULL; if (is_type_incomplete(type)) { - if (!is_type_atomic(type, ATOMIC_TYPE_VOID) || !GNU_MODE) + if (!is_type_void(type) || !GNU_MODE) wrong_type = "incomplete"; } else if (type->kind == TYPE_FUNCTION) { if (GNU_MODE) { @@ -7481,16 +7491,14 @@ end_error:; /* 6.5.15.3 */ source_position_t const *const pos = &conditional->base.source_position; type_t *result_type; - if (is_type_atomic(true_type, ATOMIC_TYPE_VOID) || - is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { + if (is_type_void(true_type) || is_type_void(false_type)) { /* ISO/IEC 14882:1998(E) §5.16:2 */ if (true_expression->kind == EXPR_UNARY_THROW) { result_type = false_type; } else if (false_expression->kind == EXPR_UNARY_THROW) { result_type = true_type; } else { - if (!is_type_atomic(true_type, ATOMIC_TYPE_VOID) || - !is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { + if (!is_type_void(true_type) || !is_type_void(false_type)) { warningf(WARN_OTHER, pos, "ISO C forbids conditional expression with only one void side"); } result_type = type_void; @@ -7523,8 +7531,7 @@ end_error:; type_t *to2 = skip_typeref(other_type->pointer.points_to); type_t *to; - if (is_type_atomic(to1, ATOMIC_TYPE_VOID) || - is_type_atomic(to2, ATOMIC_TYPE_VOID)) { + if (is_type_void(to1) || is_type_void(to2)) { to = type_void; } else if (types_compatible(get_unqualified_type(to1), get_unqualified_type(to2))) { @@ -7618,7 +7625,7 @@ end_error:; errorf(&value->base.source_position, "operand of delete must have pointer type"); } - } else if (is_type_atomic(skip_typeref(type->pointer.points_to), ATOMIC_TYPE_VOID)) { + } else if (is_type_void(skip_typeref(type->pointer.points_to))) { source_position_t const *const pos = &value->base.source_position; warningf(WARN_OTHER, pos, "deleting 'void*' is undefined"); } @@ -7649,8 +7656,7 @@ static expression_t *parse_throw(void) "cannot throw object of incomplete type '%T'", orig_type); } else if (is_type_pointer(type)) { type_t *const points_to = skip_typeref(type->pointer.points_to); - if (is_type_incomplete(points_to) && - !is_type_atomic(points_to, ATOMIC_TYPE_VOID)) { + if (is_type_incomplete(points_to) && !is_type_void(points_to)) { errorf(&value->base.source_position, "cannot throw pointer to incomplete type '%T'", orig_type); } @@ -7673,7 +7679,7 @@ static bool check_pointer_arithmetic(const source_position_t *source_position, points_to = skip_typeref(points_to); if (is_type_incomplete(points_to)) { - if (!GNU_MODE || !is_type_atomic(points_to, ATOMIC_TYPE_VOID)) { + if (!GNU_MODE || !is_type_void(points_to)) { errorf(source_position, "arithmetic with pointer to incomplete type '%T' not allowed", orig_pointer_type); @@ -8187,7 +8193,7 @@ static void semantic_sub(binary_expression_t *expression) "subtracting pointers to incompatible types '%T' and '%T'", orig_type_left, orig_type_right); } else if (!is_type_object(unqual_left)) { - if (!is_type_atomic(unqual_left, ATOMIC_TYPE_VOID)) { + if (!is_type_void(unqual_left)) { errorf(pos, "subtracting pointers to non-object types '%T'", orig_type_left); } else { @@ -8542,7 +8548,7 @@ static bool expression_has_effect(const expression_t *const expr) switch (expr->kind) { case EXPR_ERROR: return true; /* do NOT warn */ case EXPR_REFERENCE: return false; - case EXPR_REFERENCE_ENUM_VALUE: return false; + case EXPR_ENUM_CONSTANT: return false; case EXPR_LABEL_ADDRESS: return false; /* suppress the warning for microsoft __noop operations */ @@ -8610,7 +8616,7 @@ static bool expression_has_effect(const expression_t *const expr) * suppress the warning */ case EXPR_UNARY_CAST: { type_t *const type = skip_typeref(expr->base.type); - return is_type_atomic(type, ATOMIC_TYPE_VOID); + return is_type_void(type); } case EXPR_UNARY_ASSUME: return true; @@ -9281,6 +9287,23 @@ static statement_t *parse_inner_statement(void) return stmt; } +/** + * Parse an expression in parentheses and mark its variables as read. + */ +static expression_t *parse_condition(void) +{ + expect('(', end_error0); + add_anchor_token(')'); + expression_t *const expr = parse_expression(); + mark_vars_read(expr, NULL); + rem_anchor_token(')'); + expect(')', end_error1); +end_error1: + return expr; +end_error0: + return create_error_expression(); +} + /** * Parse an if statement. */ @@ -9294,18 +9317,12 @@ static statement_t *parse_if(void) add_anchor_token('{'); - expect('(', end_error); - add_anchor_token(')'); - expression_t *const expr = parse_expression(); + expression_t *const expr = parse_condition(); statement->ifs.condition = 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(')', end_error); -end_error: rem_anchor_token('{'); add_anchor_token(T_else); @@ -9389,10 +9406,7 @@ static statement_t *parse_switch(void) PUSH_PARENT(statement); - expect('(', end_error); - add_anchor_token(')'); - expression_t *const expr = parse_expression(); - mark_vars_read(expr, NULL); + expression_t *const expr = parse_condition(); type_t * type = skip_typeref(expr->base.type); if (is_type_integer(type)) { type = promote_integer(type); @@ -9405,8 +9419,6 @@ static statement_t *parse_switch(void) type = type_error_type; } statement->switchs.expression = create_implicit_cast(expr, type); - expect(')', end_error); - rem_anchor_token(')'); switch_statement_t *rem = current_switch; current_switch = &statement->switchs; @@ -9420,9 +9432,6 @@ static statement_t *parse_switch(void) POP_PARENT(); return statement; -end_error: - POP_PARENT(); - return create_error_statement(); } static statement_t *parse_loop_body(statement_t *const loop) @@ -9447,24 +9456,16 @@ static statement_t *parse_while(void) PUSH_PARENT(statement); - expect('(', end_error); - add_anchor_token(')'); - expression_t *const cond = parse_expression(); + expression_t *const cond = parse_condition(); statement->whiles.condition = 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(')', end_error); statement->whiles.body = parse_loop_body(statement); POP_PARENT(); return statement; -end_error: - POP_PARENT(); - return create_error_statement(); } /** @@ -9483,16 +9484,11 @@ static statement_t *parse_do(void) rem_anchor_token(T_while); expect(T_while, end_error); - expect('(', end_error); - add_anchor_token(')'); - expression_t *const cond = parse_expression(); + expression_t *const cond = parse_condition(); statement->do_while.condition = 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(')', end_error); expect(';', end_error); POP_PARENT(); @@ -9531,7 +9527,8 @@ static statement_t *parse_for(void) warningf(WARN_UNUSED_VALUE, &init->base.source_position, "initialisation of 'for'-statement has no effect"); } rem_anchor_token(';'); - expect(';', end_error2); + expect(';', end_error3); +end_error3:; } POP_EXTENSION(); @@ -9619,7 +9616,7 @@ static statement_t *parse_goto(void) else parse_error_expected("while parsing goto", T_IDENTIFIER, NULL); eat_until_anchor(); - return create_error_statement(); + statement->gotos.label = &allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym_anonymous)->label; } } @@ -9734,6 +9731,15 @@ entity_t *expression_is_variable(const expression_t *expression) return entity; } +static void err_or_warn(source_position_t const *const pos, char const *const msg) +{ + if (c_mode & _CXX || strict_mode) { + errorf(pos, msg); + } else { + warningf(WARN_OTHER, pos, msg); + } +} + /** * Parse a return statement. */ @@ -9756,24 +9762,14 @@ static statement_t *parse_return(void) if (return_value != NULL) { type_t *return_value_type = skip_typeref(return_value->base.type); - if (is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { - if (is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) { + if (is_type_void(return_type)) { + if (!is_type_void(return_value_type)) { /* ISO/IEC 14882:1998(E) §6.6.3:2 */ /* Only warn in C mode, because GCC does the same */ - if (c_mode & _CXX || strict_mode) { - errorf(pos, - "'return' with a value, in function returning 'void'"); - } else { - warningf(WARN_OTHER, pos, "'return' with a value, in function returning 'void'"); - } + err_or_warn(pos, "'return' with a value, in function returning 'void'"); } else if (!(c_mode & _CXX)) { /* ISO/IEC 14882:1998(E) §6.6.3:3 */ /* Only warn in C mode, because GCC does the same */ - if (strict_mode) { - errorf(pos, - "'return' with expression in function returning 'void'"); - } else { - warningf(WARN_OTHER, pos, "'return' with expression in function returning 'void'"); - } + err_or_warn(pos, "'return' with expression in function returning 'void'"); } } else { assign_error_t error = semantic_assign(return_type, return_value); @@ -9788,14 +9784,9 @@ static statement_t *parse_return(void) warningf(WARN_OTHER, pos, "function returns address of local variable"); } } - } else if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { + } else if (!is_type_void(return_type)) { /* ISO/IEC 14882:1998(E) §6.6.3:3 */ - if (c_mode & _CXX || strict_mode) { - errorf(pos, - "'return' without value, in function returning non-void"); - } else { - warningf(WARN_OTHER, pos, "'return' without value, in function returning non-void"); - } + err_or_warn(pos, "'return' without value, in function returning non-void"); } statement->returns.value = return_value; @@ -9864,10 +9855,7 @@ static statement_t *parse_ms_try_statment(void) POP_PARENT(); if (next_if(T___except)) { - expect('(', end_error); - add_anchor_token(')'); - expression_t *const expr = parse_expression(); - mark_vars_read(expr, NULL); + expression_t *const expr = parse_condition(); type_t * type = skip_typeref(expr->base.type); if (is_type_integer(type)) { type = promote_integer(type); @@ -9877,18 +9865,11 @@ static statement_t *parse_ms_try_statment(void) type = type_error_type; } statement->ms_try.except_expression = create_implicit_cast(expr, type); - rem_anchor_token(')'); - expect(')', end_error); - statement->ms_try.final_statement = parse_compound_statement(false); - } else if (next_if(T__finally)) { - statement->ms_try.final_statement = parse_compound_statement(false); - } else { + } else if (!next_if(T__finally)) { parse_error_expected("while parsing __try statement", T___except, T___finally, NULL); - return create_error_statement(); } + statement->ms_try.final_statement = parse_compound_statement(false); return statement; -end_error: - return create_error_statement(); } static statement_t *parse_empty_statement(void) @@ -9998,10 +9979,8 @@ end_error: */ static statement_t *intern_parse_statement(void) { - statement_t *statement = NULL; - /* declaration or statement */ - add_anchor_token(';'); + statement_t *statement; switch (token.kind) { case T_IDENTIFIER: { token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind; @@ -10072,14 +10051,9 @@ static statement_t *intern_parse_statement(void) default: errorf(HERE, "unexpected token %K while parsing statement", &token); statement = create_error_statement(); - if (!at_anchor()) - next_token(); + eat_until_anchor(); break; } - rem_anchor_token(';'); - - assert(statement != NULL - && statement->base.source_position.input_name != NULL); return statement; } @@ -10124,6 +10098,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) add_anchor_token('*'); add_anchor_token('+'); add_anchor_token('-'); + add_anchor_token(';'); add_anchor_token('{'); add_anchor_token('~'); add_anchor_token(T_CHARACTER_CONSTANT); @@ -10336,6 +10311,7 @@ end_error: rem_anchor_token(T_CHARACTER_CONSTANT); rem_anchor_token('~'); rem_anchor_token('{'); + rem_anchor_token(';'); rem_anchor_token('-'); rem_anchor_token('+'); rem_anchor_token('*');