X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=200f5ae7d0b2dc95bb6a14a9933a45048bdb65b3;hb=9a9a71f0190e6a79bc3712a1adb8c935fe7e48ca;hp=e8997b4160232874bb216531f061ab1e1697ae1b;hpb=f91a0738737d5ece68d8291e56f7a7809da56ef9;p=cparser diff --git a/parser.c b/parser.c index e8997b4..200f5ae 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" @@ -93,7 +94,7 @@ 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; @@ -283,25 +284,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); @@ -316,9 +318,9 @@ 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), @@ -397,17 +399,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); } /** @@ -705,7 +709,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) @@ -738,7 +741,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; @@ -852,22 +855,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) +static atomic_type_kind_t get_akind(const type_t *type) { - return (int) akind; -} - -/** - * Return the type rank for an atomic type. - */ -static int get_rank(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; } /** @@ -878,7 +870,7 @@ static int get_rank(const type_t *type) */ static type_t *promote_integer(type_t *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; @@ -1007,10 +999,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; } @@ -1081,22 +1073,6 @@ static string_t parse_string_literals(void) 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)); @@ -1241,8 +1217,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; } @@ -1359,19 +1334,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: { @@ -1448,10 +1421,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; } @@ -1465,7 +1441,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; @@ -1546,9 +1522,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? @@ -1561,7 +1536,7 @@ unary: case EXPR_OFFSETOF: case EXPR_STATEMENT: // TODO case EXPR_LABEL_ADDRESS: - case EXPR_REFERENCE_ENUM_VALUE: + case EXPR_ENUM_CONSTANT: return; } @@ -1691,15 +1666,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. * @@ -1720,7 +1686,7 @@ static initializer_t *parse_scalar_initializer(type_t *type, 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); @@ -1843,11 +1809,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 { @@ -1987,7 +1952,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; @@ -2141,7 +2106,7 @@ finish_designator: 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); @@ -2517,9 +2482,9 @@ static type_t *parse_enum_specifier(void) 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.kind == '{') { if (symbol != NULL) { @@ -2638,9 +2603,9 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute) symbol_t **prop; symbol_t *symbol = token.identifier.symbol; - if (strcmp(symbol->string, "put") == 0) { + if (streq(symbol->string, "put")) { prop = &property->put_symbol; - } else if (strcmp(symbol->string, "get") == 0) { + } else if (streq(symbol->string, "get")) { prop = &property->get_symbol; } else { errorf(HERE, "expected put or get in property declspec"); @@ -2676,7 +2641,7 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void) 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; } @@ -3145,15 +3110,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"); @@ -3245,6 +3208,8 @@ static void semantic_parameter_incomplete(const entity_t *entity) static bool has_parameters(void) { /* func(void) is not a parameter */ + if (look_ahead(1)->kind != ')') + return true; if (token.kind == T_IDENTIFIER) { entity_t const *const entity = get_entity(token.identifier.symbol, NAMESPACE_NORMAL); @@ -3252,13 +3217,20 @@ static bool has_parameters(void) return true; if (entity->kind != ENTITY_TYPEDEF) return true; - if (skip_typeref(entity->typedefe.type) != type_void) + type_t const *const type = skip_typeref(entity->typedefe.type); + if (!is_type_void(type)) return true; + if (c_mode & _CXX) { + /* ISO/IEC 14882:1998(E) §8.3.5:2 It must be literally (void). A typedef + * is not allowed. */ + errorf(HERE, "empty parameter list defined with a typedef of 'void' not allowed in C++"); + } else if (type->base.qualifiers != TYPE_QUALIFIER_NONE) { + /* §6.7.5.3:10 Qualification is not allowed here. */ + errorf(HERE, "'void' as parameter must not have type qualifiers"); + } } else if (token.kind != T_void) { return true; } - if (look_ahead(1)->kind != ')') - return true; next_token(); return false; } @@ -3336,8 +3308,7 @@ end_error: } typedef enum construct_type_kind_t { - CONSTRUCT_INVALID, - CONSTRUCT_POINTER, + CONSTRUCT_POINTER = 1, CONSTRUCT_REFERENCE, CONSTRUCT_FUNCTION, CONSTRUCT_ARRAY @@ -3634,8 +3605,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; @@ -3650,7 +3619,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"); } } @@ -3904,6 +3873,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; } @@ -3994,7 +3967,7 @@ warn_arg_count: */ static bool is_sym_main(const symbol_t *const sym) { - return strcmp(sym->string, "main") == 0; + return streq(sym->string, "main"); } static void error_redefined_as_different_kind(const source_position_t *pos, @@ -4120,8 +4093,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; } @@ -4201,7 +4188,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) { @@ -4643,10 +4630,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(); @@ -4746,10 +4729,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; } @@ -4765,8 +4750,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 @@ -4778,7 +4763,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: { @@ -4819,20 +4804,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"); @@ -4875,7 +4857,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; @@ -5027,20 +5009,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: @@ -5137,8 +5120,8 @@ 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) && + if (!is_type_void(ret) && + is_type_valid(ret) && !is_sym_main(current_function->base.base.symbol)) { source_position_t const *const pos = &stmt->base.source_position; warningf(WARN_RETURN_TYPE, pos, "control reaches end of non-void function"); @@ -5147,7 +5130,7 @@ found_break_parent: } switch (next->kind) { - case STATEMENT_INVALID: + case STATEMENT_ERROR: case STATEMENT_EMPTY: case STATEMENT_DECLARATION: case STATEMENT_EXPRESSION: @@ -5155,6 +5138,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"); @@ -5338,6 +5322,22 @@ 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 parse_external_declaration(void) { /* function-definitions and declarations both start with declaration @@ -5487,6 +5487,9 @@ static void parse_external_declaration(void) } } + if (is_main(entity) && enable_main_collect2_hack) + prepare_main_collect2(entity); + POP_PARENT(); assert(current_function == function); assert(current_entity == entity); @@ -5722,6 +5725,8 @@ static void parse_compound_declarators(compound_t *compound, 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"); } } } @@ -5808,7 +5813,7 @@ static expression_t *expected_expression_error(void) } next_token(); - return create_invalid_expression(); + return create_error_expression(); } static type_t *get_string_type(void) @@ -6205,7 +6210,8 @@ static entity_t *parse_qualified_identifier(void) if (entity == NULL) { 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); @@ -6236,7 +6242,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; @@ -6276,7 +6282,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 */ @@ -6361,7 +6367,7 @@ static expression_t *parse_cast(void) return cast; end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -6576,14 +6582,14 @@ 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(); + return create_error_expression(); } /** @@ -6619,7 +6625,7 @@ static expression_t *parse_va_start(void) } expect(')', end_error); end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -6643,7 +6649,7 @@ static expression_t *parse_va_arg(void) return expression; end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -6672,7 +6678,7 @@ static expression_t *parse_va_copy(void) return expression; end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -6693,7 +6699,7 @@ static expression_t *parse_builtin_constant(void) return expression; end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -6718,7 +6724,7 @@ static expression_t *parse_builtin_types_compatible(void) return expression; end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -6775,7 +6781,7 @@ static expression_t *parse_compare_builtin(void) return expression; end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -6796,7 +6802,7 @@ static expression_t *parse_assume(void) expression->base.type = type_void; return expression; end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -6833,7 +6839,7 @@ static expression_t *parse_label_address(void) eat(T_ANDAND); 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(); @@ -6871,9 +6877,10 @@ static expression_t *parse_noop_expression(void) 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); end_error: @@ -6937,13 +6944,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) @@ -7054,7 +7061,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) { @@ -7097,7 +7104,7 @@ static expression_t *parse_select_expression(expression_t *addr) if (token.kind != T_IDENTIFIER) { parse_error_expected("while parsing select", T_IDENTIFIER, NULL); - return create_invalid_expression(); + return create_error_expression(); } symbol_t *symbol = token.identifier.symbol; next_token(); @@ -7131,14 +7138,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; @@ -7147,7 +7154,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; @@ -7211,32 +7218,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; @@ -7246,22 +7246,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; } } @@ -7357,7 +7372,7 @@ 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); } @@ -7476,16 +7491,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; @@ -7518,8 +7531,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))) { @@ -7584,7 +7596,7 @@ static expression_t *parse_builtin_classify_type(void) return result; end_error: - return create_invalid_expression(); + return create_error_expression(); } /** @@ -7613,7 +7625,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"); } @@ -7644,8 +7656,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); } @@ -7668,7 +7679,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); @@ -7735,6 +7746,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; @@ -7746,9 +7764,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) @@ -7777,7 +7797,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) @@ -7927,45 +7947,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"); } } @@ -8174,7 +8193,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 { @@ -8527,10 +8546,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 */ @@ -8598,7 +8616,7 @@ static bool expression_has_effect(const expression_t *const expr) * suppress the warning */ case EXPR_UNARY_CAST: { type_t *const type = skip_typeref(expr->base.type); - return is_type_atomic(type, ATOMIC_TYPE_VOID); + return is_type_void(type); } case EXPR_UNARY_ASSUME: return true; @@ -8746,7 +8764,6 @@ static expression_t *parse_subexpression(precedence_t precedence) left = parser->infix_parser(left); assert(left != NULL); - assert(left->kind != EXPR_UNKNOWN); } return left; @@ -9039,7 +9056,7 @@ end_of_asm: return statement; end_error: - return create_invalid_statement(); + return create_error_statement(); } static statement_t *parse_label_inner_statement(statement_t const *const label, char const *const label_kind) @@ -9048,7 +9065,7 @@ static statement_t *parse_label_inner_statement(statement_t const *const label, 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 ';': @@ -9084,7 +9101,22 @@ static statement_t *parse_case_statement(void) eat(T_case); - expression_t *const expression = parse_expression(); + 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); + } + } + statement->case_label.expression = expression; expression_classification_t const expr_class = is_constant_expression(expression); if (expr_class != EXPR_CLASS_CONSTANT) { @@ -9100,7 +9132,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) { @@ -9279,8 +9319,18 @@ end_error: 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; @@ -9352,7 +9402,7 @@ static statement_t *parse_switch(void) 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)) { @@ -9378,7 +9428,7 @@ static statement_t *parse_switch(void) return statement; end_error: POP_PARENT(); - return create_invalid_statement(); + return create_error_statement(); } static statement_t *parse_loop_body(statement_t *const loop) @@ -9420,7 +9470,7 @@ static statement_t *parse_while(void) return statement; end_error: POP_PARENT(); - return create_invalid_statement(); + return create_error_statement(); } /** @@ -9455,7 +9505,7 @@ static statement_t *parse_do(void) return statement; end_error: POP_PARENT(); - return create_invalid_statement(); + return create_error_statement(); } /** @@ -9526,7 +9576,7 @@ end_error2: /* fallthrough */ end_error1: - return create_invalid_statement(); + return create_error_statement(); } /** @@ -9534,10 +9584,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); @@ -9555,24 +9607,28 @@ static statement_t *parse_goto(void) expression = create_implicit_cast(expression, type_void_ptr); } - statement->gotos.expression = expression; - } else if (token.kind == 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(); + return create_error_statement(); + } } - /* remember the goto's in a list for later checking */ - *goto_anchor = &statement->gotos; - goto_anchor = &statement->gotos.next; - expect(';', end_error); end_error: @@ -9684,6 +9740,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. */ @@ -9706,24 +9771,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); @@ -9738,14 +9793,9 @@ 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; @@ -9834,11 +9884,11 @@ static statement_t *parse_ms_try_statment(void) statement->ms_try.final_statement = parse_compound_statement(false); } else { parse_error_expected("while parsing __try statement", T___except, T___finally, NULL); - return create_invalid_statement(); + return create_error_statement(); } return statement; end_error: - return create_invalid_statement(); + return create_error_statement(); } static statement_t *parse_empty_statement(void) @@ -10021,9 +10071,8 @@ 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(';'); @@ -10164,7 +10213,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) break; } statement_t *sub_statement = intern_parse_statement(); - if (is_invalid_statement(sub_statement)) { + if (sub_statement->kind == STATEMENT_ERROR) { /* an error occurred. if we are at an anchor, return */ if (at_anchor()) goto end_error; @@ -10363,13 +10412,13 @@ 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; @@ -10416,7 +10465,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; } @@ -10563,6 +10612,8 @@ static void complete_incomplete_arrays(void) void prepare_main_collect2(entity_t *entity) { + PUSH_SCOPE(&entity->function.statement->compound.scope); + // create call to __main symbol_t *symbol = symbol_table_insert("__main"); entity_t *subsubmain_ent @@ -10589,6 +10640,8 @@ void prepare_main_collect2(entity_t *entity) expr_statement->base.next = compounds->statements; compounds->statements = expr_statement; + + POP_SCOPE(); } void parse(void)