X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=443946edbddb1c6b4879b162e2f38d5af5c4d352;hb=c0e7bebc766fcdd5ed3e42ca34ef9bdb3c573f7a;hp=f9920b894b0951a8d001110239d820cd021f449c;hpb=3bfe0ebbeec975e63a9583c91ea5d5b3fe213164;p=cparser diff --git a/parser.c b/parser.c index f9920b8..443946e 100644 --- a/parser.c +++ b/parser.c @@ -39,6 +39,14 @@ #include "adt/error.h" #include "adt/array.h" +/** if wchar_t is equal to unsigned short. */ +bool opt_short_wchar_t = +#ifdef _WIN32 + true; +#else + false; +#endif + //#define PRINT_TOKENS #define MAX_LOOKAHEAD 2 @@ -839,8 +847,12 @@ static void label_pop_to(size_t new_top) stack_pop_to(&label_stack, new_top); } +static int get_akind_rank(atomic_type_kind_t akind) +{ + return (int) akind; +} -static atomic_type_kind_t get_rank(const type_t *type) +static int 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 @@ -849,10 +861,10 @@ static atomic_type_kind_t get_rank(const type_t *type) * (unsigned int would be preferable when possible... for stuff like * struct { enum { ... } bla : 4; } ) */ if (type->kind == TYPE_ENUM) - return ATOMIC_TYPE_INT; + return get_akind_rank(ATOMIC_TYPE_INT); assert(type->kind == TYPE_ATOMIC); - return type->atomic.akind; + return get_akind_rank(type->atomic.akind); } static type_t *promote_integer(type_t *type) @@ -860,7 +872,7 @@ static type_t *promote_integer(type_t *type) if (type->kind == TYPE_BITFIELD) type = type->bitfield.base_type; - if (get_rank(type) < ATOMIC_TYPE_INT) + if (get_rank(type) < get_akind_rank(ATOMIC_TYPE_INT)) type = type_int; return type; @@ -959,9 +971,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 pointer target type", + orig_type_left, context, orig_type_right, missing_qualifiers); return; } @@ -1004,12 +1016,13 @@ static assign_error_t semantic_assign(type_t *orig_type_left, = skip_typeref(type_left->pointer.points_to); type_t *points_to_right = skip_typeref(type_right->pointer.points_to); + assign_error_t res = ASSIGN_SUCCESS; /* the left type has all qualifiers from the right type */ unsigned missing_qualifiers = points_to_right->base.qualifiers & ~points_to_left->base.qualifiers; if (missing_qualifiers != 0) { - return ASSIGN_ERROR_POINTER_QUALIFIER_MISSING; + res = ASSIGN_ERROR_POINTER_QUALIFIER_MISSING; } points_to_left = get_unqualified_type(points_to_left); @@ -1017,14 +1030,14 @@ static assign_error_t semantic_assign(type_t *orig_type_left, if (is_type_atomic(points_to_left, ATOMIC_TYPE_VOID) || is_type_atomic(points_to_right, ATOMIC_TYPE_VOID)) { - return ASSIGN_SUCCESS; + return res; } if (!types_compatible(points_to_left, points_to_right)) { return ASSIGN_WARNING_POINTER_INCOMPATIBLE; } - return ASSIGN_SUCCESS; + return res; } else if (is_type_integer(type_right)) { return ASSIGN_WARNING_POINTER_FROM_INT; } @@ -1079,6 +1092,7 @@ static type_t *make_global_typedef(const char *name, type_t *type) declaration->type = type; declaration->symbol = symbol; declaration->source_position = builtin_source_position; + declaration->implicit = true; record_declaration(declaration); @@ -3047,6 +3061,20 @@ end_error: return; } +static declaration_t *create_error_declaration(symbol_t *symbol, storage_class_tag_t storage_class) +{ + declaration_t *const decl = allocate_declaration_zero(); + decl->source_position = *HERE; + decl->storage_class = + storage_class != STORAGE_CLASS_NONE || scope == global_scope ? + storage_class : STORAGE_CLASS_AUTO; + decl->declared_storage_class = decl->storage_class; + decl->symbol = symbol; + decl->implicit = true; + record_declaration(decl); + return decl; +} + static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) { type_t *type = NULL; @@ -3222,7 +3250,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) case T__forceinline: /* ^ DECLARATION_START except for __attribute__ */ case T_IDENTIFIER: case '*': - errorf(HERE, "discarding stray %K in declaration specifer", &token); + errorf(HERE, "discarding stray %K in declaration specifier", &token); next_token(); continue; @@ -3240,13 +3268,21 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) switch (la1_type) { DECLARATION_START case T_IDENTIFIER: - case '*': + case '*': { errorf(HERE, "%K does not name a type", &token); + + declaration_t *const decl = + create_error_declaration(token.v.symbol, STORAGE_CLASS_TYPEDEF); + + type = allocate_type_zero(TYPE_TYPEDEF, HERE); + type->typedeft.declaration = decl; + next_token(); saw_error = true; if (la1_type == '*') goto finish_specifiers; continue; + } default: goto finish_specifiers; @@ -3265,8 +3301,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) } finish_specifiers: - - if (type == NULL) { + if (type == NULL || (saw_error && type_specifiers != 0)) { atomic_type_kind_t atomic_type; /* match valid basic types */ @@ -3568,9 +3603,10 @@ static declaration_t *parse_parameters(function_type_t *type) add_anchor_token(')'); int saved_comma_state = save_and_reset_anchor_state(','); - if (token.type == T_IDENTIFIER) { - symbol_t *symbol = token.v.symbol; - if (!is_typedef_symbol(symbol)) { + if (token.type == T_IDENTIFIER && + !is_typedef_symbol(token.v.symbol)) { + token_type_t la1_type = look_ahead(1)->type; + if (la1_type == ',' || la1_type == ')') { type->kr_style_parameters = true; declarations = parse_identifier_list(); goto parameters_finished; @@ -4706,6 +4742,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) { @@ -5053,9 +5093,9 @@ continue_for:; static void check_unreachable(statement_t const* const stmt) { if (!stmt->base.reachable && - stmt->kind != STATEMENT_COMPOUND && stmt->kind != STATEMENT_DO_WHILE && - stmt->kind != STATEMENT_FOR) { + stmt->kind != STATEMENT_FOR && + (stmt->kind != STATEMENT_COMPOUND || stmt->compound.statements == NULL)) { warningf(&stmt->base.source_position, "statement is unreachable"); } @@ -5207,6 +5247,12 @@ static void parse_external_declaration(void) return; } + if (warning.aggregate_return && + is_type_compound(skip_typeref(type->function.return_type))) { + warningf(HERE, "function '%Y' returns an aggregate", + ndeclaration->symbol); + } + /* § 6.7.5.3 (14) a function definition with () means no * parameters (and not unspecified parameters) */ if (type->function.unspecified_parameters @@ -5512,7 +5558,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; } @@ -5535,7 +5581,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; } @@ -5639,6 +5685,7 @@ static declaration_t *create_implicit_function(symbol_t *symbol, declaration->type = type; declaration->symbol = symbol; declaration->source_position = *source_position; + declaration->implicit = true; bool strict_prototypes_old = warning.strict_prototypes; warning.strict_prototypes = false; @@ -5829,9 +5876,11 @@ static expression_t *parse_reference(void) next_token(); if (declaration == NULL) { - if (! strict_mode && token.type == '(') { - /* an implicitly defined function */ - if (warning.implicit_function_declaration) { + if (token.type == '(') { + /* an implicitly declared function */ + if (strict_mode) { + errorf(HERE, "unknown symbol '%Y' found.", symbol); + } else if (warning.implicit_function_declaration) { warningf(HERE, "implicit declaration of function '%Y'", symbol); } @@ -5840,11 +5889,11 @@ static expression_t *parse_reference(void) &source_position); } else { errorf(HERE, "unknown symbol '%Y' found.", symbol); - return create_invalid_expression(); + declaration = create_error_declaration(symbol, STORAGE_CLASS_NONE); } } - type_t *type = declaration->type; + type_t *type = declaration->type; /* we always do the auto-type conversions; the & and sizeof parser contains * code to revert this! */ @@ -5877,11 +5926,52 @@ static expression_t *parse_reference(void) return expression; } -static void check_cast_allowed(expression_t *expression, type_t *dest_type) +static bool semantic_cast(expression_t *cast) { - (void) expression; - (void) dest_type; - /* TODO check if explicit cast is allowed and issue warnings/errors */ + expression_t *expression = cast->unary.value; + type_t *orig_dest_type = cast->base.type; + type_t *orig_type_right = expression->base.type; + type_t const *dst_type = skip_typeref(orig_dest_type); + type_t const *src_type = skip_typeref(orig_type_right); + 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) + return true; + + /* only integer and pointer can be casted to pointer */ + if (is_type_pointer(dst_type) && + !is_type_pointer(src_type) && + !is_type_integer(src_type) && + is_type_valid(src_type)) { + errorf(pos, "cannot convert type '%T' to a pointer type", orig_type_right); + return false; + } + + if (!is_type_scalar(dst_type) && is_type_valid(dst_type)) { + errorf(pos, "conversion to non-scalar type '%T' requested", orig_dest_type); + return false; + } + + if (!is_type_scalar(src_type) && is_type_valid(src_type)) { + errorf(pos, "conversion from non-scalar type '%T' requested", orig_type_right); + return false; + } + + if (warning.cast_qual && + is_type_pointer(src_type) && + is_type_pointer(dst_type)) { + type_t *src = skip_typeref(src_type->pointer.points_to); + type_t *dst = skip_typeref(dst_type->pointer.points_to); + unsigned missing_qualifiers = + src->base.qualifiers & ~dst->base.qualifiers; + if (missing_qualifiers != 0) { + warningf(pos, + "cast discards qualifiers '%Q' in pointer target type of '%T'", + missing_qualifiers, orig_type_right); + } + } + return true; } static expression_t *parse_compound_literal(type_t *type) @@ -5923,12 +6013,13 @@ static expression_t *parse_cast(void) cast->base.source_position = source_position; expression_t *value = parse_sub_expression(20); - - check_cast_allowed(value, type); - cast->base.type = type; cast->unary.value = value; + if (! semantic_cast(cast)) { + /* TODO: record the error in the AST. else it is impossible to detect it */ + } + return cast; end_error: return create_invalid_expression(); @@ -5968,9 +6059,9 @@ end_error: } /** - * Parse a braced expression. + * Parse a parenthesized expression. */ -static expression_t *parse_brace_expression(void) +static expression_t *parse_parenthesized_expression(void) { eat('('); add_anchor_token(')'); @@ -6456,7 +6547,7 @@ static expression_t *parse_primary_expression(void) case T___builtin_prefetch: return parse_builtin_prefetch(); case T__assume: return parse_assume(); - case '(': return parse_brace_expression(); + case '(': return parse_parenthesized_expression(); case T___noop: return parse_noop_expression(); } @@ -6809,6 +6900,12 @@ static expression_t *parse_call_expression(unsigned precedence, check_format(&result->call); + if (warning.aggregate_return && + is_type_compound(skip_typeref(function_type->return_type))) { + warningf(&result->base.source_position, + "function call has aggregate value"); + } + return result; end_error: return create_invalid_expression(); @@ -6849,7 +6946,12 @@ static expression_t *parse_conditional_expression(unsigned precedence, &expression->base.source_position, condition_type_orig); } - expression_t *true_expression = parse_expression(); + expression_t *true_expression = expression; + bool gnu_cond = false; + if ((c_mode & _GNUC) && token.type == ':') { + gnu_cond = true; + } else + true_expression = parse_expression(); rem_anchor_token(':'); expect(':'); expression_t *false_expression = parse_sub_expression(precedence); @@ -6946,7 +7048,7 @@ static expression_t *parse_conditional_expression(unsigned precedence, } conditional->true_expression - = create_implicit_cast(true_expression, result_type); + = gnu_cond ? NULL : create_implicit_cast(true_expression, result_type); conditional->false_expression = create_implicit_cast(false_expression, result_type); conditional->base.type = result_type; @@ -6997,18 +7099,28 @@ static bool check_pointer_arithmetic(const source_position_t *source_position, type_t *points_to = pointer_type->pointer.points_to; points_to = skip_typeref(points_to); - if (is_type_incomplete(points_to) && - (! (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); - return false; + if (is_type_incomplete(points_to)) { + if (!(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); + return false; + } else if (warning.pointer_arith) { + warningf(source_position, + "pointer of type '%T' used in arithmetic", + orig_pointer_type); + } } else if (is_type_function(points_to)) { - errorf(source_position, - "arithmetic with pointer to function type '%T' not allowed", - orig_pointer_type); - return false; + if (!(c_mode && _GNUC)) { + errorf(source_position, + "arithmetic with pointer to function type '%T' not allowed", + orig_pointer_type); + return false; + } else if (warning.pointer_arith) { + warningf(source_position, + "pointer to a function '%T' used in arithmetic", + orig_pointer_type); + } } return true; } @@ -7204,16 +7316,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); - atomic_type_kind_t const rank_left = get_rank(type_left); - atomic_type_kind_t const rank_right = get_rank(type_right); + int const rank_left = get_rank(type_left); + int const rank_right = get_rank(type_right); if (signed_left == signed_right) return rank_left >= rank_right ? type_left : type_right; - atomic_type_kind_t s_rank; - atomic_type_kind_t u_rank; - type_t *s_type; - type_t *u_type; + int s_rank; + int u_rank; + type_t *s_type; + type_t *u_type; if (signed_left) { s_rank = rank_left; s_type = type_left; @@ -7229,13 +7341,16 @@ static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) if (u_rank >= s_rank) return u_type; - if (get_atomic_type_size(s_rank) > get_atomic_type_size(u_rank)) + /* 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)) return s_type; switch (s_rank) { - case ATOMIC_TYPE_INT: return type_int; - case ATOMIC_TYPE_LONG: return type_long; - case ATOMIC_TYPE_LONGLONG: return type_long_long; + 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"); } @@ -7268,6 +7383,24 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression) expression->base.type = arithmetic_type; } +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) { + warningf(&expression->base.source_position, "division by zero"); + } +} + +/** + * Check the semantic restrictions for a div/mod expression. + */ +static void semantic_divmod_arithmetic(binary_expression_t *expression) { + semantic_binexpr_arithmetic(expression); + warn_div_by_zero(expression); +} + static void semantic_shift_op(binary_expression_t *expression) { expression_t *const left = expression->left; @@ -7539,6 +7672,12 @@ static void semantic_arithmetic_assign(binary_expression_t *expression) expression->base.type = type_left; } +static void semantic_divmod_assign(binary_expression_t *expression) +{ + semantic_arithmetic_assign(expression); + warn_div_by_zero(expression); +} + static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression) { expression_t *const left = expression->left; @@ -7778,8 +7917,8 @@ static expression_t *parse_##binexpression_type(unsigned precedence, \ CREATE_BINEXPR_PARSER(',', EXPR_BINARY_COMMA, semantic_comma, 1) CREATE_BINEXPR_PARSER('*', EXPR_BINARY_MUL, semantic_binexpr_arithmetic, 1) -CREATE_BINEXPR_PARSER('/', EXPR_BINARY_DIV, semantic_binexpr_arithmetic, 1) -CREATE_BINEXPR_PARSER('%', EXPR_BINARY_MOD, semantic_binexpr_arithmetic, 1) +CREATE_BINEXPR_PARSER('/', EXPR_BINARY_DIV, semantic_divmod_arithmetic, 1) +CREATE_BINEXPR_PARSER('%', EXPR_BINARY_MOD, semantic_divmod_arithmetic, 1) CREATE_BINEXPR_PARSER('+', EXPR_BINARY_ADD, semantic_add, 1) CREATE_BINEXPR_PARSER('-', EXPR_BINARY_SUB, semantic_sub, 1) CREATE_BINEXPR_PARSER('<', EXPR_BINARY_LESS, semantic_comparison, 1) @@ -7816,9 +7955,9 @@ CREATE_BINEXPR_PARSER(T_MINUSEQUAL, EXPR_BINARY_SUB_ASSIGN, CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, EXPR_BINARY_MUL_ASSIGN, semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_SLASHEQUAL, EXPR_BINARY_DIV_ASSIGN, - semantic_arithmetic_assign, 0) + semantic_divmod_assign, 0) CREATE_BINEXPR_PARSER(T_PERCENTEQUAL, EXPR_BINARY_MOD_ASSIGN, - semantic_arithmetic_assign, 0) + semantic_divmod_assign, 0) CREATE_BINEXPR_PARSER(T_LESSLESSEQUAL, EXPR_BINARY_SHIFTLEFT_ASSIGN, semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_GREATERGREATEREQUAL, EXPR_BINARY_SHIFTRIGHT_ASSIGN, @@ -8229,7 +8368,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) + if (l->is_bad || l->is_empty || l->expression == NULL) continue; if (c->last_case < l->first_case || c->first_case > l->last_case) @@ -8973,8 +9112,9 @@ static statement_t *parse_empty_statement(void) if (warning.empty_statement) { warningf(HERE, "statement is empty"); } + statement_t *const statement = create_empty_statement(); eat(';'); - return create_empty_statement(); + return statement; } /** @@ -8989,15 +9129,25 @@ static statement_t *intern_parse_statement(void) /* declaration or statement */ add_anchor_token(';'); switch (token.type) { - case T_IDENTIFIER: - if (look_ahead(1)->type == ':') { + case T_IDENTIFIER: { + token_type_t la1_type = (token_type_t)look_ahead(1)->type; + if (la1_type == ':') { statement = parse_label_statement(); } else if (is_typedef_symbol(token.v.symbol)) { statement = parse_declaration_statement(); - } else { - statement = parse_expression_statement(); + } else switch (la1_type) { + DECLARATION_START + case T_IDENTIFIER: + case '*': + statement = parse_declaration_statement(); + break; + + default: + statement = parse_expression_statement(); + break; } break; + } case T___extension__: /* This can be a prefix to a declaration or an expression statement. @@ -9076,9 +9226,8 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) scope_t *last_scope = scope; set_scope(&statement->compound.scope); - statement_t *last_statement = NULL; - - bool only_decls_so_far = true; + statement_t **anchor = &statement->compound.statements; + bool only_decls_so_far = true; while (token.type != '}' && token.type != T_EOF) { statement_t *sub_statement = intern_parse_statement(); if (is_invalid_statement(sub_statement)) { @@ -9097,16 +9246,12 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) } } - if (last_statement != NULL) { - last_statement->base.next = sub_statement; - } else { - statement->compound.statements = sub_statement; - } + *anchor = sub_statement; while (sub_statement->base.next != NULL) sub_statement = sub_statement->base.next; - last_statement = sub_statement; + anchor = &sub_statement->base.next; } if (token.type == '}') { @@ -9156,13 +9301,20 @@ static void initialize_builtin_types(void) type_ptrdiff_t = make_global_typedef("__PTRDIFF_TYPE__", type_long); type_uintmax_t = make_global_typedef("__uintmax_t__", type_unsigned_long_long); type_uptrdiff_t = make_global_typedef("__UPTRDIFF_TYPE__", type_unsigned_long); - type_wchar_t = make_global_typedef("__WCHAR_TYPE__", type_int); + type_wchar_t = make_global_typedef("__WCHAR_TYPE__", opt_short_wchar_t ? type_unsigned_short : type_int); type_wint_t = make_global_typedef("__WINT_TYPE__", type_int); type_intmax_t_ptr = make_pointer_type(type_intmax_t, TYPE_QUALIFIER_NONE); 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); } /**