X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=fa85c3c12549b48574bd7566100ea8032b5e7e11;hb=bafab880eb08fe9a867aae7e52fc290e09a915f2;hp=dab67a1b4b1a8f4b0d78b2c6fdeea161278db180;hpb=acd1bd5e2ef817b3c4dd5ad765bb54b7e33a715c;p=cparser diff --git a/parser.c b/parser.c index dab67a1..fa85c3c 100644 --- a/parser.c +++ b/parser.c @@ -105,15 +105,21 @@ typedef struct parse_initializer_env_t { typedef declaration_t* (*parsed_declaration_func) (declaration_t *declaration, bool is_definition); +/** The current token. */ static token_t token; +/** The lookahead ring-buffer. */ static token_t lookahead_buffer[MAX_LOOKAHEAD]; +/** Position of the next token in the lookahead buffer. */ static int lookahead_bufpos; static stack_entry_t *environment_stack = NULL; static stack_entry_t *label_stack = NULL; static stack_entry_t *local_label_stack = NULL; -static scope_t *global_scope = NULL; +/** The global file scope. */ +static scope_t *file_scope = NULL; +/** The current scope. */ static scope_t *scope = NULL; static declaration_t *last_declaration = NULL; +/** Point to the current function declaration if inside a function. */ static declaration_t *current_function = NULL; static declaration_t *current_init_decl = NULL; static switch_statement_t *current_switch = NULL; @@ -124,16 +130,25 @@ static goto_statement_t *goto_first = NULL; static goto_statement_t *goto_last = NULL; static label_statement_t *label_first = NULL; static label_statement_t *label_last = 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 in we are in a __extension__ context. */ +static bool in_gcc_extension = false; static struct obstack temp_obst; + #define PUSH_PARENT(stmt) \ statement_t *const prev_parent = current_parent; \ - current_parent = (stmt); + ((void)(current_parent = (stmt))) #define POP_PARENT ((void)(current_parent = prev_parent)) static source_position_t null_position = { NULL, 0 }; +/** special symbol used for anonymous entities. */ +static const symbol_t *sym_anonymous = NULL; + /* symbols for Microsoft extended-decl-modifier */ static const symbol_t *sym_align = NULL; static const symbol_t *sym_allocate = NULL; @@ -160,6 +175,9 @@ static unsigned char token_anchor_set[T_LAST_TOKEN]; /** The current source position. */ #define HERE (&token.source_position) +/** true if we are in GCC mode. */ +#define GNU_MODE ((c_mode & _GNUC) || in_gcc_extension) + static type_t *type_valist; static statement_t *parse_compound_statement(bool inside_expression_statement); @@ -338,8 +356,9 @@ static statement_t *allocate_statement_zero(statement_kind_t kind) size_t size = get_statement_struct_size(kind); statement_t *res = allocate_ast_zero(size); - res->base.kind = kind; - res->base.parent = current_parent; + res->base.kind = kind; + res->base.parent = current_parent; + res->base.source_position = token.source_position; return res; } @@ -372,9 +391,7 @@ static expression_t *create_invalid_expression(void) */ static statement_t *create_invalid_statement(void) { - statement_t *statement = allocate_statement_zero(STATEMENT_INVALID); - statement->base.source_position = token.source_position; - return statement; + return allocate_statement_zero(STATEMENT_INVALID); } /** @@ -382,9 +399,7 @@ static statement_t *create_invalid_statement(void) */ static statement_t *create_empty_statement(void) { - statement_t *statement = allocate_statement_zero(STATEMENT_EMPTY); - statement->base.source_position = token.source_position; - return statement; + return allocate_statement_zero(STATEMENT_EMPTY); } /** @@ -552,6 +567,7 @@ static void restore_anchor_state(int token_type, int count) 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]; } @@ -621,13 +637,9 @@ check_stop: */ static void eat_until_anchor(void) { - if (token.type == T_EOF) - return; while (token_anchor_set[token.type] == 0) { if (token.type == '(' || token.type == '{' || token.type == '[') eat_until_matching_token(token.type); - if (token.type == T_EOF) - break; next_token(); } } @@ -639,16 +651,6 @@ static void eat_block(void) next_token(); } -/** - * eat all token until a ';' is reached or a stop token is found. - */ -static void eat_statement(void) -{ - eat_until_matching_token(';'); - if (token.type == ';') - next_token(); -} - #define eat(token_type) do { assert(token.type == token_type); next_token(); } while (0) /** @@ -693,30 +695,39 @@ static void type_error_incompatible(const char *msg, * If not, generate an error, eat the current statement, * and goto the end_error label. */ -#define expect(expected) \ - do { \ - if (UNLIKELY(token.type != (expected))) { \ - parse_error_expected(NULL, (expected), NULL); \ - add_anchor_token(expected); \ - eat_until_anchor(); \ - if (token.type == expected) \ - next_token(); \ - rem_anchor_token(expected); \ - goto end_error; \ - } \ - next_token(); \ +#define expect(expected) \ + do { \ + if (UNLIKELY(token.type != (expected))) { \ + parse_error_expected(NULL, (expected), NULL); \ + add_anchor_token(expected); \ + eat_until_anchor(); \ + if (token.type == expected) \ + next_token(); \ + rem_anchor_token(expected); \ + goto end_error; \ + } \ + next_token(); \ } while (0) -static void set_scope(scope_t *new_scope) +static void scope_push(scope_t *new_scope) { if (scope != NULL) { scope->last_declaration = last_declaration; + new_scope->depth = scope->depth + 1; } - scope = new_scope; + new_scope->parent = scope; + scope = new_scope; last_declaration = new_scope->last_declaration; } +static void scope_pop(void) +{ + scope->last_declaration = last_declaration; + scope = scope->parent; + last_declaration = scope->last_declaration; +} + /** * Search a symbol in a given namespace and returns its declaration or * NULL if this symbol was not found. @@ -743,28 +754,20 @@ static void stack_push(stack_entry_t **stack_ptr, declaration_t *declaration) namespace_t namespc = (namespace_t) declaration->namespc; /* replace/add declaration into declaration list of the symbol */ - declaration_t *iter = symbol->declaration; - if (iter == NULL) { - symbol->declaration = declaration; - } else { - declaration_t *iter_last = NULL; - for( ; iter != NULL; iter_last = iter, iter = iter->symbol_next) { - /* replace an entry? */ - if (iter->namespc == namespc) { - if (iter_last == NULL) { - symbol->declaration = declaration; - } else { - iter_last->symbol_next = declaration; - } - declaration->symbol_next = iter->symbol_next; - break; - } - } - if (iter == NULL) { - assert(iter_last->symbol_next == NULL); - iter_last->symbol_next = declaration; + declaration_t **anchor; + declaration_t *iter; + for (anchor = &symbol->declaration;; anchor = &iter->symbol_next) { + iter = *anchor; + if (iter == NULL) + break; + + /* replace an entry? */ + if (iter->namespc == namespc) { + declaration->symbol_next = iter->symbol_next; + break; } } + *anchor = declaration; /* remember old declaration */ stack_entry_t entry; @@ -829,29 +832,23 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top) namespace_t namespc = (namespace_t)entry->namespc; /* replace/remove declaration */ - declaration_t *declaration = symbol->declaration; - assert(declaration != NULL); - if (declaration->namespc == namespc) { - if (old_declaration == NULL) { - symbol->declaration = declaration->symbol_next; - } else { - symbol->declaration = old_declaration; - } - } else { - declaration_t *iter_last = declaration; - declaration_t *iter = declaration->symbol_next; - for( ; iter != NULL; iter_last = iter, iter = iter->symbol_next) { - /* replace an entry? */ - if (iter->namespc == namespc) { - assert(iter_last != NULL); - iter_last->symbol_next = old_declaration; - if (old_declaration != NULL) { - old_declaration->symbol_next = iter->symbol_next; - } - break; - } - } + declaration_t **anchor; + declaration_t *iter; + for (anchor = &symbol->declaration;; anchor = &iter->symbol_next) { + iter = *anchor; assert(iter != NULL); + /* replace an entry? */ + if (iter->namespc == namespc) + break; + } + + /* Not all declarations adhere scopes (e.g. jump labels), so this + * correction is necessary */ + if (old_declaration != NULL) { + old_declaration->symbol_next = iter->symbol_next; + *anchor = old_declaration; + } else { + *anchor = iter->symbol_next; } } @@ -1030,7 +1027,7 @@ static void report_assign_error(assign_error_t error, type_t *orig_type_left, case ASSIGN_WARNING_POINTER_FROM_INT: warningf(source_position, - "%s makes integer '%T' from pointer '%T' without a cast", + "%s makes pointer '%T' from integer '%T' without a cast", context, orig_type_left, orig_type_right); return; @@ -1497,12 +1494,12 @@ static void parse_gnu_attribute_format_args(gnu_attribute_t *attribute) add_anchor_token(','); parse_constant_expression(); rem_anchor_token(','); - rem_anchor_token('('); + rem_anchor_token(')'); expect(','); add_anchor_token(')'); parse_constant_expression(); - rem_anchor_token('('); + rem_anchor_token(')'); expect(')'); return; end_error: @@ -1665,7 +1662,6 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes) } switch(kind) { - case GNU_AK_CONST: case GNU_AK_VOLATILE: case GNU_AK_NAKED: case GNU_AK_MALLOC: @@ -1705,6 +1701,7 @@ static decl_modifiers_t parse_gnu_attribute(gnu_attribute_t **attributes) case GNU_AK_UNUSED: modifiers |= DM_UNUSED; goto no_arg; case GNU_AK_USED: modifiers |= DM_USED; goto no_arg; case GNU_AK_PURE: modifiers |= DM_PURE; goto no_arg; + case GNU_AK_CONST: modifiers |= DM_CONST; goto no_arg; case GNU_AK_ALWAYS_INLINE: modifiers |= DM_FORCEINLINE; goto no_arg; case GNU_AK_DLLIMPORT: modifiers |= DM_DLLIMPORT; goto no_arg; case GNU_AK_DLLEXPORT: modifiers |= DM_DLLEXPORT; goto no_arg; @@ -1994,6 +1991,11 @@ static initializer_t *initializer_from_expression(type_t *orig_type, &expression->base.source_position); initializer_t *const result = allocate_initializer_zero(INITIALIZER_VALUE); +#if 0 + if (type->kind == TYPE_BITFIELD) { + type = type->bitfield.base_type; + } +#endif result->value.value = create_implicit_cast(expression, type); return result; @@ -2148,8 +2150,6 @@ static void descend_into_subtype(type_path_t *path) type_t *orig_top_type = path->top_type; type_t *top_type = skip_typeref(orig_top_type); - assert(is_type_compound(top_type) || is_type_array(top_type)); - type_path_entry_t *top = append_to_type_path(path); top->type = top_type; @@ -2163,11 +2163,11 @@ static void descend_into_subtype(type_path_t *path) } else { path->top_type = NULL; } - } else { - assert(is_type_array(top_type)); - + } else if (is_type_array(top_type)) { top->v.index = 0; path->top_type = top_type->array.element_type; + } else { + assert(!is_type_valid(top_type)); } } @@ -2216,34 +2216,37 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, "'.%Y' designator used for non-compound type '%T'", symbol, orig_type); } - goto failed; - } - declaration_t *declaration = type->compound.declaration; - declaration_t *iter = declaration->scope.declarations; - for( ; iter != NULL; iter = iter->next) { - if (iter->symbol == symbol) { - break; + top->type = type_error_type; + top->v.compound_entry = NULL; + orig_type = type_error_type; + } else { + declaration_t *declaration = type->compound.declaration; + declaration_t *iter = declaration->scope.declarations; + for( ; iter != NULL; iter = iter->next) { + if (iter->symbol == symbol) { + break; + } } - } - if (iter == NULL) { - errorf(&designator->source_position, - "'%T' has no member named '%Y'", orig_type, symbol); - goto failed; - } - if (used_in_offsetof) { - type_t *real_type = skip_typeref(iter->type); - if (real_type->kind == TYPE_BITFIELD) { + if (iter == NULL) { errorf(&designator->source_position, - "offsetof designator '%Y' may not specify bitfield", - symbol); + "'%T' has no member named '%Y'", orig_type, symbol); goto failed; } - } + if (used_in_offsetof) { + type_t *real_type = skip_typeref(iter->type); + if (real_type->kind == TYPE_BITFIELD) { + errorf(&designator->source_position, + "offsetof designator '%Y' may not specify bitfield", + symbol); + goto failed; + } + } - top->type = orig_type; - top->v.compound_entry = iter; - orig_type = iter->type; + top->type = orig_type; + top->v.compound_entry = iter; + orig_type = iter->type; + } } else { expression_t *array_index = designator->array_index; assert(designator->array_index != NULL); @@ -2256,24 +2259,18 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, } goto failed; } - if (!is_type_valid(array_index->base.type)) { - goto failed; - } long index = fold_constant(array_index); if (!used_in_offsetof) { if (index < 0) { errorf(&designator->source_position, "array index [%E] must be positive", array_index); - goto failed; - } - if (type->array.size_constant == true) { + } else if (type->array.size_constant) { long array_size = type->array.size; if (index >= array_size) { errorf(&designator->source_position, "designator [%E] (%d) exceeds array size %d", array_index, index, array_size); - goto failed; } } } @@ -2311,7 +2308,7 @@ static void advance_current_object(type_path_t *path, size_t top_path_level) path->top_type = entry->type; return; } - } else { + } else if (is_type_array(type)) { assert(is_type_array(type)); top->v.index++; @@ -2319,6 +2316,9 @@ static void advance_current_object(type_path_t *path, size_t top_path_level) if (!type->array.size_constant || top->v.index < type->array.size) { return; } + } else { + assert(!is_type_valid(type)); + return; } /* we're past the last member of the current sub-aggregate, try if we @@ -2390,13 +2390,6 @@ static initializer_t *parse_sub_initializer(type_path_t *path, /* We are initializing an empty compound. */ } else { type = skip_typeref(orig_type); - - /* we can't do usefull stuff if we didn't even parse the type. Skip the - * initializers in this case. */ - if (!is_type_valid(type)) { - skip_initializers(); - return create_empty_initializer(); - } } initializer_t **initializers = NEW_ARR_F(initializer_t*, 0); @@ -2473,6 +2466,11 @@ finish_designator: if (type == NULL) { /* we are already outside, ... */ + type_t *const outer_type_skip = skip_typeref(outer_type); + if (is_type_compound(outer_type_skip) && + !outer_type_skip->compound.declaration->init.complete) { + goto error_parse_next; + } goto error_excess; } @@ -2857,16 +2855,16 @@ static type_t *parse_typeof(void) expression_t *expression = NULL; -restart: - switch(token.type) { - case T___extension__: - /* This can be a prefix to a typename or an expression. We simply eat - * it now. */ - do { - next_token(); - } while (token.type == T___extension__); - goto restart; + bool old_type_prop = in_type_prop; + bool old_gcc_extension = in_gcc_extension; + in_type_prop = true; + while (token.type == T___extension__) { + /* This can be a prefix to a typename or an expression. */ + next_token(); + in_gcc_extension = true; + } + switch (token.type) { case T_IDENTIFIER: if (is_typedef_symbol(token.v.symbol)) { type = parse_typename(); @@ -2885,6 +2883,8 @@ restart: type = expression->base.type; break; } + in_type_prop = old_type_prop; + in_gcc_extension = old_gcc_extension; rem_anchor_token(')'); expect(')'); @@ -2957,7 +2957,7 @@ static bool check_alignment_value(long long intvalue) return false; } unsigned v = (unsigned)intvalue; - for(unsigned i = 1; i <= 8192; i += i) { + for (unsigned i = 1; i <= 8192; i += i) { if (i == v) return true; } @@ -3028,7 +3028,7 @@ static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *spe } else if (symbol == sym_property) { next_token(); expect('('); - for(;;) { + for (;;) { bool is_get = false; if (token.type != T_IDENTIFIER) goto end_error; @@ -3112,7 +3112,7 @@ static declaration_t *create_error_declaration(symbol_t *symbol, storage_class_t decl->source_position = *HERE; decl->declared_storage_class = storage_class; decl->storage_class = - storage_class != STORAGE_CLASS_NONE || scope == global_scope ? + storage_class != STORAGE_CLASS_NONE || scope == file_scope ? storage_class : STORAGE_CLASS_AUTO; decl->symbol = symbol; decl->implicit = true; @@ -3131,33 +3131,38 @@ static void finish_struct_type(compound_type_t *type) { if (! struct_decl->init.complete) return; - il_size_t size = 0; - il_size_t new_size; - il_alignment_t alignment = 1; - bool need_pad = false; + il_size_t size = 0; + il_size_t offset; + il_alignment_t alignment = 1; + bool need_pad = false; declaration_t *entry = struct_decl->scope.declarations; for (; entry != NULL; entry = entry->next) { if (entry->namespc != NAMESPACE_NORMAL) continue; - type_t *m_type = skip_typeref(entry->type); - il_alignment_t m_alignment = m_type->base.alignment; - - new_size = (size + m_alignment - 1) & -m_alignment; + type_t *m_type = skip_typeref(entry->type); + if (! is_type_valid(m_type)) { + /* simply ignore errors here */ + continue; + } + il_alignment_t m_alignment = m_type->base.alignment; if (m_alignment > alignment) alignment = m_alignment; - if (new_size > size) + + offset = (size + m_alignment - 1) & -m_alignment; + + if (offset > size) need_pad = true; - entry->offset = new_size; - size = new_size + m_type->base.size; + entry->offset = offset; + size = offset + m_type->base.size; } if (type->base.alignment != 0) { alignment = type->base.alignment; } - new_size = (size + alignment - 1) & -alignment; - if (new_size > size) + offset = (size + alignment - 1) & -alignment; + if (offset > size) need_pad = true; if (warning.padded && need_pad) { @@ -3170,7 +3175,7 @@ static void finish_struct_type(compound_type_t *type) { type, struct_decl->symbol); } - type->base.size = new_size; + type->base.size = offset; type->base.alignment = alignment; } @@ -3194,6 +3199,8 @@ static void finish_union_type(compound_type_t *type) { continue; type_t *m_type = skip_typeref(entry->type); + if (! is_type_valid(m_type)) + continue; entry->offset = 0; if (m_type->base.size > size) @@ -3211,12 +3218,13 @@ static void finish_union_type(compound_type_t *type) { static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) { - type_t *type = NULL; - type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE; - type_modifiers_t modifiers = TYPE_MODIFIER_NONE; - unsigned type_specifiers = 0; - bool newtype = false; - bool saw_error = false; + type_t *type = NULL; + type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE; + type_modifiers_t modifiers = TYPE_MODIFIER_NONE; + unsigned type_specifiers = 0; + bool newtype = false; + bool saw_error = false; + bool old_gcc_extension = in_gcc_extension; specifiers->source_position = token.source_position; @@ -3226,7 +3234,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) if (specifiers->modifiers & DM_TRANSPARENT_UNION) modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION; - switch(token.type) { + switch (token.type) { /* storage class */ #define MATCH_STORAGE_CLASS(token, class) \ @@ -3291,8 +3299,8 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) MATCH_TYPE_QUALIFIER(T___sptr, TYPE_QUALIFIER_SPTR); case T___extension__: - /* TODO */ next_token(); + in_gcc_extension = true; break; /* type specifiers */ @@ -3356,8 +3364,8 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) type->compound.declaration = parse_compound_type_specifier(false); if (type->compound.declaration->modifiers & DM_TRANSPARENT_UNION) modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION; - break; finish_union_type(&type->compound); + break; } case T_enum: type = parse_enum_specifier(); @@ -3437,6 +3445,8 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) } finish_specifiers: + in_gcc_extension = old_gcc_extension; + if (type == NULL || (saw_error && type_specifiers != 0)) { atomic_type_kind_t atomic_type; @@ -3575,10 +3585,8 @@ warn_about_long_long: default: /* invalid specifier combination, give an error message */ if (type_specifiers == 0) { - if (saw_error) { - specifiers->type = type_error_type; - return; - } + if (saw_error) + goto end_error; if (!strict_mode) { if (warning.implicit_int) { @@ -3597,15 +3605,13 @@ warn_about_long_long: } else { errorf(HERE, "multiple datatypes in declaration"); } - atomic_type = ATOMIC_TYPE_INVALID; + goto end_error; } - if (type_specifiers & SPECIFIER_COMPLEX && - atomic_type != ATOMIC_TYPE_INVALID) { + if (type_specifiers & SPECIFIER_COMPLEX) { type = allocate_type_zero(TYPE_COMPLEX, &builtin_source_position); type->complex.akind = atomic_type; - } else if (type_specifiers & SPECIFIER_IMAGINARY && - atomic_type != ATOMIC_TYPE_INVALID) { + } else if (type_specifiers & SPECIFIER_IMAGINARY) { type = allocate_type_zero(TYPE_IMAGINARY, &builtin_source_position); type->imaginary.akind = atomic_type; } else { @@ -3628,7 +3634,10 @@ warn_about_long_long: } specifiers->type = result; + return; + end_error: + specifiers->type = type_error_type; return; } @@ -3655,7 +3664,13 @@ static type_qualifiers_t parse_type_qualifiers(void) } } -static declaration_t *parse_identifier_list(void) +/** + * Parses an K&R identifier list and return a list of declarations. + * + * @param last points to the last declaration in the list + * @return the list of declarations + */ +static declaration_t *parse_identifier_list(declaration_t **last) { declaration_t *declarations = NULL; declaration_t *last_declaration = NULL; @@ -3679,6 +3694,7 @@ static declaration_t *parse_identifier_list(void) next_token(); } while (token.type == T_IDENTIFIER); + *last = last_declaration; return declarations; } @@ -3731,7 +3747,13 @@ static declaration_t *parse_parameter(void) return declaration; } -static declaration_t *parse_parameters(function_type_t *type) +/** + * Parses a function type parameter list and return a list of declarations. + * + * @param last point to the last element of the list + * @return the parameter list + */ +static declaration_t *parse_parameters(function_type_t *type, declaration_t **last) { declaration_t *declarations = NULL; @@ -3744,7 +3766,7 @@ static declaration_t *parse_parameters(function_type_t *type) token_type_t la1_type = (token_type_t)look_ahead(1)->type; if (la1_type == ',' || la1_type == ')') { type->kr_style_parameters = true; - declarations = parse_identifier_list(); + declarations = parse_identifier_list(last); goto parameters_finished; } } @@ -3810,10 +3832,12 @@ parameters_finished: expect(')'); restore_anchor_state(',', saved_comma_state); + *last = last_declaration; return declarations; end_error: restore_anchor_state(',', saved_comma_state); + *last = NULL; return NULL; } @@ -3902,9 +3926,8 @@ static construct_type_t *parse_array_declarator(void) rem_anchor_token(']'); expect(']'); - return (construct_type_t*) array; end_error: - return NULL; + return (construct_type_t*) array; } static construct_type_t *parse_function_declarator(declaration_t *declaration) @@ -3950,9 +3973,12 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration) type = allocate_type_zero(TYPE_FUNCTION, HERE); } - declaration_t *parameters = parse_parameters(&type->function); + declaration_t *last; + declaration_t *parameters = parse_parameters(&type->function, &last); if (declaration != NULL) { - declaration->scope.declarations = parameters; + declaration->scope.declarations = parameters; + declaration->scope.last_declaration = last; + declaration->scope.is_parameter = true; } construct_function_type_t *construct_function_type = @@ -4043,13 +4069,7 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration, if (may_be_abstract) break; parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL); - /* avoid a loop in the outermost scope, because eat_statement doesn't - * eat '}' */ - if (token.type == '}' && current_function == NULL) { - next_token(); - } else { - eat_statement(); - } + eat_until_anchor(); return NULL; } @@ -4148,15 +4168,19 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, function_type->function.return_type = type; type_t *skipped_return_type = skip_typeref(type); + /* §6.7.5.3(1) */ if (is_type_function(skipped_return_type)) { errorf(HERE, "function returning function is not allowed"); - type = type_error_type; } else if (is_type_array(skipped_return_type)) { errorf(HERE, "function returning array is not allowed"); - type = type_error_type; } else { - type = function_type; + if (skipped_return_type->base.qualifiers != 0) { + warningf(HERE, + "type qualifiers in return type of function type are meaningless"); + } } + + type = function_type; break; } @@ -4197,12 +4221,13 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, } type_t *skipped_type = skip_typeref(type); - if (is_type_atomic(skipped_type, ATOMIC_TYPE_VOID)) { - errorf(HERE, "array of void is not allowed"); - type = type_error_type; - } else { - type = array_type; + /* §6.7.5.2(1) */ + if (is_type_incomplete(skipped_type)) { + errorf(HERE, "array of incomplete type '%T' is not allowed", type); + } else if (is_type_function(skipped_type)) { + errorf(HERE, "array of functions is not allowed"); } + type = array_type; break; } } @@ -4234,8 +4259,8 @@ static declaration_t *parse_declarator( declaration->is_inline = specifiers->is_inline; declaration->storage_class = specifiers->declared_storage_class; - if (declaration->storage_class == STORAGE_CLASS_NONE - && scope != global_scope) { + if (declaration->storage_class == STORAGE_CLASS_NONE && + scope != file_scope) { declaration->storage_class = STORAGE_CLASS_AUTO; } @@ -4299,7 +4324,7 @@ static void check_type_of_main(const declaration_t *const decl, const function_t warningf(&decl->source_position, "'main' is normally a non-static function"); } - if (skip_typeref(func_type->return_type) != type_int) { + if (!types_compatible(skip_typeref(func_type->return_type), type_int)) { warningf(&decl->source_position, "return type of 'main' should be 'int', but is '%T'", func_type->return_type); @@ -4362,7 +4387,7 @@ static declaration_t *record_declaration( previous_declaration == NULL) { warningf(&declaration->source_position, "function declaration '%#T' is not a prototype", - orig_type, declaration->symbol); + orig_type, symbol); } if (warning.main && is_type_function(type) && is_sym_main(symbol)) { @@ -4371,14 +4396,23 @@ static declaration_t *record_declaration( if (warning.nested_externs && declaration->storage_class == STORAGE_CLASS_EXTERN && - scope != global_scope) { + scope != file_scope) { warningf(&declaration->source_position, "nested extern declaration of '%#T'", declaration->type, symbol); } assert(declaration != previous_declaration); - if (previous_declaration != NULL - && previous_declaration->parent_scope == scope) { + if (previous_declaration != NULL && + previous_declaration->parent_scope->is_parameter && + scope->depth == previous_declaration->parent_scope->depth + 1) { + errorf(&declaration->source_position, + "declaration '%#T' redeclares the parameter '%#T' (declared %P)", + orig_type, symbol, previous_declaration->type, symbol, + &previous_declaration->source_position); + goto finish; + } + if (previous_declaration != NULL && + previous_declaration->parent_scope == scope) { /* can happen for K&R style declarations */ if (previous_declaration->type == NULL) { previous_declaration->type = declaration->type; @@ -4452,8 +4486,9 @@ static declaration_t *record_declaration( if (old_storage_class == STORAGE_CLASS_EXTERN && new_storage_class == STORAGE_CLASS_EXTERN) { warn_redundant_declaration: - if (!is_definition && - warning.redundant_decls && + if (!is_definition && + warning.redundant_decls && + is_type_valid(prev_type) && strcmp(previous_declaration->source_position.input_name, "") != 0) { warningf(&declaration->source_position, "redundant declaration for '%Y' (declared %P)", @@ -4471,14 +4506,16 @@ warn_redundant_declaration: } else { goto warn_redundant_declaration; } - } else if (old_storage_class == new_storage_class) { - errorf(&declaration->source_position, - "redeclaration of '%Y' (declared %P)", - symbol, &previous_declaration->source_position); - } else { - errorf(&declaration->source_position, - "redeclaration of '%Y' with different linkage (declared %P)", - symbol, &previous_declaration->source_position); + } else if (is_type_valid(prev_type)) { + if (old_storage_class == new_storage_class) { + errorf(&declaration->source_position, + "redeclaration of '%Y' (declared %P)", + symbol, &previous_declaration->source_position); + } else { + errorf(&declaration->source_position, + "redeclaration of '%Y' with different linkage (declared %P)", + symbol, &previous_declaration->source_position); + } } } @@ -4499,7 +4536,7 @@ warn_redundant_declaration: } } else { if (warning.missing_declarations && - scope == global_scope && ( + scope == file_scope && ( declaration->storage_class == STORAGE_CLASS_NONE || declaration->storage_class == STORAGE_CLASS_THREAD )) { @@ -4507,7 +4544,7 @@ warn_redundant_declaration: "no previous declaration for '%#T'", orig_type, symbol); } } - +finish: assert(declaration->parent_scope == NULL); assert(scope != NULL); @@ -4527,7 +4564,7 @@ static void parser_error_multiple_definition(declaration_t *declaration, static bool is_declaration_specifier(const token_t *token, bool only_specifiers_qualifiers) { - switch(token->type) { + switch (token->type) { TYPE_SPECIFIERS TYPE_QUALIFIERS return true; @@ -4555,9 +4592,9 @@ static void parse_init_declarator_rest(declaration_t *declaration) } bool must_be_constant = false; - if (declaration->storage_class == STORAGE_CLASS_STATIC - || declaration->storage_class == STORAGE_CLASS_THREAD_STATIC - || declaration->parent_scope == global_scope) { + if (declaration->storage_class == STORAGE_CLASS_STATIC || + declaration->storage_class == STORAGE_CLASS_THREAD_STATIC || + declaration->parent_scope == file_scope) { must_be_constant = true; } @@ -4590,24 +4627,17 @@ static void parse_anonymous_declaration_rest( { eat(';'); - declaration_t *const declaration = allocate_declaration_zero(); - declaration->type = specifiers->type; - declaration->declared_storage_class = specifiers->declared_storage_class; - declaration->source_position = specifiers->source_position; - declaration->modifiers = specifiers->modifiers; - - if (declaration->declared_storage_class != STORAGE_CLASS_NONE) { - warningf(&declaration->source_position, + if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) { + warningf(&specifiers->source_position, "useless storage class in empty declaration"); } - declaration->storage_class = STORAGE_CLASS_NONE; - type_t *type = declaration->type; + type_t *type = specifiers->type; switch (type->kind) { case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: { if (type->compound.declaration->symbol == NULL) { - warningf(&declaration->source_position, + warningf(&specifiers->source_position, "unnamed struct/union that defines no instances"); } break; @@ -4617,11 +4647,20 @@ static void parse_anonymous_declaration_rest( break; default: - warningf(&declaration->source_position, "empty declaration"); + warningf(&specifiers->source_position, "empty declaration"); break; } +#ifdef RECORD_EMPTY_DECLARATIONS + declaration_t *const declaration = allocate_declaration_zero(); + declaration->type = specifiers->type; + declaration->declared_storage_class = specifiers->declared_storage_class; + declaration->source_position = specifiers->source_position; + declaration->modifiers = specifiers->modifiers; + declaration->storage_class = STORAGE_CLASS_NONE; + append_declaration(declaration); +#endif } static void parse_declaration_rest(declaration_t *ndeclaration, @@ -4629,7 +4668,6 @@ static void parse_declaration_rest(declaration_t *ndeclaration, parsed_declaration_func finished_declaration) { add_anchor_token(';'); - add_anchor_token('='); add_anchor_token(','); while(true) { declaration_t *declaration = @@ -4653,13 +4691,14 @@ static void parse_declaration_rest(declaration_t *ndeclaration, break; eat(','); + add_anchor_token('='); ndeclaration = parse_declarator(specifiers, /*may_be_abstract=*/false); + rem_anchor_token('='); } expect(';'); end_error: rem_anchor_token(';'); - rem_anchor_token('='); rem_anchor_token(','); } @@ -4702,7 +4741,10 @@ static void parse_declaration(parsed_declaration_func finished_declaration) { declaration_specifiers_t specifiers; memset(&specifiers, 0, sizeof(specifiers)); + + add_anchor_token(';'); parse_declaration_specifiers(&specifiers); + rem_anchor_token(';'); if (token.type == ';') { parse_anonymous_declaration_rest(&specifiers); @@ -4735,10 +4777,11 @@ static void parse_kr_declaration_list(declaration_t *declaration) if (!type->function.kr_style_parameters) return; + add_anchor_token('{'); + /* push function parameters */ - int top = environment_top(); - scope_t *last_scope = scope; - set_scope(&declaration->scope); + size_t const top = environment_top(); + scope_push(&declaration->scope); declaration_t *parameter = declaration->scope.declarations; for ( ; parameter != NULL; parameter = parameter->next) { @@ -4754,7 +4797,7 @@ static void parse_kr_declaration_list(declaration_t *declaration) /* pop function parameters */ assert(scope == &declaration->scope); - set_scope(last_scope); + scope_pop(); environment_pop_to(top); /* update function type */ @@ -4813,6 +4856,8 @@ static void parse_kr_declaration_list(declaration_t *declaration) } declaration->type = type; + + rem_anchor_token('{'); } static bool first_err = true; @@ -5372,14 +5417,16 @@ static void parse_external_declaration(void) add_anchor_token(','); add_anchor_token('='); - rem_anchor_token(';'); + add_anchor_token(';'); + add_anchor_token('{'); /* declarator is common to both function-definitions and declarations */ declaration_t *ndeclaration = parse_declarator(&specifiers, /*may_be_abstract=*/false); - rem_anchor_token(','); - rem_anchor_token('='); + rem_anchor_token('{'); rem_anchor_token(';'); + rem_anchor_token('='); + rem_anchor_token(','); /* must be a declaration */ switch (token.type) { @@ -5448,9 +5495,8 @@ static void parse_external_declaration(void) type = skip_typeref(declaration->type); /* push function parameters and switch scope */ - int top = environment_top(); - scope_t *last_scope = scope; - set_scope(&declaration->scope); + size_t const top = environment_top(); + scope_push(&declaration->scope); declaration_t *parameter = declaration->scope.declarations; for( ; parameter != NULL; parameter = parameter->next) { @@ -5505,17 +5551,45 @@ static void parse_external_declaration(void) } assert(scope == &declaration->scope); - set_scope(last_scope); + scope_pop(); environment_pop_to(top); } static type_t *make_bitfield_type(type_t *base_type, expression_t *size, - source_position_t *source_position) + source_position_t *source_position, + const symbol_t *symbol) { type_t *type = allocate_type_zero(TYPE_BITFIELD, source_position); - type->bitfield.base_type = base_type; - type->bitfield.size = size; + 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(HERE, "bitfield base type '%T' is not an integer type", + base_type); + bit_size = 0; + } else { + bit_size = skipped_type->base.size * 8; + } + + if (is_constant_expression(size)) { + long v = fold_constant(size); + + if (v < 0) { + errorf(source_position, "negative width in bit-field '%Y'", + symbol); + } else if (v == 0) { + errorf(source_position, "zero width for bit-field '%Y'", + symbol); + } else if (bit_size > 0 && (il_size_t)v > bit_size) { + errorf(source_position, "width of '%Y' exceeds its type", + symbol); + } else { + type->bitfield.bit_size = v; + } + } return type; } @@ -5567,12 +5641,8 @@ static void parse_compound_declarators(declaration_t *struct_declaration, type_t *base_type = specifiers->type; expression_t *size = parse_constant_expression(); - if (!is_type_integer(skip_typeref(base_type))) { - errorf(HERE, "bitfield base type '%T' is not an integer type", - base_type); - } - - type_t *type = make_bitfield_type(base_type, size, &source_position); + type_t *type = make_bitfield_type(base_type, size, + &source_position, sym_anonymous); declaration = allocate_declaration_zero(); declaration->namespc = NAMESPACE_NORMAL; @@ -5592,12 +5662,8 @@ static void parse_compound_declarators(declaration_t *struct_declaration, next_token(); expression_t *size = parse_constant_expression(); - if (!is_type_integer(type)) { - errorf(HERE, "bitfield base type '%T' is not an integer type", - orig_type); - } - - type_t *bitfield_type = make_bitfield_type(orig_type, size, &source_position); + type_t *bitfield_type = make_bitfield_type(orig_type, size, + &source_position, declaration->symbol); declaration->type = bitfield_type; } else { /* TODO we ignore arrays for now... what is missing is a check @@ -5650,7 +5716,11 @@ static void parse_compound_type_entries(declaration_t *compound_declaration) eat('{'); add_anchor_token('}'); - while (token.type != '}' && token.type != T_EOF) { + while (token.type != '}') { + if (token.type == T_EOF) { + errorf(HERE, "EOF while parsing struct"); + break; + } declaration_specifiers_t specifiers; memset(&specifiers, 0, sizeof(specifiers)); parse_declaration_specifiers(&specifiers); @@ -5658,10 +5728,6 @@ static void parse_compound_type_entries(declaration_t *compound_declaration) parse_compound_declarators(compound_declaration, &specifiers); } rem_anchor_token('}'); - - if (token.type == T_EOF) { - errorf(HERE, "EOF while parsing struct"); - } next_token(); } @@ -5790,8 +5856,7 @@ static expression_t *parse_character_constant(void) cnst->conste.v.character = token.v.string; if (cnst->conste.v.character.size != 1) { - if (warning.multichar && (c_mode & _GNUC)) { - /* TODO */ + if (warning.multichar && GNU_MODE) { warningf(HERE, "multi-character character constant"); } else { errorf(HERE, "more than 1 characters in character constant"); @@ -5814,8 +5879,7 @@ static expression_t *parse_wide_character_constant(void) cnst->conste.v.wide_character = token.v.wide_string; if (cnst->conste.v.wide_character.size != 1) { - if (warning.multichar && (c_mode & _GNUC)) { - /* TODO */ + if (warning.multichar && GNU_MODE) { warningf(HERE, "multi-character character constant"); } else { errorf(HERE, "more than 1 characters in character constant"); @@ -5950,11 +6014,17 @@ static type_t *get_builtin_symbol_type(symbol_t *symbol) return make_function_1_type(type_void_ptr, type_size_t); case T___builtin_huge_val: return make_function_0_type(type_double); + case T___builtin_inf: + return make_function_0_type(type_double); + case T___builtin_inff: + return make_function_0_type(type_float); + case T___builtin_infl: + return make_function_0_type(type_long_double); case T___builtin_nan: return make_function_1_type(type_double, type_char_ptr); case T___builtin_nanf: return make_function_1_type(type_float, type_char_ptr); - case T___builtin_nand: + case T___builtin_nanl: return make_function_1_type(type_long_double, type_char_ptr); case T___builtin_va_end: return make_function_1_type(type_void, type_valist); @@ -6048,32 +6118,26 @@ static expression_t *parse_reference(void) declaration_t *declaration = get_declaration(symbol, NAMESPACE_NORMAL); - source_position_t source_position = token.source_position; - next_token(); - if (declaration == NULL) { - if (token.type == '(') { + if (!strict_mode && look_ahead(1)->type == '(') { /* an implicitly declared function */ - if (strict_mode) { - errorf(HERE, "unknown symbol '%Y' found.", symbol); - } else if (warning.implicit_function_declaration) { + if (warning.implicit_function_declaration) { warningf(HERE, "implicit declaration of function '%Y'", symbol); } - declaration = create_implicit_function(symbol, - &source_position); + declaration = create_implicit_function(symbol, HERE); } else { errorf(HERE, "unknown symbol '%Y' found.", symbol); declaration = create_error_declaration(symbol, STORAGE_CLASS_NONE); } } - type_t *type = declaration->type; + type_t *orig_type = declaration->type; /* we always do the auto-type conversions; the & and sizeof parser contains * code to revert this! */ - type = automatic_type_conversion(type); + type_t *type = automatic_type_conversion(orig_type); ref->declaration = declaration; ref->base.type = type; @@ -6081,6 +6145,15 @@ static expression_t *parse_reference(void) /* this declaration is used */ declaration->used = true; + if (declaration->parent_scope != file_scope && + declaration->parent_scope->depth < current_function->scope.depth && + is_type_valid(orig_type) && !is_type_function(orig_type)) { + /* access of a variable from an outer function */ + declaration->address_taken = true; + ref->is_outer_ref = true; + current_function->need_closure = true; + } + /* check for deprecated functions */ if (warning.deprecated_declarations && declaration->modifiers & DM_DEPRECATED) { @@ -6088,23 +6161,21 @@ static expression_t *parse_reference(void) "function" : "variable"; if (declaration->deprecated_string != NULL) { - warningf(&source_position, - "%s '%Y' is deprecated (declared %P): \"%s\"", prefix, - declaration->symbol, &declaration->source_position, + warningf(HERE, "%s '%Y' is deprecated (declared %P): \"%s\"", + prefix, declaration->symbol, &declaration->source_position, declaration->deprecated_string); } else { - warningf(&source_position, - "%s '%Y' is deprecated (declared %P)", prefix, + warningf(HERE, "%s '%Y' is deprecated (declared %P)", prefix, declaration->symbol, &declaration->source_position); } } - if (warning.init_self && declaration == current_init_decl) { + if (warning.init_self && declaration == current_init_decl && !in_type_prop) { current_init_decl = NULL; - warningf(&source_position, - "variable '%#T' is initialized by itself", + warningf(HERE, "variable '%#T' is initialized by itself", declaration->type, declaration->symbol); } + next_token(); return expression; } @@ -6179,11 +6250,12 @@ static expression_t *parse_compound_literal(type_t *type) */ static expression_t *parse_cast(void) { + add_anchor_token(')'); + source_position_t source_position = token.source_position; type_t *type = parse_typename(); - /* matching add_anchor_token() is at call site */ rem_anchor_token(')'); expect(')'); @@ -6212,6 +6284,8 @@ end_error: */ static expression_t *parse_statement_expression(void) { + add_anchor_token(')'); + expression_t *expression = allocate_expression_zero(EXPR_STATEMENT); statement_t *statement = parse_compound_statement(true); @@ -6233,11 +6307,11 @@ static expression_t *parse_statement_expression(void) } expression->base.type = type; + rem_anchor_token(')'); expect(')'); - return expression; end_error: - return create_invalid_expression(); + return expression; } /** @@ -6246,7 +6320,6 @@ end_error: static expression_t *parse_parenthesized_expression(void) { eat('('); - add_anchor_token(')'); switch(token.type) { case '{': @@ -6262,13 +6335,13 @@ static expression_t *parse_parenthesized_expression(void) } } + add_anchor_token(')'); expression_t *result = parse_expression(); rem_anchor_token(')'); expect(')'); - return result; end_error: - return create_invalid_expression(); + return result; } static expression_t *parse_function_keyword(void) @@ -6445,17 +6518,15 @@ static expression_t *parse_va_start(void) expression_t *const expr = parse_assignment_expression(); if (expr->kind == EXPR_REFERENCE) { declaration_t *const decl = expr->reference.declaration; - if (decl == NULL) - return create_invalid_expression(); - if (decl->parent_scope == ¤t_function->scope && - decl->next == NULL) { - expression->va_starte.parameter = decl; - expect(')'); - return expression; + if (decl->parent_scope != ¤t_function->scope || decl->next != NULL) { + errorf(&expr->base.source_position, + "second argument of 'va_start' must be last parameter of the current function"); } + expression->va_starte.parameter = decl; + expect(')'); + return expression; } - errorf(&expr->base.source_position, - "second argument of 'va_start' must be last parameter of the current function"); + expect(')'); end_error: return create_invalid_expression(); } @@ -6574,7 +6645,6 @@ static expression_t *parse_compare_builtin(void) break; default: internal_errorf(HERE, "invalid compare builtin found"); - break; } expression->base.source_position = *HERE; next_token(); @@ -6664,7 +6734,10 @@ static declaration_t *get_label(symbol_t *symbol) candidate = get_declaration(symbol, NAMESPACE_LOCAL_LABEL); /* if we found a local label, we already created the declaration */ if (candidate != NULL) { - assert(candidate->parent_scope == scope); + if (candidate->parent_scope != scope) { + assert(candidate->parent_scope->depth < scope->depth); + current_function->goto_to_outer = true; + } return candidate; } @@ -6779,9 +6852,12 @@ static expression_t *parse_primary_expression(void) case T___builtin_va_arg: return parse_va_arg(); case T___builtin_expect: case T___builtin_alloca: + case T___builtin_inf: + case T___builtin_inff: + case T___builtin_infl: case T___builtin_nan: - case T___builtin_nand: case T___builtin_nanf: + case T___builtin_nanl: case T___builtin_huge_val: case T___builtin_va_end: return parse_builtin_symbol(); case T___builtin_isgreater: @@ -6794,7 +6870,7 @@ static expression_t *parse_primary_expression(void) case T___builtin_prefetch: return parse_builtin_prefetch(); case T__assume: return parse_assume(); case T_ANDAND: - if (c_mode & _GNUC) + if (GNU_MODE) return parse_label_address(); break; @@ -6860,19 +6936,18 @@ static expression_t *parse_array_expression(unsigned precedence, orig_type_left, orig_type_inside); } return_type = type_error_type; - array_access->array_ref = create_invalid_expression(); + array_access->array_ref = left; + array_access->index = inside; } + expression->base.type = automatic_type_conversion(return_type); + rem_anchor_token(']'); - if (token.type != ']') { + if (token.type == ']') { + next_token(); + } else { parse_error_expected("Problem while parsing array access", ']', NULL); - return expression; } - next_token(); - - return_type = automatic_type_conversion(return_type); - expression->base.type = return_type; - return expression; } @@ -6880,12 +6955,15 @@ static expression_t *parse_typeprop(expression_kind_t const kind, source_position_t const pos, unsigned const precedence) { - expression_t *tp_expression = allocate_expression_zero(kind); + expression_t *tp_expression = allocate_expression_zero(kind); tp_expression->base.type = type_size_t; tp_expression->base.source_position = pos; char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; + /* we only refer to a type property, mark this case */ + bool old = in_type_prop; + in_type_prop = true; if (token.type == '(' && is_declaration_specifier(look_ahead(1), true)) { next_token(); add_anchor_token(')'); @@ -6925,9 +7003,9 @@ static expression_t *parse_typeprop(expression_kind_t const kind, tp_expression->typeprop.tp_expression = expression; } - return tp_expression; end_error: - return create_invalid_expression(); + in_type_prop = old; + return tp_expression; } static expression_t *parse_sizeof(unsigned precedence) @@ -6992,7 +7070,7 @@ static expression_t *parse_select_expression(unsigned precedence, if (!declaration->init.complete) { errorf(HERE, "request for member '%Y' of incomplete type '%T'", symbol, type_left); - return create_invalid_expression(); + goto create_error_entry; } entry = find_compound_entry(declaration, symbol); @@ -7074,26 +7152,15 @@ static void check_call_argument(const function_parameter_t *parameter, snprintf(buf, sizeof(buf), "call argument %u", pos); report_assign_error(error, expected_type, arg_expr, buf, &arg_expr->base.source_position); - } else if (warning.traditional | warning.conversion) { - if ( - /* passing as integer instead of float or complex */ - (is_type_integer(expected_type) && - (is_type_float(arg_type) || is_type_complex(arg_type))) || - /* passing as complex instead of integer or float */ - (is_type_complex(expected_type) && - (is_type_integer(arg_type) || is_type_float(arg_type))) || - /* passing as float instead of integer or complex */ - (is_type_float(expected_type) && - (is_type_integer(arg_type) || is_type_complex(arg_type))) || - /* passing as float instead of double */ - (is_type_float(expected_type) && expected_type != type_double && - is_type_float(arg_type))) { + } else if (warning.traditional || warning.conversion) { + type_t *const promoted_type = get_default_promoted_type(arg_type); + if (!types_compatible(expected_type_skip, promoted_type) && + !types_compatible(expected_type_skip, type_void_ptr) && + !types_compatible(type_void_ptr, promoted_type)) { + /* Deliberately show the skipped types in this warning */ warningf(&arg_expr->base.source_position, "passing call argument %u as '%T' rather than '%T' due to prototype", - pos, expected_type, arg_type); - } - if (is_type_integer(expected_type) && is_type_integer(arg_type)) { - /* TODO check for size HERE */ + pos, expected_type_skip, promoted_type); } } } @@ -7194,9 +7261,8 @@ static expression_t *parse_call_expression(unsigned precedence, "function call has aggregate value"); } - return result; end_error: - return create_invalid_expression(); + return result; } static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right); @@ -7236,7 +7302,7 @@ static expression_t *parse_conditional_expression(unsigned precedence, expression_t *true_expression = expression; bool gnu_cond = false; - if ((c_mode & _GNUC) && token.type == ':') { + if (GNU_MODE && token.type == ':') { gnu_cond = true; } else true_expression = parse_expression(); @@ -7315,13 +7381,13 @@ static expression_t *parse_conditional_expression(unsigned precedence, "pointer/integer type mismatch in conditional expression ('%T' and '%T')", true_type, false_type); result_type = pointer_type; } else { - type_error_incompatible("while parsing conditional", - &expression->base.source_position, true_type, false_type); + if (is_type_valid(other_type)) { + type_error_incompatible("while parsing conditional", + &expression->base.source_position, true_type, false_type); + } result_type = type_error_type; } } else { - /* TODO: one pointer to void*, other some pointer */ - if (is_type_valid(true_type) && is_type_valid(false_type)) { type_error_incompatible("while parsing conditional", &conditional->base.source_position, true_type, @@ -7347,9 +7413,10 @@ static expression_t *parse_extension(unsigned precedence) { eat(T___extension__); - /* TODO enable extensions */ + bool old_gcc_extension = in_gcc_extension; + in_gcc_extension = true; expression_t *expression = parse_sub_expression(precedence); - /* TODO disable extensions */ + in_gcc_extension = old_gcc_extension; return expression; } @@ -7383,7 +7450,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 (!(c_mode & _GNUC) || !is_type_atomic(points_to, ATOMIC_TYPE_VOID)) { + if (!GNU_MODE || !is_type_atomic(points_to, ATOMIC_TYPE_VOID)) { errorf(source_position, "arithmetic with pointer to incomplete type '%T' not allowed", orig_pointer_type); @@ -7394,7 +7461,7 @@ static bool check_pointer_arithmetic(const source_position_t *source_position, orig_pointer_type); } } else if (is_type_function(points_to)) { - if (!(c_mode && _GNUC)) { + if (!GNU_MODE) { errorf(source_position, "arithmetic with pointer to function type '%T' not allowed", orig_pointer_type); @@ -7418,7 +7485,10 @@ static bool is_lvalue(const expression_t *expression) return true; default: - return false; + /* Claim it is an lvalue, if the type is invalid. There was a parse + * error before, which maybe prevented properly recognizing it as + * lvalue. */ + return !is_type_valid(skip_typeref(expression->base.type)); } } @@ -7468,6 +7538,46 @@ static void semantic_unexpr_plus(unary_expression_t *expression) "traditional C rejects the unary plus operator"); } +static expression_t const *get_reference_address(expression_t const *expr) +{ + bool regular_take_address = true; + for (;;) { + if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) { + expr = expr->unary.value; + } else { + regular_take_address = false; + } + + if (expr->kind != EXPR_UNARY_DEREFERENCE) + break; + + expr = expr->unary.value; + } + + if (expr->kind != EXPR_REFERENCE) + return NULL; + + if (!regular_take_address && + !is_type_function(skip_typeref(expr->reference.declaration->type))) { + return NULL; + } + + return expr; +} + +static void warn_function_address_as_bool(expression_t const* expr) +{ + if (!warning.address) + return; + + expr = get_reference_address(expr); + if (expr != NULL) { + warningf(&expr->base.source_position, + "the address of '%Y' will always evaluate as 'true'", + expr->reference.declaration->symbol); + } +} + static void semantic_not(unary_expression_t *expression) { type_t *const orig_type = expression->value->base.type; @@ -7477,6 +7587,8 @@ static void semantic_not(unary_expression_t *expression) "operand of ! must be of scalar type"); } + warn_function_address_as_bool(expression->value); + expression->base.type = type_int; } @@ -7546,7 +7658,7 @@ static void semantic_take_addr(unary_expression_t *expression) value->base.type = revert_automatic_type_conversion(value); type_t *orig_type = value->base.type; - if (!is_type_valid(orig_type)) + if (!is_type_valid(skip_typeref(orig_type))) return; set_address_taken(value, false); @@ -7614,6 +7726,9 @@ static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) { /* TODO: handle complex + imaginary types */ + type_left = get_unqualified_type(type_left); + type_right = get_unqualified_type(type_right); + /* § 6.3.1.8 Usual arithmetic conversions */ if (type_left == type_long_double || type_right == type_long_double) { return type_long_double; @@ -7700,10 +7815,15 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression) static void warn_div_by_zero(binary_expression_t const *const expression) { - if (warning.div_by_zero && - is_type_integer(expression->base.type) && - is_constant_expression(expression->right) && - fold_constant(expression->right) == 0) { + if (!warning.div_by_zero || + !is_type_integer(expression->base.type)) + return; + + expression_t const *const right = expression->right; + /* The type of the right operand can be different for /= */ + if (is_type_integer(right->base.type) && + is_constant_expression(right) && + fold_constant(right) == 0) { warningf(&expression->base.source_position, "division by zero"); } } @@ -7816,6 +7936,22 @@ static void semantic_sub(binary_expression_t *expression) } } +static void warn_string_literal_address(expression_t const* expr) +{ + while (expr->kind == EXPR_UNARY_TAKE_ADDRESS) { + expr = expr->unary.value; + if (expr->kind != EXPR_UNARY_DEREFERENCE) + return; + expr = expr->unary.value; + } + + if (expr->kind == EXPR_STRING_LITERAL || + expr->kind == EXPR_WIDE_STRING_LITERAL) { + warningf(&expr->base.source_position, + "comparison with string literal results in unspecified behaviour"); + } +} + /** * Check the semantics of comparison expressions. * @@ -7823,13 +7959,32 @@ static void semantic_sub(binary_expression_t *expression) */ static void semantic_comparison(binary_expression_t *expression) { - expression_t *left = expression->left; - expression_t *right = expression->right; - type_t *orig_type_left = left->base.type; - type_t *orig_type_right = right->base.type; + expression_t *left = expression->left; + expression_t *right = expression->right; - type_t *type_left = skip_typeref(orig_type_left); - type_t *type_right = skip_typeref(orig_type_right); + if (warning.address) { + warn_string_literal_address(left); + warn_string_literal_address(right); + + expression_t const* const func_left = get_reference_address(left); + if (func_left != NULL && is_null_pointer_constant(right)) { + warningf(&expression->base.source_position, + "the address of '%Y' will never be NULL", + func_left->reference.declaration->symbol); + } + + expression_t const* const func_right = get_reference_address(right); + if (func_right != NULL && is_null_pointer_constant(right)) { + warningf(&expression->base.source_position, + "the address of '%Y' will never be NULL", + func_right->reference.declaration->symbol); + } + } + + type_t *orig_type_left = left->base.type; + type_t *orig_type_right = right->base.type; + type_t *type_left = skip_typeref(orig_type_left); + type_t *type_right = skip_typeref(orig_type_right); /* TODO non-arithmetic types */ if (is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { @@ -8022,6 +8177,9 @@ static void semantic_logical_op(binary_expression_t *expression) type_t *const type_left = skip_typeref(orig_type_left); type_t *const type_right = skip_typeref(orig_type_right); + warn_function_address_as_bool(left); + warn_function_address_as_bool(right); + if (!is_type_scalar(type_left) || !is_type_scalar(type_right)) { /* TODO: improve error message */ if (is_type_valid(type_left) && is_type_valid(type_right)) { @@ -8562,13 +8720,11 @@ static asm_clobber_t *parse_asm_clobbers(void) */ static statement_t *parse_asm_statement(void) { - eat(T_asm); - - statement_t *statement = allocate_statement_zero(STATEMENT_ASM); - statement->base.source_position = token.source_position; - + statement_t *statement = allocate_statement_zero(STATEMENT_ASM); asm_statement_t *asm_statement = &statement->asms; + eat(T_asm); + if (token.type == T_volatile) { next_token(); asm_statement->is_volatile = true; @@ -8623,35 +8779,46 @@ end_error: */ static statement_t *parse_case_statement(void) { - eat(T_case); - statement_t *const statement = allocate_statement_zero(STATEMENT_CASE_LABEL); source_position_t *const pos = &statement->base.source_position; - *pos = token.source_position; - statement->case_label.expression = parse_expression(); - if (! is_constant_expression(statement->case_label.expression)) { - errorf(pos, "case label does not reduce to an integer constant"); + eat(T_case); + + expression_t *const expression = parse_expression(); + statement->case_label.expression = expression; + if (!is_constant_expression(expression)) { + /* This check does not prevent the error message in all cases of an + * prior error while parsing the expression. At least it catches the + * common case of a mistyped enum entry. */ + if (is_type_valid(skip_typeref(expression->base.type))) { + errorf(pos, "case label does not reduce to an integer constant"); + } statement->case_label.is_bad = true; } else { - long const val = fold_constant(statement->case_label.expression); + long const val = fold_constant(expression); statement->case_label.first_case = val; statement->case_label.last_case = val; } - if (c_mode & _GNUC) { + if (GNU_MODE) { if (token.type == T_DOTDOTDOT) { next_token(); - statement->case_label.end_range = parse_expression(); - if (! is_constant_expression(statement->case_label.end_range)) { - errorf(pos, "case range does not reduce to an integer constant"); + expression_t *const end_range = parse_expression(); + statement->case_label.end_range = end_range; + if (!is_constant_expression(end_range)) { + /* This check does not prevent the error message in all cases of an + * prior error while parsing the expression. At least it catches the + * common case of a mistyped enum entry. */ + if (is_type_valid(skip_typeref(end_range->base.type))) { + errorf(pos, "case range does not reduce to an integer constant"); + } statement->case_label.is_bad = true; } else { - long const val = fold_constant(statement->case_label.end_range); + long const val = fold_constant(end_range); statement->case_label.last_case = val; if (val < statement->case_label.first_case) { - statement->case_label.is_empty = true; + statement->case_label.is_empty_range = true; warningf(pos, "empty range specified"); } } @@ -8667,7 +8834,7 @@ static statement_t *parse_case_statement(void) /* Check for duplicate case values */ case_label_statement_t *c = &statement->case_label; for (case_label_statement_t *l = current_switch->first_case; l != NULL; l = l->next) { - if (l->is_bad || l->is_empty || l->expression == NULL) + if (l->is_bad || l->is_empty_range || l->expression == NULL) continue; if (c->last_case < l->first_case || c->first_case > l->last_case) @@ -8707,10 +8874,9 @@ end_error: */ static statement_t *parse_default_statement(void) { - eat(T_default); - statement_t *statement = allocate_statement_zero(STATEMENT_CASE_LABEL); - statement->base.source_position = token.source_position; + + eat(T_default); PUSH_PARENT(statement); @@ -8755,14 +8921,13 @@ end_error: static statement_t *parse_label_statement(void) { assert(token.type == T_IDENTIFIER); - symbol_t *symbol = token.v.symbol; - next_token(); - - declaration_t *label = get_label(symbol); + symbol_t *symbol = token.v.symbol; + declaration_t *label = get_label(symbol); statement_t *const statement = allocate_statement_zero(STATEMENT_LABEL); - statement->base.source_position = token.source_position; - statement->label.label = label; + statement->label.label = label; + + next_token(); PUSH_PARENT(statement); @@ -8818,19 +8983,23 @@ static statement_t *parse_label_statement(void) */ static statement_t *parse_if(void) { - eat(T_if); + statement_t *statement = allocate_statement_zero(STATEMENT_IF); - statement_t *statement = allocate_statement_zero(STATEMENT_IF); - statement->base.source_position = token.source_position; + eat(T_if); PUSH_PARENT(statement); + add_anchor_token('{'); + expect('('); add_anchor_token(')'); statement->ifs.condition = parse_expression(); rem_anchor_token(')'); expect(')'); +end_error: + rem_anchor_token('{'); + add_anchor_token(T_else); statement->ifs.true_statement = parse_statement(); rem_anchor_token(T_else); @@ -8842,9 +9011,6 @@ static statement_t *parse_if(void) POP_PARENT; return statement; -end_error: - POP_PARENT; - return create_invalid_statement(); } /** @@ -8892,10 +9058,9 @@ static void check_enum_cases(const switch_statement_t *statement) { */ static statement_t *parse_switch(void) { - eat(T_switch); + statement_t *statement = allocate_statement_zero(STATEMENT_SWITCH); - statement_t *statement = allocate_statement_zero(STATEMENT_SWITCH); - statement->base.source_position = token.source_position; + eat(T_switch); PUSH_PARENT(statement); @@ -8956,10 +9121,9 @@ static statement_t *parse_loop_body(statement_t *const loop) */ static statement_t *parse_while(void) { - eat(T_while); + statement_t *statement = allocate_statement_zero(STATEMENT_WHILE); - statement_t *statement = allocate_statement_zero(STATEMENT_WHILE); - statement->base.source_position = token.source_position; + eat(T_while); PUSH_PARENT(statement); @@ -8983,12 +9147,11 @@ end_error: */ static statement_t *parse_do(void) { - eat(T_do); - statement_t *statement = allocate_statement_zero(STATEMENT_DO_WHILE); - statement->base.source_position = token.source_position; - PUSH_PARENT(statement) + eat(T_do); + + PUSH_PARENT(statement); add_anchor_token(T_while); statement->do_while.body = parse_loop_body(statement); @@ -9014,16 +9177,14 @@ end_error: */ static statement_t *parse_for(void) { - eat(T_for); + statement_t *statement = allocate_statement_zero(STATEMENT_FOR); - statement_t *statement = allocate_statement_zero(STATEMENT_FOR); - statement->base.source_position = token.source_position; + eat(T_for); PUSH_PARENT(statement); - int top = environment_top(); - scope_t *last_scope = scope; - set_scope(&statement->fors.scope); + size_t const top = environment_top(); + scope_push(&statement->fors.scope); expect('('); add_anchor_token(')'); @@ -9065,7 +9226,7 @@ static statement_t *parse_for(void) statement->fors.body = parse_loop_body(statement); assert(scope == &statement->fors.scope); - set_scope(last_scope); + scope_pop(); environment_pop_to(top); POP_PARENT; @@ -9075,7 +9236,7 @@ end_error: POP_PARENT; rem_anchor_token(')'); assert(scope == &statement->fors.scope); - set_scope(last_scope); + scope_pop(); environment_pop_to(top); return create_invalid_statement(); @@ -9086,11 +9247,10 @@ end_error: */ static statement_t *parse_goto(void) { - source_position_t source_position = token.source_position; + statement_t *statement = allocate_statement_zero(STATEMENT_GOTO); eat(T_goto); - statement_t *statement; - if (c_mode & _GNUC && token.type == '*') { + if (GNU_MODE && token.type == '*') { next_token(); expression_t *expression = parse_expression(); @@ -9100,32 +9260,33 @@ static statement_t *parse_goto(void) if (type != type_error_type) { if (!is_type_pointer(type) && !is_type_integer(type)) { - errorf(&source_position, "cannot convert to a pointer type"); + errorf(&expression->base.source_position, + "cannot convert to a pointer type"); } else if (type != type_void_ptr) { - warningf(&source_position, + warningf(&expression->base.source_position, "type of computed goto expression should be 'void*' not '%T'", type); } expression = create_implicit_cast(expression, type_void_ptr); } - statement = allocate_statement_zero(STATEMENT_GOTO); - statement->base.source_position = source_position; - statement->gotos.expression = expression; + statement->gotos.expression = expression; } else { if (token.type != T_IDENTIFIER) { - if (c_mode & _GNUC) + if (GNU_MODE) parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL); else parse_error_expected("while parsing goto", T_IDENTIFIER, NULL); - eat_statement(); + eat_until_anchor(); goto end_error; } symbol_t *symbol = token.v.symbol; next_token(); - statement = allocate_statement_zero(STATEMENT_GOTO); - statement->base.source_position = source_position; - statement->gotos.label = get_label(symbol); + statement->gotos.label = get_label(symbol); + + if (statement->gotos.label->parent_scope->depth < current_function->scope.depth) { + statement->gotos.outer_fkt_jmp = true; + } } /* remember the goto's in a list for later checking */ @@ -9153,7 +9314,6 @@ static statement_t *parse_continue(void) } statement_t *statement = allocate_statement_zero(STATEMENT_CONTINUE); - statement->base.source_position = token.source_position; eat(T_continue); expect(';'); @@ -9172,7 +9332,6 @@ static statement_t *parse_break(void) } statement_t *statement = allocate_statement_zero(STATEMENT_BREAK); - statement->base.source_position = token.source_position; eat(T_break); expect(';'); @@ -9191,7 +9350,6 @@ static statement_t *parse_leave_statement(void) } statement_t *statement = allocate_statement_zero(STATEMENT_LEAVE); - statement->base.source_position = token.source_position; eat(T___leave); expect(';'); @@ -9264,11 +9422,10 @@ declaration_t *expr_is_variable(const expression_t *expression) */ static statement_t *parse_return(void) { - statement_t *statement = allocate_statement_zero(STATEMENT_RETURN); - statement->base.source_position = token.source_position; - eat(T_return); + statement_t *statement = allocate_statement_zero(STATEMENT_RETURN); + expression_t *return_value = NULL; if (token.type != ';') { return_value = parse_expression(); @@ -9322,10 +9479,11 @@ static statement_t *parse_declaration_statement(void) { statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION); - statement->base.source_position = token.source_position; - declaration_t *before = last_declaration; - parse_declaration(record_declaration); + if (GNU_MODE) + parse_external_declaration(); + else + parse_declaration(record_declaration); if (before == NULL) { statement->declaration.declarations_begin = scope->declarations; @@ -9344,7 +9502,6 @@ static statement_t *parse_expression_statement(void) { statement_t *statement = allocate_statement_zero(STATEMENT_EXPRESSION); - statement->base.source_position = token.source_position; expression_t *const expr = parse_expression(); statement->expression.expression = expr; @@ -9361,7 +9518,6 @@ end_error: static statement_t *parse_ms_try_statment(void) { statement_t *statement = allocate_statement_zero(STATEMENT_MS_TRY); - statement->base.source_position = token.source_position; eat(T___try); PUSH_PARENT(statement); @@ -9414,7 +9570,6 @@ static statement_t *parse_empty_statement(void) static statement_t *parse_local_label_declaration(void) { statement_t *statement = allocate_statement_zero(STATEMENT_DECLARATION); - statement->base.source_position = token.source_position; eat(T___label__); @@ -9479,13 +9634,18 @@ static statement_t *intern_parse_statement(void) } else if (is_typedef_symbol(token.v.symbol)) { statement = parse_declaration_statement(); } else switch (la1_type) { + case '*': + if (get_declaration(token.v.symbol, NAMESPACE_NORMAL) != NULL) + goto expression_statment; + /* FALLTHROUGH */ + DECLARATION_START case T_IDENTIFIER: - case '*': statement = parse_declaration_statement(); break; default: +expression_statment: statement = parse_expression_statement(); break; } @@ -9498,7 +9658,10 @@ static statement_t *intern_parse_statement(void) do { next_token(); } while (token.type == T___extension__); + bool old_gcc_extension = in_gcc_extension; + in_gcc_extension = true; statement = parse_statement(); + in_gcc_extension = old_gcc_extension; break; DECLARATION_START @@ -9511,7 +9674,7 @@ static statement_t *intern_parse_statement(void) case ';': statement = parse_empty_statement(); break; case '{': statement = parse_compound_statement(false); break; - case T___leave: statement = parse_leave_statement(); break; + case T___leave: statement = parse_leave_statement(); break; case T___try: statement = parse_ms_try_statment(); break; case T_asm: statement = parse_asm_statement(); break; case T_break: statement = parse_break(); break; @@ -9525,7 +9688,61 @@ static statement_t *intern_parse_statement(void) case T_return: statement = parse_return(); break; case T_switch: statement = parse_switch(); break; case T_while: statement = parse_while(); break; - default: statement = parse_expression_statement(); break; + + case '!': + case '&': + case '(': + case '*': + case '+': + case '-': + case '~': + case T_ANDAND: + case T_CHARACTER_CONSTANT: + case T_FLOATINGPOINT: + case T_INTEGER: + case T_MINUSMINUS: + case T_PLUSPLUS: + case T_STRING_LITERAL: + case T_WIDE_CHARACTER_CONSTANT: + case T_WIDE_STRING_LITERAL: + case T___FUNCDNAME__: + case T___FUNCSIG__: + case T___FUNCTION__: + case T___PRETTY_FUNCTION__: + case T___builtin_alloca: + case T___builtin_classify_type: + case T___builtin_constant_p: + case T___builtin_expect: + case T___builtin_huge_val: + case T___builtin_isgreater: + case T___builtin_isgreaterequal: + case T___builtin_isless: + case T___builtin_islessequal: + case T___builtin_islessgreater: + case T___builtin_isunordered: + case T___builtin_inf: + case T___builtin_inff: + case T___builtin_infl: + case T___builtin_nan: + case T___builtin_nanf: + case T___builtin_nanl: + case T___builtin_offsetof: + case T___builtin_prefetch: + case T___builtin_va_arg: + case T___builtin_va_end: + case T___builtin_va_start: + case T___func__: + case T___noop: + case T__assume: + statement = parse_expression_statement(); + break; + + default: + errorf(HERE, "unexpected token %K while parsing statement", &token); + statement = create_invalid_statement(); + if (!at_anchor()) + next_token(); + break; } rem_anchor_token(';'); @@ -9562,21 +9779,24 @@ static statement_t *parse_statement(void) static statement_t *parse_compound_statement(bool inside_expression_statement) { statement_t *statement = allocate_statement_zero(STATEMENT_COMPOUND); - statement->base.source_position = token.source_position; PUSH_PARENT(statement); eat('{'); add_anchor_token('}'); - int top = environment_top(); - int top_local = local_label_top(); - scope_t *last_scope = scope; - set_scope(&statement->compound.scope); + size_t const top = environment_top(); + size_t const top_local = local_label_top(); + scope_push(&statement->compound.scope); statement_t **anchor = &statement->compound.statements; bool only_decls_so_far = true; - while (token.type != '}' && token.type != T_EOF) { + while (token.type != '}') { + if (token.type == T_EOF) { + errorf(&statement->base.source_position, + "EOF while parsing compound statement"); + break; + } statement_t *sub_statement = intern_parse_statement(); if (is_invalid_statement(sub_statement)) { /* an error occurred. if we are at an anchor, return */ @@ -9601,13 +9821,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) anchor = &sub_statement->base.next; } - - if (token.type == '}') { - next_token(); - } else { - errorf(&statement->base.source_position, - "end of file while looking for closing '}'"); - } + next_token(); /* look over all statements again to produce no effect warnings */ if (warning.unused_value) { @@ -9631,7 +9845,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) end_error: rem_anchor_token('}'); assert(scope == &statement->compound.scope); - set_scope(last_scope); + scope_pop(); environment_pop_to(top); local_label_pop_to(top_local); @@ -9674,7 +9888,7 @@ static void check_unused_globals(void) if (!warning.unused_function && !warning.unused_variable) return; - for (const declaration_t *decl = global_scope->declarations; decl != NULL; decl = decl->next) { + for (const declaration_t *decl = file_scope->declarations; decl != NULL; decl = decl->next) { if (decl->used || decl->modifiers & DM_UNUSED || decl->modifiers & DM_USED || @@ -9702,14 +9916,14 @@ static void check_unused_globals(void) static void parse_global_asm(void) { + statement_t *statement = allocate_statement_zero(STATEMENT_ASM); + eat(T_asm); expect('('); - statement_t *statement = allocate_statement_zero(STATEMENT_ASM); - statement->base.source_position = token.source_position; - statement->asms.asm_text = parse_string_literals(); - statement->base.next = unit->global_asm; - unit->global_asm = statement; + statement->asms.asm_text = parse_string_literals(); + statement->base.next = unit->global_asm; + unit->global_asm = statement; expect(')'); expect(';'); @@ -9722,32 +9936,61 @@ end_error:; */ static void parse_translation_unit(void) { - for (;;) switch (token.type) { - DECLARATION_START - case T_IDENTIFIER: - case T___extension__: - parse_external_declaration(); - break; + add_anchor_token(T_EOF); - case T_asm: - parse_global_asm(); - break; +#ifndef NDEBUG + unsigned char token_anchor_copy[T_LAST_TOKEN]; + memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy)); +#endif + for (;;) { +#ifndef NDEBUG + bool anchor_leak = false; + for (int i = 0; i != T_LAST_TOKEN; ++i) { + unsigned char count = token_anchor_set[i] - token_anchor_copy[i]; + if (count != 0) { + errorf(HERE, "Leaked anchor token %k %d times", i, count); + anchor_leak = true; + } + } + if (in_gcc_extension) { + errorf(HERE, "Leaked __extension__"); + anchor_leak = true; + } - case T_EOF: - return; + if (anchor_leak) + abort(); +#endif - case ';': - /* TODO error in strict mode */ - warningf(HERE, "stray ';' outside of function"); - next_token(); - break; + switch (token.type) { + DECLARATION_START + case T_IDENTIFIER: + case T___extension__: + parse_external_declaration(); + break; - default: - errorf(HERE, "stray %K outside of function", &token); - if (token.type == '(' || token.type == '{' || token.type == '[') - eat_until_matching_token(token.type); - next_token(); - break; + case T_asm: + parse_global_asm(); + break; + + case T_EOF: + rem_anchor_token(T_EOF); + return; + + case ';': + if (!strict_mode) { + warningf(HERE, "stray ';' outside of function"); + next_token(); + break; + } + /* FALLTHROUGH */ + + default: + errorf(HERE, "stray %K outside of function", &token); + if (token.type == '(' || token.type == '{' || token.type == '[') + eat_until_matching_token(token.type); + next_token(); + break; + } } } @@ -9771,24 +10014,25 @@ void start_parsing(void) assert(unit == NULL); unit = allocate_ast_zero(sizeof(unit[0])); - assert(global_scope == NULL); - global_scope = &unit->scope; + assert(file_scope == NULL); + file_scope = &unit->scope; assert(scope == NULL); - set_scope(&unit->scope); + scope_push(&unit->scope); initialize_builtin_types(); } translation_unit_t *finish_parsing(void) { + /* do NOT use scope_pop() here, this will crash, will it by hand */ assert(scope == &unit->scope); - scope = NULL; + scope = NULL; last_declaration = NULL; - assert(global_scope == &unit->scope); + assert(file_scope == &unit->scope); check_unused_globals(); - global_scope = NULL; + file_scope = NULL; DEL_ARR_F(environment_stack); DEL_ARR_F(label_stack); @@ -9813,6 +10057,8 @@ void parse(void) */ void init_parser(void) { + sym_anonymous = symbol_table_insert(""); + if (c_mode & _MS) { /* add predefined symbols for extended-decl-modifier */ sym_align = symbol_table_insert("align");