X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=596169248812112b979726b5328c8e6ae150a20a;hb=15eb8da2da4c40c34c52b62c8eeda0e715c06d4a;hp=30023cdddaefc605afd2a11afda19f011216d6fa;hpb=5841c7316c07c15f9bbbd5751293152ee6fe75e1;p=cparser diff --git a/parser.c b/parser.c index 30023cd..5961692 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 @@ -3053,7 +3053,8 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) type_qualifiers_t qualifiers = TYPE_QUALIFIER_NONE; type_modifiers_t modifiers = TYPE_MODIFIER_NONE; unsigned type_specifiers = 0; - int newtype = 0; + bool newtype = false; + bool saw_error = false; specifiers->source_position = token.source_position; @@ -3207,13 +3208,50 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) case T_IDENTIFIER: { /* only parse identifier if we haven't found a type yet */ - if (type != NULL || type_specifiers != 0) - goto finish_specifiers; + if (type != NULL || type_specifiers != 0) { + /* Be somewhat resilient to typos like 'unsigned lng* f()' in a + * declaration, so it doesn't generate errors about expecting '(' or + * '{' later on. */ + switch (look_ahead(1)->type) { + STORAGE_CLASSES + TYPE_SPECIFIERS + case T_const: + case T_restrict: + case T_volatile: + case T_inline: + case T__forceinline: /* ^ DECLARATION_START except for __attribute__ */ + case T_IDENTIFIER: + case '*': + errorf(HERE, "discarding stray %K in declaration specifer", &token); + next_token(); + continue; + + default: + goto finish_specifiers; + } + } - type_t *typedef_type = get_typedef_type(token.v.symbol); + type_t *const typedef_type = get_typedef_type(token.v.symbol); + if (typedef_type == NULL) { + /* Be somewhat resilient to typos like 'vodi f()' at the beginning of a + * declaration, so it doesn't generate 'implicit int' followed by more + * errors later on. */ + token_type_t const la1_type = (token_type_t)look_ahead(1)->type; + switch (la1_type) { + DECLARATION_START + case T_IDENTIFIER: + case '*': + errorf(HERE, "%K does not name a type", &token); + next_token(); + saw_error = true; + if (la1_type == '*') + goto finish_specifiers; + continue; - if (typedef_type == NULL) - goto finish_specifiers; + default: + goto finish_specifiers; + } + } next_token(); type = typedef_type; @@ -3366,7 +3404,12 @@ warn_about_long_long: default: /* invalid specifier combination, give an error message */ if (type_specifiers == 0) { - if (! strict_mode) { + if (saw_error) { + specifiers->type = type_error_type; + return; + } + + if (!strict_mode) { if (warning.implicit_int) { warningf(HERE, "no type specifiers in declaration, using 'int'"); } @@ -3377,7 +3420,7 @@ warn_about_long_long: } } else if ((type_specifiers & SPECIFIER_SIGNED) && (type_specifiers & SPECIFIER_UNSIGNED)) { - errorf(HERE, "signed and unsigned specifiers gives"); + errorf(HERE, "signed and unsigned specifiers given"); } else if (type_specifiers & (SPECIFIER_SIGNED | SPECIFIER_UNSIGNED)) { errorf(HERE, "only integer types can be signed or unsigned"); } else { @@ -3398,11 +3441,9 @@ warn_about_long_long: type = allocate_type_zero(TYPE_ATOMIC, &builtin_source_position); type->atomic.akind = atomic_type; } - newtype = 1; - } else { - if (type_specifiers != 0) { - errorf(HERE, "multiple datatypes in declaration"); - } + newtype = true; + } else if (type_specifiers != 0) { + errorf(HERE, "multiple datatypes in declaration"); } /* FIXME: check type qualifiers here */ @@ -3715,7 +3756,7 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration) else if (second == NULL) second = "stdcall"; } if (declaration->modifiers & DM_FASTCALL) { - if (first == NULL) first = "faslcall"; + if (first == NULL) first = "fastcall"; else if (second == NULL) second = "fastcall"; } if (declaration->modifiers & DM_THISCALL) { @@ -3819,6 +3860,8 @@ static construct_type_t *parse_inner_declarator(declaration_t *declaration, next_token(); add_anchor_token(')'); inner_types = parse_inner_declarator(declaration, may_be_abstract); + /* All later declarators only modify the return type, not declaration */ + declaration = NULL; rem_anchor_token(')'); expect(')'); break; @@ -4008,6 +4051,7 @@ static declaration_t *parse_declarator( const declaration_specifiers_t *specifiers, bool may_be_abstract) { declaration_t *const declaration = allocate_declaration_zero(); + declaration->source_position = specifiers->source_position; declaration->declared_storage_class = specifiers->declared_storage_class; declaration->modifiers = specifiers->modifiers; declaration->deprecated_string = specifiers->deprecated_string; @@ -4742,9 +4786,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; } @@ -4897,6 +4939,7 @@ found_break_parent: type_t *const ret = skip_typeref(type->function.return_type); if (warning.return_type && !is_type_atomic(ret, ATOMIC_TYPE_VOID) && + is_type_valid(ret) && !is_sym_main(current_function->symbol)) { warningf(&stmt->base.source_position, "control reaches end of non-void function"); @@ -5199,7 +5242,7 @@ static void parse_external_declaration(void) || parameter->parent_scope == scope); parameter->parent_scope = scope; if (parameter->symbol == NULL) { - errorf(&ndeclaration->source_position, "parameter name omitted"); + errorf(¶meter->source_position, "parameter name omitted"); continue; } environment_push(parameter); @@ -5469,7 +5512,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; } @@ -5492,7 +5535,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; } @@ -6789,13 +6832,14 @@ static bool same_compound_type(const type_t *type1, const type_t *type2) static expression_t *parse_conditional_expression(unsigned precedence, expression_t *expression) { - eat('?'); - add_anchor_token(':'); - expression_t *result = allocate_expression_zero(EXPR_CONDITIONAL); conditional_expression_t *conditional = &result->conditional; - conditional->condition = expression; + conditional->base.source_position = *HERE; + conditional->condition = expression; + + eat('?'); + add_anchor_token(':'); /* 6.5.15.2 */ type_t *const condition_type_orig = expression->base.type; @@ -6821,7 +6865,7 @@ static expression_t *parse_conditional_expression(unsigned precedence, is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { if (!is_type_atomic(true_type, ATOMIC_TYPE_VOID) || !is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { - warningf(&expression->base.source_position, + warningf(&conditional->base.source_position, "ISO C forbids conditional expression with only one void side"); } result_type = type_void; @@ -6867,7 +6911,7 @@ static expression_t *parse_conditional_expression(unsigned precedence, get_unqualified_type(to2))) { to = to1; } else { - warningf(&expression->base.source_position, + warningf(&conditional->base.source_position, "pointer types '%T' and '%T' in conditional expression are incompatible", true_type, false_type); to = type_void; @@ -6882,7 +6926,7 @@ static expression_t *parse_conditional_expression(unsigned precedence, result_type = make_pointer_type(type, TYPE_QUALIFIER_NONE); } else if (is_type_integer(other_type)) { - warningf(&expression->base.source_position, + warningf(&conditional->base.source_position, "pointer/integer type mismatch in conditional expression ('%T' and '%T')", true_type, false_type); result_type = pointer_type; } else { @@ -6895,7 +6939,7 @@ static expression_t *parse_conditional_expression(unsigned precedence, if (is_type_valid(true_type) && is_type_valid(false_type)) { type_error_incompatible("while parsing conditional", - &expression->base.source_position, true_type, + &conditional->base.source_position, true_type, false_type); } result_type = type_error_type; @@ -6954,18 +6998,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; } @@ -7160,16 +7215,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; @@ -8148,34 +8203,54 @@ static statement_t *parse_case_statement(void) *pos = token.source_position; statement->case_label.expression = parse_expression(); - - PUSH_PARENT(statement); + if (! is_constant_expression(statement->case_label.expression)) { + 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); + statement->case_label.first_case = val; + statement->case_label.last_case = val; + } if (c_mode & _GNUC) { 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"); + statement->case_label.is_bad = true; + } else { + long const val = fold_constant(statement->case_label.end_range); + statement->case_label.last_case = val; + + if (val < statement->case_label.first_case) { + statement->case_label.is_empty = true; + warningf(pos, "empty range specified"); + } + } } } + PUSH_PARENT(statement); + expect(':'); - if (! is_constant_expression(statement->case_label.expression)) { - errorf(pos, "case label does not reduce to an integer constant"); - } else if (current_switch != NULL) { - /* Check for duplicate case values */ - /* FIXME slow */ - long const val = fold_constant(statement->case_label.expression); - for (case_label_statement_t *l = current_switch->first_case; l != NULL; l = l->next) { - expression_t const* const e = l->expression; - if (e == NULL || !is_constant_expression(e) || fold_constant(e) != val) - continue; + if (current_switch != NULL) { + if (! statement->case_label.is_bad) { + /* 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) + continue; - errorf(pos, "duplicate case value (previously used %P)", - &l->base.source_position); - break; - } + if (c->last_case < l->first_case || c->first_case > l->last_case) + continue; + errorf(pos, "duplicate case value (previously used %P)", + &l->base.source_position); + break; + } + } /* link all cases into the switch statement */ if (current_switch->last_case == NULL) { current_switch->first_case = &statement->case_label; @@ -8200,20 +8275,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. */ @@ -8228,11 +8289,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; @@ -8383,6 +8446,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. */ @@ -8396,6 +8499,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)) { @@ -8407,6 +8511,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; @@ -8414,9 +8519,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; @@ -9067,6 +9174,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.modifiers |= TYPE_QUALIFIER_CONST; + + type_const_wchar_t_ptr = make_pointer_type(type_const_wchar_t, TYPE_QUALIFIER_NONE); } /**