X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=c4523d80034f1cee86be46589d7290717e28512c;hb=953a820405dfd857ff9f5e24f3b630b6103dad46;hp=dab67a1b4b1a8f4b0d78b2c6fdeea161278db180;hpb=acd1bd5e2ef817b3c4dd5ad765bb54b7e33a715c;p=cparser diff --git a/parser.c b/parser.c index dab67a1..c4523d8 100644 --- a/parser.c +++ b/parser.c @@ -134,6 +134,9 @@ static struct obstack temp_obst; static source_position_t null_position = { NULL, 0 }; +/** special symbol used for anonymous entities. */ +static const symbol_t *sym_anonymous = NULL; + /* symbols for Microsoft extended-decl-modifier */ static const symbol_t *sym_align = NULL; static const symbol_t *sym_allocate = NULL; @@ -1030,7 +1033,7 @@ static void report_assign_error(assign_error_t error, type_t *orig_type_left, case ASSIGN_WARNING_POINTER_FROM_INT: warningf(source_position, - "%s makes integer '%T' from pointer '%T' without a cast", + "%s makes pointer '%T' from integer '%T' without a cast", context, orig_type_left, orig_type_right); return; @@ -2148,8 +2151,6 @@ static void descend_into_subtype(type_path_t *path) type_t *orig_top_type = path->top_type; type_t *top_type = skip_typeref(orig_top_type); - assert(is_type_compound(top_type) || is_type_array(top_type)); - type_path_entry_t *top = append_to_type_path(path); top->type = top_type; @@ -2163,11 +2164,11 @@ static void descend_into_subtype(type_path_t *path) } else { path->top_type = NULL; } - } else { - assert(is_type_array(top_type)); - + } else if (is_type_array(top_type)) { top->v.index = 0; path->top_type = top_type->array.element_type; + } else { + assert(!is_type_valid(top_type)); } } @@ -2696,7 +2697,6 @@ static declaration_t *parse_compound_type_specifier(bool is_struct) errorf(HERE, "multiple definitions of '%s %Y' (previous definition at %P)", is_struct ? "struct" : "union", symbol, &declaration->source_position); - declaration->scope.declarations = NULL; } } } else if (token.type != '{') { @@ -2711,18 +2711,17 @@ static declaration_t *parse_compound_type_specifier(bool is_struct) return NULL; } - if (declaration == NULL) { - declaration = allocate_declaration_zero(); - declaration->namespc = - (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION); - declaration->source_position = token.source_position; - declaration->symbol = symbol; - declaration->parent_scope = scope; - if (symbol != NULL) { - environment_push(declaration); - } - append_declaration(declaration); + /* always create a new declaration, do NOT modify old one */ + declaration = allocate_declaration_zero(); + declaration->namespc = + (is_struct ? NAMESPACE_STRUCT : NAMESPACE_UNION); + declaration->source_position = token.source_position; + declaration->symbol = symbol; + declaration->parent_scope = scope; + if (symbol != NULL) { + environment_push(declaration); } + append_declaration(declaration); if (token.type == '{') { declaration->init.complete = true; @@ -2785,11 +2784,14 @@ end_error: ; } +/** + * Parse enum specifier and return the enum type or NULL on error. + */ static type_t *parse_enum_specifier(void) { - gnu_attribute_t *attributes = NULL; - declaration_t *declaration; - symbol_t *symbol; + gnu_attribute_t *attributes = NULL; + declaration_t *declaration = NULL; + symbol_t *symbol = NULL; eat(T_enum); if (token.type == T_IDENTIFIER) { @@ -2801,30 +2803,31 @@ static type_t *parse_enum_specifier(void) parse_error_expected("while parsing enum type specifier", T_IDENTIFIER, '{', NULL); return NULL; - } else { - declaration = NULL; - symbol = NULL; } - if (declaration == NULL) { - declaration = allocate_declaration_zero(); - declaration->namespc = NAMESPACE_ENUM; - declaration->source_position = token.source_position; - declaration->symbol = symbol; - declaration->parent_scope = scope; + if (token.type == '{' && declaration != NULL && declaration->init.complete) { + errorf(HERE, "multiple definitions of enum '%Y' (previous definition at %P)", + symbol, &declaration->source_position); } + declaration = allocate_declaration_zero(); + declaration->namespc = NAMESPACE_ENUM; + declaration->source_position = token.source_position; + declaration->symbol = symbol; + declaration->parent_scope = scope; + if (symbol != NULL) { + environment_push(declaration); + } + append_declaration(declaration); + type_t *const type = allocate_type_zero(TYPE_ENUM, &declaration->source_position); type->enumt.declaration = declaration; if (token.type == '{') { if (declaration->init.complete) { - errorf(HERE, "multiple definitions of enum %Y", symbol); - } - if (symbol != NULL) { - environment_push(declaration); + errorf(HERE, "multiple definitions of enum '%Y' (previous definition at %P)", + symbol, &declaration->source_position); } - append_declaration(declaration); declaration->init.complete = true; parse_enum_entries(type); @@ -3131,33 +3134,38 @@ static void finish_struct_type(compound_type_t *type) { if (! struct_decl->init.complete) return; - il_size_t size = 0; - il_size_t new_size; - il_alignment_t alignment = 1; - bool need_pad = false; + il_size_t size = 0; + il_size_t offset; + il_alignment_t alignment = 1; + bool need_pad = false; declaration_t *entry = struct_decl->scope.declarations; for (; entry != NULL; entry = entry->next) { if (entry->namespc != NAMESPACE_NORMAL) continue; - type_t *m_type = skip_typeref(entry->type); - il_alignment_t m_alignment = m_type->base.alignment; - - new_size = (size + m_alignment - 1) & -m_alignment; + type_t *m_type = skip_typeref(entry->type); + if (! is_type_valid(m_type)) { + /* simply ignore errors here */ + continue; + } + il_alignment_t m_alignment = m_type->base.alignment; if (m_alignment > alignment) alignment = m_alignment; - if (new_size > size) + + offset = (size + m_alignment - 1) & -m_alignment; + + if (offset > size) need_pad = true; - entry->offset = new_size; - size = new_size + m_type->base.size; + entry->offset = offset; + size = offset + m_type->base.size; } if (type->base.alignment != 0) { alignment = type->base.alignment; } - new_size = (size + alignment - 1) & -alignment; - if (new_size > size) + offset = (size + alignment - 1) & -alignment; + if (offset > size) need_pad = true; if (warning.padded && need_pad) { @@ -3170,7 +3178,7 @@ static void finish_struct_type(compound_type_t *type) { type, struct_decl->symbol); } - type->base.size = new_size; + type->base.size = offset; type->base.alignment = alignment; } @@ -3194,6 +3202,8 @@ static void finish_union_type(compound_type_t *type) { continue; type_t *m_type = skip_typeref(entry->type); + if (! is_type_valid(m_type)) + continue; entry->offset = 0; if (m_type->base.size > size) @@ -4452,8 +4462,9 @@ static declaration_t *record_declaration( if (old_storage_class == STORAGE_CLASS_EXTERN && new_storage_class == STORAGE_CLASS_EXTERN) { warn_redundant_declaration: - if (!is_definition && - warning.redundant_decls && + if (!is_definition && + warning.redundant_decls && + is_type_valid(prev_type) && strcmp(previous_declaration->source_position.input_name, "") != 0) { warningf(&declaration->source_position, "redundant declaration for '%Y' (declared %P)", @@ -4471,14 +4482,16 @@ warn_redundant_declaration: } else { goto warn_redundant_declaration; } - } else if (old_storage_class == new_storage_class) { - errorf(&declaration->source_position, - "redeclaration of '%Y' (declared %P)", - symbol, &previous_declaration->source_position); - } else { - errorf(&declaration->source_position, - "redeclaration of '%Y' with different linkage (declared %P)", - symbol, &previous_declaration->source_position); + } else if (is_type_valid(prev_type)) { + if (old_storage_class == new_storage_class) { + errorf(&declaration->source_position, + "redeclaration of '%Y' (declared %P)", + symbol, &previous_declaration->source_position); + } else { + errorf(&declaration->source_position, + "redeclaration of '%Y' with different linkage (declared %P)", + symbol, &previous_declaration->source_position); + } } } @@ -4590,24 +4603,26 @@ static void parse_anonymous_declaration_rest( { eat(';'); + if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) { + warningf(&specifiers->source_position, + "useless storage class in empty declaration"); + } + +#ifdef RECORD_EMPTY_DECLARARTIONS declaration_t *const declaration = allocate_declaration_zero(); declaration->type = specifiers->type; declaration->declared_storage_class = specifiers->declared_storage_class; declaration->source_position = specifiers->source_position; declaration->modifiers = specifiers->modifiers; + declaration->storage_class = STORAGE_CLASS_NONE; +#endif - if (declaration->declared_storage_class != STORAGE_CLASS_NONE) { - warningf(&declaration->source_position, - "useless storage class in empty declaration"); - } - declaration->storage_class = STORAGE_CLASS_NONE; - - type_t *type = declaration->type; + type_t *type = specifiers->type; switch (type->kind) { case TYPE_COMPOUND_STRUCT: case TYPE_COMPOUND_UNION: { if (type->compound.declaration->symbol == NULL) { - warningf(&declaration->source_position, + warningf(&specifiers->source_position, "unnamed struct/union that defines no instances"); } break; @@ -4617,11 +4632,13 @@ static void parse_anonymous_declaration_rest( break; default: - warningf(&declaration->source_position, "empty declaration"); + warningf(&specifiers->source_position, "empty declaration"); break; } +#ifdef RECORD_EMPTY_DECLARARTIONS append_declaration(declaration); +#endif } static void parse_declaration_rest(declaration_t *ndeclaration, @@ -5510,12 +5527,40 @@ static void parse_external_declaration(void) } static type_t *make_bitfield_type(type_t *base_type, expression_t *size, - source_position_t *source_position) + source_position_t *source_position, + const symbol_t *symbol) { type_t *type = allocate_type_zero(TYPE_BITFIELD, source_position); - type->bitfield.base_type = base_type; - type->bitfield.size = size; + type->bitfield.base_type = base_type; + type->bitfield.size_expression = size; + + il_size_t bit_size; + type_t *skipped_type = skip_typeref(base_type); + if (!is_type_integer(skipped_type)) { + errorf(HERE, "bitfield base type '%T' is not an integer type", + base_type); + bit_size = 0; + } else { + bit_size = skipped_type->base.size * 8; + } + + if (is_constant_expression(size)) { + long v = fold_constant(size); + + if (v < 0) { + errorf(source_position, "negative width in bit-field '%Y'", + symbol); + } else if (v == 0) { + errorf(source_position, "zero width for bit-field '%Y'", + symbol); + } else if (bit_size > 0 && (il_size_t)v > bit_size) { + errorf(source_position, "width of '%Y' exceeds its type", + symbol); + } else { + type->bitfield.bit_size = v; + } + } return type; } @@ -5567,12 +5612,8 @@ static void parse_compound_declarators(declaration_t *struct_declaration, type_t *base_type = specifiers->type; expression_t *size = parse_constant_expression(); - if (!is_type_integer(skip_typeref(base_type))) { - errorf(HERE, "bitfield base type '%T' is not an integer type", - base_type); - } - - type_t *type = make_bitfield_type(base_type, size, &source_position); + type_t *type = make_bitfield_type(base_type, size, + &source_position, sym_anonymous); declaration = allocate_declaration_zero(); declaration->namespc = NAMESPACE_NORMAL; @@ -5592,12 +5633,8 @@ static void parse_compound_declarators(declaration_t *struct_declaration, next_token(); expression_t *size = parse_constant_expression(); - if (!is_type_integer(type)) { - errorf(HERE, "bitfield base type '%T' is not an integer type", - orig_type); - } - - type_t *bitfield_type = make_bitfield_type(orig_type, size, &source_position); + type_t *bitfield_type = make_bitfield_type(orig_type, size, + &source_position, declaration->symbol); declaration->type = bitfield_type; } else { /* TODO we ignore arrays for now... what is missing is a check @@ -6048,21 +6085,15 @@ static expression_t *parse_reference(void) declaration_t *declaration = get_declaration(symbol, NAMESPACE_NORMAL); - source_position_t source_position = token.source_position; - next_token(); - if (declaration == NULL) { - if (token.type == '(') { + if (!strict_mode && look_ahead(1)->type == '(') { /* an implicitly declared function */ - if (strict_mode) { - errorf(HERE, "unknown symbol '%Y' found.", symbol); - } else if (warning.implicit_function_declaration) { + if (warning.implicit_function_declaration) { warningf(HERE, "implicit declaration of function '%Y'", symbol); } - declaration = create_implicit_function(symbol, - &source_position); + declaration = create_implicit_function(symbol, HERE); } else { errorf(HERE, "unknown symbol '%Y' found.", symbol); declaration = create_error_declaration(symbol, STORAGE_CLASS_NONE); @@ -6088,23 +6119,21 @@ static expression_t *parse_reference(void) "function" : "variable"; if (declaration->deprecated_string != NULL) { - warningf(&source_position, - "%s '%Y' is deprecated (declared %P): \"%s\"", prefix, - declaration->symbol, &declaration->source_position, + warningf(HERE, "%s '%Y' is deprecated (declared %P): \"%s\"", + prefix, declaration->symbol, &declaration->source_position, declaration->deprecated_string); } else { - warningf(&source_position, - "%s '%Y' is deprecated (declared %P)", prefix, + warningf(HERE, "%s '%Y' is deprecated (declared %P)", prefix, declaration->symbol, &declaration->source_position); } } if (warning.init_self && declaration == current_init_decl) { current_init_decl = NULL; - warningf(&source_position, - "variable '%#T' is initialized by itself", + warningf(HERE, "variable '%#T' is initialized by itself", declaration->type, declaration->symbol); } + next_token(); return expression; } @@ -6860,19 +6889,18 @@ static expression_t *parse_array_expression(unsigned precedence, orig_type_left, orig_type_inside); } return_type = type_error_type; - array_access->array_ref = create_invalid_expression(); + array_access->array_ref = left; + array_access->index = inside; } + expression->base.type = automatic_type_conversion(return_type); + rem_anchor_token(']'); - if (token.type != ']') { + if (token.type == ']') { + next_token(); + } else { parse_error_expected("Problem while parsing array access", ']', NULL); - return expression; } - next_token(); - - return_type = automatic_type_conversion(return_type); - expression->base.type = return_type; - return expression; } @@ -6992,7 +7020,7 @@ static expression_t *parse_select_expression(unsigned precedence, if (!declaration->init.complete) { errorf(HERE, "request for member '%Y' of incomplete type '%T'", symbol, type_left); - return create_invalid_expression(); + goto create_error_entry; } entry = find_compound_entry(declaration, symbol); @@ -7074,26 +7102,15 @@ static void check_call_argument(const function_parameter_t *parameter, snprintf(buf, sizeof(buf), "call argument %u", pos); report_assign_error(error, expected_type, arg_expr, buf, &arg_expr->base.source_position); - } else if (warning.traditional | warning.conversion) { - if ( - /* passing as integer instead of float or complex */ - (is_type_integer(expected_type) && - (is_type_float(arg_type) || is_type_complex(arg_type))) || - /* passing as complex instead of integer or float */ - (is_type_complex(expected_type) && - (is_type_integer(arg_type) || is_type_float(arg_type))) || - /* passing as float instead of integer or complex */ - (is_type_float(expected_type) && - (is_type_integer(arg_type) || is_type_complex(arg_type))) || - /* passing as float instead of double */ - (is_type_float(expected_type) && expected_type != type_double && - is_type_float(arg_type))) { + } else if (warning.traditional || warning.conversion) { + type_t *const promoted_type = get_default_promoted_type(arg_type); + if (!types_compatible(expected_type_skip, promoted_type) && + !types_compatible(expected_type_skip, type_void_ptr) && + !types_compatible(type_void_ptr, promoted_type)) { + /* Deliberately show the skipped types in this warning */ warningf(&arg_expr->base.source_position, "passing call argument %u as '%T' rather than '%T' due to prototype", - pos, expected_type, arg_type); - } - if (is_type_integer(expected_type) && is_type_integer(arg_type)) { - /* TODO check for size HERE */ + pos, expected_type_skip, promoted_type); } } } @@ -7614,6 +7631,9 @@ static type_t *semantic_arithmetic(type_t *type_left, type_t *type_right) { /* TODO: handle complex + imaginary types */ + type_left = get_unqualified_type(type_left); + type_right = get_unqualified_type(type_right); + /* § 6.3.1.8 Usual arithmetic conversions */ if (type_left == type_long_double || type_right == type_long_double) { return type_long_double; @@ -7700,10 +7720,15 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression) 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) { + if (!warning.div_by_zero || + !is_type_integer(expression->base.type)) + return; + + expression_t const *const right = expression->right; + /* The type of the right operand can be different for /= */ + if (is_type_integer(right->base.type) && + is_constant_expression(right) && + fold_constant(right) == 0) { warningf(&expression->base.source_position, "division by zero"); } } @@ -8629,12 +8654,18 @@ static statement_t *parse_case_statement(void) source_position_t *const pos = &statement->base.source_position; *pos = token.source_position; - statement->case_label.expression = parse_expression(); - if (! is_constant_expression(statement->case_label.expression)) { - errorf(pos, "case label does not reduce to an integer constant"); + expression_t *const expression = parse_expression(); + statement->case_label.expression = expression; + if (!is_constant_expression(expression)) { + /* This check does not prevent the error message in all cases of an + * prior error while parsing the expression. At least it catches the + * common case of a mistyped enum entry. */ + if (is_type_valid(expression->base.type)) { + 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); + long const val = fold_constant(expression); statement->case_label.first_case = val; statement->case_label.last_case = val; } @@ -8642,16 +8673,22 @@ static statement_t *parse_case_statement(void) 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"); + expression_t *const end_range = parse_expression(); + statement->case_label.end_range = end_range; + if (!is_constant_expression(end_range)) { + /* This check does not prevent the error message in all cases of an + * prior error while parsing the expression. At least it catches the + * common case of a mistyped enum entry. */ + if (is_type_valid(end_range->base.type)) { + 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); + long const val = fold_constant(end_range); statement->case_label.last_case = val; if (val < statement->case_label.first_case) { - statement->case_label.is_empty = true; + statement->case_label.is_empty_range = true; warningf(pos, "empty range specified"); } } @@ -8667,7 +8704,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 || l->expression == NULL) + if (l->is_bad || l->is_empty_range || l->expression == NULL) continue; if (c->last_case < l->first_case || c->first_case > l->last_case) @@ -9479,13 +9516,18 @@ static statement_t *intern_parse_statement(void) } else if (is_typedef_symbol(token.v.symbol)) { statement = parse_declaration_statement(); } else switch (la1_type) { + case '*': + if (get_declaration(token.v.symbol, NAMESPACE_NORMAL) != NULL) + goto expression_statment; + /* FALLTHROUGH */ + DECLARATION_START case T_IDENTIFIER: - case '*': statement = parse_declaration_statement(); break; default: +expression_statment: statement = parse_expression_statement(); break; } @@ -9813,6 +9855,8 @@ void parse(void) */ void init_parser(void) { + sym_anonymous = symbol_table_insert(""); + if (c_mode & _MS) { /* add predefined symbols for extended-decl-modifier */ sym_align = symbol_table_insert("align");