X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=3c5383b8918f1bf20be8cc32dd9145dc0f6d7b68;hb=e628f683385763274b551d468107872a058b31d7;hp=2bbdbf4cafdf5e2401ed89a8ea1f9556a9964e59;hpb=bf92df408b5fef01d5ee065b02c1deb7e4289a5b;p=cparser diff --git a/parser.c b/parser.c index 2bbdbf4..3c5383b 100644 --- a/parser.c +++ b/parser.c @@ -111,10 +111,26 @@ static declaration_t **incomplete_arrays; static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT; -#define PUSH_PARENT(stmt) \ - statement_t *const prev_parent = current_parent; \ - ((void)(current_parent = (stmt))) -#define POP_PARENT() ((void)(current_parent = prev_parent)) +#define PUSH_PARENT(stmt) \ + statement_t *const new_parent = (stmt); \ + statement_t *const old_parent = current_parent; \ + ((void)(current_parent = new_parent)) +#define POP_PARENT() (assert(current_parent == new_parent), (void)(current_parent = old_parent)) + +#define PUSH_SCOPE(scope) \ + size_t const top = environment_top(); \ + scope_t *const new_scope = (scope); \ + scope_t *const old_scope = scope_push(new_scope) +#define POP_SCOPE() (assert(current_scope == new_scope), scope_pop(old_scope), environment_pop_to(top)) + +#define PUSH_EXTENSION() \ + bool const old_gcc_extension = in_gcc_extension; \ + while (next_if(T___extension__)) { \ + in_gcc_extension = true; \ + } \ + do {} while (0) +#define POP_EXTENSION() \ + ((void)(in_gcc_extension = old_gcc_extension)) /** special symbol used for anonymous entities. */ static symbol_t *sym_anonymous = NULL; @@ -2567,14 +2583,9 @@ static type_t *parse_typeof(void) expression_t *expression = NULL; - bool old_type_prop = in_type_prop; - bool old_gcc_extension = in_gcc_extension; - in_type_prop = true; + bool old_type_prop = in_type_prop; + in_type_prop = true; - while (next_if(T___extension__)) { - /* This can be a prefix to a typename or an expression. */ - in_gcc_extension = true; - } switch (token.type) { case T_IDENTIFIER: if (is_typedef_symbol(token.symbol)) { @@ -2587,8 +2598,7 @@ static type_t *parse_typeof(void) } break; } - in_type_prop = old_type_prop; - in_gcc_extension = old_gcc_extension; + in_type_prop = old_type_prop; rem_anchor_token(')'); expect(')', end_error); @@ -2770,12 +2780,11 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) { - type_t *type = NULL; - type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE; - unsigned type_specifiers = 0; - bool newtype = false; - bool saw_error = false; - bool old_gcc_extension = in_gcc_extension; + type_t *type = NULL; + type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE; + unsigned type_specifiers = 0; + bool newtype = false; + bool saw_error = false; memset(specifiers, 0, sizeof(*specifiers)); specifiers->source_position = token.source_position; @@ -2847,11 +2856,6 @@ wrong_thread_storage_class: MATCH_TYPE_QUALIFIER(T___uptr, TYPE_QUALIFIER_UPTR); MATCH_TYPE_QUALIFIER(T___sptr, TYPE_QUALIFIER_SPTR); - case T___extension__: - next_token(); - in_gcc_extension = true; - break; - /* type specifiers */ #define MATCH_SPECIFIER(token, specifier, name) \ case token: \ @@ -3002,8 +3006,6 @@ wrong_thread_storage_class: finish_specifiers: specifiers->attributes = parse_attributes(specifiers->attributes); - in_gcc_extension = old_gcc_extension; - if (type == NULL || (saw_error && type_specifiers != 0)) { atomic_type_kind_t atomic_type; @@ -3316,7 +3318,6 @@ static void parse_parameters(function_type_t *type, scope_t *scope) goto parameters_finished; case T_IDENTIFIER: - case T___extension__: DECLARATION_START { entity_t *entity = parse_parameter(); @@ -4528,9 +4529,7 @@ static void parse_kr_declaration_list(entity_t *entity) add_anchor_token('{'); - /* push function parameters */ - size_t const top = environment_top(); - scope_t *old_scope = scope_push(&entity->function.parameters); + PUSH_SCOPE(&entity->function.parameters); entity_t *parameter = entity->function.parameters.entities; for ( ; parameter != NULL; parameter = parameter->base.next) { @@ -4543,7 +4542,6 @@ static void parse_kr_declaration_list(entity_t *entity) for (;;) { switch (token.type) { DECLARATION_START - case T___extension__: /* This covers symbols, which are no type, too, and results in * better error messages. The typical cases are misspelled type * names and missing includes. */ @@ -4556,10 +4554,7 @@ static void parse_kr_declaration_list(entity_t *entity) } decl_list_end: - /* pop function parameters */ - assert(current_scope == &entity->function.parameters); - scope_pop(old_scope); - environment_pop_to(top); + POP_SCOPE(); /* update function type */ type_t *new_type = duplicate_type(type); @@ -5462,9 +5457,7 @@ static void parse_external_declaration(void) assert(is_declaration(entity)); type = skip_typeref(entity->declaration.type); - /* push function parameters and switch scope */ - size_t const top = environment_top(); - scope_t *old_scope = scope_push(&function->parameters); + PUSH_SCOPE(&function->parameters); entity_t *parameter = function->parameters.entities; for (; parameter != NULL; parameter = parameter->base.next) { @@ -5525,9 +5518,7 @@ static void parse_external_declaration(void) label_pop_to(label_stack_top); } - assert(current_scope == &function->parameters); - scope_pop(old_scope); - environment_pop_to(top); + POP_SCOPE(); } static type_t *make_bitfield_type(type_t *base_type, expression_t *size, @@ -5776,10 +5767,13 @@ static void parse_compound_type_entries(compound_t *compound) for (;;) { switch (token.type) { DECLARATION_START + case T___extension__: case T_IDENTIFIER: { + PUSH_EXTENSION(); declaration_specifiers_t specifiers; parse_declaration_specifiers(&specifiers); parse_compound_declarators(compound, &specifiers); + POP_EXTENSION(); break; } @@ -7591,12 +7585,9 @@ types_incompatible: */ static expression_t *parse_extension(void) { - eat(T___extension__); - - bool old_gcc_extension = in_gcc_extension; - in_gcc_extension = true; + PUSH_EXTENSION(); expression_t *expression = parse_subexpression(PREC_UNARY); - in_gcc_extension = old_gcc_extension; + POP_EXTENSION(); return expression; } @@ -9101,7 +9092,8 @@ static statement_t *parse_label_inner_statement(statement_t const *const label, default: inner_stmt = parse_statement(); - /* ISO/IEC 14882:1998(E) §6:1/§6.7 Declarations are statements */ + /* ISO/IEC 9899:1999(E) §6.8:1/6.8.2:1 Declarations are no statements */ + /* ISO/IEC 14882:1998(E) §6:1/§6.7 Declarations are statements */ if (inner_stmt->kind == STATEMENT_DECLARATION && !(c_mode & _CXX)) { errorf(&inner_stmt->base.source_position, "declaration after %s", label_kind); } @@ -9268,6 +9260,17 @@ static statement_t *parse_label_statement(void) return statement; } +static statement_t *parse_inner_statement(void) +{ + statement_t *const stmt = parse_statement(); + /* ISO/IEC 9899:1999(E) §6.8:1/6.8.2:1 Declarations are no statements */ + /* ISO/IEC 14882:1998(E) §6:1/§6.7 Declarations are statements */ + if (stmt->kind == STATEMENT_DECLARATION && !(c_mode & _CXX)) { + errorf(&stmt->base.source_position, "declaration as inner statement, use {}"); + } + return stmt; +} + /** * Parse an if statement. */ @@ -9296,12 +9299,12 @@ end_error: rem_anchor_token('{'); add_anchor_token(T_else); - statement_t *const true_stmt = parse_statement(); + statement_t *const true_stmt = parse_inner_statement(); statement->ifs.true_statement = true_stmt; rem_anchor_token(T_else); if (next_if(T_else)) { - statement->ifs.false_statement = parse_statement(); + statement->ifs.false_statement = parse_inner_statement(); } else if (true_stmt->kind == STATEMENT_IF && true_stmt->ifs.false_statement != NULL) { source_position_t const *const pos = &true_stmt->base.source_position; @@ -9387,7 +9390,7 @@ static statement_t *parse_switch(void) switch_statement_t *rem = current_switch; current_switch = &statement->switchs; - statement->switchs.body = parse_statement(); + statement->switchs.body = parse_inner_statement(); current_switch = rem; if (statement->switchs.default_label == NULL) { @@ -9407,7 +9410,7 @@ static statement_t *parse_loop_body(statement_t *const loop) statement_t *const rem = current_loop; current_loop = loop; - statement_t *const body = parse_statement(); + statement_t *const body = parse_inner_statement(); current_loop = rem; return body; @@ -9492,14 +9495,9 @@ static statement_t *parse_for(void) add_anchor_token(')'); PUSH_PARENT(statement); + PUSH_SCOPE(&statement->fors.scope); - size_t const top = environment_top(); - scope_t *old_scope = scope_push(&statement->fors.scope); - - bool old_gcc_extension = in_gcc_extension; - while (next_if(T___extension__)) { - in_gcc_extension = true; - } + PUSH_EXTENSION(); if (next_if(';')) { } else if (is_declaration_specifier(&token)) { @@ -9515,7 +9513,8 @@ static statement_t *parse_for(void) rem_anchor_token(';'); expect(';', end_error2); } - in_gcc_extension = old_gcc_extension; + + POP_EXTENSION(); if (token.type != ';') { add_anchor_token(';'); @@ -9540,19 +9539,14 @@ static statement_t *parse_for(void) rem_anchor_token(')'); statement->fors.body = parse_loop_body(statement); - assert(current_scope == &statement->fors.scope); - scope_pop(old_scope); - environment_pop_to(top); - + POP_SCOPE(); POP_PARENT(); return statement; end_error2: POP_PARENT(); rem_anchor_token(')'); - assert(current_scope == &statement->fors.scope); - scope_pop(old_scope); - environment_pop_to(top); + POP_SCOPE(); /* fallthrough */ end_error1: @@ -9956,8 +9950,7 @@ static void parse_namespace_definition(void) environment_push(entity); append_entity(current_scope, entity); - size_t const top = environment_top(); - scope_t *old_scope = scope_push(&entity->namespacee.members); + PUSH_SCOPE(&entity->namespacee.members); entity_t *old_current_entity = current_entity; current_entity = entity; @@ -9967,11 +9960,9 @@ static void parse_namespace_definition(void) expect('}', end_error); end_error: - assert(current_scope == &entity->namespacee.members); assert(current_entity == entity); current_entity = old_current_entity; - scope_pop(old_scope); - environment_pop_to(top); + POP_SCOPE(); } /** @@ -10014,15 +10005,14 @@ static statement_t *intern_parse_statement(void) break; } - case T___extension__: + case T___extension__: { /* This can be a prefix to a declaration or an expression statement. * We simply eat it now and parse the rest with tail recursion. */ - while (next_if(T___extension__)) {} - bool old_gcc_extension = in_gcc_extension; - in_gcc_extension = true; + PUSH_EXTENSION(); statement = intern_parse_statement(); - in_gcc_extension = old_gcc_extension; + POP_EXTENSION(); break; + } DECLARATION_START statement = parse_declaration_statement(); @@ -10096,6 +10086,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) statement_t *statement = allocate_statement_zero(STATEMENT_COMPOUND); PUSH_PARENT(statement); + PUSH_SCOPE(&statement->compound.scope); eat('{'); add_anchor_token('}'); @@ -10188,9 +10179,6 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) add_anchor_token(T_wchar_t); add_anchor_token(T_while); - size_t const top = environment_top(); - scope_t *old_scope = scope_push(&statement->compound.scope); - statement_t **anchor = &statement->compound.statements; bool only_decls_so_far = true; while (token.type != '}') { @@ -10329,10 +10317,8 @@ end_error: rem_anchor_token('&'); rem_anchor_token('!'); rem_anchor_token('}'); - assert(current_scope == &statement->compound.scope); - scope_pop(old_scope); - environment_pop_to(top); + POP_SCOPE(); POP_PARENT(); return statement; } @@ -10426,22 +10412,21 @@ end_error: static void parse_external(void) { switch (token.type) { - DECLARATION_START_NO_EXTERN - case T_IDENTIFIER: - case T___extension__: - /* tokens below are for implicit int */ - case '&': /* & x; -> int& x; (and error later, because C++ has no - implicit int) */ - case '*': /* * x; -> int* x; */ - case '(': /* (x); -> int (x); */ - parse_external_declaration(); - return; - case T_extern: if (look_ahead(1)->type == T_STRING_LITERAL) { parse_linkage_specification(); } else { + DECLARATION_START_NO_EXTERN + case T_IDENTIFIER: + case T___extension__: + /* tokens below are for implicit int */ + case '&': /* & x; -> int& x; (and error later, because C++ has no + implicit int) */ + case '*': /* * x; -> int* x; */ + case '(':; /* (x); -> int (x); */ + PUSH_EXTENSION(); parse_external_declaration(); + POP_EXTENSION(); } return;