X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=04adbc1f321f4c013436dd2d9c0436adc55f5537;hb=c8dfa04bfc2911fd2e49853003d43a46e0073291;hp=1f30b1623492094da5bd239c1127ca3f1dc3ccd4;hpb=b44cca466ef8b9d3320cec8d284853074a0935db;p=cparser diff --git a/parser.c b/parser.c index 1f30b16..04adbc1 100644 --- a/parser.c +++ b/parser.c @@ -23,6 +23,7 @@ #include #include +#include "adt/strutil.h" #include "parser.h" #include "diagnostic.h" #include "format_check.h" @@ -36,7 +37,7 @@ #include "entity_t.h" #include "attribute_t.h" #include "lang_features.h" -#include "walk_statements.h" +#include "walk.h" #include "warning.h" #include "printer.h" #include "adt/bitfiddle.h" @@ -89,20 +90,17 @@ 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; static ms_try_statement_t *current_try = NULL; -static linkage_kind_t current_linkage = LINKAGE_INVALID; +static linkage_kind_t current_linkage; static goto_statement_t *goto_first = NULL; static goto_statement_t **goto_anchor = NULL; 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; @@ -111,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; \ @@ -120,10 +124,12 @@ 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; \ bool const old_gcc_extension = in_gcc_extension; \ while (next_if(T___extension__)) { \ in_gcc_extension = true; \ @@ -136,10 +142,10 @@ static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT; 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) +#define HERE (&token.base.source_position) /** true if we are in GCC mode. */ #define GNU_MODE ((c_mode & _GNUC) || in_gcc_extension) @@ -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: \ @@ -285,25 +288,26 @@ static void semantic_comparison(binary_expression_t *expression); static size_t get_statement_struct_size(statement_kind_t kind) { static const size_t sizes[] = { - [STATEMENT_INVALID] = sizeof(invalid_statement_t), - [STATEMENT_EMPTY] = sizeof(empty_statement_t), - [STATEMENT_COMPOUND] = sizeof(compound_statement_t), - [STATEMENT_RETURN] = sizeof(return_statement_t), - [STATEMENT_DECLARATION] = sizeof(declaration_statement_t), - [STATEMENT_IF] = sizeof(if_statement_t), - [STATEMENT_SWITCH] = sizeof(switch_statement_t), - [STATEMENT_EXPRESSION] = sizeof(expression_statement_t), - [STATEMENT_CONTINUE] = sizeof(statement_base_t), - [STATEMENT_BREAK] = sizeof(statement_base_t), - [STATEMENT_GOTO] = sizeof(goto_statement_t), - [STATEMENT_LABEL] = sizeof(label_statement_t), - [STATEMENT_CASE_LABEL] = sizeof(case_label_statement_t), - [STATEMENT_WHILE] = sizeof(while_statement_t), - [STATEMENT_DO_WHILE] = sizeof(do_while_statement_t), - [STATEMENT_FOR] = sizeof(for_statement_t), - [STATEMENT_ASM] = sizeof(asm_statement_t), - [STATEMENT_MS_TRY] = sizeof(ms_try_statement_t), - [STATEMENT_LEAVE] = sizeof(leave_statement_t) + [STATEMENT_ERROR] = sizeof(statement_base_t), + [STATEMENT_EMPTY] = sizeof(statement_base_t), + [STATEMENT_COMPOUND] = sizeof(compound_statement_t), + [STATEMENT_RETURN] = sizeof(return_statement_t), + [STATEMENT_DECLARATION] = sizeof(declaration_statement_t), + [STATEMENT_IF] = sizeof(if_statement_t), + [STATEMENT_SWITCH] = sizeof(switch_statement_t), + [STATEMENT_EXPRESSION] = sizeof(expression_statement_t), + [STATEMENT_CONTINUE] = sizeof(statement_base_t), + [STATEMENT_BREAK] = sizeof(statement_base_t), + [STATEMENT_COMPUTED_GOTO] = sizeof(computed_goto_statement_t), + [STATEMENT_GOTO] = sizeof(goto_statement_t), + [STATEMENT_LABEL] = sizeof(label_statement_t), + [STATEMENT_CASE_LABEL] = sizeof(case_label_statement_t), + [STATEMENT_WHILE] = sizeof(while_statement_t), + [STATEMENT_DO_WHILE] = sizeof(do_while_statement_t), + [STATEMENT_FOR] = sizeof(for_statement_t), + [STATEMENT_ASM] = sizeof(asm_statement_t), + [STATEMENT_MS_TRY] = sizeof(ms_try_statement_t), + [STATEMENT_LEAVE] = sizeof(leave_statement_t) }; assert((size_t)kind < lengthof(sizes)); assert(sizes[kind] != 0); @@ -318,15 +322,12 @@ static size_t get_statement_struct_size(statement_kind_t kind) static size_t get_expression_struct_size(expression_kind_t kind) { static const size_t sizes[] = { - [EXPR_INVALID] = sizeof(expression_base_t), + [EXPR_ERROR] = sizeof(expression_base_t), [EXPR_REFERENCE] = sizeof(reference_expression_t), - [EXPR_REFERENCE_ENUM_VALUE] = sizeof(reference_expression_t), + [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), @@ -374,7 +375,7 @@ static statement_t *allocate_statement_zero(statement_kind_t kind) res->base.kind = kind; res->base.parent = current_parent; - res->base.source_position = token.source_position; + res->base.source_position = token.base.source_position; return res; } @@ -391,7 +392,7 @@ static expression_t *allocate_expression_zero(expression_kind_t kind) res->base.kind = kind; res->base.type = type_error_type; - res->base.source_position = token.source_position; + res->base.source_position = token.base.source_position; return res; } @@ -399,17 +400,19 @@ static expression_t *allocate_expression_zero(expression_kind_t kind) * Creates a new invalid expression at the source position * of the current token. */ -static expression_t *create_invalid_expression(void) +static expression_t *create_error_expression(void) { - return allocate_expression_zero(EXPR_INVALID); + expression_t *expression = allocate_expression_zero(EXPR_ERROR); + expression->base.type = type_error_type; + return expression; } /** * Creates a new invalid statement. */ -static statement_t *create_invalid_statement(void) +static statement_t *create_error_statement(void) { - return allocate_statement_zero(STATEMENT_INVALID); + return allocate_statement_zero(STATEMENT_ERROR); } /** @@ -484,9 +487,9 @@ 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.type == type) { + if (token.kind == type) { next_token(); return true; } else { @@ -507,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_type) -{ - assert(0 <= token_type && token_type < T_LAST_TOKEN); - ++token_anchor_set[token_type]; -} - -/** - * 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_type) -{ - assert(0 <= token_type && token_type < T_LAST_TOKEN); - int count = token_anchor_set[token_type]; - token_anchor_set[token_type] = 0; - return count; -} - -/** - * Restore the number of token types to the given count. - */ -static void restore_anchor_state(int token_type, int count) +static void add_anchor_token(token_kind_t const token_kind) { - assert(0 <= token_type && token_type < T_LAST_TOKEN); - token_anchor_set[token_type] = count; + 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_type) -{ - assert(0 <= token_type && token_type < T_LAST_TOKEN); - assert(token_anchor_set[token_type] != 0); - --token_anchor_set[token_type]; -} - -/** - * Return true if the token type of the current token is - * in the anchor set. - */ -static bool at_anchor(void) +static void rem_anchor_token(token_kind_t const token_kind) { - if (token.type < 0) - return false; - return token_anchor_set[token.type]; + assert(token_kind < T_LAST_TOKEN); + assert(token_anchor_set[token_kind] != 0); + --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; @@ -571,11 +542,11 @@ static void eat_until_matching_token(int type) unsigned parenthesis_count = 0; unsigned brace_count = 0; unsigned bracket_count = 0; - while (token.type != end_token || + while (token.kind != end_token || parenthesis_count != 0 || brace_count != 0 || bracket_count != 0) { - switch (token.type) { + switch (token.kind) { case T_EOF: return; case '(': ++parenthesis_count; break; case '{': ++brace_count; break; @@ -595,7 +566,7 @@ static void eat_until_matching_token(int type) if (bracket_count > 0) --bracket_count; check_stop: - if (token.type == end_token && + if (token.kind == end_token && parenthesis_count == 0 && brace_count == 0 && bracket_count == 0) @@ -614,9 +585,9 @@ check_stop: */ static void eat_until_anchor(void) { - while (token_anchor_set[token.type] == 0) { - if (token.type == '(' || token.type == '{' || token.type == '[') - eat_until_matching_token(token.type); + while (token_anchor_set[token.kind] == 0) { + if (token.kind == '(' || token.kind == '{' || token.kind == '[') + eat_until_matching_token(token.kind); next_token(); } } @@ -630,7 +601,7 @@ static void eat_block(void) next_if('}'); } -#define eat(token_type) (assert(token.type == (token_type)), next_token()) +#define eat(token_kind) (assert(token.kind == (token_kind)), next_token()) /** * Report a parse error because an expected token was not found. @@ -662,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.type != (expected))) { \ - parse_error_expected(NULL, (expected), NULL); \ - add_anchor_token(expected); \ - eat_until_anchor(); \ - rem_anchor_token(expected); \ - if (token.type != (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 @@ -707,7 +694,6 @@ static void scope_pop(scope_t *old_scope) static entity_t *get_entity(const symbol_t *const symbol, namespace_tag_t namespc) { - assert(namespc != NAMESPACE_INVALID); entity_t *entity = symbol->entity; for (; entity != NULL; entity = entity->base.symbol_next) { if ((namespace_tag_t)entity->base.namespc == namespc) @@ -740,7 +726,7 @@ static void stack_push(stack_entry_t **stack_ptr, entity_t *entity) { symbol_t *symbol = entity->base.symbol; entity_namespace_t namespc = entity->base.namespc; - assert(namespc != NAMESPACE_INVALID); + assert(namespc != 0); /* replace/add entity into entity list of the symbol */ entity_t **anchor; @@ -854,22 +840,11 @@ static void label_pop_to(size_t new_top) stack_pop_to(&label_stack, new_top); } -static int get_akind_rank(atomic_type_kind_t akind) -{ - return (int) akind; -} - -/** - * Return the type rank for an atomic type. - */ -static int get_rank(const type_t *type) +static atomic_type_kind_t get_akind(const type_t *type) { - assert(!is_typeref(type)); - if (type->kind == TYPE_ENUM) - return get_akind_rank(type->enumt.akind); - - assert(type->kind == TYPE_ATOMIC); - return get_akind_rank(type->atomic.akind); + assert(type->kind == TYPE_ATOMIC || type->kind == TYPE_COMPLEX + || type->kind == TYPE_IMAGINARY || type->kind == TYPE_ENUM); + return type->atomic.akind; } /** @@ -880,32 +855,12 @@ static int get_rank(const type_t *type) */ static type_t *promote_integer(type_t *type) { - if (type->kind == TYPE_BITFIELD) - type = type->bitfield.base_type; - - if (get_rank(type) < get_akind_rank(ATOMIC_TYPE_INT)) + if (get_akind_rank(get_akind(type)) < get_akind_rank(ATOMIC_TYPE_INT)) type = type_int; 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. * @@ -914,8 +869,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; @@ -945,7 +899,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 { @@ -1025,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; } @@ -1085,36 +1044,20 @@ static void warn_string_concat(const source_position_t *pos) static string_t parse_string_literals(void) { - assert(token.type == T_STRING_LITERAL); - string_t result = token.literal; + assert(token.kind == T_STRING_LITERAL); + string_t result = token.string.string; next_token(); - while (token.type == T_STRING_LITERAL) { - warn_string_concat(&token.source_position); - result = concat_strings(&result, &token.literal); + while (token.kind == T_STRING_LITERAL) { + warn_string_concat(&token.base.source_position); + result = concat_strings(&result, &token.string.string); next_token(); } return result; } -/** - * compare two string, ignoring double underscores on the second. - */ -static int strcmp_underscore(const char *s1, const char *s2) -{ - if (s2[0] == '_' && s2[1] == '_') { - size_t len2 = strlen(s2); - size_t len1 = strlen(s1); - if (len1 == len2-4 && s2[len2-2] == '_' && s2[len2-1] == '_') { - return strncmp(s1, s2+2, len2-4); - } - } - - return strcmp(s1, s2); -} - static attribute_t *allocate_attribute_zero(attribute_kind_t kind) { attribute_t *attribute = allocate_ast_zero(sizeof(*attribute)); @@ -1155,13 +1098,13 @@ static attribute_argument_t *parse_attribute_arguments(void) { attribute_argument_t *first = NULL; attribute_argument_t **anchor = &first; - if (token.type != ')') do { + if (token.kind != ')') do { attribute_argument_t *argument = allocate_ast_zero(sizeof(*argument)); /* is it an identifier */ - if (token.type == T_IDENTIFIER - && (look_ahead(1)->type == ',' || look_ahead(1)->type == ')')) { - symbol_t *symbol = token.symbol; + if (token.kind == T_IDENTIFIER + && (look_ahead(1)->kind == ',' || look_ahead(1)->kind == ')')) { + symbol_t *symbol = token.identifier.symbol; argument->kind = ATTRIBUTE_ARGUMENT_SYMBOL; argument->v.symbol = symbol; next_token(); @@ -1177,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; } @@ -1190,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.type) { - case T_IDENTIFIER: - return token.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_symbol(&token); - default: + switch(token.kind) { + 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; } } @@ -1259,8 +1170,7 @@ static attribute_t *parse_attribute_gnu_single(void) } const char *attribute_name = get_attribute_name(kind); - if (attribute_name != NULL - && strcmp_underscore(attribute_name, name) == 0) + if (attribute_name != NULL && streq_underscore(attribute_name, name)) break; } @@ -1280,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('('); - if (token.type != ')') do { + 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; } @@ -1307,7 +1219,7 @@ static attribute_t *parse_attributes(attribute_t *first) anchor = &(*anchor)->next; attribute_t *attribute; - switch (token.type) { + switch (token.kind) { case T___attribute__: attribute = parse_attribute_gnu(); if (attribute == NULL) @@ -1377,19 +1289,17 @@ static entity_t *determine_lhs_ent(expression_t *const expr, ent = determine_lhs_ent(ref, lhs_ent); lhs_ent = ent; } else { - mark_vars_read(expr->select.compound, lhs_ent); + mark_vars_read(ref, lhs_ent); } mark_vars_read(expr->array_access.index, lhs_ent); return ent; } case EXPR_SELECT: { - if (is_type_compound(skip_typeref(expr->base.type))) { + mark_vars_read(expr->select.compound, lhs_ent); + if (is_type_compound(skip_typeref(expr->base.type))) return determine_lhs_ent(expr->select.compound, lhs_ent); - } else { - mark_vars_read(expr->select.compound, lhs_ent); - return NULL; - } + return NULL; } case EXPR_UNARY_DEREFERENCE: { @@ -1466,10 +1376,13 @@ static void mark_vars_read(expression_t *const expr, entity_t *lhs_ent) return; case EXPR_ARRAY_ACCESS: { + mark_vars_read(expr->array_access.index, lhs_ent); expression_t *const ref = expr->array_access.array_ref; + if (!is_type_array(skip_typeref(revert_automatic_type_conversion(ref)))) { + if (lhs_ent == ENT_ANY) + lhs_ent = NULL; + } mark_vars_read(ref, lhs_ent); - lhs_ent = determine_lhs_ent(ref, lhs_ent); - mark_vars_read(expr->array_access.index, lhs_ent); return; } @@ -1483,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; @@ -1508,7 +1421,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); @@ -1565,9 +1477,8 @@ unary: determine_lhs_ent(expr->va_starte.ap, lhs_ent); return; - EXPR_LITERAL_CASES - case EXPR_UNKNOWN: - case EXPR_INVALID: + case EXPR_LITERAL_CASES: + case EXPR_ERROR: case EXPR_STRING_LITERAL: case EXPR_WIDE_STRING_LITERAL: case EXPR_COMPOUND_LITERAL: // TODO init? @@ -1580,7 +1491,7 @@ unary: case EXPR_OFFSETOF: case EXPR_STATEMENT: // TODO case EXPR_LABEL_ADDRESS: - case EXPR_REFERENCE_ENUM_VALUE: + case EXPR_ENUM_CONSTANT: return; } @@ -1594,30 +1505,26 @@ static designator_t *parse_designation(void) for (;;) { designator_t *designator; - switch (token.type) { + switch (token.kind) { case '[': designator = allocate_ast_zero(sizeof(designator[0])); - designator->source_position = token.source_position; + designator->source_position = token.base.source_position; next_token(); 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.source_position; + designator->source_position = token.base.source_position; next_token(); - if (token.type != 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.symbol; - next_token(); break; default: - expect('=', end_error); + expect('='); return result; } @@ -1625,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, @@ -1710,15 +1615,6 @@ static initializer_t *initializer_from_expression(type_t *orig_type, return result; } -/** - * Checks if a given expression can be used as a constant initializer. - */ -static bool is_initializer_constant(const expression_t *expression) -{ - return is_constant_expression(expression) != EXPR_CLASS_VARIABLE || - is_linker_constant(expression) != EXPR_CLASS_VARIABLE; -} - /** * Parses an scalar initializer. * @@ -1729,17 +1625,17 @@ static initializer_t *parse_scalar_initializer(type_t *type, { /* there might be extra {} hierarchies */ int braces = 0; - if (token.type == '{') { + if (token.kind == '{') { warningf(WARN_OTHER, HERE, "extra curly braces around scalar initializer"); do { eat('{'); ++braces; - } while (token.type == '{'); + } while (token.kind == '{'); } expression_t *expression = parse_assignment_expression(); mark_vars_read(expression, NULL); - if (must_be_constant && !is_initializer_constant(expression)) { + if (must_be_constant && !is_linker_constant(expression)) { errorf(&expression->base.source_position, "initialisation expression '%E' is not constant", expression); @@ -1758,7 +1654,7 @@ static initializer_t *parse_scalar_initializer(type_t *type, bool additional_warning_displayed = false; while (braces > 0) { next_if(','); - if (token.type != '}') { + if (token.kind != '}') { if (!additional_warning_displayed) { warningf(WARN_OTHER, HERE, "additional elements in scalar initializer"); additional_warning_displayed = true; @@ -1862,11 +1758,10 @@ static void descend_into_subtype(type_path_t *path) top->type = top_type; if (is_type_compound(top_type)) { - compound_t *compound = top_type->compound.compound; - entity_t *entry = compound->members.entities; + compound_t *const compound = top_type->compound.compound; + entity_t *const entry = skip_unnamed_bitfields(compound->members.entities); if (entry != NULL) { - assert(entry->kind == ENTITY_COMPOUND_MEMBER); top->v.compound_entry = &entry->declaration; path->top_type = entry->declaration.type; } else { @@ -1943,14 +1838,11 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, return false; } assert(iter->kind == ENTITY_COMPOUND_MEMBER); - if (used_in_offsetof) { - type_t *real_type = skip_typeref(iter->declaration.type); - if (real_type->kind == TYPE_BITFIELD) { - errorf(&designator->source_position, - "offsetof designator '%Y' must not specify bitfield", - symbol); - return false; - } + if (used_in_offsetof && iter->compound_member.bitfield) { + errorf(&designator->source_position, + "offsetof designator '%Y' must not specify bitfield", + symbol); + return false; } top->type = orig_type; @@ -2009,7 +1901,7 @@ static void advance_current_object(type_path_t *path, size_t top_path_level) } else if (is_type_struct(type)) { declaration_t *entry = top->v.compound_entry; - entity_t *next_entity = entry->base.next; + entity_t *const next_entity = skip_unnamed_bitfields(entry->base.next); if (next_entity != NULL) { assert(is_declaration(next_entity)); entry = &next_entity->declaration; @@ -2054,10 +1946,10 @@ static void skip_initializers(void) { next_if('{'); - while (token.type != '}') { - if (token.type == T_EOF) + while (token.kind != '}') { + if (token.kind == T_EOF) return; - if (token.type == '{') { + if (token.kind == '{') { eat_block(); continue; } @@ -2079,7 +1971,7 @@ static initializer_t *parse_sub_initializer(type_path_t *path, type_t *outer_type, size_t top_path_level, parse_initializer_env_t *env) { - if (token.type == '}') { + if (token.kind == '}') { /* empty initializer */ return create_empty_initializer(); } @@ -2097,14 +1989,14 @@ static initializer_t *parse_sub_initializer(type_path_t *path, while (true) { designator_t *designator = NULL; - if (token.type == '.' || token.type == '[') { + if (token.kind == '.' || token.kind == '[') { designator = parse_designation(); goto finish_designator; - } else if (token.type == T_IDENTIFIER && look_ahead(1)->type == ':') { + } else if (token.kind == T_IDENTIFIER && look_ahead(1)->kind == ':') { /* GNU-style designator ("identifier: value") */ designator = allocate_ast_zero(sizeof(designator[0])); - designator->source_position = token.source_position; - designator->symbol = token.symbol; + designator->source_position = token.base.source_position; + designator->symbol = token.identifier.symbol; eat(T_IDENTIFIER); eat(':'); @@ -2127,7 +2019,7 @@ finish_designator: initializer_t *sub; - if (token.type == '{') { + if (token.kind == '{') { if (type != NULL && is_type_scalar(type)) { sub = parse_scalar_initializer(type, env->must_be_constant); } else { @@ -2150,20 +2042,19 @@ 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 */ expression_t *expression = parse_assignment_expression(); mark_vars_read(expression, NULL); - if (env->must_be_constant && !is_initializer_constant(expression)) { + if (env->must_be_constant && !is_linker_constant(expression)) { errorf(&expression->base.source_position, "Initialisation expression '%E' is not constant", expression); @@ -2195,7 +2086,7 @@ finish_designator: sub = initializer_from_expression(outer_type, expression); if (sub != NULL) { next_if(','); - if (token.type != '}') { + if (token.kind != '}') { warningf(WARN_OTHER, HERE, "excessive elements in initializer for type '%T'", orig_type); } /* TODO: eat , ... */ @@ -2240,11 +2131,13 @@ finish_designator: ARR_APP1(initializer_t*, initializers, sub); error_parse_next: - if (token.type == '}') { + if (token.kind == '}') { break; } - expect(',', end_error); - if (token.type == '}') { + add_anchor_token('}'); + expect(','); + rem_anchor_token('}'); + if (token.kind == '}') { break; } @@ -2303,7 +2196,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env) if (is_type_scalar(type)) { result = parse_scalar_initializer(type, env->must_be_constant); - } else if (token.type == '{') { + } else if (token.kind == '{') { eat('{'); type_path_t path; @@ -2320,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 */ @@ -2390,31 +2282,31 @@ static compound_t *parse_compound_type_specifier(bool is_struct) entity_t *entity = NULL; attribute_t *attributes = NULL; - if (token.type == T___attribute__) { + if (token.kind == T___attribute__) { attributes = parse_attributes(NULL); } entity_kind_tag_t const kind = is_struct ? ENTITY_STRUCT : ENTITY_UNION; - if (token.type == T_IDENTIFIER) { + if (token.kind == T_IDENTIFIER) { /* the compound has a name, check if we have seen it already */ - symbol = token.symbol; + symbol = token.identifier.symbol; entity = get_tag(symbol, kind); next_token(); if (entity != NULL) { if (entity->base.parent_scope != current_scope && - (token.type == '{' || token.type == ';')) { + (token.kind == '{' || token.kind == ';')) { /* we're in an inner scope and have a definition. Shadow * existing definition in outer scope */ entity = NULL; - } else if (entity->compound.complete && token.type == '{') { + } else if (entity->compound.complete && token.kind == '{') { source_position_t const *const ppos = &entity->base.source_position; errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos); /* clear members in the hope to avoid further errors */ entity->compound.members.entities = NULL; } } - } else if (token.type != '{') { + } else if (token.kind != '{') { char const *const msg = is_struct ? "while parsing struct type specifier" : "while parsing union type specifier"; @@ -2424,17 +2316,16 @@ 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); } append_entity(current_scope, entity); } - if (token.type == '{') { + if (token.kind == '{') { parse_compound_type_entries(&entity->compound); /* ISO/IEC 14882:1998(E) §7.1.3:5 */ @@ -2455,25 +2346,21 @@ static void parse_enum_entries(type_t *const enum_type) { eat('{'); - if (token.type == '}') { + if (token.kind == '}') { errorf(HERE, "empty enum not allowed"); next_token(); return; } add_anchor_token('}'); + add_anchor_token(','); do { - if (token.type != T_IDENTIFIER) { - parse_error_expected("while parsing enum entry", T_IDENTIFIER, NULL); - eat_block(); - rem_anchor_token('}'); - return; - } - - entity_t *const entity = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, token.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.source_position; - next_token(); + rem_anchor_token('='); if (next_if('=')) { expression_t *value = parse_constant_expression(); @@ -2485,13 +2372,11 @@ static void parse_enum_entries(type_t *const enum_type) } record_entity(entity, false); - } while (next_if(',') && token.type != '}'); + } while (next_if(',') && token.kind != '}'); + rem_anchor_token(','); rem_anchor_token('}'); - expect('}', end_error); - -end_error: - ; + expect('}'); } static type_t *parse_enum_specifier(void) @@ -2501,19 +2386,19 @@ static type_t *parse_enum_specifier(void) symbol_t *symbol; eat(T_enum); - switch (token.type) { + switch (token.kind) { case T_IDENTIFIER: - symbol = token.symbol; + symbol = token.identifier.symbol; entity = get_tag(symbol, ENTITY_ENUM); next_token(); if (entity != NULL) { if (entity->base.parent_scope != current_scope && - (token.type == '{' || token.type == ';')) { + (token.kind == '{' || token.kind == ';')) { /* we're in an inner scope and have a definition. Shadow * existing definition in outer scope */ entity = NULL; - } else if (entity->enume.complete && token.type == '{') { + } else if (entity->enume.complete && token.kind == '{') { source_position_t const *const ppos = &entity->base.source_position; errorf(&pos, "multiple definitions of '%N' (previous definition %P)", entity, ppos); } @@ -2532,16 +2417,15 @@ 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); - type->enumt.enume = &entity->enume; - type->enumt.akind = ATOMIC_TYPE_INT; + type_t *const type = allocate_type_zero(TYPE_ENUM); + type->enumt.enume = &entity->enume; + type->enumt.base.akind = ATOMIC_TYPE_INT; - if (token.type == '{') { + if (token.kind == '{') { if (symbol != NULL) { environment_push(entity); } @@ -2578,17 +2462,14 @@ static type_t *parse_typeof(void) type_t *type; - expect('(', end_error); + expect('('); add_anchor_token(')'); expression_t *expression = NULL; - bool old_type_prop = in_type_prop; - in_type_prop = true; - - switch (token.type) { + switch (token.kind) { case T_IDENTIFIER: - if (is_typedef_symbol(token.symbol)) { + if (is_typedef_symbol(token.identifier.symbol)) { DECLARATION_START type = parse_typename(); } else { @@ -2598,18 +2479,15 @@ static type_t *parse_typeof(void) } break; } - in_type_prop = old_type_prop; 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 { @@ -2648,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.type != 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.symbol; - if (strcmp(symbol->string, "put") == 0) { - prop = &property->put_symbol; - } else if (strcmp(symbol->string, "get") == 0) { - prop = &property->get_symbol; - } else { - errorf(HERE, "expected put or get in property declspec"); - prop = NULL; - } - eat(T_IDENTIFIER); - expect('=', end_error); - if (token.type != 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.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; } @@ -2695,12 +2571,12 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void) attribute_kind_t kind = ATTRIBUTE_UNKNOWN; if (next_if(T_restrict)) { kind = ATTRIBUTE_MS_RESTRICT; - } else if (token.type == T_IDENTIFIER) { - const char *name = token.symbol->string; + } else if (token.kind == T_IDENTIFIER) { + const char *name = token.identifier.symbol->string; for (attribute_kind_t k = ATTRIBUTE_MS_FIRST; k <= ATTRIBUTE_MS_LAST; ++k) { const char *attribute_name = get_attribute_name(k); - if (attribute_name != NULL && strcmp(attribute_name, name) == 0) { + if (attribute_name != NULL && streq(attribute_name, name)) { kind = k; break; } @@ -2732,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; @@ -2780,20 +2649,19 @@ 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; + specifiers->source_position = token.base.source_position; while (true) { specifiers->attributes = parse_attributes(specifiers->attributes); - switch (token.type) { + switch (token.kind) { /* storage class */ #define MATCH_STORAGE_CLASS(token, class) \ case token: \ @@ -2857,11 +2725,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: \ @@ -2949,7 +2812,7 @@ wrong_thread_storage_class: /* Be somewhat resilient to typos like 'unsigned lng* f()' in a * declaration, so it doesn't generate errors about expecting '(' or * '{' later on. */ - switch (look_ahead(1)->type) { + switch (look_ahead(1)->kind) { STORAGE_CLASSES TYPE_SPECIFIERS case T_const: @@ -2969,12 +2832,12 @@ wrong_thread_storage_class: } } - type_t *const typedef_type = get_typedef_type(token.symbol); + type_t *const typedef_type = get_typedef_type(token.identifier.symbol); if (typedef_type == NULL) { /* Be somewhat resilient to typos like 'vodi f()' at the beginning of a * declaration, so it doesn't generate 'implicit int' followed by more * errors later on. */ - token_type_t const la1_type = (token_type_t)look_ahead(1)->type; + token_kind_t const la1_type = (token_kind_t)look_ahead(1)->kind; switch (la1_type) { DECLARATION_START case T_IDENTIFIER: @@ -2982,8 +2845,9 @@ wrong_thread_storage_class: case '*': { errorf(HERE, "%K does not name a type", &token); - entity_t *entity = - create_error_entity(token.symbol, ENTITY_TYPEDEF); + symbol_t *symbol = token.identifier.symbol; + entity_t *entity + = create_error_entity(symbol, ENTITY_TYPEDEF); type = allocate_type_zero(TYPE_TYPEDEF); type->typedeft.typedefe = &entity->typedefe; @@ -3012,8 +2876,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; @@ -3176,15 +3038,13 @@ warn_about_long_long: } if (type_specifiers & SPECIFIER_COMPLEX) { - type = allocate_type_zero(TYPE_COMPLEX); - type->complex.akind = atomic_type; + type = allocate_type_zero(TYPE_COMPLEX); } else if (type_specifiers & SPECIFIER_IMAGINARY) { - type = allocate_type_zero(TYPE_IMAGINARY); - type->imaginary.akind = atomic_type; + type = allocate_type_zero(TYPE_IMAGINARY); } else { - type = allocate_type_zero(TYPE_ATOMIC); - type->atomic.akind = atomic_type; + type = allocate_type_zero(TYPE_ATOMIC); } + type->atomic.akind = atomic_type; newtype = true; } else if (type_specifiers != 0) { errorf(&specifiers->source_position, "multiple datatypes in declaration"); @@ -3213,7 +3073,7 @@ static type_qualifiers_t parse_type_qualifiers(void) type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE; while (true) { - switch (token.type) { + switch (token.kind) { /* type qualifiers */ MATCH_TYPE_QUALIFIER(T_const, TYPE_QUALIFIER_CONST); MATCH_TYPE_QUALIFIER(T_restrict, TYPE_QUALIFIER_RESTRICT); @@ -3236,15 +3096,15 @@ static type_qualifiers_t parse_type_qualifiers(void) */ 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.symbol); - entity->base.source_position = token.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(); if (scope != NULL) append_entity(scope, entity); - } while (next_if(',') && token.type == T_IDENTIFIER); + } while (next_if(',') && token.kind == T_IDENTIFIER); } static entity_t *parse_parameter(void) @@ -3275,19 +3135,29 @@ static void semantic_parameter_incomplete(const entity_t *entity) static bool has_parameters(void) { /* func(void) is not a parameter */ - if (token.type == T_IDENTIFIER) { - entity_t const *const entity = get_entity(token.symbol, NAMESPACE_NORMAL); + if (look_ahead(1)->kind != ')') + return true; + if (token.kind == T_IDENTIFIER) { + entity_t const *const entity + = get_entity(token.identifier.symbol, NAMESPACE_NORMAL); if (entity == NULL) 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; - } else if (token.type != T_void) { + 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)->type != ')') - return true; next_token(); return false; } @@ -3300,26 +3170,21 @@ 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.type == T_IDENTIFIER && - !is_typedef_symbol(token.symbol)) { - token_type_t la1_type = (token_type_t)look_ahead(1)->type; - if (la1_type == ',' || la1_type == ')') { - type->kr_style_parameters = true; - parse_identifier_list(scope); - goto parameters_finished; - } - } - if (token.type == ')') { + 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.type) { + switch (token.kind) { case T_DOTDOTDOT: next_token(); type->variadic = true; @@ -3354,19 +3219,16 @@ 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 { - CONSTRUCT_INVALID, - CONSTRUCT_POINTER, + CONSTRUCT_POINTER = 1, CONSTRUCT_REFERENCE, CONSTRUCT_FUNCTION, CONSTRUCT_ARRAY @@ -3464,10 +3326,10 @@ static construct_type_t *parse_array_declarator(void) array->is_static = is_static; expression_t *size = NULL; - if (token.type == '*' && look_ahead(1)->type == ']') { + if (token.kind == '*' && look_ahead(1)->kind == ']') { array->is_variable = true; next_token(); - } else if (token.type != ']') { + } else if (token.kind != ']') { size = parse_assignment_expression(); /* §6.7.5.2:1 Array size must have integer type */ @@ -3487,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; } @@ -3534,7 +3394,7 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env) for (;;) { construct_type_t *type; //variable_t *based = NULL; /* MS __based extension */ - switch (token.type) { + switch (token.kind) { case '&': type = parse_reference_declarator(); break; @@ -3562,13 +3422,13 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env) ptr_operator_end: ; construct_type_t *inner_types = NULL; - switch (token.type) { + switch (token.kind) { case T_IDENTIFIER: if (env->must_be_abstract) { errorf(HERE, "no identifier expected in typename"); } else { - env->symbol = token.symbol; - env->source_position = token.source_position; + env->symbol = token.identifier.symbol; + env->source_position = token.base.source_position; } next_token(); break; @@ -3576,9 +3436,9 @@ ptr_operator_end: ; case '(': { /* Parenthesized declarator or function declarator? */ token_t const *const la1 = look_ahead(1); - switch (la1->type) { + switch (la1->kind) { case T_IDENTIFIER: - if (is_typedef_symbol(la1->symbol)) { + if (is_typedef_symbol(la1->identifier.symbol)) { case ')': /* §6.7.6:2 footnote 126: Empty parentheses in a type name are * interpreted as ``function with no parameter specification'', rather @@ -3603,7 +3463,7 @@ ptr_operator_end: ; env->must_be_abstract = true; } rem_anchor_token(')'); - expect(')', end_error); + expect(')'); } break; } @@ -3622,7 +3482,7 @@ ptr_operator_end: ; for (;;) { construct_type_t *type; - switch (token.type) { + switch (token.kind) { case '(': { scope_t *scope = NULL; if (!env->must_be_abstract) { @@ -3652,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, @@ -3663,8 +3521,6 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, for (; iter != NULL; iter = iter->base.next) { source_position_t const* const pos = &iter->base.pos; switch (iter->kind) { - case CONSTRUCT_INVALID: - break; case CONSTRUCT_FUNCTION: { construct_function_type_t *function = &iter->function; type_t *function_type = function->function_type; @@ -3679,7 +3535,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, errorf(pos, "function returning array is not allowed"); } else { if (skipped_return_type->base.qualifiers != 0) { - warningf(WARN_OTHER, pos, "type qualifiers in return type of function type are meaningless"); + warningf(WARN_IGNORED_QUALIFIERS, pos, "type qualifiers in return type of function type are meaningless"); } } @@ -3829,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)) { @@ -3849,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)) { @@ -3866,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; @@ -3887,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; @@ -3915,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; @@ -3933,6 +3788,10 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, handle_entity_attributes(attributes, entity); } + if (entity->kind == ENTITY_FUNCTION && !freestanding) { + adapt_special_functions(&entity->function); + } + return entity; } @@ -4018,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 strcmp(sym->string, "main") == 0; -} - static void error_redefined_as_different_kind(const source_position_t *pos, const entity_t *old, entity_kind_t new_kind) { @@ -4085,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 @@ -4099,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); @@ -4114,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); } } @@ -4149,8 +4006,22 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) goto finish; } if (previous_entity->kind == ENTITY_TYPEDEF) { - /* TODO: C++ allows this for exactly the same type */ - errorf(pos, "redefinition of '%N' (declared %P)", entity, ppos); + type_t *const type = skip_typeref(entity->typedefe.type); + type_t *const prev_type + = skip_typeref(previous_entity->typedefe.type); + if (c_mode & _CXX) { + /* C++ allows double typedef if they are identical + * (after skipping typedefs) */ + if (type == prev_type) + goto finish; + } else { + /* GCC extension: redef in system headers is allowed */ + if ((pos->is_system_header || ppos->is_system_header) && + types_compatible(type, prev_type)) + goto finish; + } + errorf(pos, "redefinition of '%N' (declared %P)", + entity, ppos); goto finish; } @@ -4204,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) { @@ -4230,7 +4101,7 @@ warn_redundant_declaration: ; merge_in_attributes(decl, prev_decl->attributes); } else if (!is_definition && is_type_valid(prev_type) && - strcmp(ppos->input_name, "") != 0) { + !pos->is_system_header) { warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%Y' (declared %P)", symbol, ppos); } } else if (current_function == NULL) { @@ -4274,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 { @@ -4291,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); @@ -4310,11 +4177,11 @@ static void parser_error_multiple_definition(entity_t *entity, static bool is_declaration_specifier(const token_t *token) { - switch (token->type) { + switch (token->kind) { DECLARATION_START return true; case T_IDENTIFIER: - return is_typedef_symbol(token->symbol); + return is_typedef_symbol(token->identifier.symbol); default: return false; @@ -4358,10 +4225,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 @@ -4438,20 +4303,18 @@ static void parse_declaration_rest(entity_t *ndeclaration, add_anchor_token(';'); add_anchor_token(','); while (true) { - entity_t *entity = finished_declaration(ndeclaration, token.type == '='); + entity_t *entity = finished_declaration(ndeclaration, token.kind == '='); - if (token.type == '=') { + if (token.kind == '=') { parse_init_declarator_rest(entity); } else if (entity->kind == ENTITY_VARIABLE) { /* 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); } } @@ -4464,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) @@ -4502,7 +4364,7 @@ static void parse_declaration(parsed_declaration_func finished_declaration, parse_declaration_specifiers(&specifiers); rem_anchor_token(';'); - if (token.type == ';') { + if (token.kind == ';') { parse_anonymous_declaration_rest(&specifiers); } else { entity_t *entity = parse_declarator(&specifiers, flags); @@ -4548,7 +4410,7 @@ static void parse_kr_declaration_list(entity_t *entity) /* parse declaration list */ for (;;) { - switch (token.type) { + switch (token.kind) { DECLARATION_START /* This covers symbols, which are no type, too, and results in * better error messages. The typical cases are misspelled type @@ -4674,10 +4536,6 @@ static void check_labels(void) for (const goto_statement_t *goto_statement = goto_first; goto_statement != NULL; goto_statement = goto_statement->next) { - /* skip computed gotos */ - if (goto_statement->expression != NULL) - continue; - label_t *label = goto_statement->label; if (label->base.source_position.input_name == NULL) { print_in_function(); @@ -4749,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, @@ -4777,10 +4631,12 @@ static bool expression_returns(expression_t const *const expr) switch (expr->kind) { case EXPR_CALL: { expression_t const *const func = expr->call.function; - if (func->kind == EXPR_REFERENCE) { - entity_t *entity = func->reference.entity; - if (entity->kind == ENTITY_FUNCTION - && entity->declaration.modifiers & DM_NORETURN) + type_t const *const type = skip_typeref(func->base.type); + if (type->kind == TYPE_POINTER) { + type_t const *const points_to + = skip_typeref(type->pointer.points_to); + if (points_to->kind == TYPE_FUNCTION + && points_to->function.modifiers & DM_NORETURN) return false; } @@ -4796,8 +4652,8 @@ static bool expression_returns(expression_t const *const expr) } case EXPR_REFERENCE: - case EXPR_REFERENCE_ENUM_VALUE: - EXPR_LITERAL_CASES + case EXPR_ENUM_CONSTANT: + case EXPR_LITERAL_CASES: case EXPR_STRING_LITERAL: case EXPR_WIDE_STRING_LITERAL: case EXPR_COMPOUND_LITERAL: // TODO descend into initialisers @@ -4809,7 +4665,7 @@ static bool expression_returns(expression_t const *const expr) case EXPR_BUILTIN_CONSTANT_P: case EXPR_BUILTIN_TYPES_COMPATIBLE_P: case EXPR_OFFSETOF: - case EXPR_INVALID: + case EXPR_ERROR: return true; case EXPR_STATEMENT: { @@ -4850,20 +4706,17 @@ static bool expression_returns(expression_t const *const expr) case EXPR_VA_COPY: return expression_returns(expr->va_copye.src); - EXPR_UNARY_CASES_MANDATORY + case EXPR_UNARY_CASES_MANDATORY: return expression_returns(expr->unary.value); case EXPR_UNARY_THROW: return false; - EXPR_BINARY_CASES + case EXPR_BINARY_CASES: // TODO handle constant lhs of && and || return expression_returns(expr->binary.left) && expression_returns(expr->binary.right); - - case EXPR_UNKNOWN: - break; } panic("unhandled expression"); @@ -4906,7 +4759,7 @@ static void check_reachable(statement_t *const stmt) statement_t *last = stmt; statement_t *next; switch (stmt->kind) { - case STATEMENT_INVALID: + case STATEMENT_ERROR: case STATEMENT_EMPTY: case STATEMENT_ASM: next = stmt->base.next; @@ -5058,20 +4911,21 @@ static void check_reachable(statement_t *const stmt) found_break_parent: break; - case STATEMENT_GOTO: - if (stmt->gotos.expression) { - if (!expression_returns(stmt->gotos.expression)) - return; + case STATEMENT_COMPUTED_GOTO: { + if (!expression_returns(stmt->computed_goto.expression)) + return; - statement_t *parent = stmt->base.parent; - if (parent == NULL) /* top level goto */ - return; - next = parent; - } else { - next = stmt->gotos.label->statement; - if (next == NULL) /* missing label */ - return; - } + statement_t *parent = stmt->base.parent; + if (parent == NULL) /* top level goto */ + return; + next = parent; + break; + } + + case STATEMENT_GOTO: + next = stmt->gotos.label->statement; + if (next == NULL) /* missing label */ + return; break; case STATEMENT_LABEL: @@ -5168,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"); } @@ -5178,7 +5032,7 @@ found_break_parent: } switch (next->kind) { - case STATEMENT_INVALID: + case STATEMENT_ERROR: case STATEMENT_EMPTY: case STATEMENT_DECLARATION: case STATEMENT_EXPRESSION: @@ -5186,6 +5040,7 @@ found_break_parent: case STATEMENT_RETURN: case STATEMENT_CONTINUE: case STATEMENT_BREAK: + case STATEMENT_COMPUTED_GOTO: case STATEMENT_GOTO: case STATEMENT_LEAVE: panic("invalid control flow in function"); @@ -5369,6 +5224,24 @@ warn_unreachable: } } +static bool is_main(entity_t *entity) +{ + static symbol_t *sym_main = NULL; + if (sym_main == NULL) { + sym_main = symbol_table_insert("main"); + } + + if (entity->base.symbol != sym_main) + return false; + /* must be in outermost scope */ + if (entity->base.parent_scope != file_scope) + return false; + + return true; +} + +static void prepare_main_collect2(entity_t*); + static void parse_external_declaration(void) { /* function-definitions and declarations both start with declaration @@ -5379,7 +5252,7 @@ static void parse_external_declaration(void) rem_anchor_token(';'); /* must be a declaration */ - if (token.type == ';') { + if (token.kind == ';') { parse_anonymous_declaration_rest(&specifiers); return; } @@ -5398,7 +5271,7 @@ static void parse_external_declaration(void) rem_anchor_token(','); /* must be a declaration */ - switch (token.type) { + switch (token.kind) { case ',': case ';': case '=': @@ -5410,7 +5283,7 @@ static void parse_external_declaration(void) /* must be a function definition */ parse_kr_declaration_list(ndeclaration); - if (token.type != '{') { + if (token.kind != '{') { parse_error_expected("while parsing function definition", '{', NULL); eat_until_matching_token(';'); return; @@ -5462,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); @@ -5489,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; @@ -5518,10 +5388,23 @@ static void parse_external_declaration(void) } } + 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); } @@ -5529,45 +5412,6 @@ static void parse_external_declaration(void) POP_SCOPE(); } -static type_t *make_bitfield_type(type_t *base_type, expression_t *size, - source_position_t *source_position, - const symbol_t *symbol) -{ - type_t *type = allocate_type_zero(TYPE_BITFIELD); - - type->bitfield.base_type = base_type; - type->bitfield.size_expression = size; - - il_size_t bit_size; - type_t *skipped_type = skip_typeref(base_type); - if (!is_type_integer(skipped_type)) { - errorf(source_position, "bitfield base type '%T' is not an integer type", base_type); - bit_size = 0; - } else { - bit_size = get_type_size(base_type) * 8; - } - - if (is_constant_expression(size) == EXPR_CLASS_CONSTANT) { - long v = fold_constant_to_int(size); - const symbol_t *user_symbol = symbol == NULL ? sym_anonymous : symbol; - - if (v < 0) { - errorf(source_position, "negative width in bit-field '%Y'", - user_symbol); - } else if (v == 0 && symbol != NULL) { - errorf(source_position, "zero width for bit-field '%Y'", - user_symbol); - } else if (bit_size > 0 && (il_size_t)v > bit_size) { - errorf(source_position, "width of '%Y' exceeds its type", - user_symbol); - } else { - type->bitfield.bit_size = v; - } - } - - return type; -} - static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol) { entity_t *iter = compound->members.entities; @@ -5626,12 +5470,19 @@ static expression_t *create_select(const source_position_t *pos, type_t *entry_type = entry->declaration.type; type_t *res_type = get_qualified_type(entry_type, qualifiers); + /* bitfields need special treatment */ + if (entry->compound_member.bitfield) { + unsigned bit_size = entry->compound_member.bit_size; + /* if fewer bits than an int, convert to int (see §6.3.1.1) */ + if (bit_size < get_atomic_type_size(ATOMIC_TYPE_INT) * BITS_PER_BYTE) { + res_type = type_int; + } + } + /* we always do the auto-type conversions; the & and sizeof parser contains * code to revert this! */ select->base.type = automatic_type_conversion(res_type); - if (res_type->kind == TYPE_BITFIELD) { - select->base.type = res_type->bitfield.base_type; - } + return select; } @@ -5665,7 +5516,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); } @@ -5678,38 +5529,77 @@ static expression_t *find_create_select(const source_position_t *pos, return NULL; } +static void parse_bitfield_member(entity_t *entity) +{ + eat(':'); + + expression_t *size = parse_constant_expression(); + long size_long; + + assert(entity->kind == ENTITY_COMPOUND_MEMBER); + type_t *type = entity->declaration.type; + if (!is_type_integer(skip_typeref(type))) { + errorf(HERE, "bitfield base type '%T' is not an integer type", + type); + } + + if (is_constant_expression(size) != EXPR_CLASS_CONSTANT) { + /* error already reported by parse_constant_expression */ + size_long = get_type_size(type) * 8; + } else { + size_long = fold_constant_to_int(size); + + const symbol_t *symbol = entity->base.symbol; + const symbol_t *user_symbol + = symbol == NULL ? sym_anonymous : symbol; + unsigned bit_size = get_type_size(type) * 8; + if (size_long < 0) { + errorf(HERE, "negative width in bit-field '%Y'", user_symbol); + } else if (size_long == 0 && symbol != NULL) { + errorf(HERE, "zero width for bit-field '%Y'", user_symbol); + } else if (bit_size > 0 && (unsigned)size_long > bit_size) { + errorf(HERE, "width of bitfield '%Y' exceeds its type", + user_symbol); + } else { + /* hope that people don't invent crazy types with more bits + * than our struct can hold */ + assert(size_long < + (1 << sizeof(entity->compound_member.bit_size)*8)); + } + } + + entity->compound_member.bitfield = true; + entity->compound_member.bit_size = (unsigned char)size_long; +} + 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.type == ':') { - source_position_t source_position = *HERE; - next_token(); - - type_t *base_type = specifiers->type; - expression_t *size = parse_constant_expression(); + if (token.kind == ':') { + /* anonymous bitfield */ + type_t *type = specifiers->type; + 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; - type_t *type = make_bitfield_type(base_type, size, - &source_position, NULL); + parse_bitfield_member(entity); attribute_t *attributes = parse_attributes(NULL); attribute_t **anchor = &attributes; while (*anchor != NULL) anchor = &(*anchor)->next; *anchor = specifiers->attributes; - - entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, NULL); - entity->base.source_position = source_position; - entity->declaration.declared_storage_class = STORAGE_CLASS_NONE; - entity->declaration.storage_class = STORAGE_CLASS_NONE; - entity->declaration.type = type; - entity->declaration.attributes = attributes; - if (attributes != NULL) { handle_entity_attributes(attributes, entity); } + entity->declaration.attributes = attributes; + append_entity(&compound->members, entity); } else { entity = parse_declarator(specifiers, @@ -5730,17 +5620,10 @@ static void parse_compound_declarators(compound_t *compound, } } - if (token.type == ':') { - source_position_t source_position = *HERE; - next_token(); - expression_t *size = parse_constant_expression(); - - type_t *type = entity->declaration.type; - type_t *bitfield_type = make_bitfield_type(type, size, - &source_position, entity->base.symbol); + if (token.kind == ':') { + parse_bitfield_member(entity); attribute_t *attributes = parse_attributes(NULL); - entity->declaration.type = bitfield_type; handle_entity_attributes(attributes, entity); } else { type_t *orig_type = entity->declaration.type; @@ -5750,9 +5633,11 @@ static void parse_compound_declarators(compound_t *compound, } else if (is_type_incomplete(type)) { /* §6.7.2.1:16 flexible array member */ if (!is_type_array(type) || - token.type != ';' || - look_ahead(1)->type != '}') { + token.kind != ';' || + look_ahead(1)->kind != '}') { errorf(pos, "'%N' has incomplete type '%T'", entity, orig_type); + } else if (compound->members.entities == NULL) { + errorf(pos, "flexible array member in otherwise empty struct"); } } } @@ -5761,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; } @@ -5773,7 +5659,7 @@ static void parse_compound_type_entries(compound_t *compound) add_anchor_token('}'); for (;;) { - switch (token.type) { + switch (token.kind) { DECLARATION_START case T___extension__: case T_IDENTIFIER: { @@ -5787,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; @@ -5828,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.type != T_ERROR) { - errorf(HERE, "expected expression, got token %K", &token); - } - next_token(); - - return create_invalid_expression(); -} - static type_t *get_string_type(void) { return is_warn_on(WARN_WRITE_STRINGS) ? type_const_char_ptr : type_char_ptr; @@ -5857,17 +5728,17 @@ static type_t *get_wide_string_type(void) */ static expression_t *parse_string_literal(void) { - source_position_t begin = token.source_position; - string_t res = token.literal; - bool is_wide = (token.type == T_WIDE_STRING_LITERAL); + source_position_t begin = token.base.source_position; + string_t res = token.string.string; + bool is_wide = (token.kind == T_WIDE_STRING_LITERAL); next_token(); - while (token.type == T_STRING_LITERAL - || token.type == T_WIDE_STRING_LITERAL) { - warn_string_concat(&token.source_position); - res = concat_strings(&res, &token.literal); + while (token.kind == T_STRING_LITERAL + || token.kind == T_WIDE_STRING_LITERAL) { + warn_string_concat(&token.base.source_position); + res = concat_strings(&res, &token.string.string); next_token(); - is_wide |= token.type == T_WIDE_STRING_LITERAL; + is_wide |= token.kind == T_WIDE_STRING_LITERAL; } expression_t *literal; @@ -5900,17 +5771,18 @@ static expression_t *parse_boolean_literal(bool value) static void warn_traditional_suffix(void) { - warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%Y' suffix", token.symbol); + warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%S' suffix", + &token.number.suffix); } static void check_integer_suffix(void) { - symbol_t *suffix = token.symbol; - if (suffix == NULL) + const string_t *suffix = &token.number.suffix; + if (suffix->size == 0) return; bool not_traditional = false; - const char *c = suffix->string; + const char *c = suffix->begin; if (*c == 'l' || *c == 'L') { ++c; if (*c == *(c-1)) { @@ -5934,8 +5806,8 @@ static void check_integer_suffix(void) } } if (*c != '\0') { - errorf(&token.source_position, - "invalid suffix '%s' on integer constant", suffix->string); + errorf(&token.base.source_position, + "invalid suffix '%S' on integer constant", suffix); } else if (not_traditional) { warn_traditional_suffix(); } @@ -5943,13 +5815,13 @@ static void check_integer_suffix(void) static type_t *check_floatingpoint_suffix(void) { - symbol_t *suffix = token.symbol; - type_t *type = type_double; - if (suffix == NULL) + const string_t *suffix = &token.number.suffix; + type_t *type = type_double; + if (suffix->size == 0) return type; bool not_traditional = false; - const char *c = suffix->string; + const char *c = suffix->begin; if (*c == 'f' || *c == 'F') { ++c; type = type_float; @@ -5958,8 +5830,8 @@ static type_t *check_floatingpoint_suffix(void) type = type_long_double; } if (*c != '\0') { - errorf(&token.source_position, - "invalid suffix '%s' on floatingpoint constant", suffix->string); + errorf(&token.base.source_position, + "invalid suffix '%S' on floatingpoint constant", suffix); } else if (not_traditional) { warn_traditional_suffix(); } @@ -5975,38 +5847,26 @@ static expression_t *parse_number_literal(void) expression_kind_t kind; type_t *type; - switch (token.type) { + switch (token.kind) { case T_INTEGER: kind = EXPR_LITERAL_INTEGER; 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"); } expression_t *literal = allocate_expression_zero(kind); literal->base.type = type; - literal->literal.value = token.literal; - literal->literal.suffix = token.symbol; + literal->literal.value = token.number.number; + literal->literal.suffix = token.number.suffix; next_token(); /* integer type depends on the size of the number and the size @@ -6024,7 +5884,7 @@ static expression_t *parse_character_constant(void) { expression_t *literal = allocate_expression_zero(EXPR_LITERAL_CHARACTER); literal->base.type = c_mode & _CXX ? type_char : type_int; - literal->literal.value = token.literal; + literal->literal.value = token.string.string; size_t len = literal->literal.value.size; if (len > 1) { @@ -6047,7 +5907,7 @@ static expression_t *parse_wide_character_constant(void) { expression_t *literal = allocate_expression_zero(EXPR_LITERAL_WIDE_CHARACTER); literal->base.type = type_int; - literal->literal.value = token.literal; + literal->literal.value = token.string.string; size_t len = wstrlen(&literal->literal.value); if (len > 1) { @@ -6058,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; @@ -6067,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); @@ -6125,8 +5983,7 @@ type_t *revert_automatic_type_conversion(const expression_t *expression) entity_t *entity = expression->select.compound_entry; assert(is_declaration(entity)); type_t *type = entity->declaration.type; - return get_qualified_type(type, - expression->base.type->base.qualifiers); + return get_qualified_type(type, expression->base.type->base.qualifiers); } case EXPR_UNARY_DEREFERENCE: { @@ -6199,13 +6056,9 @@ static entity_t *parse_qualified_identifier(void) entity_t *entity; while (true) { - if (token.type != 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.symbol; - pos = *HERE; - next_token(); /* lookup entity */ entity = lookup_entity(lookup_scope, symbol, NAMESPACE_NORMAL); @@ -6234,9 +6087,10 @@ static entity_t *parse_qualified_identifier(void) } if (entity == NULL) { - if (!strict_mode && token.type == '(') { + if (!strict_mode && token.kind == '(') { /* an implicitly declared function */ - warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, "implicit declaration of function '%Y'", symbol); + warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, + "implicit declaration of function '%Y'", symbol); entity = create_implicit_function(symbol, &pos); } else { errorf(&pos, "unknown identifier '%Y' found.", symbol); @@ -6249,7 +6103,7 @@ static entity_t *parse_qualified_identifier(void) static expression_t *parse_reference(void) { - source_position_t const pos = token.source_position; + source_position_t const pos = token.base.source_position; entity_t *const entity = parse_qualified_identifier(); type_t *orig_type; @@ -6267,7 +6121,7 @@ static expression_t *parse_reference(void) expression_kind_t kind = EXPR_REFERENCE; if (entity->kind == ENTITY_ENUM_VALUE) - kind = EXPR_REFERENCE_ENUM_VALUE; + kind = EXPR_ENUM_CONSTANT; expression_t *expression = allocate_expression_zero(kind); expression->base.source_position = pos; @@ -6294,11 +6148,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; } @@ -6312,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 */ @@ -6378,9 +6227,9 @@ static expression_t *parse_cast(void) type_t *type = parse_typename(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); - if (token.type == '{') { + if (token.kind == '{') { return parse_compound_literal(&pos, type); } @@ -6396,8 +6245,6 @@ static expression_t *parse_cast(void) } return cast; -end_error: - return create_invalid_expression(); } /** @@ -6431,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; } @@ -6443,13 +6288,13 @@ end_error: static expression_t *parse_parenthesized_expression(void) { token_t const* const la1 = look_ahead(1); - switch (la1->type) { + switch (la1->kind) { case '{': /* gcc extension: a statement expression */ return parse_statement_expression(); case T_IDENTIFIER: - if (is_typedef_symbol(la1->symbol)) { + if (is_typedef_symbol(la1->identifier.symbol)) { DECLARATION_START return parse_cast(); } @@ -6460,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; } @@ -6530,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.type != 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.symbol; - next_token(); designator_t *last_designator = result; while (true) { if (next_if('.')) { - if (token.type != 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.symbol; - next_token(); last_designator->next = designator; last_designator = designator; @@ -6564,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; } @@ -6577,8 +6410,6 @@ static designator_t *parse_designator(void) } return result; -end_error: - return NULL; } /** @@ -6591,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; @@ -6612,14 +6443,12 @@ static expression_t *parse_offsetof(void) descend_into_subtype(&path); if (!walk_designator(&path, designator, true)) { - return create_invalid_expression(); + return create_error_expression(); } DEL_ARR_F(path.path); return expression; -end_error: - return create_invalid_expression(); } /** @@ -6631,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; @@ -6650,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_invalid_expression(); + rem_anchor_token(')'); + expect(')'); + return expression; } /** @@ -6667,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_invalid_expression(); } /** @@ -6691,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_invalid_expression(); } /** @@ -6720,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_invalid_expression(); } /** @@ -6741,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_invalid_expression(); } /** @@ -6764,7 +6594,7 @@ static expression_t *parse_compare_builtin(void) { expression_t *expression; - switch (token.type) { + switch (token.kind) { case T___builtin_isgreater: expression = allocate_expression_zero(EXPR_BINARY_ISGREATER); break; @@ -6789,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; @@ -6810,8 +6644,6 @@ static expression_t *parse_compare_builtin(void) } return expression; -end_error: - return create_invalid_expression(); } /** @@ -6823,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_invalid_expression(); } /** @@ -6840,10 +6670,10 @@ end_error: */ static label_t *get_label(void) { - assert(token.type == T_IDENTIFIER); + assert(token.kind == T_IDENTIFIER); assert(current_function != NULL); - entity_t *label = get_entity(token.symbol, NAMESPACE_LABEL); + entity_t *label = get_entity(token.identifier.symbol, NAMESPACE_LABEL); /* If we find a local label, we already created the declaration. */ if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) { if (label->base.parent_scope != current_scope) { @@ -6852,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.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); } @@ -6865,11 +6696,11 @@ static label_t *get_label(void) */ static expression_t *parse_label_address(void) { - source_position_t source_position = token.source_position; + source_position_t source_position = token.base.source_position; eat(T_ANDAND); - if (token.type != T_IDENTIFIER) { + if (token.kind != T_IDENTIFIER) { parse_error_expected("while parsing label address", T_IDENTIFIER, NULL); - return create_invalid_expression(); + return create_error_expression(); } label_t *const label = get_label(); @@ -6898,21 +6729,21 @@ static expression_t *parse_noop_expression(void) eat(T___noop); - if (token.type == '(') { + if (token.kind == '(') { /* parse arguments */ eat('('); add_anchor_token(')'); add_anchor_token(','); - if (token.type != ')') do { + if (token.kind != ')') do { (void)parse_assignment_expression(); } while (next_if(',')); + + rem_anchor_token(','); + rem_anchor_token(')'); } - rem_anchor_token(','); - rem_anchor_token(')'); - expect(')', end_error); + expect(')'); -end_error: return literal; } @@ -6921,14 +6752,11 @@ end_error: */ static expression_t *parse_primary_expression(void) { - switch (token.type) { + switch (token.kind) { 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: @@ -6963,7 +6791,7 @@ static expression_t *parse_primary_expression(void) case T_COLONCOLON: return parse_reference(); case T_IDENTIFIER: - if (!is_typedef_symbol(token.symbol)) { + if (!is_typedef_symbol(token.identifier.symbol)) { return parse_reference(); } /* FALLTHROUGH */ @@ -6973,13 +6801,13 @@ static expression_t *parse_primary_expression(void) parse_declaration_specifiers(&specifiers); type_t const *const type = parse_abstract_declarator(specifiers.type); errorf(&pos, "encountered type '%T' while parsing expression", type); - return create_invalid_expression(); + return create_error_expression(); } } errorf(HERE, "unexpected token %K, expected an expression", &token); eat_until_anchor(); - return create_invalid_expression(); + return create_error_expression(); } static expression_t *parse_array_expression(expression_t *left) @@ -7036,11 +6864,16 @@ check_idx: arr->base.type = res_type; rem_anchor_token(']'); - expect(']', end_error); -end_error: + expect(']'); return expr; } +static bool is_bitfield(const expression_t *expression) +{ + return expression->kind == EXPR_SELECT + && expression->select.compound_entry->compound_member.bitfield; +} + static expression_t *parse_typeprop(expression_kind_t const kind) { expression_t *tp_expression = allocate_expression_zero(kind); @@ -7048,21 +6881,17 @@ 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))) { + if (token.kind == '(' && is_declaration_specifier(look_ahead(1))) { source_position_t const pos = *HERE; next_token(); add_anchor_token(')'); orig_type = parse_typename(); rem_anchor_token(')'); - expect(')', end_error); + expect(')'); - if (token.type == '{') { + if (token.kind == '{') { /* It was not sizeof(type) after all. It is sizeof of an expression * starting with a compound literal */ expression = parse_compound_literal(&pos, orig_type); @@ -7072,6 +6901,12 @@ static expression_t *parse_typeprop(expression_kind_t const kind) expression = parse_subexpression(PREC_UNARY); typeprop_expression: + if (is_bitfield(expression)) { + char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; + errorf(&tp_expression->base.source_position, + "operand of %s expression must not be a bitfield", what); + } + tp_expression->typeprop.tp_expression = expression; orig_type = revert_automatic_type_conversion(expression); @@ -7082,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) { @@ -7093,12 +6928,7 @@ typeprop_expression: } else { wrong_type = "function"; } - } else { - if (is_type_incomplete(type)) - wrong_type = "incomplete"; } - if (type->kind == TYPE_BITFIELD) - wrong_type = "bitfield"; if (wrong_type != NULL) { char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; @@ -7107,8 +6937,6 @@ typeprop_expression: what, wrong_type, orig_type); } -end_error: - in_type_prop = old; return tp_expression; } @@ -7124,17 +6952,14 @@ static expression_t *parse_alignof(void) static expression_t *parse_select_expression(expression_t *addr) { - assert(token.type == '.' || token.type == T_MINUSGREATER); - bool select_left_arrow = (token.type == T_MINUSGREATER); + assert(token.kind == '.' || token.kind == T_MINUSGREATER); + bool select_left_arrow = (token.kind == T_MINUSGREATER); source_position_t const pos = *HERE; next_token(); - if (token.type != T_IDENTIFIER) { - parse_error_expected("while parsing select", T_IDENTIFIER, NULL); - return create_invalid_expression(); - } - symbol_t *symbol = token.symbol; - next_token(); + symbol_t *const symbol = expect_identifier("while parsing select", NULL); + if (!symbol) + return create_error_expression(); type_t *const orig_type = addr->base.type; type_t *const type = skip_typeref(orig_type); @@ -7165,14 +6990,14 @@ static expression_t *parse_select_expression(expression_t *addr) "request for member '%Y' in something not a struct or union, but '%T'", symbol, type_left); } - return create_invalid_expression(); + return create_error_expression(); } compound_t *compound = type_left->compound.compound; if (!compound->complete) { errorf(&pos, "request for member '%Y' in incomplete type '%T'", symbol, type_left); - return create_invalid_expression(); + return create_error_expression(); } type_qualifiers_t qualifiers = type_left->base.qualifiers; @@ -7181,7 +7006,7 @@ static expression_t *parse_select_expression(expression_t *addr) if (result == NULL) { errorf(&pos, "'%T' has no member named '%Y'", orig_type, symbol); - return create_invalid_expression(); + return create_error_expression(); } return result; @@ -7245,32 +7070,25 @@ static void check_call_argument(type_t *expected_type, /** * Handle the semantic restrictions of builtin calls */ -static void handle_builtin_argument_restrictions(call_expression_t *call) { - switch (call->function->reference.entity->function.btk) { - case bk_gnu_builtin_return_address: - case bk_gnu_builtin_frame_address: { +static void handle_builtin_argument_restrictions(call_expression_t *call) +{ + entity_t *entity = call->function->reference.entity; + switch (entity->function.btk) { + case BUILTIN_FIRM: + switch (entity->function.b.firm_builtin_kind) { + case ir_bk_return_address: + case ir_bk_frame_address: { /* argument must be constant */ call_argument_t *argument = call->arguments; if (is_constant_expression(argument->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, - "argument of '%Y' must be a constant expression", - call->function->reference.entity->base.symbol); - } - break; - } - case bk_gnu_builtin_object_size: - if (call->arguments == NULL) - break; - - call_argument_t *arg = call->arguments->next; - if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) { - errorf(&call->base.source_position, - "second argument of '%Y' must be a constant expression", + "argument of '%Y' must be a constant expression", call->function->reference.entity->base.symbol); } break; - case bk_gnu_builtin_prefetch: + } + case ir_bk_prefetch: /* second and third argument must be constant if existent */ if (call->arguments == NULL) break; @@ -7280,22 +7098,37 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) { if (rw != NULL) { if (is_constant_expression(rw->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, - "second argument of '%Y' must be a constant expression", - call->function->reference.entity->base.symbol); + "second argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); } locality = rw->next; } if (locality != NULL) { if (is_constant_expression(locality->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, - "third argument of '%Y' must be a constant expression", - call->function->reference.entity->base.symbol); + "third argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); } locality = rw->next; } break; default: break; + } + + case BUILTIN_OBJECT_SIZE: + if (call->arguments == NULL) + break; + + call_argument_t *arg = call->arguments->next; + if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) { + errorf(&call->base.source_position, + "second argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); + } + break; + default: + break; } } @@ -7334,7 +7167,7 @@ static expression_t *parse_call_expression(expression_t *expression) add_anchor_token(')'); add_anchor_token(','); - if (token.type != ')') { + if (token.kind != ')') { call_argument_t **anchor = &call->arguments; do { call_argument_t *argument = allocate_ast_zero(sizeof(*argument)); @@ -7346,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; @@ -7391,11 +7224,10 @@ static expression_t *parse_call_expression(expression_t *expression) if (expression->kind == EXPR_REFERENCE) { reference_expression_t *reference = &expression->reference; if (reference->entity->kind == ENTITY_FUNCTION && - reference->entity->function.btk != bk_none) + reference->entity->function.btk != BUILTIN_NONE) handle_builtin_argument_restrictions(call); } -end_error: return result; } @@ -7491,14 +7323,13 @@ static expression_t *parse_conditional_expression(expression_t *expression) expression_t *true_expression = expression; bool gnu_cond = false; - if (GNU_MODE && token.type == ':') { + if (GNU_MODE && token.kind == ':') { gnu_cond = true; } else { 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); @@ -7510,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; @@ -7552,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))) { @@ -7609,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_invalid_expression(); } /** @@ -7634,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); @@ -7647,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"); } @@ -7667,7 +7492,7 @@ static expression_t *parse_throw(void) eat(T_throw); expression_t *value = NULL; - switch (token.type) { + switch (token.kind) { EXPRESSION_START { value = parse_assignment_expression(); /* ISO/IEC 14882:1998(E) §15.1:3 */ @@ -7678,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); } @@ -7702,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); @@ -7769,6 +7593,13 @@ static void semantic_incdec(unary_expression_t *expression) expression->base.type = orig_type; } +static void promote_unary_int_expr(unary_expression_t *const expr, type_t *const type) +{ + type_t *const res_type = promote_integer(type); + expr->base.type = res_type; + expr->value = create_implicit_cast(expr->value, res_type); +} + static void semantic_unexpr_arithmetic(unary_expression_t *expression) { type_t *const orig_type = expression->value->base.type; @@ -7780,9 +7611,11 @@ static void semantic_unexpr_arithmetic(unary_expression_t *expression) "operation needs an arithmetic type"); } return; + } else if (is_type_integer(type)) { + promote_unary_int_expr(expression, type); + } else { + expression->base.type = orig_type; } - - expression->base.type = orig_type; } static void semantic_unexpr_plus(unary_expression_t *expression) @@ -7811,7 +7644,7 @@ static void semantic_unexpr_integer(unary_expression_t *expression) return; } - expression->base.type = orig_type; + promote_unary_int_expr(expression, type); } static void semantic_dereference(unary_expression_t *expression) @@ -7878,10 +7711,9 @@ static void semantic_take_addr(unary_expression_t *expression) if (!is_lvalue(value)) { errorf(&expression->base.source_position, "'&' requires an lvalue"); } - if (type->kind == TYPE_BITFIELD) { + if (is_bitfield(value)) { errorf(&expression->base.source_position, - "'&' not allowed on object with bitfield type '%T'", - type); + "'&' not allowed on bitfield"); } set_address_taken(value, false); @@ -7889,12 +7721,12 @@ static void semantic_take_addr(unary_expression_t *expression) expression->base.type = make_pointer_type(orig_type, TYPE_QUALIFIER_NONE); } -#define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type, sfunc) \ +#define CREATE_UNARY_EXPRESSION_PARSER(token_kind, unexpression_type, sfunc) \ static expression_t *parse_##unexpression_type(void) \ { \ expression_t *unary_expression \ = allocate_expression_zero(unexpression_type); \ - eat(token_type); \ + eat(token_kind); \ unary_expression->unary.value = parse_subexpression(PREC_UNARY); \ \ sfunc(&unary_expression->unary); \ @@ -7919,13 +7751,13 @@ CREATE_UNARY_EXPRESSION_PARSER(T_PLUSPLUS, EXPR_UNARY_PREFIX_INCREMENT, CREATE_UNARY_EXPRESSION_PARSER(T_MINUSMINUS, EXPR_UNARY_PREFIX_DECREMENT, semantic_incdec) -#define CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(token_type, unexpression_type, \ +#define CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(token_kind, unexpression_type, \ sfunc) \ static expression_t *parse_##unexpression_type(expression_t *left) \ { \ expression_t *unary_expression \ = allocate_expression_zero(unexpression_type); \ - eat(token_type); \ + eat(token_kind); \ unary_expression->unary.value = left; \ \ sfunc(&unary_expression->unary); \ @@ -7962,45 +7794,44 @@ static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) if (type_left == type_right) return type_left; - bool const signed_left = is_type_signed(type_left); - bool const signed_right = is_type_signed(type_right); - int const rank_left = get_rank(type_left); - int const rank_right = get_rank(type_right); + bool const signed_left = is_type_signed(type_left); + bool const signed_right = is_type_signed(type_right); + unsigned const rank_left = get_akind_rank(get_akind(type_left)); + unsigned const rank_right = get_akind_rank(get_akind(type_right)); if (signed_left == signed_right) return rank_left >= rank_right ? type_left : type_right; - int s_rank; - int u_rank; + unsigned s_rank; + unsigned u_rank; + atomic_type_kind_t s_akind; + atomic_type_kind_t u_akind; type_t *s_type; type_t *u_type; if (signed_left) { - s_rank = rank_left; s_type = type_left; - u_rank = rank_right; u_type = type_right; } else { - s_rank = rank_right; s_type = type_right; - u_rank = rank_left; u_type = type_left; } + s_akind = get_akind(s_type); + u_akind = get_akind(u_type); + s_rank = get_akind_rank(s_akind); + u_rank = get_akind_rank(u_akind); if (u_rank >= s_rank) return u_type; - /* casting rank to atomic_type_kind is a bit hacky, but makes things - * easier here... */ - if (get_atomic_type_size((atomic_type_kind_t) s_rank) - > get_atomic_type_size((atomic_type_kind_t) u_rank)) + if (get_atomic_type_size(s_akind) > get_atomic_type_size(u_akind)) return s_type; - switch (s_rank) { - case ATOMIC_TYPE_INT: return type_unsigned_int; - case ATOMIC_TYPE_LONG: return type_unsigned_long; - case ATOMIC_TYPE_LONGLONG: return type_unsigned_long_long; + switch (s_akind) { + case ATOMIC_TYPE_INT: return type_unsigned_int; + case ATOMIC_TYPE_LONG: return type_unsigned_long; + case ATOMIC_TYPE_LONGLONG: return type_unsigned_long_long; - default: panic("invalid atomic type"); + default: panic("invalid atomic type"); } } @@ -8209,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 { @@ -8243,7 +8074,7 @@ static bool maybe_negative(expression_t const *const expr) { switch (is_constant_expression(expr)) { case EXPR_CLASS_ERROR: return false; - case EXPR_CLASS_CONSTANT: return fold_constant_to_int(expr) < 0; + case EXPR_CLASS_CONSTANT: return constant_is_negative(expr); default: return true; } } @@ -8562,10 +8393,9 @@ static void semantic_binexpr_assign(binary_expression_t *expression) static bool expression_has_effect(const expression_t *const expr) { switch (expr->kind) { - case EXPR_UNKNOWN: break; - case EXPR_INVALID: return true; /* do NOT warn */ + case EXPR_ERROR: return true; /* do NOT warn */ case EXPR_REFERENCE: return false; - case EXPR_REFERENCE_ENUM_VALUE: return false; + case EXPR_ENUM_CONSTANT: return false; case EXPR_LABEL_ADDRESS: return false; /* suppress the warning for microsoft __noop operations */ @@ -8574,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; @@ -8633,10 +8460,9 @@ 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_CAST_IMPLICIT: return true; case EXPR_UNARY_ASSUME: return true; case EXPR_UNARY_DELETE: return true; case EXPR_UNARY_DELETE_ARRAY: return true; @@ -8704,12 +8530,12 @@ static void semantic_comma(binary_expression_t *expression) /** * @param prec_r precedence of the right operand */ -#define CREATE_BINEXPR_PARSER(token_type, binexpression_type, prec_r, sfunc) \ +#define CREATE_BINEXPR_PARSER(token_kind, binexpression_type, prec_r, sfunc) \ static expression_t *parse_##binexpression_type(expression_t *left) \ { \ expression_t *binexpr = allocate_expression_zero(binexpression_type); \ binexpr->binary.left = left; \ - eat(token_type); \ + eat(token_kind); \ \ expression_t *right = parse_subexpression(prec_r); \ \ @@ -8753,12 +8579,8 @@ CREATE_BINEXPR_PARSER(',', EXPR_BINARY_COMMA, PR static expression_t *parse_subexpression(precedence_t precedence) { - if (token.type < 0) { - return expected_expression_error(); - } - expression_parser_function_t *parser - = &expression_parsers[token.type]; + = &expression_parsers[token.kind]; expression_t *left; if (parser->parser != NULL) { @@ -8769,11 +8591,7 @@ static expression_t *parse_subexpression(precedence_t precedence) assert(left != NULL); while (true) { - if (token.type < 0) { - return expected_expression_error(); - } - - parser = &expression_parsers[token.type]; + parser = &expression_parsers[token.kind]; if (parser->infix_parser == NULL) break; if (parser->infix_precedence < precedence) @@ -8782,7 +8600,6 @@ static expression_t *parse_subexpression(precedence_t precedence) left = parser->infix_parser(left); assert(left != NULL); - assert(left->kind != EXPR_UNKNOWN); } return left; @@ -8800,15 +8617,15 @@ static expression_t *parse_expression(void) * Register a parser for a prefix-like operator. * * @param parser the parser function - * @param token_type the token type of the prefix token + * @param token_kind the token type of the prefix token */ static void register_expression_parser(parse_expression_function parser, - int token_type) + int token_kind) { - expression_parser_function_t *entry = &expression_parsers[token_type]; + expression_parser_function_t *entry = &expression_parsers[token_kind]; if (entry->parser != NULL) { - diagnosticf("for token '%k'\n", (token_type_t)token_type); + diagnosticf("for token '%k'\n", (token_kind_t)token_kind); panic("trying to register multiple expression parsers for a token"); } entry->parser = parser; @@ -8818,16 +8635,16 @@ static void register_expression_parser(parse_expression_function parser, * Register a parser for an infix operator with given precedence. * * @param parser the parser function - * @param token_type the token type of the infix operator + * @param token_kind the token type of the infix operator * @param precedence the precedence of the operator */ static void register_infix_parser(parse_expression_infix_function parser, - int token_type, precedence_t precedence) + int token_kind, precedence_t precedence) { - expression_parser_function_t *entry = &expression_parsers[token_type]; + expression_parser_function_t *entry = &expression_parsers[token_kind]; if (entry->infix_parser != NULL) { - diagnosticf("for token '%k'\n", (token_type_t)token_type); + diagnosticf("for token '%k'\n", (token_kind_t)token_kind); panic("trying to register multiple infix expression parsers for a " "token"); } @@ -8904,23 +8721,20 @@ static asm_argument_t *parse_asm_arguments(bool is_out) asm_argument_t *result = NULL; asm_argument_t **anchor = &result; - while (token.type == T_STRING_LITERAL || token.type == '[') { + 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.type != 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.symbol; - - expect(']', end_error); } argument->constraints = parse_string_literals(); - expect('(', end_error); + expect('('); add_anchor_token(')'); expression_t *expression = parse_expression(); rem_anchor_token(')'); @@ -8940,7 +8754,7 @@ static asm_argument_t *parse_asm_arguments(bool is_out) size = get_atomic_type_size(akind); } else { flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC; - size = get_atomic_type_size(get_intptr_kind()); + size = get_type_size(type_void_ptr); } do { @@ -8956,7 +8770,7 @@ static asm_argument_t *parse_asm_arguments(bool is_out) value_size = get_atomic_type_size(value_akind); } else if (value_kind == TYPE_POINTER) { value_flags = ATOMIC_TYPE_FLAG_INTEGER | ATOMIC_TYPE_FLAG_ARITHMETIC; - value_size = get_atomic_type_size(get_intptr_kind()); + value_size = get_type_size(type_void_ptr); } else { break; } @@ -8982,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); @@ -8994,8 +8808,6 @@ static asm_argument_t *parse_asm_arguments(bool is_out) } return result; -end_error: - return NULL; } /** @@ -9006,7 +8818,7 @@ static asm_clobber_t *parse_asm_clobbers(void) asm_clobber_t *result = NULL; asm_clobber_t **anchor = &result; - while (token.type == T_STRING_LITERAL) { + while (token.kind == T_STRING_LITERAL) { asm_clobber_t *clobber = allocate_ast_zero(sizeof(clobber[0])); clobber->clobber = parse_string_literals(); @@ -9033,9 +8845,9 @@ 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.type != T_STRING_LITERAL) { + if (token.kind != T_STRING_LITERAL) { parse_error_expected("after asm(", T_STRING_LITERAL, NULL); goto end_of_asm; } @@ -9064,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 @@ -9074,17 +8886,15 @@ end_of_asm: } return statement; -end_error: - return create_invalid_statement(); } static statement_t *parse_label_inner_statement(statement_t const *const label, char const *const label_kind) { statement_t *inner_stmt; - switch (token.type) { + switch (token.kind) { case '}': errorf(&label->base.source_position, "%s at end of compound statement", label_kind); - inner_stmt = create_invalid_statement(); + inner_stmt = create_error_statement(); break; case ';': @@ -9119,8 +8929,24 @@ 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; + type_t *skipped = skip_typeref(expression_type); + if (!is_type_integer(skipped) && is_type_valid(skipped)) { + errorf(pos, "case expression '%E' must have integer type but has type '%T'", + expression, expression_type); + } + + type_t *type = expression_type; + if (current_switch != NULL) { + type_t *switch_type = current_switch->expression->base.type; + if (is_type_valid(switch_type)) { + expression = create_implicit_cast(expression, switch_type); + } + } - expression_t *const expression = parse_expression(); statement->case_label.expression = expression; expression_classification_t const expr_class = is_constant_expression(expression); if (expr_class != EXPR_CLASS_CONSTANT) { @@ -9136,7 +8962,15 @@ static statement_t *parse_case_statement(void) if (GNU_MODE) { if (next_if(T_DOTDOTDOT)) { - expression_t *const end_range = parse_expression(); + expression_t *end_range = parse_expression(); + expression_type = expression->base.type; + skipped = skip_typeref(expression_type); + if (!is_type_integer(skipped) && is_type_valid(skipped)) { + errorf(pos, "case expression '%E' must have integer type but has type '%T'", + expression, expression_type); + } + + end_range = create_implicit_cast(end_range, type); statement->case_label.end_range = end_range; expression_classification_t const end_class = is_constant_expression(end_range); if (end_class != EXPR_CLASS_CONSTANT) { @@ -9158,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) { @@ -9205,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; @@ -9258,6 +9091,10 @@ static statement_t *parse_label_statement(void) eat(':'); + if (token.kind == 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 */ @@ -9279,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. */ @@ -9289,36 +9140,39 @@ 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); + if (true_stmt->kind == STATEMENT_EMPTY) { + warningf(WARN_EMPTY_BODY, HERE, + "suggest braces around empty body in an ‘if’ statement"); + } + if (next_if(T_else)) { statement->ifs.false_statement = parse_inner_statement(); + + if (statement->ifs.false_statement->kind == STATEMENT_EMPTY) { + warningf(WARN_EMPTY_BODY, HERE, + "suggest braces around empty body in an ‘if’ statement"); + } } else if (true_stmt->kind == STATEMENT_IF && true_stmt->ifs.false_statement != NULL) { source_position_t const *const pos = &true_stmt->base.source_position; warningf(WARN_PARENTHESES, pos, "suggest explicit braces to avoid ambiguous 'else'"); } + POP_SCOPE(); POP_PARENT(); return statement; } @@ -9376,15 +9230,13 @@ 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); - if (get_rank(type) >= get_akind_rank(ATOMIC_TYPE_LONG)) { + if (get_akind_rank(get_akind(type)) >= get_akind_rank(ATOMIC_TYPE_LONG)) { warningf(WARN_TRADITIONAL, &expr->base.source_position, "'%T' switch expression not converted to '%T' in ISO C", type, type_int); } } else if (is_type_valid(type)) { @@ -9393,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; @@ -9406,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_invalid_statement(); } static statement_t *parse_loop_body(statement_t *const loop) @@ -9434,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_invalid_statement(); } /** @@ -9465,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_invalid_statement(); } /** @@ -9499,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(); @@ -9519,12 +9355,12 @@ 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(); - if (token.type != ';') { + if (token.kind != ';') { add_anchor_token(';'); expression_t *const cond = parse_expression(); statement->fors.condition = cond; @@ -9534,8 +9370,8 @@ static statement_t *parse_for(void) mark_vars_read(cond, NULL); rem_anchor_token(';'); } - expect(';', end_error2); - if (token.type != ')') { + expect(';'); + if (token.kind != ')') { expression_t *const step = parse_expression(); statement->fors.step = step; mark_vars_read(step, ENT_ANY); @@ -9543,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_invalid_statement(); } /** @@ -9566,10 +9393,12 @@ end_error1: */ static statement_t *parse_goto(void) { - statement_t *statement = allocate_statement_zero(STATEMENT_GOTO); - eat(T_goto); + statement_t *statement; + if (GNU_MODE && look_ahead(1)->kind == '*') { + statement = allocate_statement_zero(STATEMENT_COMPUTED_GOTO); + eat(T_goto); + eat('*'); - if (GNU_MODE && next_if('*')) { expression_t *expression = parse_expression(); mark_vars_read(expression, NULL); @@ -9587,27 +9416,29 @@ static statement_t *parse_goto(void) expression = create_implicit_cast(expression, type_void_ptr); } - statement->gotos.expression = expression; - } else if (token.type == T_IDENTIFIER) { - label_t *const label = get_label(); - label->used = true; - statement->gotos.label = label; + statement->computed_goto.expression = expression; } else { - if (GNU_MODE) - parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL); - else - parse_error_expected("while parsing goto", T_IDENTIFIER, NULL); - eat_until_anchor(); - return create_invalid_statement(); + statement = allocate_statement_zero(STATEMENT_GOTO); + eat(T_goto); + if (token.kind == T_IDENTIFIER) { + label_t *const label = get_label(); + label->used = true; + statement->gotos.label = label; + + /* remember the goto's in a list for later checking */ + *goto_anchor = &statement->gotos; + goto_anchor = &statement->gotos.next; + } else { + if (GNU_MODE) + parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL); + else + parse_error_expected("while parsing goto", T_IDENTIFIER, NULL); + eat_until_anchor(); + statement->gotos.label = &allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, sym_anonymous, &builtin_source_position)->label; + } } - /* remember the goto's in a list for later checking */ - *goto_anchor = &statement->gotos; - goto_anchor = &statement->gotos.next; - - expect(';', end_error); - -end_error: + expect(';'); return statement; } @@ -9623,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; } @@ -9641,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; } @@ -9659,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; } @@ -9716,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. */ @@ -9725,7 +9559,7 @@ static statement_t *parse_return(void) eat(T_return); expression_t *return_value = NULL; - if (token.type != ';') { + if (token.kind != ';') { return_value = parse_expression(); mark_vars_read(return_value, NULL); } @@ -9738,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); @@ -9770,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; } @@ -9821,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; } @@ -9846,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); @@ -9859,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_invalid_statement(); } + statement->ms_try.final_statement = parse_compound_statement(false); return statement; -end_error: - return create_invalid_statement(); } static statement_t *parse_empty_statement(void) @@ -9891,20 +9696,18 @@ static statement_t *parse_local_label_declaration(void) entity_t *end = NULL; entity_t **anchor = &begin; do { - if (token.type != 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.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.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; @@ -9912,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; @@ -9928,8 +9730,8 @@ static void parse_namespace_definition(void) entity_t *entity = NULL; symbol_t *symbol = NULL; - if (token.type == T_IDENTIFIER) { - symbol = token.symbol; + if (token.kind == T_IDENTIFIER) { + symbol = token.identifier.symbol; next_token(); entity = get_entity(symbol, NAMESPACE_NORMAL); @@ -9937,7 +9739,7 @@ static void parse_namespace_definition(void) && entity->kind != ENTITY_NAMESPACE && entity->base.parent_scope == current_scope) { if (is_entity_valid(entity)) { - error_redefined_as_different_kind(&token.source_position, + error_redefined_as_different_kind(&token.base.source_position, entity, ENTITY_NAMESPACE); } entity = NULL; @@ -9945,12 +9747,11 @@ static void parse_namespace_definition(void) } if (entity == NULL) { - entity = allocate_entity_zero(ENTITY_NAMESPACE, NAMESPACE_NORMAL, symbol); - entity->base.source_position = token.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.type == '=') { + if (token.kind == '=') { /* TODO: parse namespace alias */ panic("namespace alias definition not supported yet"); } @@ -9959,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(); } @@ -9980,16 +9779,14 @@ end_error: */ static statement_t *intern_parse_statement(void) { - statement_t *statement = NULL; - /* declaration or statement */ - add_anchor_token(';'); - switch (token.type) { + statement_t *statement; + switch (token.kind) { case T_IDENTIFIER: { - token_type_t la1_type = (token_type_t)look_ahead(1)->type; + token_kind_t la1_type = (token_kind_t)look_ahead(1)->kind; if (la1_type == ':') { statement = parse_label_statement(); - } else if (is_typedef_symbol(token.symbol)) { + } else if (is_typedef_symbol(token.identifier.symbol)) { statement = parse_declaration_statement(); } else { /* it's an identifier, the grammar says this must be an @@ -9999,7 +9796,7 @@ static statement_t *intern_parse_statement(void) switch (la1_type) { case '&': case '*': - if (get_entity(token.symbol, NAMESPACE_NORMAL) != NULL) { + if (get_entity(token.identifier.symbol, NAMESPACE_NORMAL) != NULL) { default: statement = parse_expression_statement(); } else { @@ -10053,15 +9850,10 @@ static statement_t *intern_parse_statement(void) default: errorf(HERE, "unexpected token %K while parsing statement", &token); - statement = create_invalid_statement(); - if (!at_anchor()) - next_token(); + statement = create_error_statement(); + eat_until_anchor(); break; } - rem_anchor_token(';'); - - assert(statement != NULL - && statement->base.source_position.input_name != NULL); return statement; } @@ -10106,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); @@ -10189,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.type != '}') { - if (token.type == 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 (is_invalid_statement(sub_statement)) { - /* an error occurred. if we are at an anchor, return */ - if (at_anchor()) - goto end_error; - continue; + if (sub_statement->kind == STATEMENT_ERROR) { + break; } if (sub_statement->kind != STATEMENT_DECLARATION) { @@ -10211,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)) { @@ -10237,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); @@ -10318,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('*'); @@ -10374,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) @@ -10395,33 +10180,32 @@ static void parse_linkage_specification(void) linkage_kind_t old_linkage = current_linkage; linkage_kind_t new_linkage; - if (strcmp(linkage, "C") == 0) { + if (streq(linkage, "C")) { new_linkage = LINKAGE_C; - } else if (strcmp(linkage, "C++") == 0) { + } else if (streq(linkage, "C++")) { new_linkage = LINKAGE_CXX; } else { errorf(&pos, "linkage string \"%s\" not recognized", linkage); - new_linkage = LINKAGE_INVALID; + new_linkage = LINKAGE_C; } current_linkage = new_linkage; if (next_if('{')) { parse_externals(); - expect('}', end_error); + expect('}'); } else { parse_external(); } -end_error: assert(current_linkage == new_linkage); current_linkage = old_linkage; } static void parse_external(void) { - switch (token.type) { + switch (token.kind) { case T_extern: - if (look_ahead(1)->type == T_STRING_LITERAL) { + if (look_ahead(1)->kind == T_STRING_LITERAL) { parse_linkage_specification(); } else { DECLARATION_START_NO_EXTERN @@ -10431,7 +10215,7 @@ static void parse_external(void) case '&': /* & x; -> int& x; (and error later, because C++ has no implicit int) */ case '*': /* * x; -> int* x; */ - case '(':; /* (x); -> int (x); */ + case '(': /* (x); -> int (x); */ PUSH_EXTENSION(); parse_external_declaration(); POP_EXTENSION(); @@ -10448,7 +10232,7 @@ static void parse_external(void) case ';': if (!strict_mode) { - warningf(WARN_OTHER, HERE, "stray ';' outside of function"); + warningf(WARN_STRAY_SEMICOLON, HERE, "stray ';' outside of function"); next_token(); return; } @@ -10456,8 +10240,8 @@ static void parse_external(void) default: errorf(HERE, "stray %K outside of function", &token); - if (token.type == '(' || token.type == '{' || token.type == '[') - eat_until_matching_token(token.type); + if (token.kind == '(' || token.kind == '{' || token.kind == '[') + eat_until_matching_token(token.kind); next_token(); return; } @@ -10470,14 +10254,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 != '}') { + while (token.kind != T_EOF && token.kind != '}') { #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); @@ -10506,12 +10290,12 @@ static void parse_translation_unit(void) while (true) { parse_externals(); - if (token.type == T_EOF) + if (token.kind == T_EOF) break; errorf(HERE, "stray %K outside of function", &token); - if (token.type == '(' || token.type == '{' || token.type == '[') - eat_until_matching_token(token.type); + if (token.kind == '(' || token.kind == '{' || token.kind == '[') + eat_until_matching_token(token.kind); next_token(); } } @@ -10593,8 +10377,10 @@ 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); + // create call to __main symbol_t *symbol = symbol_table_insert("__main"); entity_t *subsubmain_ent @@ -10621,6 +10407,8 @@ void prepare_main_collect2(entity_t *entity) expr_statement->base.next = compounds->statements; compounds->statements = expr_statement; + + POP_SCOPE(); } void parse(void)