X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=77c5884acbb8765442f7d5ae46aa83dc1d66f2f6;hb=38ab672b23c1de6fff8e672fde96509e113507e7;hp=a1622ddd6d865b1ae576b6de95f28d1aab08e062;hpb=f5241ea7db945ac029eb86ce9387cc0831c33eb4;p=cparser diff --git a/parser.c b/parser.c index a1622dd..77c5884 100644 --- a/parser.c +++ b/parser.c @@ -643,16 +643,6 @@ static void eat_block(void) next_token(); } -/** - * eat all token until a ';' is reached or a stop token is found. - */ -static void eat_statement(void) -{ - eat_until_matching_token(';'); - if (token.type == ';') - next_token(); -} - #define eat(token_type) do { assert(token.type == token_type); next_token(); } while (0) /** @@ -2475,6 +2465,10 @@ finish_designator: if (type == NULL) { /* we are already outside, ... */ + if (is_type_compound(outer_type) && + !outer_type->compound.declaration->init.complete) { + goto error_parse_next; + } goto error_excess; } @@ -3584,10 +3578,8 @@ warn_about_long_long: default: /* invalid specifier combination, give an error message */ if (type_specifiers == 0) { - if (saw_error) { - specifiers->type = type_error_type; - return; - } + if (saw_error) + goto end_error; if (!strict_mode) { if (warning.implicit_int) { @@ -3606,15 +3598,13 @@ warn_about_long_long: } else { errorf(HERE, "multiple datatypes in declaration"); } - atomic_type = ATOMIC_TYPE_INVALID; + goto end_error; } - if (type_specifiers & SPECIFIER_COMPLEX && - atomic_type != ATOMIC_TYPE_INVALID) { + if (type_specifiers & SPECIFIER_COMPLEX) { type = allocate_type_zero(TYPE_COMPLEX, &builtin_source_position); type->complex.akind = atomic_type; - } else if (type_specifiers & SPECIFIER_IMAGINARY && - atomic_type != ATOMIC_TYPE_INVALID) { + } else if (type_specifiers & SPECIFIER_IMAGINARY) { type = allocate_type_zero(TYPE_IMAGINARY, &builtin_source_position); type->imaginary.akind = atomic_type; } else { @@ -3637,7 +3627,10 @@ warn_about_long_long: } specifiers->type = result; + return; + end_error: + specifiers->type = type_error_type; return; } @@ -3911,9 +3904,8 @@ static construct_type_t *parse_array_declarator(void) rem_anchor_token(']'); expect(']'); - return (construct_type_t*) array; end_error: - return NULL; + return (construct_type_t*) array; } static construct_type_t *parse_function_declarator(declaration_t *declaration) @@ -4052,13 +4044,7 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration, if (may_be_abstract) break; parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL); - /* avoid a loop in the outermost scope, because eat_statement doesn't - * eat '}' */ - if (token.type == '}' && current_function == NULL) { - next_token(); - } else { - eat_statement(); - } + eat_until_anchor(); return NULL; } @@ -4157,15 +4143,19 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, function_type->function.return_type = type; type_t *skipped_return_type = skip_typeref(type); + /* §6.7.5.3(1) */ if (is_type_function(skipped_return_type)) { errorf(HERE, "function returning function is not allowed"); - type = type_error_type; } else if (is_type_array(skipped_return_type)) { errorf(HERE, "function returning array is not allowed"); - type = type_error_type; } else { - type = function_type; + if (skipped_return_type->base.qualifiers != 0) { + warningf(HERE, + "type qualifiers in return type of function type are meaningless"); + } } + + type = function_type; break; } @@ -4206,12 +4196,13 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, } type_t *skipped_type = skip_typeref(type); - if (is_type_atomic(skipped_type, ATOMIC_TYPE_VOID)) { - errorf(HERE, "array of void is not allowed"); - type = type_error_type; - } else { - type = array_type; + /* §6.7.5.2(1) */ + if (is_type_incomplete(skipped_type)) { + errorf(HERE, "array of incomplete type '%T' is not allowed", type); + } else if (is_type_function(skipped_type)) { + errorf(HERE, "array of functions is not allowed"); } + type = array_type; break; } } @@ -4308,7 +4299,7 @@ static void check_type_of_main(const declaration_t *const decl, const function_t warningf(&decl->source_position, "'main' is normally a non-static function"); } - if (skip_typeref(func_type->return_type) != type_int) { + if (!types_compatible(skip_typeref(func_type->return_type), type_int)) { warningf(&decl->source_position, "return type of 'main' should be 'int', but is '%T'", func_type->return_type); @@ -4371,7 +4362,7 @@ static declaration_t *record_declaration( previous_declaration == NULL) { warningf(&declaration->source_position, "function declaration '%#T' is not a prototype", - orig_type, declaration->symbol); + orig_type, symbol); } if (warning.main && is_type_function(type) && is_sym_main(symbol)) { @@ -4602,24 +4593,17 @@ static void parse_anonymous_declaration_rest( { eat(';'); - declaration_t *const declaration = allocate_declaration_zero(); - declaration->type = specifiers->type; - declaration->declared_storage_class = specifiers->declared_storage_class; - declaration->source_position = specifiers->source_position; - declaration->modifiers = specifiers->modifiers; - - if (declaration->declared_storage_class != STORAGE_CLASS_NONE) { - warningf(&declaration->source_position, + if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) { + warningf(&specifiers->source_position, "useless storage class in empty declaration"); } - declaration->storage_class = STORAGE_CLASS_NONE; - type_t *type = declaration->type; + type_t *type = specifiers->type; switch (type->kind) { case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: { if (type->compound.declaration->symbol == NULL) { - warningf(&declaration->source_position, + warningf(&specifiers->source_position, "unnamed struct/union that defines no instances"); } break; @@ -4629,11 +4613,20 @@ static void parse_anonymous_declaration_rest( break; default: - warningf(&declaration->source_position, "empty declaration"); + warningf(&specifiers->source_position, "empty declaration"); break; } +#ifdef RECORD_EMPTY_DECLARATIONS + declaration_t *const declaration = allocate_declaration_zero(); + declaration->type = specifiers->type; + declaration->declared_storage_class = specifiers->declared_storage_class; + declaration->source_position = specifiers->source_position; + declaration->modifiers = specifiers->modifiers; + declaration->storage_class = STORAGE_CLASS_NONE; + append_declaration(declaration); +#endif } static void parse_declaration_rest(declaration_t *ndeclaration, @@ -4714,7 +4707,10 @@ static void parse_declaration(parsed_declaration_func finished_declaration) { declaration_specifiers_t specifiers; memset(&specifiers, 0, sizeof(specifiers)); + + add_anchor_token(';'); parse_declaration_specifiers(&specifiers); + rem_anchor_token(';'); if (token.type == ';') { parse_anonymous_declaration_rest(&specifiers); @@ -6203,11 +6199,12 @@ static expression_t *parse_compound_literal(type_t *type) */ static expression_t *parse_cast(void) { + add_anchor_token(')'); + source_position_t source_position = token.source_position; type_t *type = parse_typename(); - /* matching add_anchor_token() is at call site */ rem_anchor_token(')'); expect(')'); @@ -6236,6 +6233,8 @@ end_error: */ static expression_t *parse_statement_expression(void) { + add_anchor_token(')'); + expression_t *expression = allocate_expression_zero(EXPR_STATEMENT); statement_t *statement = parse_compound_statement(true); @@ -6257,6 +6256,7 @@ static expression_t *parse_statement_expression(void) } expression->base.type = type; + rem_anchor_token(')'); expect(')'); end_error: @@ -6269,7 +6269,6 @@ end_error: static expression_t *parse_parenthesized_expression(void) { eat('('); - add_anchor_token(')'); switch(token.type) { case '{': @@ -6285,6 +6284,7 @@ static expression_t *parse_parenthesized_expression(void) } } + add_anchor_token(')'); expression_t *result = parse_expression(); rem_anchor_token(')'); expect(')'); @@ -6467,17 +6467,15 @@ static expression_t *parse_va_start(void) expression_t *const expr = parse_assignment_expression(); if (expr->kind == EXPR_REFERENCE) { declaration_t *const decl = expr->reference.declaration; - if (decl == NULL) - return create_invalid_expression(); - if (decl->parent_scope == ¤t_function->scope && - decl->next == NULL) { - expression->va_starte.parameter = decl; - expect(')'); - return expression; + if (decl->parent_scope != ¤t_function->scope || decl->next != NULL) { + errorf(&expr->base.source_position, + "second argument of 'va_start' must be last parameter of the current function"); } + expression->va_starte.parameter = decl; + expect(')'); + return expression; } - errorf(&expr->base.source_position, - "second argument of 'va_start' must be last parameter of the current function"); + expect(')'); end_error: return create_invalid_expression(); } @@ -6901,12 +6899,16 @@ static expression_t *parse_typeprop(expression_kind_t const kind, source_position_t const pos, unsigned const precedence) { - expression_t *tp_expression = allocate_expression_zero(kind); + expression_t *tp_expression = allocate_expression_zero(kind); tp_expression->base.type = type_size_t; tp_expression->base.source_position = pos; char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; + /* we only refer to a type property, not the value, so do not warn + * when using current_init_decl */ + declaration_t *old = current_init_decl; + current_init_decl = NULL; if (token.type == '(' && is_declaration_specifier(look_ahead(1), true)) { next_token(); add_anchor_token(')'); @@ -6947,6 +6949,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind, } end_error: + current_init_decl = old; return tp_expression; } @@ -9145,7 +9148,7 @@ static statement_t *parse_goto(void) parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL); else parse_error_expected("while parsing goto", T_IDENTIFIER, NULL); - eat_statement(); + eat_until_anchor(); goto end_error; } symbol_t *symbol = token.v.symbol; @@ -9353,7 +9356,10 @@ static statement_t *parse_declaration_statement(void) statement->base.source_position = token.source_position; declaration_t *before = last_declaration; - parse_declaration(record_declaration); + if (c_mode & _GNUC) + parse_external_declaration(); + else + parse_declaration(record_declaration); if (before == NULL) { statement->declaration.declarations_begin = scope->declarations; @@ -9544,7 +9550,7 @@ expression_statment: case ';': statement = parse_empty_statement(); break; case '{': statement = parse_compound_statement(false); break; - case T___leave: statement = parse_leave_statement(); break; + case T___leave: statement = parse_leave_statement(); break; case T___try: statement = parse_ms_try_statment(); break; case T_asm: statement = parse_asm_statement(); break; case T_break: statement = parse_break(); break; @@ -9558,7 +9564,58 @@ expression_statment: case T_return: statement = parse_return(); break; case T_switch: statement = parse_switch(); break; case T_while: statement = parse_while(); break; - default: statement = parse_expression_statement(); break; + + case '!': + case '&': + case '(': + case '*': + case '+': + case '-': + case '~': + case T_ANDAND: + case T_CHARACTER_CONSTANT: + case T_FLOATINGPOINT: + case T_INTEGER: + case T_MINUSMINUS: + case T_PLUSPLUS: + case T_STRING_LITERAL: + case T_WIDE_CHARACTER_CONSTANT: + case T_WIDE_STRING_LITERAL: + case T___FUNCDNAME__: + case T___FUNCSIG__: + case T___FUNCTION__: + case T___PRETTY_FUNCTION__: + case T___builtin_alloca: + case T___builtin_classify_type: + case T___builtin_constant_p: + case T___builtin_expect: + case T___builtin_huge_val: + case T___builtin_isgreater: + case T___builtin_isgreaterequal: + case T___builtin_isless: + case T___builtin_islessequal: + case T___builtin_islessgreater: + case T___builtin_isunordered: + case T___builtin_nan: + case T___builtin_nand: + case T___builtin_nanf: + case T___builtin_offsetof: + case T___builtin_prefetch: + case T___builtin_va_arg: + case T___builtin_va_end: + case T___builtin_va_start: + case T___func__: + case T___noop: + case T__assume: + statement = parse_expression_statement(); + break; + + default: + errorf(HERE, "unexpected token %K while parsing statement", &token); + statement = create_invalid_statement(); + if (!at_anchor()) + next_token(); + break; } rem_anchor_token(';'); @@ -9766,7 +9823,7 @@ static void parse_translation_unit(void) } } if (anchor_leak) - exit(1); + abort(); #endif switch (token.type) {