X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=04adbc1f321f4c013436dd2d9c0436adc55f5537;hb=c8dfa04bfc2911fd2e49853003d43a46e0073291;hp=b496be7a00be95068a911c652e0c166c24d407b1;hpb=f73f9f5dedcc67410cdda02691af29114342be8c;p=cparser diff --git a/parser.c b/parser.c index b496be7..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; \ @@ -242,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: \ @@ -324,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), @@ -487,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(); @@ -510,18 +510,18 @@ 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]; } /** * 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]; } @@ -529,9 +529,9 @@ static void rem_anchor_token(int 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; @@ -1136,40 +1136,17 @@ static attribute_t *parse_attribute_asm(void) 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; } } @@ -3194,22 +3171,18 @@ static void parse_parameters(function_type_t *type, scope_t *scope) eat('('); add_anchor_token(')'); - 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: @@ -3246,9 +3219,10 @@ 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(')'); } @@ -3903,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) { @@ -3970,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 @@ -3984,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); @@ -3999,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); } } @@ -4103,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) { @@ -4173,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 { @@ -4190,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); @@ -4639,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, @@ -5060,7 +5024,7 @@ found_break_parent: type_t *const ret = skip_typeref(type->function.return_type); if (!is_type_void(ret) && is_type_valid(ret) && - !is_sym_main(current_function->base.base.symbol)) { + !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"); } @@ -5276,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 @@ -5369,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); @@ -5396,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; @@ -5425,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); } @@ -5740,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; @@ -5894,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"); } @@ -6809,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: @@ -8460,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; @@ -8638,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; @@ -8654,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; @@ -9827,9 +9760,7 @@ static void parse_namespace_definition(void) append_entity(current_scope, entity); PUSH_SCOPE(&entity->namespacee.members); - - entity_t *old_current_entity = current_entity; - current_entity = entity; + PUSH_CURRENT_ENTITY(entity); add_anchor_token('}'); expect('{'); @@ -9837,8 +9768,7 @@ static void parse_namespace_definition(void) rem_anchor_token('}'); expect('}'); - assert(current_entity == entity); - current_entity = old_current_entity; + POP_CURRENT_ENTITY(); POP_SCOPE(); } @@ -10447,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);