X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=inline;f=parser.c;h=d60a90d58d66e3e792247d061738ea7da748e66d;hb=d9f64d8f165b5c987cc723765f15b8535af6ac67;hp=67f83eaa908d520724d510522531fc5ae3530e6d;hpb=032760cdf02b03c4815b4c840e19a97b294b083e;p=cparser diff --git a/parser.c b/parser.c index 67f83ea..d60a90d 100644 --- a/parser.c +++ b/parser.c @@ -89,7 +89,6 @@ static scope_t *current_scope = NULL; /** Point to the current function declaration if inside a function. */ static function_t *current_function = NULL; static entity_t *current_entity = NULL; -static entity_t *current_init_decl = NULL; static switch_statement_t *current_switch = NULL; static statement_t *current_loop = NULL; static statement_t *current_parent = NULL; @@ -101,8 +100,6 @@ static label_statement_t *label_first = NULL; static label_statement_t **label_anchor = NULL; /** current translation unit. */ static translation_unit_t *unit = NULL; -/** true if we are in a type property context (evaluation only for type) */ -static bool in_type_prop = false; /** true if we are in an __extension__ context. */ static bool in_gcc_extension = false; static struct obstack temp_obst; @@ -117,11 +114,27 @@ static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT; ((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() \ + (void)0; \ + 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; /** The token anchor set */ -static unsigned char token_anchor_set[T_LAST_TOKEN]; +static unsigned short token_anchor_set[T_LAST_TOKEN]; /** The current source position. */ #define HERE (&token.source_position) @@ -874,23 +887,6 @@ static type_t *promote_integer(type_t *type) return type; } -/** - * Create a cast expression. - * - * @param expression the expression to cast - * @param dest_type the destination type - */ -static expression_t *create_cast_expression(expression_t *expression, - type_t *dest_type) -{ - expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST_IMPLICIT); - - cast->unary.value = expression; - cast->base.type = dest_type; - - return cast; -} - /** * Check if a given expression represents a null pointer constant. * @@ -899,8 +895,7 @@ static expression_t *create_cast_expression(expression_t *expression, static bool is_null_pointer_constant(const expression_t *expression) { /* skip void* cast */ - if (expression->kind == EXPR_UNARY_CAST || - expression->kind == EXPR_UNARY_CAST_IMPLICIT) { + if (expression->kind == EXPR_UNARY_CAST) { type_t *const type = skip_typeref(expression->base.type); if (types_compatible(type, type_void_ptr)) expression = expression->unary.value; @@ -930,7 +925,12 @@ static expression_t *create_implicit_cast(expression_t *expression, if (source_type == dest_type) return expression; - return create_cast_expression(expression, dest_type); + expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST); + cast->unary.value = expression; + cast->base.type = dest_type; + cast->base.implicit = true; + + return cast; } typedef enum assign_error_t { @@ -1493,7 +1493,6 @@ static void mark_vars_read(expression_t *const expr, entity_t *lhs_ent) case EXPR_UNARY_POSTFIX_DECREMENT: case EXPR_UNARY_PREFIX_INCREMENT: case EXPR_UNARY_PREFIX_DECREMENT: - case EXPR_UNARY_CAST_IMPLICIT: case EXPR_UNARY_ASSUME: unary: mark_vars_read(expr->unary.value, lhs_ent); @@ -2568,14 +2567,6 @@ 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; - - 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 +2579,6 @@ static type_t *parse_typeof(void) } break; } - in_type_prop = old_type_prop; - in_gcc_extension = old_gcc_extension; rem_anchor_token(')'); expect(')', end_error); @@ -2771,12 +2760,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 +2836,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 +2986,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 +3298,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(); @@ -4350,10 +4330,8 @@ static void parse_init_declarator_rest(entity_t *entity) env.type = orig_type; env.must_be_constant = must_be_constant; env.entity = entity; - current_init_decl = entity; initializer_t *initializer = parse_initializer(&env); - current_init_decl = NULL; if (entity->kind == ENTITY_VARIABLE) { /* §6.7.5:22 array initializers for arrays with unknown size @@ -4529,9 +4507,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 +4520,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 +4532,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 +5435,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) { @@ -5526,9 +5496,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, @@ -5667,7 +5635,7 @@ static expression_t *find_create_select(const source_position_t *pos, expression_t *sub_addr = create_select(pos, addr, qualifiers, iter); sub_addr->base.source_position = *pos; - sub_addr->select.implicit = true; + sub_addr->base.implicit = true; return find_create_select(pos, sub_addr, qualifiers, sub_compound, symbol); } @@ -5777,10 +5745,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; } @@ -6293,11 +6264,6 @@ static expression_t *parse_reference(void) check_deprecated(&pos, entity); - if (entity == current_init_decl && !in_type_prop && entity->kind == ENTITY_VARIABLE) { - current_init_decl = NULL; - warningf(WARN_INIT_SELF, &pos, "variable '%#N' is initialized by itself", entity); - } - return expression; } @@ -7047,10 +7013,6 @@ static expression_t *parse_typeprop(expression_kind_t const kind) eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__); - /* we only refer to a type property, mark this case */ - bool old = in_type_prop; - in_type_prop = true; - type_t *orig_type; expression_t *expression; if (token.type == '(' && is_declaration_specifier(look_ahead(1))) { @@ -7107,7 +7069,6 @@ typeprop_expression: } end_error: - in_type_prop = old; return tp_expression; } @@ -7592,12 +7553,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; } @@ -8638,7 +8596,6 @@ static bool expression_has_effect(const expression_t *const expr) return is_type_atomic(type, ATOMIC_TYPE_VOID); } - case EXPR_UNARY_CAST_IMPLICIT: return true; case EXPR_UNARY_ASSUME: return true; case EXPR_UNARY_DELETE: return true; case EXPR_UNARY_DELETE_ARRAY: return true; @@ -9102,7 +9059,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); } @@ -9259,6 +9217,10 @@ static statement_t *parse_label_statement(void) eat(':'); + if (token.type == T___attribute__ && !(c_mode & _CXX)) { + parse_attributes(NULL); // TODO process attributes + } + statement->label.statement = parse_label_inner_statement(statement, "label"); /* remember the labels in a list for later checking */ @@ -9269,6 +9231,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. */ @@ -9297,12 +9270,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; @@ -9388,7 +9361,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) { @@ -9408,7 +9381,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; @@ -9493,14 +9466,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)) { @@ -9516,7 +9484,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(';'); @@ -9541,19 +9510,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: @@ -9957,8 +9921,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; @@ -9968,11 +9931,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(); } /** @@ -10015,15 +9976,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(); @@ -10097,6 +10057,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('}'); @@ -10189,9 +10150,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 != '}') { @@ -10330,10 +10288,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; } @@ -10427,22 +10383,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; @@ -10478,14 +10433,14 @@ static void parse_externals(void) #ifndef NDEBUG /* make a copy of the anchor set, so we can check if it is restored after parsing */ - unsigned char token_anchor_copy[T_LAST_TOKEN]; + unsigned short token_anchor_copy[T_LAST_TOKEN]; memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy)); #endif while (token.type != T_EOF && token.type != '}') { #ifndef NDEBUG for (int i = 0; i < T_LAST_TOKEN; ++i) { - unsigned char count = token_anchor_set[i] - token_anchor_copy[i]; + unsigned short count = token_anchor_set[i] - token_anchor_copy[i]; if (count != 0) { /* the anchor set and its copy differs */ internal_errorf(HERE, "Leaked anchor token %k %d times", i, count);