X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=parser.c;h=501f575b62c9f10898c6bf2d20e8c9545eec8382;hb=1518ab3996492fbb86a084cca8ea8cb851cd3b80;hp=6b7842676cd962ee36808684ea467191e7cc4474;hpb=e80619e26225a890600f8e668ed6149312d22465;p=cparser diff --git a/parser.c b/parser.c index 6b78426..501f575 100644 --- a/parser.c +++ b/parser.c @@ -840,7 +840,7 @@ static void label_pop_to(size_t new_top) } -static int get_rank(const type_t *type) +static atomic_type_kind_t get_rank(const type_t *type) { assert(!is_typeref(type)); /* The C-standard allows promoting enums to int or unsigned int (see § 7.2.2 @@ -959,9 +959,9 @@ static void report_assign_error(assign_error_t error, type_t *orig_type_left, /* the left type has all qualifiers from the right type */ unsigned missing_qualifiers = points_to_right->base.qualifiers & ~points_to_left->base.qualifiers; - errorf(source_position, - "destination type '%T' in %s from type '%T' lacks qualifiers '%Q' in pointed-to type", - orig_type_left, context, orig_type_right, missing_qualifiers); + warningf(source_position, + "destination type '%T' in %s from type '%T' lacks qualifiers '%Q' in pointed-to type", + orig_type_left, context, orig_type_right, missing_qualifiers); return; } @@ -3236,7 +3236,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) /* Be somewhat resilient to typos like 'vodi f()' at the beginning of a * declaration, so it doesn't generate 'implicit int' followed by more * errors later on. */ - token_type_t const la1_type = look_ahead(1)->type; + token_type_t const la1_type = (token_type_t)look_ahead(1)->type; switch (la1_type) { DECLARATION_START case T_IDENTIFIER: @@ -4706,6 +4706,10 @@ static void check_declarations(void) if (warning.unused_parameter) { const scope_t *scope = ¤t_function->scope; + if (is_sym_main(current_function->symbol)) { + /* do not issue unused warnings for main */ + return; + } const declaration_t *parameter = scope->declarations; for (; parameter != NULL; parameter = parameter->next) { if (! parameter->used) { @@ -4786,9 +4790,7 @@ static void check_reachable(statement_t *const stmt) continue; } - expression_t *const case_expr = i->expression; - if (is_constant_expression(case_expr) && - fold_constant(case_expr) == val) { + if (i->first_case <= val && val <= i->last_case) { check_reachable((statement_t*)i); return; } @@ -5514,7 +5516,7 @@ static expression_t *parse_string_const(void) /* note: that we use type_char_ptr here, which is already the * automatic converted type. revert_automatic_type_conversion * will construct the array type */ - cnst->base.type = type_char_ptr; + cnst->base.type = warning.write_strings ? type_const_char_ptr : type_char_ptr; cnst->string.value = res; return cnst; } @@ -5537,7 +5539,7 @@ static expression_t *parse_string_const(void) default: { expression_t *const cnst = allocate_expression_zero(EXPR_WIDE_STRING_LITERAL); - cnst->base.type = type_wchar_t_ptr; + cnst->base.type = warning.write_strings ? type_const_wchar_t_ptr : type_wchar_t_ptr; cnst->wide_string.value = wres; return cnst; } @@ -7000,18 +7002,29 @@ static bool check_pointer_arithmetic(const source_position_t *source_position, points_to = skip_typeref(points_to); if (is_type_incomplete(points_to) && - (! (c_mode & _GNUC) - || !is_type_atomic(points_to, ATOMIC_TYPE_VOID))) { + !((c_mode & _GNUC) + && is_type_atomic(points_to, ATOMIC_TYPE_VOID))) { errorf(source_position, - "arithmetic with pointer to incomplete type '%T' not allowed", - orig_pointer_type); + "arithmetic with pointer to incomplete type '%T' not allowed", + orig_pointer_type); return false; - } else if (is_type_function(points_to)) { + } else if (!(c_mode & _GNUC) && is_type_function(points_to)) { errorf(source_position, - "arithmetic with pointer to function type '%T' not allowed", - orig_pointer_type); + "arithmetic with pointer to function type '%T' not allowed", + orig_pointer_type); return false; } + if (warning.pointer_arith) { + if (is_type_atomic(points_to, ATOMIC_TYPE_VOID)) { + warningf(source_position, + "pointer of type '%T' used in arithmetic", + orig_pointer_type); + } else if (is_type_function(points_to)) { + warningf(source_position, + "pointer to a function '%T' used in arithmetic", + orig_pointer_type); + } + } return true; } @@ -7206,16 +7219,16 @@ static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) 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); + atomic_type_kind_t const rank_left = get_rank(type_left); + atomic_type_kind_t const rank_right = get_rank(type_right); if (signed_left == signed_right) return rank_left >= rank_right ? type_left : type_right; - int s_rank; - int u_rank; - type_t *s_type; - type_t *u_type; + atomic_type_kind_t s_rank; + atomic_type_kind_t u_rank; + type_t *s_type; + type_t *u_type; if (signed_left) { s_rank = rank_left; s_type = type_left; @@ -8266,20 +8279,6 @@ end_error: return create_invalid_statement(); } -/** - * Finds an existing default label of a switch statement. - */ -static case_label_statement_t * -find_default_label(const switch_statement_t *statement) -{ - case_label_statement_t *label = statement->first_case; - for ( ; label != NULL; label = label->next) { - if (label->expression == NULL) - return label; - } - return NULL; -} - /** * Parse a default statement. */ @@ -8294,11 +8293,13 @@ static statement_t *parse_default_statement(void) expect(':'); if (current_switch != NULL) { - const case_label_statement_t *def_label = find_default_label(current_switch); + const case_label_statement_t *def_label = current_switch->default_label; if (def_label != NULL) { errorf(HERE, "multiple default labels in one switch (previous declared %P)", &def_label->base.source_position); } else { + current_switch->default_label = &statement->case_label; + /* link all cases into the switch statement */ if (current_switch->last_case == NULL) { current_switch->first_case = &statement->case_label; @@ -8449,6 +8450,46 @@ end_error: return create_invalid_statement(); } +/** + * Check that all enums are handled in a switch. + * + * @param statement the switch statement to check + */ +static void check_enum_cases(const switch_statement_t *statement) { + const type_t *type = skip_typeref(statement->expression->base.type); + if (! is_type_enum(type)) + return; + const enum_type_t *enumt = &type->enumt; + + /* if we have a default, no warnings */ + if (statement->default_label != NULL) + return; + + /* FIXME: calculation of value should be done while parsing */ + const declaration_t *declaration; + long last_value = -1; + for (declaration = enumt->declaration->next; + declaration != NULL && declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY; + declaration = declaration->next) { + const expression_t *expression = declaration->init.enum_value; + long value = expression != NULL ? fold_constant(expression) : last_value + 1; + bool found = false; + for (const case_label_statement_t *l = statement->first_case; l != NULL; l = l->next) { + if (l->expression == NULL) + continue; + if (l->first_case <= value && value <= l->last_case) { + found = true; + break; + } + } + if (! found) { + warningf(&statement->base.source_position, + "enumeration value '%Y' not handled in switch", declaration->symbol); + } + last_value = value; + } +} + /** * Parse a switch statement. */ @@ -8462,6 +8503,7 @@ static statement_t *parse_switch(void) PUSH_PARENT(statement); expect('('); + add_anchor_token(')'); expression_t *const expr = parse_expression(); type_t * type = skip_typeref(expr->base.type); if (is_type_integer(type)) { @@ -8473,6 +8515,7 @@ static statement_t *parse_switch(void) } statement->switchs.expression = create_implicit_cast(expr, type); expect(')'); + rem_anchor_token(')'); switch_statement_t *rem = current_switch; current_switch = &statement->switchs; @@ -8480,9 +8523,11 @@ static statement_t *parse_switch(void) current_switch = rem; if (warning.switch_default && - find_default_label(&statement->switchs) == NULL) { + statement->switchs.default_label == NULL) { warningf(&statement->base.source_position, "switch has no default case"); } + if (warning.switch_enum) + check_enum_cases(&statement->switchs); POP_PARENT; return statement; @@ -9133,6 +9178,13 @@ static void initialize_builtin_types(void) type_ptrdiff_t_ptr = make_pointer_type(type_ptrdiff_t, TYPE_QUALIFIER_NONE); type_ssize_t_ptr = make_pointer_type(type_ssize_t, TYPE_QUALIFIER_NONE); type_wchar_t_ptr = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE); + + /* const version of wchar_t */ + type_const_wchar_t = allocate_type_zero(TYPE_TYPEDEF, &builtin_source_position); + type_const_wchar_t->typedeft.declaration = type_wchar_t->typedeft.declaration; + type_const_wchar_t->base.qualifiers |= TYPE_QUALIFIER_CONST; + + type_const_wchar_t_ptr = make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE); } /**