X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=2e18543ca869e7a8fab4abcee728ef05fe211623;hb=c58c01e7c180f68d3d3a721997693abcc6e26352;hp=c4523d80034f1cee86be46589d7290717e28512c;hpb=953a820405dfd857ff9f5e24f3b630b6103dad46;p=cparser diff --git a/parser.c b/parser.c index c4523d8..2e18543 100644 --- a/parser.c +++ b/parser.c @@ -555,6 +555,7 @@ static void restore_anchor_state(int token_type, int count) static void rem_anchor_token(int token_type) { assert(0 <= token_type && token_type < T_LAST_TOKEN); + assert(token_anchor_set[token_type] != 0); --token_anchor_set[token_type]; } @@ -696,18 +697,18 @@ static void type_error_incompatible(const char *msg, * If not, generate an error, eat the current statement, * and goto the end_error label. */ -#define expect(expected) \ - do { \ - if (UNLIKELY(token.type != (expected))) { \ - parse_error_expected(NULL, (expected), NULL); \ - add_anchor_token(expected); \ - eat_until_anchor(); \ - if (token.type == expected) \ - next_token(); \ - rem_anchor_token(expected); \ - goto end_error; \ - } \ - next_token(); \ +#define expect(expected) \ + do { \ + if (UNLIKELY(token.type != (expected))) { \ + parse_error_expected(NULL, (expected), NULL); \ + add_anchor_token(expected); \ + eat_until_anchor(); \ + if (token.type == expected) \ + next_token(); \ + rem_anchor_token(expected); \ + goto end_error; \ + } \ + next_token(); \ } while (0) static void set_scope(scope_t *new_scope) @@ -1500,12 +1501,12 @@ static void parse_gnu_attribute_format_args(gnu_attribute_t *attribute) add_anchor_token(','); parse_constant_expression(); rem_anchor_token(','); - rem_anchor_token('('); + rem_anchor_token(')'); expect(','); add_anchor_token(')'); parse_constant_expression(); - rem_anchor_token('('); + rem_anchor_token(')'); expect(')'); return; end_error: @@ -2697,6 +2698,7 @@ static declaration_t *parse_compound_type_specifier(bool is_struct) errorf(HERE, "multiple definitions of '%s %Y' (previous definition at %P)", is_struct ? "struct" : "union", symbol, &declaration->source_position); + declaration->scope.declarations = NULL; } } } else if (token.type != '{') { @@ -2711,17 +2713,18 @@ static declaration_t *parse_compound_type_specifier(bool is_struct) return NULL; } - /* always create a new declaration, do NOT modify old one */ - declaration = allocate_declaration_zero(); - declaration->namespc = - (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION); - declaration->source_position = token.source_position; - declaration->symbol = symbol; - declaration->parent_scope = scope; - if (symbol != NULL) { - environment_push(declaration); + if (declaration == NULL) { + declaration = allocate_declaration_zero(); + declaration->namespc = + (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION); + declaration->source_position = token.source_position; + declaration->symbol = symbol; + declaration->parent_scope = scope; + if (symbol != NULL) { + environment_push(declaration); + } + append_declaration(declaration); } - append_declaration(declaration); if (token.type == '{') { declaration->init.complete = true; @@ -2784,14 +2787,11 @@ end_error: ; } -/** - * Parse enum specifier and return the enum type or NULL on error. - */ static type_t *parse_enum_specifier(void) { - gnu_attribute_t *attributes = NULL; - declaration_t *declaration = NULL; - symbol_t *symbol = NULL; + gnu_attribute_t *attributes = NULL; + declaration_t *declaration; + symbol_t *symbol; eat(T_enum); if (token.type == T_IDENTIFIER) { @@ -2803,31 +2803,30 @@ static type_t *parse_enum_specifier(void) parse_error_expected("while parsing enum type specifier", T_IDENTIFIER, '{', NULL); return NULL; + } else { + declaration = NULL; + symbol = NULL; } - if (token.type == '{' && declaration != NULL && declaration->init.complete) { - errorf(HERE, "multiple definitions of enum '%Y' (previous definition at %P)", - symbol, &declaration->source_position); - } - - declaration = allocate_declaration_zero(); - declaration->namespc = NAMESPACE_ENUM; - declaration->source_position = token.source_position; - declaration->symbol = symbol; - declaration->parent_scope = scope; - if (symbol != NULL) { - environment_push(declaration); + if (declaration == NULL) { + declaration = allocate_declaration_zero(); + declaration->namespc = NAMESPACE_ENUM; + declaration->source_position = token.source_position; + declaration->symbol = symbol; + declaration->parent_scope = scope; } - append_declaration(declaration); type_t *const type = allocate_type_zero(TYPE_ENUM, &declaration->source_position); type->enumt.declaration = declaration; if (token.type == '{') { if (declaration->init.complete) { - errorf(HERE, "multiple definitions of enum '%Y' (previous definition at %P)", - symbol, &declaration->source_position); + errorf(HERE, "multiple definitions of enum %Y", symbol); } + if (symbol != NULL) { + environment_push(declaration); + } + append_declaration(declaration); declaration->init.complete = true; parse_enum_entries(type); @@ -4603,26 +4602,24 @@ static void parse_anonymous_declaration_rest( { eat(';'); - if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) { - warningf(&specifiers->source_position, - "useless storage class in empty declaration"); - } - -#ifdef RECORD_EMPTY_DECLARARTIONS 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; -#endif - type_t *type = specifiers->type; + if (declaration->declared_storage_class != STORAGE_CLASS_NONE) { + warningf(&declaration->source_position, + "useless storage class in empty declaration"); + } + declaration->storage_class = STORAGE_CLASS_NONE; + + type_t *type = declaration->type; switch (type->kind) { case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: { if (type->compound.declaration->symbol == NULL) { - warningf(&specifiers->source_position, + warningf(&declaration->source_position, "unnamed struct/union that defines no instances"); } break; @@ -4632,13 +4629,11 @@ static void parse_anonymous_declaration_rest( break; default: - warningf(&specifiers->source_position, "empty declaration"); + warningf(&declaration->source_position, "empty declaration"); break; } -#ifdef RECORD_EMPTY_DECLARARTIONS append_declaration(declaration); -#endif } static void parse_declaration_rest(declaration_t *ndeclaration, @@ -5389,7 +5384,7 @@ static void parse_external_declaration(void) add_anchor_token(','); add_anchor_token('='); - rem_anchor_token(';'); + add_anchor_token(';'); /* declarator is common to both function-definitions and declarations */ declaration_t *ndeclaration = parse_declarator(&specifiers, /*may_be_abstract=*/false); @@ -6208,11 +6203,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(')'); @@ -6241,6 +6237,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); @@ -6262,11 +6260,11 @@ static expression_t *parse_statement_expression(void) } expression->base.type = type; + rem_anchor_token(')'); expect(')'); - return expression; end_error: - return create_invalid_expression(); + return expression; } /** @@ -6275,7 +6273,6 @@ end_error: static expression_t *parse_parenthesized_expression(void) { eat('('); - add_anchor_token(')'); switch(token.type) { case '{': @@ -6291,13 +6288,13 @@ static expression_t *parse_parenthesized_expression(void) } } + add_anchor_token(')'); expression_t *result = parse_expression(); rem_anchor_token(')'); expect(')'); - return result; end_error: - return create_invalid_expression(); + return result; } static expression_t *parse_function_keyword(void) @@ -6474,17 +6471,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(); } @@ -6953,9 +6948,8 @@ static expression_t *parse_typeprop(expression_kind_t const kind, tp_expression->typeprop.tp_expression = expression; } - return tp_expression; end_error: - return create_invalid_expression(); + return tp_expression; } static expression_t *parse_sizeof(unsigned precedence) @@ -7211,9 +7205,8 @@ static expression_t *parse_call_expression(unsigned precedence, "function call has aggregate value"); } - return result; end_error: - return create_invalid_expression(); + return result; } static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right); @@ -9553,7 +9546,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; @@ -9567,7 +9560,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(';'); @@ -9764,32 +9808,47 @@ end_error:; */ static void parse_translation_unit(void) { - for (;;) switch (token.type) { - DECLARATION_START - case T_IDENTIFIER: - case T___extension__: - parse_external_declaration(); - break; + for (;;) { +#ifndef NDEBUG + bool anchor_leak = false; + for (token_type_t i = 0; i != T_LAST_TOKEN; ++i) { + unsigned char count = token_anchor_set[i]; + if (count != 0) { + errorf(HERE, "Leaked anchor token %k %d times", i, count); + anchor_leak = true; + } + } + if (anchor_leak) + abort(); +#endif - case T_asm: - parse_global_asm(); - break; + switch (token.type) { + DECLARATION_START + case T_IDENTIFIER: + case T___extension__: + parse_external_declaration(); + break; - case T_EOF: - return; + case T_asm: + parse_global_asm(); + break; - case ';': - /* TODO error in strict mode */ - warningf(HERE, "stray ';' outside of function"); - next_token(); - break; + case T_EOF: + return; - default: - errorf(HERE, "stray %K outside of function", &token); - if (token.type == '(' || token.type == '{' || token.type == '[') - eat_until_matching_token(token.type); - next_token(); - break; + case ';': + /* TODO error in strict mode */ + warningf(HERE, "stray ';' outside of function"); + next_token(); + break; + + default: + errorf(HERE, "stray %K outside of function", &token); + if (token.type == '(' || token.type == '{' || token.type == '[') + eat_until_matching_token(token.type); + next_token(); + break; + } } }