X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=3c5383b8918f1bf20be8cc32dd9145dc0f6d7b68;hb=e628f683385763274b551d468107872a058b31d7;hp=f14a3f141ce7162f2d749886093878674a11abc7;hpb=197cc147f33d924bba478120859e0ade5decc45e;p=cparser diff --git a/parser.c b/parser.c index f14a3f1..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; @@ -655,9 +671,9 @@ static void type_error_incompatible(const char *msg, parse_error_expected(NULL, (expected), NULL); \ add_anchor_token(expected); \ eat_until_anchor(); \ - next_if((expected)); \ rem_anchor_token(expected); \ - goto error_label; \ + if (token.type != (expected)) \ + goto error_label; \ } \ next_token(); \ } while (0) @@ -1102,7 +1118,8 @@ static int strcmp_underscore(const char *s1, const char *s2) static attribute_t *allocate_attribute_zero(attribute_kind_t kind) { attribute_t *attribute = allocate_ast_zero(sizeof(*attribute)); - attribute->kind = kind; + attribute->kind = kind; + attribute->source_position = *HERE; return attribute; } @@ -1171,9 +1188,8 @@ end_error: static attribute_t *parse_attribute_asm(void) { - eat(T_asm); - attribute_t *attribute = allocate_attribute_zero(ATTRIBUTE_GNU_ASM); + eat(T_asm); expect('(', end_error); attribute->a.arguments = parse_attribute_arguments(); @@ -1248,9 +1264,8 @@ static attribute_t *parse_attribute_gnu_single(void) break; } - next_token(); - attribute_t *attribute = allocate_attribute_zero(kind); + next_token(); /* parse arguments */ if (next_if('(')) @@ -1304,30 +1319,30 @@ static attribute_t *parse_attributes(attribute_t *first) break; case T_cdecl: - next_token(); attribute = allocate_attribute_zero(ATTRIBUTE_MS_CDECL); + eat(T_cdecl); break; case T__fastcall: - next_token(); attribute = allocate_attribute_zero(ATTRIBUTE_MS_FASTCALL); + eat(T__fastcall); break; case T__forceinline: - next_token(); attribute = allocate_attribute_zero(ATTRIBUTE_MS_FORCEINLINE); + eat(T__forceinline); break; case T__stdcall: - next_token(); attribute = allocate_attribute_zero(ATTRIBUTE_MS_STDCALL); + eat(T__stdcall); break; case T___thiscall: /* TODO record modifier */ warningf(WARN_OTHER, HERE, "Ignoring declaration modifier %K", &token); - eat(T___thiscall); attribute = allocate_attribute_zero(ATTRIBUTE_MS_THISCALL); + eat(T___thiscall); break; default: @@ -2568,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)) { @@ -2588,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); @@ -2700,13 +2709,13 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void) if (kind == ATTRIBUTE_UNKNOWN) { warningf(WARN_ATTRIBUTE, HERE, "unknown __declspec '%s' ignored", name); } - eat(T_IDENTIFIER); } else { parse_error_expected("while parsing __declspec", T_IDENTIFIER, NULL); return NULL; } attribute_t *attribute = allocate_attribute_zero(kind); + eat(T_IDENTIFIER); if (kind == ATTRIBUTE_MS_PROPERTY) { return parse_attribute_ms_property(attribute); @@ -2771,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; @@ -2848,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: \ @@ -3003,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; @@ -3317,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(); @@ -4529,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) { @@ -4544,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. */ @@ -4557,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); @@ -5463,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) { @@ -5492,7 +5484,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; @@ -5518,7 +5510,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; @@ -5526,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, @@ -5774,20 +5764,28 @@ static void parse_compound_type_entries(compound_t *compound) eat('{'); add_anchor_token('}'); - while (token.type != '}') { - if (token.type == T_EOF) { - errorf(HERE, "EOF while parsing struct"); - break; + 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; + } + + default: + rem_anchor_token('}'); + expect('}', end_error); +end_error: + /* §6.7.2.1:7 */ + compound->complete = true; + return; } - declaration_specifiers_t specifiers; - parse_declaration_specifiers(&specifiers); - parse_compound_declarators(compound, &specifiers); } - rem_anchor_token('}'); - next_token(); - - /* §6.7.2.1:7 */ - compound->complete = true; } static type_t *parse_typename(void) @@ -5884,10 +5882,9 @@ static expression_t *parse_string_literal(void) static expression_t *parse_boolean_literal(bool value) { expression_t *literal = allocate_expression_zero(EXPR_LITERAL_BOOLEAN); - literal->base.source_position = token.source_position; - literal->base.type = type_bool; - literal->literal.value.begin = value ? "true" : "false"; - literal->literal.value.size = value ? 4 : 5; + literal->base.type = type_bool; + literal->literal.value.begin = value ? "true" : "false"; + literal->literal.value.size = value ? 4 : 5; next_token(); return literal; @@ -5999,10 +5996,9 @@ static expression_t *parse_number_literal(void) } expression_t *literal = allocate_expression_zero(kind); - literal->base.source_position = token.source_position; - literal->base.type = type; - literal->literal.value = token.literal; - literal->literal.suffix = token.symbol; + literal->base.type = type; + literal->literal.value = token.literal; + literal->literal.suffix = token.symbol; next_token(); /* integer type depends on the size of the number and the size @@ -6019,9 +6015,8 @@ static expression_t *parse_number_literal(void) static expression_t *parse_character_constant(void) { expression_t *literal = allocate_expression_zero(EXPR_LITERAL_CHARACTER); - literal->base.source_position = token.source_position; - literal->base.type = c_mode & _CXX ? type_char : type_int; - literal->literal.value = token.literal; + literal->base.type = c_mode & _CXX ? type_char : type_int; + literal->literal.value = token.literal; size_t len = literal->literal.value.size; if (len > 1) { @@ -6043,9 +6038,8 @@ static expression_t *parse_character_constant(void) static expression_t *parse_wide_character_constant(void) { expression_t *literal = allocate_expression_zero(EXPR_LITERAL_WIDE_CHARACTER); - literal->base.source_position = token.source_position; - literal->base.type = type_int; - literal->literal.value = token.literal; + literal->base.type = type_int; + literal->literal.value = token.literal; size_t len = wstrlen(&literal->literal.value); if (len > 1) { @@ -6344,9 +6338,10 @@ static bool semantic_cast(expression_t *cast) return true; } -static expression_t *parse_compound_literal(type_t *type) +static expression_t *parse_compound_literal(source_position_t const *const pos, type_t *type) { expression_t *expression = allocate_expression_zero(EXPR_COMPOUND_LITERAL); + expression->base.source_position = *pos; parse_initializer_env_t env; env.type = type; @@ -6367,7 +6362,7 @@ static expression_t *parse_compound_literal(type_t *type) */ static expression_t *parse_cast(void) { - source_position_t source_position = token.source_position; + source_position_t const pos = *HERE; eat('('); add_anchor_token(')'); @@ -6378,11 +6373,11 @@ static expression_t *parse_cast(void) expect(')', end_error); if (token.type == '{') { - return parse_compound_literal(type); + return parse_compound_literal(&pos, type); } expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST); - cast->base.source_position = source_position; + cast->base.source_position = pos; expression_t *value = parse_subexpression(PREC_CAST); cast->base.type = type; @@ -6889,10 +6884,9 @@ static expression_t *parse_noop_expression(void) { /* the result is a (int)0 */ expression_t *literal = allocate_expression_zero(EXPR_LITERAL_MS_NOOP); - literal->base.type = type_int; - literal->base.source_position = token.source_position; - literal->literal.value.begin = "__noop"; - literal->literal.value.size = 6; + literal->base.type = type_int; + literal->literal.value.begin = "__noop"; + literal->literal.value.size = 6; eat(T___noop); @@ -7053,6 +7047,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind) type_t *orig_type; expression_t *expression; if (token.type == '(' && is_declaration_specifier(look_ahead(1))) { + source_position_t const pos = *HERE; next_token(); add_anchor_token(')'); orig_type = parse_typename(); @@ -7062,7 +7057,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind) if (token.type == '{') { /* It was not sizeof(type) after all. It is sizeof of an expression * starting with a compound literal */ - expression = parse_compound_literal(orig_type); + expression = parse_compound_literal(&pos, orig_type); goto typeprop_expression; } } else { @@ -7590,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; } @@ -8759,7 +8751,6 @@ static expression_t *parse_subexpression(precedence_t precedence) expression_parser_function_t *parser = &expression_parsers[token.type]; - source_position_t source_position = token.source_position; expression_t *left; if (parser->parser != NULL) { @@ -8768,7 +8759,6 @@ static expression_t *parse_subexpression(precedence_t precedence) left = parse_primary_expression(); } assert(left != NULL); - left->base.source_position = source_position; while (true) { if (token.type < 0) { @@ -8785,7 +8775,6 @@ static expression_t *parse_subexpression(precedence_t precedence) assert(left != NULL); assert(left->kind != EXPR_UNKNOWN); - left->base.source_position = source_position; } return left; @@ -9103,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); } @@ -9192,7 +9182,7 @@ end_error: statement->case_label.statement = parse_label_inner_statement(statement, "case label"); - POP_PARENT; + POP_PARENT(); return statement; } @@ -9232,7 +9222,7 @@ end_error: statement->case_label.statement = parse_label_inner_statement(statement, "default label"); - POP_PARENT; + POP_PARENT(); return statement; } @@ -9266,10 +9256,21 @@ static statement_t *parse_label_statement(void) *label_anchor = &statement->label; label_anchor = &statement->label.next; - POP_PARENT; + POP_PARENT(); 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. */ @@ -9298,19 +9299,19 @@ 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; warningf(WARN_PARENTHESES, pos, "suggest explicit braces to avoid ambiguous 'else'"); } - POP_PARENT; + POP_PARENT(); return statement; } @@ -9389,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) { @@ -9397,10 +9398,10 @@ static statement_t *parse_switch(void) } check_enum_cases(&statement->switchs); - POP_PARENT; + POP_PARENT(); return statement; end_error: - POP_PARENT; + POP_PARENT(); return create_invalid_statement(); } @@ -9409,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; @@ -9439,10 +9440,10 @@ static statement_t *parse_while(void) statement->whiles.body = parse_loop_body(statement); - POP_PARENT; + POP_PARENT(); return statement; end_error: - POP_PARENT; + POP_PARENT(); return create_invalid_statement(); } @@ -9474,10 +9475,10 @@ static statement_t *parse_do(void) expect(')', end_error); expect(';', end_error); - POP_PARENT; + POP_PARENT(); return statement; end_error: - POP_PARENT; + POP_PARENT(); return create_invalid_statement(); } @@ -9494,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)) { @@ -9517,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(';'); @@ -9542,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_PARENT; + POP_SCOPE(); + POP_PARENT(); return statement; end_error2: - POP_PARENT; + POP_PARENT(); rem_anchor_token(')'); - assert(current_scope == &statement->fors.scope); - scope_pop(old_scope); - environment_pop_to(top); + POP_SCOPE(); /* fallthrough */ end_error1: @@ -9721,9 +9713,8 @@ entity_t *expression_is_variable(const expression_t *expression) */ static statement_t *parse_return(void) { - eat(T_return); - statement_t *statement = allocate_statement_zero(STATEMENT_RETURN); + eat(T_return); expression_t *return_value = NULL; if (token.type != ';') { @@ -9844,7 +9835,7 @@ static statement_t *parse_ms_try_statment(void) statement->ms_try.try_statement = parse_compound_statement(false); current_try = rem; - POP_PARENT; + POP_PARENT(); if (next_if(T___except)) { expect('(', end_error); @@ -9959,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; @@ -9970,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(); } /** @@ -10017,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(); @@ -10099,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('}'); @@ -10191,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 != '}') { @@ -10332,11 +10317,9 @@ 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_PARENT; + POP_SCOPE(); + POP_PARENT(); return statement; } @@ -10429,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;