X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=parser.c;h=87173681dec00f570d54f3dbb1cc883076be2301;hb=ebb77232f9baed801f3a073741ff7a023acea485;hp=f9220f0a259141e0884c6aa69da1dadc88b73dca;hpb=f5c4001df5901a1184663275de9d3e63aa4d10df;p=cparser diff --git a/parser.c b/parser.c index f9220f0..8717368 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; @@ -4528,9 +4544,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) { @@ -4556,10 +4570,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 +5473,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) { @@ -5491,7 +5500,7 @@ static void parse_external_declaration(void) entity_t *old_current_entity = current_entity; current_function = function; current_entity = entity; - current_parent = NULL; + PUSH_PARENT(NULL); goto_first = NULL; goto_anchor = &goto_first; @@ -5517,7 +5526,7 @@ static void parse_external_declaration(void) } } - assert(current_parent == NULL); + POP_PARENT(); assert(current_function == function); assert(current_entity == entity); current_entity = old_current_entity; @@ -5525,9 +5534,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, @@ -7591,12 +7598,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 +9105,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 +9273,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 +9312,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 +9403,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 +9423,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 +9508,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 +9526,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 +9552,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 +9963,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 +9973,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 +10018,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 +10099,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 +10192,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 +10330,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 +10425,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;