X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=443946edbddb1c6b4879b162e2f38d5af5c4d352;hb=c0e7bebc766fcdd5ed3e42ca34ef9bdb3c573f7a;hp=c1024ea46068094bd55af15652be40cfdbcf0ad7;hpb=716965c4aa64943d0283ea2828939850991cdc9d;p=cparser diff --git a/parser.c b/parser.c index c1024ea..443946e 100644 --- a/parser.c +++ b/parser.c @@ -1092,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); @@ -3060,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; @@ -3253,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; @@ -3278,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 */ @@ -3581,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; @@ -5662,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; @@ -5852,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); } @@ -5863,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! */ @@ -5900,44 +5926,49 @@ static expression_t *parse_reference(void) return expression; } -static bool semantic_cast(expression_t *expression, type_t *orig_dest_type) +static bool semantic_cast(expression_t *cast) { + 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 *dest_type = skip_typeref(orig_dest_type); - type_t const *orig_type = skip_typeref(orig_type_right); - source_position_t const *pos = &expression->base.source_position; + 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 (dest_type == type_void) + if (dst_type == type_void) return true; - if (is_type_pointer(dest_type)) { - /* only integer and pointer can be casted to pointer */ - if (!is_type_pointer(orig_type) && - !is_type_integer(orig_type) && - is_type_valid(orig_type)) { - errorf(pos, "cannot convert type '%T' to a pointer type", orig_type_right); - return false; - } - } else if (!is_type_scalar(dest_type) && is_type_valid(dest_type)) { + /* 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; - } else if (!is_type_scalar(orig_type) && is_type_valid(orig_type)) { + } + + 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(orig_type) && - is_type_pointer(dest_type)) { - type_t *src = skip_typeref(orig_type->pointer.points_to); - type_t *dst = skip_typeref(dest_type->pointer.points_to); + 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); + missing_qualifiers, orig_type_right); } } return true; @@ -5982,13 +6013,13 @@ static expression_t *parse_cast(void) cast->base.source_position = source_position; expression_t *value = parse_sub_expression(20); - - if (! semantic_cast(value, type)) - goto end_error; - 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(); @@ -9098,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.