X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=04adbc1f321f4c013436dd2d9c0436adc55f5537;hb=c8dfa04bfc2911fd2e49853003d43a46e0073291;hp=1a64f7495519ddcd7022233206be1da86a072f9a;hpb=57b2bd82de1bc4d81969d7d7446ed54d3bffdcd6;p=cparser diff --git a/parser.c b/parser.c index 1a64f74..04adbc1 100644 --- a/parser.c +++ b/parser.c @@ -109,6 +109,12 @@ static declaration_t **incomplete_arrays; static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT; +#define PUSH_CURRENT_ENTITY(entity) \ + entity_t *const new_current_entity = (entity); \ + entity_t *const old_current_entity = current_entity; \ + ((void)(current_entity = new_current_entity)) +#define POP_CURRENT_ENTITY() (assert(current_entity == new_current_entity), (void)(current_entity = old_current_entity)) + #define PUSH_PARENT(stmt) \ statement_t *const new_parent = (stmt); \ statement_t *const old_parent = current_parent; \ @@ -118,8 +124,9 @@ static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT; #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)) + scope_t *const old_scope = (new_scope ? scope_push(new_scope) : NULL) +#define PUSH_SCOPE_STATEMENT(scope) PUSH_SCOPE(c_mode & (_C99 | _CXX) ? (scope) : NULL) +#define POP_SCOPE() (new_scope ? assert(current_scope == new_scope), scope_pop(old_scope), environment_pop_to(top) : (void)0) #define PUSH_EXTENSION() \ (void)0; \ @@ -241,10 +248,7 @@ static void semantic_comparison(binary_expression_t *expression); case T_ANDAND: \ case T_CHARACTER_CONSTANT: \ case T_FLOATINGPOINT: \ - case T_FLOATINGPOINT_HEXADECIMAL: \ case T_INTEGER: \ - case T_INTEGER_HEXADECIMAL: \ - case T_INTEGER_OCTAL: \ case T_MINUSMINUS: \ case T_PLUSPLUS: \ case T_STRING_LITERAL: \ @@ -323,10 +327,7 @@ static size_t get_expression_struct_size(expression_kind_t kind) [EXPR_ENUM_CONSTANT] = sizeof(reference_expression_t), [EXPR_LITERAL_BOOLEAN] = sizeof(literal_expression_t), [EXPR_LITERAL_INTEGER] = sizeof(literal_expression_t), - [EXPR_LITERAL_INTEGER_OCTAL] = sizeof(literal_expression_t), - [EXPR_LITERAL_INTEGER_HEXADECIMAL]= sizeof(literal_expression_t), [EXPR_LITERAL_FLOATINGPOINT] = sizeof(literal_expression_t), - [EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL] = sizeof(literal_expression_t), [EXPR_LITERAL_CHARACTER] = sizeof(literal_expression_t), [EXPR_LITERAL_WIDE_CHARACTER] = sizeof(literal_expression_t), [EXPR_STRING_LITERAL] = sizeof(string_literal_expression_t), @@ -486,7 +487,7 @@ static inline void next_token(void) #endif } -static inline bool next_if(int const type) +static inline bool next_if(token_kind_t const type) { if (token.kind == type) { next_token(); @@ -509,60 +510,28 @@ static inline const token_t *look_ahead(size_t num) /** * Adds a token type to the token type anchor set (a multi-set). */ -static void add_anchor_token(int token_kind) +static void add_anchor_token(token_kind_t const token_kind) { - assert(0 <= token_kind && token_kind < T_LAST_TOKEN); + assert(token_kind < T_LAST_TOKEN); ++token_anchor_set[token_kind]; } -/** - * Set the number of tokens types of the given type - * to zero and return the old count. - */ -static int save_and_reset_anchor_state(int token_kind) -{ - assert(0 <= token_kind && token_kind < T_LAST_TOKEN); - int count = token_anchor_set[token_kind]; - token_anchor_set[token_kind] = 0; - return count; -} - -/** - * Restore the number of token types to the given count. - */ -static void restore_anchor_state(int token_kind, int count) -{ - assert(0 <= token_kind && token_kind < T_LAST_TOKEN); - token_anchor_set[token_kind] = count; -} - /** * Remove a token type from the token type anchor set (a multi-set). */ -static void rem_anchor_token(int token_kind) +static void rem_anchor_token(token_kind_t const token_kind) { - assert(0 <= token_kind && token_kind < T_LAST_TOKEN); + assert(token_kind < T_LAST_TOKEN); assert(token_anchor_set[token_kind] != 0); --token_anchor_set[token_kind]; } -/** - * Return true if the token type of the current token is - * in the anchor set. - */ -static bool at_anchor(void) -{ - if (token.kind < 0) - return false; - return token_anchor_set[token.kind]; -} - /** * Eat tokens until a matching token type is found. */ -static void eat_until_matching_token(int type) +static void eat_until_matching_token(token_kind_t const type) { - int end_token; + token_kind_t end_token; switch (type) { case '(': end_token = ')'; break; case '{': end_token = '}'; break; @@ -664,21 +633,37 @@ static void type_error_incompatible(const char *msg, /** * Expect the current token is the expected token. - * If not, generate an error, eat the current statement, - * and goto the error_label label. - */ -#define expect(expected, error_label) \ - do { \ - if (UNLIKELY(token.kind != (expected))) { \ - parse_error_expected(NULL, (expected), NULL); \ - add_anchor_token(expected); \ - eat_until_anchor(); \ - rem_anchor_token(expected); \ - if (token.kind != (expected)) \ - goto error_label; \ - } \ - next_token(); \ - } while (0) + * If not, generate an error and skip until the next anchor. + */ +static void expect(token_kind_t const expected) +{ + if (UNLIKELY(token.kind != expected)) { + parse_error_expected(NULL, expected, NULL); + add_anchor_token(expected); + eat_until_anchor(); + rem_anchor_token(expected); + if (token.kind != expected) + return; + } + eat(expected); +} + +static symbol_t *expect_identifier(char const *const context, source_position_t *const pos) +{ + if (token.kind != T_IDENTIFIER) { + parse_error_expected(context, T_IDENTIFIER, NULL); + add_anchor_token(T_IDENTIFIER); + eat_until_anchor(); + rem_anchor_token(T_IDENTIFIER); + if (token.kind != T_IDENTIFIER) + return NULL; + } + symbol_t *const sym = token.identifier.symbol; + if (pos) + *pos = *HERE; + eat(T_IDENTIFIER); + return sym; +} /** * Push a given scope on the scope stack and make it the @@ -999,10 +984,10 @@ static assign_error_t semantic_assign(type_t *orig_type_left, points_to_left = get_unqualified_type(points_to_left); points_to_right = get_unqualified_type(points_to_right); - if (is_type_atomic(points_to_left, ATOMIC_TYPE_VOID)) + if (is_type_void(points_to_left)) return res; - if (is_type_atomic(points_to_right, ATOMIC_TYPE_VOID)) { + if (is_type_void(points_to_right)) { /* ISO/IEC 14882:1998(E) §C.1.2:6 */ return c_mode & _CXX ? ASSIGN_ERROR_INCOMPATIBLE : res; } @@ -1135,12 +1120,7 @@ static attribute_argument_t *parse_attribute_arguments(void) *anchor = argument; anchor = &argument->next; } while (next_if(',')); - expect(')', end_error); - - return first; - -end_error: - /* TODO... */ + expect(')'); return first; } @@ -1148,52 +1128,25 @@ static attribute_t *parse_attribute_asm(void) { attribute_t *attribute = allocate_attribute_zero(ATTRIBUTE_GNU_ASM); eat(T_asm); - - expect('(', end_error); + expect('('); attribute->a.arguments = parse_attribute_arguments(); return attribute; - -end_error: - return NULL; } static symbol_t *get_symbol_from_token(void) { switch(token.kind) { - case T_IDENTIFIER: - return token.identifier.symbol; - case T_auto: - case T_char: - case T_double: - case T_enum: - case T_extern: - case T_float: - case T_int: - case T_long: - case T_register: - case T_short: - case T_static: - case T_struct: - case T_union: - case T_unsigned: - case T_void: - case T_bool: - case T__Bool: - case T_class: - case T_explicit: - case T_export: - case T_wchar_t: - case T_const: - case T_signed: - case T___real__: - case T___imag__: - case T_restrict: - case T_volatile: - case T_inline: - /* maybe we need more tokens ... add them on demand */ - return get_token_kind_symbol(token.kind); - default: + case T_CHARACTER_CONSTANT: + case T_EOF: + case T_FLOATINGPOINT: + case T_INTEGER: + case T_STRING_LITERAL: + case T_WIDE_CHARACTER_CONSTANT: + case T_WIDE_STRING_LITERAL: return NULL; + + default: + return token.identifier.symbol; } } @@ -1237,21 +1190,23 @@ static attribute_t *parse_attribute_gnu(void) attribute_t **anchor = &first; eat(T___attribute__); - expect('(', end_error); - expect('(', end_error); + expect('('); + expect('('); + add_anchor_token(')'); + add_anchor_token(','); if (token.kind != ')') do { attribute_t *attribute = parse_attribute_gnu_single(); - if (attribute == NULL) - goto end_error; - - *anchor = attribute; - anchor = &attribute->next; + if (attribute) { + *anchor = attribute; + anchor = &attribute->next; + } } while (next_if(',')); - expect(')', end_error); - expect(')', end_error); + rem_anchor_token(','); + rem_anchor_token(')'); -end_error: + expect(')'); + expect(')'); return first; } @@ -1441,7 +1396,7 @@ static void mark_vars_read(expression_t *const expr, entity_t *lhs_ent) case EXPR_UNARY_CAST: /* Special case: Use void cast to mark a variable as "read" */ - if (is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_VOID)) + if (is_type_void(skip_typeref(expr->base.type))) lhs_ent = NULL; goto unary; @@ -1558,22 +1513,18 @@ static designator_t *parse_designation(void) add_anchor_token(']'); designator->array_index = parse_constant_expression(); rem_anchor_token(']'); - expect(']', end_error); + expect(']'); break; case '.': designator = allocate_ast_zero(sizeof(designator[0])); designator->source_position = token.base.source_position; next_token(); - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing designator", - T_IDENTIFIER, NULL); + designator->symbol = expect_identifier("while parsing designator", NULL); + if (!designator->symbol) return NULL; - } - designator->symbol = token.identifier.symbol; - next_token(); break; default: - expect('=', end_error); + expect('='); return result; } @@ -1581,8 +1532,6 @@ static designator_t *parse_designation(void) *anchor = designator; anchor = &designator->next; } -end_error: - return NULL; } static initializer_t *initializer_from_string(array_type_t *const type, @@ -2093,13 +2042,12 @@ finish_designator: env); rem_anchor_token('}'); - if (type != NULL) { - ascend_from_subtype(path); - expect('}', end_error); - } else { - expect('}', end_error); + expect('}'); + + if (!type) goto error_parse_next; - } + + ascend_from_subtype(path); } } else { /* must be an expression */ @@ -2186,7 +2134,9 @@ error_parse_next: if (token.kind == '}') { break; } - expect(',', end_error); + add_anchor_token('}'); + expect(','); + rem_anchor_token('}'); if (token.kind == '}') { break; } @@ -2263,8 +2213,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env) max_index = path.max_index; DEL_ARR_F(path.path); - expect('}', end_error); -end_error:; + expect('}'); } else { /* parse_scalar_initializer() also works in this case: we simply * have an expression without {} around it */ @@ -2367,10 +2316,9 @@ static compound_t *parse_compound_type_specifier(bool is_struct) } if (entity == NULL) { - entity = allocate_entity_zero(kind, NAMESPACE_TAG, symbol); - entity->compound.alignment = 1; - entity->base.source_position = pos; - entity->base.parent_scope = current_scope; + entity = allocate_entity_zero(kind, NAMESPACE_TAG, symbol, &pos); + entity->compound.alignment = 1; + entity->base.parent_scope = current_scope; if (symbol != NULL) { environment_push(entity); } @@ -2405,20 +2353,14 @@ static void parse_enum_entries(type_t *const enum_type) } add_anchor_token('}'); + add_anchor_token(','); do { - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing enum entry", T_IDENTIFIER, NULL); - eat_block(); - rem_anchor_token('}'); - return; - } - - symbol_t *symbol = token.identifier.symbol; - entity_t *const entity - = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, symbol); + add_anchor_token('='); + source_position_t pos; + symbol_t *const symbol = expect_identifier("while parsing enum entry", &pos); + entity_t *const entity = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, symbol, &pos); entity->enum_value.enum_type = enum_type; - entity->base.source_position = token.base.source_position; - next_token(); + rem_anchor_token('='); if (next_if('=')) { expression_t *value = parse_constant_expression(); @@ -2431,12 +2373,10 @@ static void parse_enum_entries(type_t *const enum_type) record_entity(entity, false); } while (next_if(',') && token.kind != '}'); + rem_anchor_token(','); rem_anchor_token('}'); - expect('}', end_error); - -end_error: - ; + expect('}'); } static type_t *parse_enum_specifier(void) @@ -2477,9 +2417,8 @@ static type_t *parse_enum_specifier(void) } if (entity == NULL) { - entity = allocate_entity_zero(ENTITY_ENUM, NAMESPACE_TAG, symbol); - entity->base.source_position = pos; - entity->base.parent_scope = current_scope; + entity = allocate_entity_zero(ENTITY_ENUM, NAMESPACE_TAG, symbol, &pos); + entity->base.parent_scope = current_scope; } type_t *const type = allocate_type_zero(TYPE_ENUM); @@ -2523,7 +2462,7 @@ static type_t *parse_typeof(void) type_t *type; - expect('(', end_error); + expect('('); add_anchor_token(')'); expression_t *expression = NULL; @@ -2542,15 +2481,13 @@ static type_t *parse_typeof(void) } rem_anchor_token(')'); - expect(')', end_error); + expect(')'); type_t *typeof_type = allocate_type_zero(TYPE_TYPEOF); typeof_type->typeoft.expression = expression; typeof_type->typeoft.typeof_type = type; return typeof_type; -end_error: - return NULL; } typedef enum specifiers_t { @@ -2589,45 +2526,43 @@ static type_t *get_typedef_type(symbol_t *symbol) static attribute_t *parse_attribute_ms_property(attribute_t *attribute) { - expect('(', end_error); + attribute_property_argument_t *const property = allocate_ast_zero(sizeof(*property)); - attribute_property_argument_t *property - = allocate_ast_zero(sizeof(*property)); + expect('('); + add_anchor_token(')'); + add_anchor_token(','); do { - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing property declspec", - T_IDENTIFIER, NULL); - goto end_error; - } + add_anchor_token('='); + source_position_t pos; + symbol_t *const prop_sym = expect_identifier("while parsing property declspec", &pos); + rem_anchor_token('='); - symbol_t **prop; - symbol_t *symbol = token.identifier.symbol; - if (streq(symbol->string, "put")) { - prop = &property->put_symbol; - } else if (streq(symbol->string, "get")) { - prop = &property->get_symbol; - } else { - errorf(HERE, "expected put or get in property declspec"); - prop = NULL; - } - eat(T_IDENTIFIER); - expect('=', end_error); - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing property declspec", - T_IDENTIFIER, NULL); - goto end_error; + symbol_t **prop = NULL; + if (prop_sym) { + if (streq(prop_sym->string, "put")) { + prop = &property->put_symbol; + } else if (streq(prop_sym->string, "get")) { + prop = &property->get_symbol; + } else { + errorf(&pos, "expected put or get in property declspec, but got '%Y'", prop_sym); + } } + + add_anchor_token(T_IDENTIFIER); + expect('='); + rem_anchor_token(T_IDENTIFIER); + + symbol_t *const sym = expect_identifier("while parsing property declspec", NULL); if (prop != NULL) - *prop = token.identifier.symbol; - next_token(); + *prop = sym ? sym : sym_anonymous; } while (next_if(',')); + rem_anchor_token(','); + rem_anchor_token(')'); attribute->a.property = property; - expect(')', end_error); - -end_error: + expect(')'); return attribute; } @@ -2673,40 +2608,33 @@ static attribute_t *parse_microsoft_extended_decl_modifier(attribute_t *first) { eat(T__declspec); - expect('(', end_error); - - if (next_if(')')) - return NULL; - - add_anchor_token(')'); - - attribute_t **anchor = &first; - do { - while (*anchor != NULL) - anchor = &(*anchor)->next; + expect('('); + if (token.kind != ')') { + add_anchor_token(')'); - attribute_t *attribute - = parse_microsoft_extended_decl_modifier_single(); - if (attribute == NULL) - goto end_error; + attribute_t **anchor = &first; + do { + while (*anchor != NULL) + anchor = &(*anchor)->next; - *anchor = attribute; - anchor = &attribute->next; - } while (next_if(',')); + attribute_t *attribute + = parse_microsoft_extended_decl_modifier_single(); + if (attribute == NULL) + break; - rem_anchor_token(')'); - expect(')', end_error); - return first; + *anchor = attribute; + anchor = &attribute->next; + } while (next_if(',')); -end_error: - rem_anchor_token(')'); + rem_anchor_token(')'); + } + expect(')'); return first; } static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) { - entity_t *const entity = allocate_entity_zero(kind, NAMESPACE_NORMAL, symbol); - entity->base.source_position = *HERE; + entity_t *const entity = allocate_entity_zero(kind, NAMESPACE_NORMAL, symbol, HERE); if (is_declaration(entity)) { entity->declaration.type = type_error_type; entity->declaration.implicit = true; @@ -3170,8 +3098,7 @@ static void parse_identifier_list(scope_t *scope) { assert(token.kind == T_IDENTIFIER); do { - entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.identifier.symbol); - entity->base.source_position = token.base.source_position; + entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.identifier.symbol, HERE); /* a K&R parameter has no type, yet */ next_token(); @@ -3208,6 +3135,8 @@ static void semantic_parameter_incomplete(const entity_t *entity) static bool has_parameters(void) { /* func(void) is not a parameter */ + if (look_ahead(1)->kind != ')') + return true; if (token.kind == T_IDENTIFIER) { entity_t const *const entity = get_entity(token.identifier.symbol, NAMESPACE_NORMAL); @@ -3215,13 +3144,20 @@ static bool has_parameters(void) return true; if (entity->kind != ENTITY_TYPEDEF) return true; - if (skip_typeref(entity->typedefe.type) != type_void) + type_t const *const type = skip_typeref(entity->typedefe.type); + if (!is_type_void(type)) return true; + if (c_mode & _CXX) { + /* ISO/IEC 14882:1998(E) §8.3.5:2 It must be literally (void). A typedef + * is not allowed. */ + errorf(HERE, "empty parameter list defined with a typedef of 'void' not allowed in C++"); + } else if (type->base.qualifiers != TYPE_QUALIFIER_NONE) { + /* §6.7.5.3:10 Qualification is not allowed here. */ + errorf(HERE, "'void' as parameter must not have type qualifiers"); + } } else if (token.kind != T_void) { return true; } - if (look_ahead(1)->kind != ')') - return true; next_token(); return false; } @@ -3234,24 +3170,19 @@ static void parse_parameters(function_type_t *type, scope_t *scope) { eat('('); add_anchor_token(')'); - int saved_comma_state = save_and_reset_anchor_state(','); - - if (token.kind == T_IDENTIFIER - && !is_typedef_symbol(token.identifier.symbol)) { - token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind; - if (la1_type == ',' || la1_type == ')') { - type->kr_style_parameters = true; - parse_identifier_list(scope); - goto parameters_finished; - } - } - if (token.kind == ')') { + if (token.kind == T_IDENTIFIER && + !is_typedef_symbol(token.identifier.symbol) && + (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) { + type->kr_style_parameters = true; + parse_identifier_list(scope); + } else if (token.kind == ')') { /* ISO/IEC 14882:1998(E) §C.1.6:1 */ if (!(c_mode & _CXX)) type->unspecified_parameters = true; } else if (has_parameters()) { function_parameter_t **anchor = &type->parameters; + add_anchor_token(','); do { switch (token.kind) { case T_DOTDOTDOT: @@ -3288,14 +3219,12 @@ static void parse_parameters(function_type_t *type, scope_t *scope) goto parameters_finished; } } while (next_if(',')); +parameters_finished: + rem_anchor_token(','); } -parameters_finished: rem_anchor_token(')'); - expect(')', end_error); - -end_error: - restore_anchor_state(',', saved_comma_state); + expect(')'); } typedef enum construct_type_kind_t { @@ -3420,9 +3349,7 @@ static construct_type_t *parse_array_declarator(void) errorf(&array->base.pos, "static array parameters require a size"); rem_anchor_token(']'); - expect(']', end_error); - -end_error: + expect(']'); return cons; } @@ -3536,7 +3463,7 @@ ptr_operator_end: ; env->must_be_abstract = true; } rem_anchor_token(')'); - expect(')', end_error); + expect(')'); } break; } @@ -3585,8 +3512,6 @@ declarator_finished: *anchor = inner_types; return first; -end_error: - return NULL; } static type_t *construct_declarator_type(construct_type_t *construct_list, @@ -3760,9 +3685,8 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, entity_t *entity; if (specifiers->storage_class == STORAGE_CLASS_TYPEDEF) { - entity = allocate_entity_zero(ENTITY_TYPEDEF, NAMESPACE_NORMAL, env.symbol); - entity->base.source_position = env.source_position; - entity->typedefe.type = orig_type; + entity = allocate_entity_zero(ENTITY_TYPEDEF, NAMESPACE_NORMAL, env.symbol, &env.source_position); + entity->typedefe.type = orig_type; if (anonymous_entity != NULL) { if (is_type_compound(type)) { @@ -3780,8 +3704,9 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, } } else { /* create a declaration type entity */ + source_position_t const *const pos = env.symbol ? &env.source_position : &specifiers->source_position; if (flags & DECL_CREATE_COMPOUND_MEMBER) { - entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, env.symbol); + entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, env.symbol, pos); if (env.symbol != NULL) { if (specifiers->is_inline && is_type_valid(type)) { @@ -3797,10 +3722,10 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, } } } else if (flags & DECL_IS_PARAMETER) { - entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, env.symbol); + entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, env.symbol, pos); orig_type = semantic_parameter(&env.source_position, orig_type, specifiers, entity); } else if (is_type_function(type)) { - entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, env.symbol); + entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, env.symbol, pos); entity->function.is_inline = specifiers->is_inline; entity->function.elf_visibility = default_visibility; entity->function.parameters = env.parameters; @@ -3818,7 +3743,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, } } } else { - entity = allocate_entity_zero(ENTITY_VARIABLE, NAMESPACE_NORMAL, env.symbol); + entity = allocate_entity_zero(ENTITY_VARIABLE, NAMESPACE_NORMAL, env.symbol, pos); entity->variable.elf_visibility = default_visibility; entity->variable.thread_local = specifiers->thread_local; @@ -3846,7 +3771,6 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, } } - entity->base.source_position = env.symbol != NULL ? env.source_position : specifiers->source_position; entity->declaration.type = orig_type; entity->declaration.alignment = get_type_alignment(orig_type); entity->declaration.modifiers = env.modifiers; @@ -3953,14 +3877,6 @@ warn_arg_count: } } -/** - * Check if a symbol is the equal to "main". - */ -static bool is_sym_main(const symbol_t *const sym) -{ - return streq(sym->string, "main"); -} - static void error_redefined_as_different_kind(const source_position_t *pos, const entity_t *old, entity_kind_t new_kind) { @@ -4020,6 +3936,8 @@ static void merge_in_attributes(declaration_t *decl, attribute_t *attributes) } } +static bool is_main(entity_t*); + /** * record entities for the NAMESPACE_NORMAL, and produce error messages/warnings * for various problems that occur for multiple definitions @@ -4034,6 +3952,10 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) if (symbol == NULL) return entity; + assert(!entity->base.parent_scope); + assert(current_scope); + entity->base.parent_scope = current_scope; + entity_t *const previous_entity = get_entity(symbol, namespc); /* pushing the same entity twice will break the stack structure */ assert(previous_entity != entity); @@ -4049,7 +3971,7 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) warningf(WARN_STRICT_PROTOTYPES, pos, "function declaration '%#N' is not a prototype", entity); } - if (current_scope == file_scope && is_sym_main(symbol)) { + if (is_main(entity)) { check_main(entity); } } @@ -4153,7 +4075,7 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) case STORAGE_CLASS_EXTERN: if (is_definition) { - if (prev_type->function.unspecified_parameters && !is_sym_main(symbol)) { + if (prev_type->function.unspecified_parameters && !is_main(entity)) { warningf(WARN_MISSING_PROTOTYPES, pos, "no previous prototype for '%#N'", entity); } } else if (new_storage_class == STORAGE_CLASS_NONE) { @@ -4223,7 +4145,7 @@ error_redeclaration: if (entity->kind == ENTITY_FUNCTION) { if (is_definition && entity->declaration.storage_class != STORAGE_CLASS_STATIC && - !is_sym_main(symbol)) { + !is_main(entity)) { if (is_warn_on(WARN_MISSING_PROTOTYPES)) { warningf(WARN_MISSING_PROTOTYPES, pos, "no previous prototype for '%#N'", entity); } else { @@ -4240,10 +4162,6 @@ warn_missing_declaration: } finish: - assert(entity->base.parent_scope == NULL); - assert(current_scope != NULL); - - entity->base.parent_scope = current_scope; environment_push(entity); append_entity(current_scope, entity); @@ -4393,12 +4311,10 @@ static void parse_declaration_rest(entity_t *ndeclaration, /* ISO/IEC 14882:1998(E) §8.5.3:3 The initializer can be omitted * [...] where the extern specifier is explicitly used. */ declaration_t *decl = &entity->declaration; - if (decl->storage_class != STORAGE_CLASS_EXTERN) { - type_t *type = decl->type; - if (is_type_reference(skip_typeref(type))) { - source_position_t const *const pos = &entity->base.source_position; - errorf(pos, "reference '%#N' must be initialized", entity); - } + if (decl->storage_class != STORAGE_CLASS_EXTERN && + is_type_reference(skip_typeref(decl->type))) { + source_position_t const *const pos = &entity->base.source_position; + errorf(pos, "reference '%#N' must be initialized", entity); } } @@ -4411,12 +4327,11 @@ static void parse_declaration_rest(entity_t *ndeclaration, ndeclaration = parse_declarator(specifiers, flags); rem_anchor_token('='); } - expect(';', end_error); + rem_anchor_token(','); + rem_anchor_token(';'); + expect(';'); -end_error: anonymous_entity = NULL; - rem_anchor_token(';'); - rem_anchor_token(','); } static entity_t *finished_kr_declaration(entity_t *entity, bool is_definition) @@ -4692,11 +4607,7 @@ static void check_declarations(void) { if (is_warn_on(WARN_UNUSED_PARAMETER)) { const scope_t *scope = ¤t_function->parameters; - - /* do not issue unused warnings for main */ - if (!is_sym_main(current_function->base.base.symbol)) { - warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL); - } + warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL); } if (is_warn_on(WARN_UNUSED_VARIABLE)) { walk_statements(current_function->statement, check_unused_variables, @@ -5111,9 +5022,9 @@ found_break_parent: type_t *const type = skip_typeref(current_function->base.type); assert(is_type_function(type)); type_t *const ret = skip_typeref(type->function.return_type); - if (!is_type_atomic(ret, ATOMIC_TYPE_VOID) && - is_type_valid(ret) && - !is_sym_main(current_function->base.base.symbol)) { + if (!is_type_void(ret) && + is_type_valid(ret) && + !is_main(current_entity)) { source_position_t const *const pos = &stmt->base.source_position; warningf(WARN_RETURN_TYPE, pos, "control reaches end of non-void function"); } @@ -5329,6 +5240,8 @@ static bool is_main(entity_t *entity) return true; } +static void prepare_main_collect2(entity_t*); + static void parse_external_declaration(void) { /* function-definitions and declarations both start with declaration @@ -5422,8 +5335,6 @@ static void parse_external_declaration(void) if (ndeclaration != entity) { function->parameters = ndeclaration->function.parameters; } - assert(is_declaration(entity)); - type = skip_typeref(entity->declaration.type); PUSH_SCOPE(&function->parameters); @@ -5449,9 +5360,8 @@ static void parse_external_declaration(void) /* parse function body */ int label_stack_top = label_top(); function_t *old_current_function = current_function; - entity_t *old_current_entity = current_entity; current_function = function; - current_entity = entity; + PUSH_CURRENT_ENTITY(entity); PUSH_PARENT(NULL); goto_first = NULL; @@ -5478,13 +5388,23 @@ static void parse_external_declaration(void) } } - if (is_main(entity) && enable_main_collect2_hack) - prepare_main_collect2(entity); + if (is_main(entity)) { + /* Force main to C linkage. */ + type_t *const type = entity->declaration.type; + assert(is_type_function(type)); + if (type->function.linkage != LINKAGE_C) { + type_t *new_type = duplicate_type(type); + new_type->function.linkage = LINKAGE_C; + entity->declaration.type = identify_new_type(new_type); + } + + if (enable_main_collect2_hack) + prepare_main_collect2(entity); + } + POP_CURRENT_ENTITY(); POP_PARENT(); assert(current_function == function); - assert(current_entity == entity); - current_entity = old_current_entity; current_function = old_current_function; label_pop_to(label_stack_top); } @@ -5655,15 +5575,15 @@ static void parse_bitfield_member(entity_t *entity) static void parse_compound_declarators(compound_t *compound, const declaration_specifiers_t *specifiers) { + add_anchor_token(';'); + add_anchor_token(','); do { entity_t *entity; if (token.kind == ':') { /* anonymous bitfield */ type_t *type = specifiers->type; - entity_t *entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, - NAMESPACE_NORMAL, NULL); - entity->base.source_position = *HERE; + entity_t *const entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, NULL, HERE); entity->declaration.declared_storage_class = STORAGE_CLASS_NONE; entity->declaration.storage_class = STORAGE_CLASS_NONE; entity->declaration.type = type; @@ -5726,9 +5646,10 @@ static void parse_compound_declarators(compound_t *compound, } } } while (next_if(',')); - expect(';', end_error); + rem_anchor_token(','); + rem_anchor_token(';'); + expect(';'); -end_error: anonymous_entity = NULL; } @@ -5752,8 +5673,7 @@ static void parse_compound_type_entries(compound_t *compound) default: rem_anchor_token('}'); - expect('}', end_error); -end_error: + expect('}'); /* §6.7.2.1:7 */ compound->complete = true; return; @@ -5793,20 +5713,6 @@ struct expression_parser_function_t { static expression_parser_function_t expression_parsers[T_LAST_TOKEN]; -/** - * Prints an error message if an expression was expected but not read - */ -static expression_t *expected_expression_error(void) -{ - /* skip the error message if the error token was read */ - if (token.kind != T_ERROR) { - errorf(HERE, "expected expression, got token %K", &token); - } - next_token(); - - return create_error_expression(); -} - static type_t *get_string_type(void) { return is_warn_on(WARN_WRITE_STRINGS) ? type_const_char_ptr : type_char_ptr; @@ -5947,24 +5853,12 @@ static expression_t *parse_number_literal(void) check_integer_suffix(); type = type_int; break; - case T_INTEGER_OCTAL: - kind = EXPR_LITERAL_INTEGER_OCTAL; - check_integer_suffix(); - type = type_int; - break; - case T_INTEGER_HEXADECIMAL: - kind = EXPR_LITERAL_INTEGER_HEXADECIMAL; - check_integer_suffix(); - type = type_int; - break; + case T_FLOATINGPOINT: kind = EXPR_LITERAL_FLOATINGPOINT; type = check_floatingpoint_suffix(); break; - case T_FLOATINGPOINT_HEXADECIMAL: - kind = EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL; - type = check_floatingpoint_suffix(); - break; + default: panic("unexpected token type in parse_number_literal"); } @@ -6024,8 +5918,7 @@ static expression_t *parse_wide_character_constant(void) return literal; } -static entity_t *create_implicit_function(symbol_t *symbol, - const source_position_t *source_position) +static entity_t *create_implicit_function(symbol_t *symbol, source_position_t const *const pos) { type_t *ntype = allocate_type_zero(TYPE_FUNCTION); ntype->function.return_type = type_int; @@ -6033,12 +5926,11 @@ static entity_t *create_implicit_function(symbol_t *symbol, ntype->function.linkage = LINKAGE_C; type_t *type = identify_new_type(ntype); - entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol); + entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol, pos); entity->declaration.storage_class = STORAGE_CLASS_EXTERN; entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN; entity->declaration.type = type; entity->declaration.implicit = true; - entity->base.source_position = *source_position; if (current_scope != NULL) record_entity(entity, false); @@ -6164,13 +6056,9 @@ static entity_t *parse_qualified_identifier(void) entity_t *entity; while (true) { - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing identifier", T_IDENTIFIER, NULL); + symbol = expect_identifier("while parsing identifier", &pos); + if (!symbol) return create_error_entity(sym_anonymous, ENTITY_VARIABLE); - } - symbol = token.identifier.symbol; - pos = *HERE; - next_token(); /* lookup entity */ entity = lookup_entity(lookup_scope, symbol, NAMESPACE_NORMAL); @@ -6273,7 +6161,7 @@ static bool semantic_cast(expression_t *cast) source_position_t const *pos = &cast->base.source_position; /* §6.5.4 A (void) cast is explicitly permitted, more for documentation than for utility. */ - if (dst_type == type_void) + if (is_type_void(dst_type)) return true; /* only integer and pointer can be casted to pointer */ @@ -6339,7 +6227,7 @@ static expression_t *parse_cast(void) type_t *type = parse_typename(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); if (token.kind == '{') { return parse_compound_literal(&pos, type); @@ -6357,8 +6245,6 @@ static expression_t *parse_cast(void) } return cast; -end_error: - return create_error_expression(); } /** @@ -6392,9 +6278,7 @@ static expression_t *parse_statement_expression(void) expression->base.type = type; rem_anchor_token(')'); - expect(')', end_error); - -end_error: + expect(')'); return expression; } @@ -6421,9 +6305,8 @@ static expression_t *parse_parenthesized_expression(void) expression_t *result = parse_expression(); result->base.parenthesized = true; rem_anchor_token(')'); - expect(')', end_error); + expect(')'); -end_error: return result; } @@ -6491,29 +6374,18 @@ static expression_t *parse_funcdname_keyword(void) static designator_t *parse_designator(void) { - designator_t *result = allocate_ast_zero(sizeof(result[0])); - result->source_position = *HERE; - - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing member designator", - T_IDENTIFIER, NULL); + designator_t *const result = allocate_ast_zero(sizeof(result[0])); + result->symbol = expect_identifier("while parsing member designator", &result->source_position); + if (!result->symbol) return NULL; - } - result->symbol = token.identifier.symbol; - next_token(); designator_t *last_designator = result; while (true) { if (next_if('.')) { - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing member designator", - T_IDENTIFIER, NULL); + designator_t *const designator = allocate_ast_zero(sizeof(result[0])); + designator->symbol = expect_identifier("while parsing member designator", &designator->source_position); + if (!designator->symbol) return NULL; - } - designator_t *designator = allocate_ast_zero(sizeof(result[0])); - designator->source_position = *HERE; - designator->symbol = token.identifier.symbol; - next_token(); last_designator->next = designator; last_designator = designator; @@ -6525,7 +6397,7 @@ static designator_t *parse_designator(void) designator->source_position = *HERE; designator->array_index = parse_expression(); rem_anchor_token(']'); - expect(']', end_error); + expect(']'); if (designator->array_index == NULL) { return NULL; } @@ -6538,8 +6410,6 @@ static designator_t *parse_designator(void) } return result; -end_error: - return NULL; } /** @@ -6552,15 +6422,15 @@ static expression_t *parse_offsetof(void) eat(T___builtin_offsetof); - expect('(', end_error); + expect('('); + add_anchor_token(')'); add_anchor_token(','); type_t *type = parse_typename(); rem_anchor_token(','); - expect(',', end_error); - add_anchor_token(')'); + expect(','); designator_t *designator = parse_designator(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); expression->offsetofe.type = type; expression->offsetofe.designator = designator; @@ -6579,8 +6449,6 @@ static expression_t *parse_offsetof(void) DEL_ARR_F(path.path); return expression; -end_error: - return create_error_expression(); } /** @@ -6592,11 +6460,12 @@ static expression_t *parse_va_start(void) eat(T___builtin_va_start); - expect('(', end_error); + expect('('); + add_anchor_token(')'); add_anchor_token(','); expression->va_starte.ap = parse_assignment_expression(); rem_anchor_token(','); - expect(',', end_error); + expect(','); expression_t *const expr = parse_assignment_expression(); if (expr->kind == EXPR_REFERENCE) { entity_t *const entity = expr->reference.entity; @@ -6611,12 +6480,12 @@ static expression_t *parse_va_start(void) } else { expression->va_starte.parameter = &entity->variable; } - expect(')', end_error); - return expression; + } else { + expression = create_error_expression(); } - expect(')', end_error); -end_error: - return create_error_expression(); + rem_anchor_token(')'); + expect(')'); + return expression; } /** @@ -6628,19 +6497,21 @@ static expression_t *parse_va_arg(void) eat(T___builtin_va_arg); - expect('(', end_error); + expect('('); + add_anchor_token(')'); + add_anchor_token(','); call_argument_t ap; ap.expression = parse_assignment_expression(); expression->va_arge.ap = ap.expression; check_call_argument(type_valist, &ap, 1); - expect(',', end_error); + rem_anchor_token(','); + expect(','); expression->base.type = parse_typename(); - expect(')', end_error); + rem_anchor_token(')'); + expect(')'); return expression; -end_error: - return create_error_expression(); } /** @@ -6652,24 +6523,26 @@ static expression_t *parse_va_copy(void) eat(T___builtin_va_copy); - expect('(', end_error); + expect('('); + add_anchor_token(')'); + add_anchor_token(','); expression_t *dst = parse_assignment_expression(); assign_error_t error = semantic_assign(type_valist, dst); report_assign_error(error, type_valist, dst, "call argument 1", &dst->base.source_position); expression->va_copye.dst = dst; - expect(',', end_error); + rem_anchor_token(','); + expect(','); call_argument_t src; src.expression = parse_assignment_expression(); check_call_argument(type_valist, &src, 2); expression->va_copye.src = src.expression; - expect(')', end_error); + rem_anchor_token(')'); + expect(')'); return expression; -end_error: - return create_error_expression(); } /** @@ -6681,16 +6554,14 @@ static expression_t *parse_builtin_constant(void) eat(T___builtin_constant_p); - expect('(', end_error); + expect('('); add_anchor_token(')'); expression->builtin_constant.value = parse_assignment_expression(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); expression->base.type = type_int; return expression; -end_error: - return create_error_expression(); } /** @@ -6702,20 +6573,18 @@ static expression_t *parse_builtin_types_compatible(void) eat(T___builtin_types_compatible_p); - expect('(', end_error); + expect('('); add_anchor_token(')'); add_anchor_token(','); expression->builtin_types_compatible.left = parse_typename(); rem_anchor_token(','); - expect(',', end_error); + expect(','); expression->builtin_types_compatible.right = parse_typename(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); expression->base.type = type_int; return expression; -end_error: - return create_error_expression(); } /** @@ -6750,11 +6619,15 @@ static expression_t *parse_compare_builtin(void) expression->base.source_position = *HERE; next_token(); - expect('(', end_error); + expect('('); + add_anchor_token(')'); + add_anchor_token(','); expression->binary.left = parse_assignment_expression(); - expect(',', end_error); + rem_anchor_token(','); + expect(','); expression->binary.right = parse_assignment_expression(); - expect(')', end_error); + rem_anchor_token(')'); + expect(')'); type_t *const orig_type_left = expression->binary.left->base.type; type_t *const orig_type_right = expression->binary.right->base.type; @@ -6771,8 +6644,6 @@ static expression_t *parse_compare_builtin(void) } return expression; -end_error: - return create_error_expression(); } /** @@ -6784,16 +6655,14 @@ static expression_t *parse_assume(void) eat(T__assume); - expect('(', end_error); + expect('('); add_anchor_token(')'); expression->unary.value = parse_assignment_expression(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); expression->base.type = type_void; return expression; -end_error: - return create_error_expression(); } /** @@ -6813,7 +6682,8 @@ static label_t *get_label(void) } } else if (label == NULL || label->base.parent_scope != ¤t_function->parameters) { /* There is no matching label in the same function, so create a new one. */ - label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.identifier.symbol); + source_position_t const nowhere = { NULL, 0, 0, false }; + label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.identifier.symbol, &nowhere); label_push(label); } @@ -6872,9 +6742,8 @@ static expression_t *parse_noop_expression(void) rem_anchor_token(','); rem_anchor_token(')'); } - expect(')', end_error); + expect(')'); -end_error: return literal; } @@ -6887,10 +6756,7 @@ static expression_t *parse_primary_expression(void) case T_false: return parse_boolean_literal(false); case T_true: return parse_boolean_literal(true); case T_INTEGER: - case T_INTEGER_OCTAL: - case T_INTEGER_HEXADECIMAL: - case T_FLOATINGPOINT: - case T_FLOATINGPOINT_HEXADECIMAL: return parse_number_literal(); + case T_FLOATINGPOINT: return parse_number_literal(); case T_CHARACTER_CONSTANT: return parse_character_constant(); case T_WIDE_CHARACTER_CONSTANT: return parse_wide_character_constant(); case T_STRING_LITERAL: @@ -6998,8 +6864,7 @@ check_idx: arr->base.type = res_type; rem_anchor_token(']'); - expect(']', end_error); -end_error: + expect(']'); return expr; } @@ -7024,7 +6889,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind) add_anchor_token(')'); orig_type = parse_typename(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); if (token.kind == '{') { /* It was not sizeof(type) after all. It is sizeof of an expression @@ -7052,7 +6917,7 @@ typeprop_expression: type_t const* const type = skip_typeref(orig_type); char const* wrong_type = NULL; if (is_type_incomplete(type)) { - if (!is_type_atomic(type, ATOMIC_TYPE_VOID) || !GNU_MODE) + if (!is_type_void(type) || !GNU_MODE) wrong_type = "incomplete"; } else if (type->kind == TYPE_FUNCTION) { if (GNU_MODE) { @@ -7072,7 +6937,6 @@ typeprop_expression: what, wrong_type, orig_type); } -end_error: return tp_expression; } @@ -7093,12 +6957,9 @@ static expression_t *parse_select_expression(expression_t *addr) source_position_t const pos = *HERE; next_token(); - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing select", T_IDENTIFIER, NULL); + symbol_t *const symbol = expect_identifier("while parsing select", NULL); + if (!symbol) return create_error_expression(); - } - symbol_t *symbol = token.identifier.symbol; - next_token(); type_t *const orig_type = addr->base.type; type_t *const type = skip_typeref(orig_type); @@ -7318,7 +7179,7 @@ static expression_t *parse_call_expression(expression_t *expression) } rem_anchor_token(','); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); if (function_type == NULL) return result; @@ -7367,7 +7228,6 @@ static expression_t *parse_call_expression(expression_t *expression) handle_builtin_argument_restrictions(call); } -end_error: return result; } @@ -7469,8 +7329,7 @@ static expression_t *parse_conditional_expression(expression_t *expression) true_expression = parse_expression(); } rem_anchor_token(':'); - expect(':', end_error); -end_error:; + expect(':'); expression_t *false_expression = parse_subexpression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL); @@ -7482,16 +7341,14 @@ end_error:; /* 6.5.15.3 */ source_position_t const *const pos = &conditional->base.source_position; type_t *result_type; - if (is_type_atomic(true_type, ATOMIC_TYPE_VOID) || - is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { + if (is_type_void(true_type) || is_type_void(false_type)) { /* ISO/IEC 14882:1998(E) §5.16:2 */ if (true_expression->kind == EXPR_UNARY_THROW) { result_type = false_type; } else if (false_expression->kind == EXPR_UNARY_THROW) { result_type = true_type; } else { - if (!is_type_atomic(true_type, ATOMIC_TYPE_VOID) || - !is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { + if (!is_type_void(true_type) || !is_type_void(false_type)) { warningf(WARN_OTHER, pos, "ISO C forbids conditional expression with only one void side"); } result_type = type_void; @@ -7524,8 +7381,7 @@ end_error:; type_t *to2 = skip_typeref(other_type->pointer.points_to); type_t *to; - if (is_type_atomic(to1, ATOMIC_TYPE_VOID) || - is_type_atomic(to2, ATOMIC_TYPE_VOID)) { + if (is_type_void(to1) || is_type_void(to2)) { to = type_void; } else if (types_compatible(get_unqualified_type(to1), get_unqualified_type(to2))) { @@ -7581,16 +7437,14 @@ static expression_t *parse_builtin_classify_type(void) eat(T___builtin_classify_type); - expect('(', end_error); + expect('('); add_anchor_token(')'); expression_t *expression = parse_expression(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); result->classify_type.type_expression = expression; return result; -end_error: - return create_error_expression(); } /** @@ -7606,8 +7460,7 @@ static expression_t *parse_delete(void) if (next_if('[')) { result->kind = EXPR_UNARY_DELETE_ARRAY; - expect(']', end_error); -end_error:; + expect(']'); } expression_t *const value = parse_subexpression(PREC_CAST); @@ -7619,7 +7472,7 @@ end_error:; errorf(&value->base.source_position, "operand of delete must have pointer type"); } - } else if (is_type_atomic(skip_typeref(type->pointer.points_to), ATOMIC_TYPE_VOID)) { + } else if (is_type_void(skip_typeref(type->pointer.points_to))) { source_position_t const *const pos = &value->base.source_position; warningf(WARN_OTHER, pos, "deleting 'void*' is undefined"); } @@ -7650,8 +7503,7 @@ static expression_t *parse_throw(void) "cannot throw object of incomplete type '%T'", orig_type); } else if (is_type_pointer(type)) { type_t *const points_to = skip_typeref(type->pointer.points_to); - if (is_type_incomplete(points_to) && - !is_type_atomic(points_to, ATOMIC_TYPE_VOID)) { + if (is_type_incomplete(points_to) && !is_type_void(points_to)) { errorf(&value->base.source_position, "cannot throw pointer to incomplete type '%T'", orig_type); } @@ -7674,7 +7526,7 @@ static bool check_pointer_arithmetic(const source_position_t *source_position, points_to = skip_typeref(points_to); if (is_type_incomplete(points_to)) { - if (!GNU_MODE || !is_type_atomic(points_to, ATOMIC_TYPE_VOID)) { + if (!GNU_MODE || !is_type_void(points_to)) { errorf(source_position, "arithmetic with pointer to incomplete type '%T' not allowed", orig_pointer_type); @@ -8188,7 +8040,7 @@ static void semantic_sub(binary_expression_t *expression) "subtracting pointers to incompatible types '%T' and '%T'", orig_type_left, orig_type_right); } else if (!is_type_object(unqual_left)) { - if (!is_type_atomic(unqual_left, ATOMIC_TYPE_VOID)) { + if (!is_type_void(unqual_left)) { errorf(pos, "subtracting pointers to non-object types '%T'", orig_type_left); } else { @@ -8552,10 +8404,7 @@ static bool expression_has_effect(const expression_t *const expr) case EXPR_LITERAL_CHARACTER: case EXPR_LITERAL_WIDE_CHARACTER: case EXPR_LITERAL_INTEGER: - case EXPR_LITERAL_INTEGER_OCTAL: - case EXPR_LITERAL_INTEGER_HEXADECIMAL: case EXPR_LITERAL_FLOATINGPOINT: - case EXPR_LITERAL_FLOATINGPOINT_HEXADECIMAL: return false; case EXPR_STRING_LITERAL: return false; case EXPR_WIDE_STRING_LITERAL: return false; @@ -8611,7 +8460,7 @@ static bool expression_has_effect(const expression_t *const expr) * suppress the warning */ case EXPR_UNARY_CAST: { type_t *const type = skip_typeref(expr->base.type); - return is_type_atomic(type, ATOMIC_TYPE_VOID); + return is_type_void(type); } case EXPR_UNARY_ASSUME: return true; @@ -8730,10 +8579,6 @@ CREATE_BINEXPR_PARSER(',', EXPR_BINARY_COMMA, PR static expression_t *parse_subexpression(precedence_t precedence) { - if (token.kind < 0) { - return expected_expression_error(); - } - expression_parser_function_t *parser = &expression_parsers[token.kind]; expression_t *left; @@ -8746,10 +8591,6 @@ static expression_t *parse_subexpression(precedence_t precedence) assert(left != NULL); while (true) { - if (token.kind < 0) { - return expected_expression_error(); - } - parser = &expression_parsers[token.kind]; if (parser->infix_parser == NULL) break; @@ -8882,21 +8723,18 @@ static asm_argument_t *parse_asm_arguments(bool is_out) while (token.kind == T_STRING_LITERAL || token.kind == '[') { asm_argument_t *argument = allocate_ast_zero(sizeof(argument[0])); - memset(argument, 0, sizeof(argument[0])); if (next_if('[')) { - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing asm argument", - T_IDENTIFIER, NULL); + add_anchor_token(']'); + argument->symbol = expect_identifier("while parsing asm argument", NULL); + rem_anchor_token(']'); + expect(']'); + if (!argument->symbol) return NULL; - } - argument->symbol = token.identifier.symbol; - - expect(']', end_error); } argument->constraints = parse_string_literals(); - expect('(', end_error); + expect('('); add_anchor_token(')'); expression_t *expression = parse_expression(); rem_anchor_token(')'); @@ -8958,7 +8796,7 @@ static asm_argument_t *parse_asm_arguments(bool is_out) mark_vars_read(expression, NULL); } argument->expression = expression; - expect(')', end_error); + expect(')'); set_address_taken(expression, true); @@ -8970,8 +8808,6 @@ static asm_argument_t *parse_asm_arguments(bool is_out) } return result; -end_error: - return NULL; } /** @@ -9009,7 +8845,7 @@ static statement_t *parse_asm_statement(void) if (next_if(T_volatile)) asm_statement->is_volatile = true; - expect('(', end_error); + expect('('); add_anchor_token(')'); if (token.kind != T_STRING_LITERAL) { parse_error_expected("after asm(", T_STRING_LITERAL, NULL); @@ -9040,8 +8876,8 @@ static statement_t *parse_asm_statement(void) end_of_asm: rem_anchor_token(')'); - expect(')', end_error); - expect(';', end_error); + expect(')'); + expect(';'); if (asm_statement->outputs == NULL) { /* GCC: An 'asm' instruction without any output operands will be treated @@ -9050,8 +8886,6 @@ end_of_asm: } return statement; -end_error: - return create_error_statement(); } static statement_t *parse_label_inner_statement(statement_t const *const label, char const *const label_kind) @@ -9095,6 +8929,7 @@ static statement_t *parse_case_statement(void) source_position_t *const pos = &statement->base.source_position; eat(T_case); + add_anchor_token(':'); expression_t *expression = parse_expression(); type_t *expression_type = expression->base.type; @@ -9157,8 +8992,8 @@ static statement_t *parse_case_statement(void) PUSH_PARENT(statement); - expect(':', end_error); -end_error: + rem_anchor_token(':'); + expect(':'); if (current_switch != NULL) { if (! statement->case_label.is_bad) { @@ -9204,8 +9039,7 @@ static statement_t *parse_default_statement(void) PUSH_PARENT(statement); - expect(':', end_error); -end_error: + expect(':'); if (current_switch != NULL) { const case_label_statement_t *def_label = current_switch->default_label; @@ -9282,6 +9116,20 @@ static statement_t *parse_inner_statement(void) return stmt; } +/** + * Parse an expression in parentheses and mark its variables as read. + */ +static expression_t *parse_condition(void) +{ + expect('('); + add_anchor_token(')'); + expression_t *const expr = parse_expression(); + mark_vars_read(expr, NULL); + rem_anchor_token(')'); + expect(')'); + return expr; +} + /** * Parse an if statement. */ @@ -9292,24 +9140,16 @@ static statement_t *parse_if(void) eat(T_if); PUSH_PARENT(statement); + PUSH_SCOPE_STATEMENT(&statement->ifs.scope); - add_anchor_token('{'); + add_anchor_token(T_else); - expect('(', end_error); - add_anchor_token(')'); - expression_t *const expr = parse_expression(); + expression_t *const expr = parse_condition(); statement->ifs.condition = expr; /* §6.8.4.1:1 The controlling expression of an if statement shall have * scalar type. */ semantic_condition(expr, "condition of 'if'-statment"); - mark_vars_read(expr, NULL); - rem_anchor_token(')'); - expect(')', end_error); - -end_error: - rem_anchor_token('{'); - add_anchor_token(T_else); statement_t *const true_stmt = parse_inner_statement(); statement->ifs.true_statement = true_stmt; rem_anchor_token(T_else); @@ -9332,6 +9172,7 @@ end_error: warningf(WARN_PARENTHESES, pos, "suggest explicit braces to avoid ambiguous 'else'"); } + POP_SCOPE(); POP_PARENT(); return statement; } @@ -9389,11 +9230,9 @@ static statement_t *parse_switch(void) eat(T_switch); PUSH_PARENT(statement); + PUSH_SCOPE_STATEMENT(&statement->switchs.scope); - expect('(', end_error); - add_anchor_token(')'); - expression_t *const expr = parse_expression(); - mark_vars_read(expr, NULL); + expression_t *const expr = parse_condition(); type_t * type = skip_typeref(expr->base.type); if (is_type_integer(type)) { type = promote_integer(type); @@ -9406,8 +9245,6 @@ static statement_t *parse_switch(void) type = type_error_type; } statement->switchs.expression = create_implicit_cast(expr, type); - expect(')', end_error); - rem_anchor_token(')'); switch_statement_t *rem = current_switch; current_switch = &statement->switchs; @@ -9419,11 +9256,9 @@ static statement_t *parse_switch(void) } check_enum_cases(&statement->switchs); + POP_SCOPE(); POP_PARENT(); return statement; -end_error: - POP_PARENT(); - return create_error_statement(); } static statement_t *parse_loop_body(statement_t *const loop) @@ -9447,25 +9282,19 @@ static statement_t *parse_while(void) eat(T_while); PUSH_PARENT(statement); + PUSH_SCOPE_STATEMENT(&statement->whiles.scope); - expect('(', end_error); - add_anchor_token(')'); - expression_t *const cond = parse_expression(); + expression_t *const cond = parse_condition(); statement->whiles.condition = cond; /* §6.8.5:2 The controlling expression of an iteration statement shall * have scalar type. */ semantic_condition(cond, "condition of 'while'-statement"); - mark_vars_read(cond, NULL); - rem_anchor_token(')'); - expect(')', end_error); statement->whiles.body = parse_loop_body(statement); + POP_SCOPE(); POP_PARENT(); return statement; -end_error: - POP_PARENT(); - return create_error_statement(); } /** @@ -9478,29 +9307,23 @@ static statement_t *parse_do(void) eat(T_do); PUSH_PARENT(statement); + PUSH_SCOPE_STATEMENT(&statement->do_while.scope); add_anchor_token(T_while); statement->do_while.body = parse_loop_body(statement); rem_anchor_token(T_while); - expect(T_while, end_error); - expect('(', end_error); - add_anchor_token(')'); - expression_t *const cond = parse_expression(); + expect(T_while); + expression_t *const cond = parse_condition(); statement->do_while.condition = cond; /* §6.8.5:2 The controlling expression of an iteration statement shall * have scalar type. */ semantic_condition(cond, "condition of 'do-while'-statement"); - mark_vars_read(cond, NULL); - rem_anchor_token(')'); - expect(')', end_error); - expect(';', end_error); + expect(';'); + POP_SCOPE(); POP_PARENT(); return statement; -end_error: - POP_PARENT(); - return create_error_statement(); } /** @@ -9512,11 +9335,11 @@ static statement_t *parse_for(void) eat(T_for); - expect('(', end_error1); - add_anchor_token(')'); - PUSH_PARENT(statement); - PUSH_SCOPE(&statement->fors.scope); + PUSH_SCOPE_STATEMENT(&statement->fors.scope); + + expect('('); + add_anchor_token(')'); PUSH_EXTENSION(); @@ -9532,7 +9355,7 @@ static statement_t *parse_for(void) warningf(WARN_UNUSED_VALUE, &init->base.source_position, "initialisation of 'for'-statement has no effect"); } rem_anchor_token(';'); - expect(';', end_error2); + expect(';'); } POP_EXTENSION(); @@ -9547,7 +9370,7 @@ static statement_t *parse_for(void) mark_vars_read(cond, NULL); rem_anchor_token(';'); } - expect(';', end_error2); + expect(';'); if (token.kind != ')') { expression_t *const step = parse_expression(); statement->fors.step = step; @@ -9556,22 +9379,13 @@ static statement_t *parse_for(void) warningf(WARN_UNUSED_VALUE, &step->base.source_position, "step of 'for'-statement has no effect"); } } - expect(')', end_error2); rem_anchor_token(')'); + expect(')'); statement->fors.body = parse_loop_body(statement); POP_SCOPE(); POP_PARENT(); return statement; - -end_error2: - POP_PARENT(); - rem_anchor_token(')'); - POP_SCOPE(); - /* fallthrough */ - -end_error1: - return create_error_statement(); } /** @@ -9620,13 +9434,11 @@ static statement_t *parse_goto(void) else parse_error_expected("while parsing goto", T_IDENTIFIER, NULL); eat_until_anchor(); - return create_error_statement(); + statement->gotos.label = &allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym_anonymous, &builtin_source_position)->label; } } - expect(';', end_error); - -end_error: + expect(';'); return statement; } @@ -9642,9 +9454,7 @@ static statement_t *parse_continue(void) statement_t *statement = allocate_statement_zero(STATEMENT_CONTINUE); eat(T_continue); - expect(';', end_error); - -end_error: + expect(';'); return statement; } @@ -9660,9 +9470,7 @@ static statement_t *parse_break(void) statement_t *statement = allocate_statement_zero(STATEMENT_BREAK); eat(T_break); - expect(';', end_error); - -end_error: + expect(';'); return statement; } @@ -9678,9 +9486,7 @@ static statement_t *parse_leave_statement(void) statement_t *statement = allocate_statement_zero(STATEMENT_LEAVE); eat(T___leave); - expect(';', end_error); - -end_error: + expect(';'); return statement; } @@ -9735,6 +9541,15 @@ entity_t *expression_is_variable(const expression_t *expression) return entity; } +static void err_or_warn(source_position_t const *const pos, char const *const msg) +{ + if (c_mode & _CXX || strict_mode) { + errorf(pos, msg); + } else { + warningf(WARN_OTHER, pos, msg); + } +} + /** * Parse a return statement. */ @@ -9757,24 +9572,14 @@ static statement_t *parse_return(void) if (return_value != NULL) { type_t *return_value_type = skip_typeref(return_value->base.type); - if (is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { - if (is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) { + if (is_type_void(return_type)) { + if (!is_type_void(return_value_type)) { /* ISO/IEC 14882:1998(E) §6.6.3:2 */ /* Only warn in C mode, because GCC does the same */ - if (c_mode & _CXX || strict_mode) { - errorf(pos, - "'return' with a value, in function returning 'void'"); - } else { - warningf(WARN_OTHER, pos, "'return' with a value, in function returning 'void'"); - } + err_or_warn(pos, "'return' with a value, in function returning 'void'"); } else if (!(c_mode & _CXX)) { /* ISO/IEC 14882:1998(E) §6.6.3:3 */ /* Only warn in C mode, because GCC does the same */ - if (strict_mode) { - errorf(pos, - "'return' with expression in function returning 'void'"); - } else { - warningf(WARN_OTHER, pos, "'return' with expression in function returning 'void'"); - } + err_or_warn(pos, "'return' with expression in function returning 'void'"); } } else { assign_error_t error = semantic_assign(return_type, return_value); @@ -9789,20 +9594,13 @@ static statement_t *parse_return(void) warningf(WARN_OTHER, pos, "function returns address of local variable"); } } - } else if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { + } else if (!is_type_void(return_type)) { /* ISO/IEC 14882:1998(E) §6.6.3:3 */ - if (c_mode & _CXX || strict_mode) { - errorf(pos, - "'return' without value, in function returning non-void"); - } else { - warningf(WARN_OTHER, pos, "'return' without value, in function returning non-void"); - } + err_or_warn(pos, "'return' without value, in function returning non-void"); } statement->returns.value = return_value; - expect(';', end_error); - -end_error: + expect(';'); return statement; } @@ -9840,9 +9638,7 @@ static statement_t *parse_expression_statement(void) statement->expression.expression = expr; mark_vars_read(expr, ENT_ANY); - expect(';', end_error); - -end_error: + expect(';'); return statement; } @@ -9865,10 +9661,7 @@ static statement_t *parse_ms_try_statment(void) POP_PARENT(); if (next_if(T___except)) { - expect('(', end_error); - add_anchor_token(')'); - expression_t *const expr = parse_expression(); - mark_vars_read(expr, NULL); + expression_t *const expr = parse_condition(); type_t * type = skip_typeref(expr->base.type); if (is_type_integer(type)) { type = promote_integer(type); @@ -9878,18 +9671,11 @@ static statement_t *parse_ms_try_statment(void) type = type_error_type; } statement->ms_try.except_expression = create_implicit_cast(expr, type); - rem_anchor_token(')'); - expect(')', end_error); - statement->ms_try.final_statement = parse_compound_statement(false); - } else if (next_if(T__finally)) { - statement->ms_try.final_statement = parse_compound_statement(false); - } else { + } else if (!next_if(T__finally)) { parse_error_expected("while parsing __try statement", T___except, T___finally, NULL); - return create_error_statement(); } + statement->ms_try.final_statement = parse_compound_statement(false); return statement; -end_error: - return create_error_statement(); } static statement_t *parse_empty_statement(void) @@ -9910,20 +9696,18 @@ static statement_t *parse_local_label_declaration(void) entity_t *end = NULL; entity_t **anchor = &begin; do { - if (token.kind != T_IDENTIFIER) { - parse_error_expected("while parsing local label declaration", - T_IDENTIFIER, NULL); + source_position_t pos; + symbol_t *const symbol = expect_identifier("while parsing local label declaration", &pos); + if (!symbol) goto end_error; - } - symbol_t *symbol = token.identifier.symbol; + entity_t *entity = get_entity(symbol, NAMESPACE_LABEL); if (entity != NULL && entity->base.parent_scope == current_scope) { source_position_t const *const ppos = &entity->base.source_position; - errorf(HERE, "multiple definitions of '%N' (previous definition %P)", entity, ppos); + errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos); } else { - entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol); - entity->base.parent_scope = current_scope; - entity->base.source_position = token.base.source_position; + entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol, &pos); + entity->base.parent_scope = current_scope; *anchor = entity; anchor = &entity->base.next; @@ -9931,9 +9715,8 @@ static statement_t *parse_local_label_declaration(void) environment_push(entity); } - next_token(); } while (next_if(',')); - expect(';', end_error); + expect(';'); end_error: statement->declaration.declarations_begin = begin; statement->declaration.declarations_end = end; @@ -9964,9 +9747,8 @@ static void parse_namespace_definition(void) } if (entity == NULL) { - entity = allocate_entity_zero(ENTITY_NAMESPACE, NAMESPACE_NORMAL, symbol); - entity->base.source_position = token.base.source_position; - entity->base.parent_scope = current_scope; + entity = allocate_entity_zero(ENTITY_NAMESPACE, NAMESPACE_NORMAL, symbol, HERE); + entity->base.parent_scope = current_scope; } if (token.kind == '=') { @@ -9978,17 +9760,15 @@ static void parse_namespace_definition(void) append_entity(current_scope, entity); PUSH_SCOPE(&entity->namespacee.members); + PUSH_CURRENT_ENTITY(entity); - entity_t *old_current_entity = current_entity; - current_entity = entity; - - expect('{', end_error); + add_anchor_token('}'); + expect('{'); parse_externals(); - expect('}', end_error); + rem_anchor_token('}'); + expect('}'); -end_error: - assert(current_entity == entity); - current_entity = old_current_entity; + POP_CURRENT_ENTITY(); POP_SCOPE(); } @@ -9999,10 +9779,8 @@ end_error: */ static statement_t *intern_parse_statement(void) { - statement_t *statement = NULL; - /* declaration or statement */ - add_anchor_token(';'); + statement_t *statement; switch (token.kind) { case T_IDENTIFIER: { token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind; @@ -10073,14 +9851,9 @@ static statement_t *intern_parse_statement(void) default: errorf(HERE, "unexpected token %K while parsing statement", &token); statement = create_error_statement(); - if (!at_anchor()) - next_token(); + eat_until_anchor(); break; } - rem_anchor_token(';'); - - assert(statement != NULL - && statement->base.source_position.input_name != NULL); return statement; } @@ -10125,6 +9898,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) add_anchor_token('*'); add_anchor_token('+'); add_anchor_token('-'); + add_anchor_token(';'); add_anchor_token('{'); add_anchor_token('~'); add_anchor_token(T_CHARACTER_CONSTANT); @@ -10208,18 +9982,10 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) statement_t **anchor = &statement->compound.statements; bool only_decls_so_far = true; - while (token.kind != '}') { - if (token.kind == T_EOF) { - errorf(&statement->base.source_position, - "EOF while parsing compound statement"); - break; - } + while (token.kind != '}' && token.kind != T_EOF) { statement_t *sub_statement = intern_parse_statement(); if (sub_statement->kind == STATEMENT_ERROR) { - /* an error occurred. if we are at an anchor, return */ - if (at_anchor()) - goto end_error; - continue; + break; } if (sub_statement->kind != STATEMENT_DECLARATION) { @@ -10230,13 +9996,9 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) } *anchor = sub_statement; - - while (sub_statement->base.next != NULL) - sub_statement = sub_statement->base.next; - - anchor = &sub_statement->base.next; + anchor = &sub_statement->base.next; } - next_token(); + expect('}'); /* look over all statements again to produce no effect warnings */ if (is_warn_on(WARN_UNUSED_VALUE)) { @@ -10256,7 +10018,6 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) } } -end_error: rem_anchor_token(T_while); rem_anchor_token(T_wchar_t); rem_anchor_token(T_volatile); @@ -10337,6 +10098,7 @@ end_error: rem_anchor_token(T_CHARACTER_CONSTANT); rem_anchor_token('~'); rem_anchor_token('{'); + rem_anchor_token(';'); rem_anchor_token('-'); rem_anchor_token('+'); rem_anchor_token('*'); @@ -10393,16 +10155,20 @@ static void parse_global_asm(void) statement_t *statement = allocate_statement_zero(STATEMENT_ASM); eat(T_asm); - expect('(', end_error); + add_anchor_token(';'); + add_anchor_token(')'); + add_anchor_token(T_STRING_LITERAL); + expect('('); + rem_anchor_token(T_STRING_LITERAL); statement->asms.asm_text = parse_string_literals(); statement->base.next = unit->global_asm; unit->global_asm = statement; - expect(')', end_error); - expect(';', end_error); - -end_error:; + rem_anchor_token(')'); + expect(')'); + rem_anchor_token(';'); + expect(';'); } static void parse_linkage_specification(void) @@ -10426,12 +10192,11 @@ static void parse_linkage_specification(void) if (next_if('{')) { parse_externals(); - expect('}', end_error); + expect('}'); } else { parse_external(); } -end_error: assert(current_linkage == new_linkage); current_linkage = old_linkage; } @@ -10612,7 +10377,7 @@ static void complete_incomplete_arrays(void) } } -void prepare_main_collect2(entity_t *entity) +static void prepare_main_collect2(entity_t *const entity) { PUSH_SCOPE(&entity->function.statement->compound.scope);