X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=7321f2dd95afc60176a25b45d4b3a5fa0140dac1;hb=4633337d25ebd26db4dc4034216acee7e22765e7;hp=e4b159e222597e90f1d4e11c6f6eb9f50b402dc0;hpb=0b129be5ed4bae2c27b2f8d2119cc3dc37568bba;p=cparser diff --git a/parser.c b/parser.c index e4b159e..7321f2d 100644 --- a/parser.c +++ b/parser.c @@ -1001,7 +1001,7 @@ static bool is_null_pointer_constant(const expression_t *expression) return is_type_integer(type) && is_constant_expression(expression) && - fold_constant(expression) == 0; + !fold_constant_to_bool(expression); } /** @@ -2113,7 +2113,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, goto failed; } - long index = fold_constant(array_index); + long index = fold_constant_to_int(array_index); if (!used_in_offsetof) { if (index < 0) { errorf(&designator->source_position, @@ -2978,6 +2978,51 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) return entity; } +static entity_t *pack_bitfield_members(il_size_t *size, type_t *type, + size_t offset, entity_t *first) +{ + /* TODO: packed handling */ + type_t *base_type = skip_typeref(type->bitfield.base_type); + size_t remaining_bits = get_type_size(base_type) * BITS_PER_BYTE; + size_t bit_offset = 0; + + entity_t *member; + for (member = first; member != NULL; member = member->base.next) { + /* TODO: make this an assert */ + if (member->kind != ENTITY_COMPOUND_MEMBER) + continue; + + type_t *member_type = member->declaration.type; + if (member_type->kind != TYPE_BITFIELD) + break; + if (base_type != NULL + && skip_typeref(member_type->bitfield.base_type) != base_type) + break; + + size_t bit_size = member_type->bitfield.bit_size; + if (bit_size > remaining_bits) + break; + + member->compound_member.offset = offset; + member->compound_member.bit_offset = bit_offset; + + bit_offset += bit_size; + + /* 0-size members end current bucket. multiple 0-size buckets + * seem to not start-end multiple buckets */ + if (bit_size == 0) { + remaining_bits = 0; + } else { + remaining_bits -= bit_size; + } + } + assert(member != first); + + *size += (bit_offset + (BITS_PER_BYTE-1)) / BITS_PER_BYTE; + + return member; +} + /** * Finish the construction of a struct type by calculating its size, offsets, * alignment. @@ -2990,22 +3035,32 @@ static void finish_struct_type(compound_type_t *type) if (!compound->complete) return; - il_size_t size = 0; il_size_t offset; + il_size_t size = 0; il_alignment_t alignment = compound->alignment; bool need_pad = false; entity_t *entry = compound->members.entities; - for (; entry != NULL; entry = entry->base.next) { - if (entry->kind != ENTITY_COMPOUND_MEMBER) + while (entry != NULL) { + if (entry->kind != ENTITY_COMPOUND_MEMBER) { + entry = entry->base.next; continue; + } - type_t *m_type = entry->declaration.type; - if (! is_type_valid(skip_typeref(m_type))) { - /* simply ignore errors here */ + type_t *m_type = entry->declaration.type; + type_t *skipped = skip_typeref(m_type); + if (! is_type_valid(skipped)) { + entry = entry->base.next; continue; } - il_alignment_t m_alignment = get_type_alignment(m_type); + + type_t *base_type = m_type; + if (skipped->kind == TYPE_BITFIELD) { + base_type = m_type->bitfield.base_type; + } + + il_alignment_t m_alignment = get_type_alignment(base_type); + il_size_t m_size = get_type_size(base_type); if (m_alignment > alignment) alignment = m_alignment; @@ -3013,8 +3068,15 @@ static void finish_struct_type(compound_type_t *type) if (offset > size) need_pad = true; - entry->compound_member.offset = offset; - size = offset + get_type_size(m_type); + + if (skipped->kind == TYPE_BITFIELD) { + entry = pack_bitfield_members(&size, m_type, offset, entry); + } else { + entry->compound_member.offset = offset; + size = offset + m_size; + + entry = entry->base.next; + } } offset = (size + alignment - 1) & -alignment; @@ -4060,7 +4122,8 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_ if (size_expression != NULL) { if (is_constant_expression(size_expression)) { - long const size = fold_constant(size_expression); + long const size + = fold_constant_to_int(size_expression); array_type->array.size = size; array_type->array.size_constant = true; /* §6.7.5.2:1 If the expression is a constant expression, it shall @@ -5082,7 +5145,7 @@ static int determine_truth(expression_t const* const cond) { return !is_constant_expression(cond) ? 0 : - fold_constant(cond) != 0 ? 1 : + fold_constant_to_bool(cond) ? 1 : -1; } @@ -5295,7 +5358,7 @@ static void check_reachable(statement_t *const stmt) return; if (is_constant_expression(expr)) { - long const val = fold_constant(expr); + long const val = fold_constant_to_int(expr); case_label_statement_t * defaults = NULL; for (case_label_statement_t *i = switchs->first_case; i != NULL; i = i->next) { if (i->expression == NULL) { @@ -5882,14 +5945,18 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size, } if (is_constant_expression(size)) { - long v = fold_constant(size); + long v = fold_constant_to_int(size); + const symbol_t *user_symbol = symbol == NULL ? sym_anonymous : symbol; 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); + errorf(source_position, "negative width in bit-field '%Y'", + user_symbol); + } else if (v == 0 && symbol != NULL) { + errorf(source_position, "zero width for bit-field '%Y'", + user_symbol); } else if (bit_size > 0 && (il_size_t)v > bit_size) { - errorf(source_position, "width of '%Y' exceeds its type", symbol); + errorf(source_position, "width of '%Y' exceeds its type", + user_symbol); } else { type->bitfield.bit_size = v; } @@ -5908,12 +5975,12 @@ static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol) if (iter->base.symbol == symbol) { return iter; } else if (iter->base.symbol == NULL) { + /* search in anonymous structs and unions */ type_t *type = skip_typeref(iter->declaration.type); if (is_type_compound(type)) { - entity_t *result - = find_compound_entry(type->compound.compound, symbol); - if (result != NULL) - return result; + if (find_compound_entry(type->compound.compound, symbol) + != NULL) + return iter; } continue; } @@ -5922,6 +5989,98 @@ static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol) return NULL; } +static void check_deprecated(const source_position_t *source_position, + const entity_t *entity) +{ + if (!warning.deprecated_declarations) + return; + if (!is_declaration(entity)) + return; + if ((entity->declaration.modifiers & DM_DEPRECATED) == 0) + return; + + char const *const prefix = get_entity_kind_name(entity->kind); + const char *deprecated_string + = get_deprecated_string(entity->declaration.attributes); + if (deprecated_string != NULL) { + warningf(source_position, "%s '%Y' is deprecated (declared %P): \"%s\"", + prefix, entity->base.symbol, &entity->base.source_position, + deprecated_string); + } else { + warningf(source_position, "%s '%Y' is deprecated (declared %P)", prefix, + entity->base.symbol, &entity->base.source_position); + } +} + + +static expression_t *create_select(const source_position_t *pos, + expression_t *addr, + type_qualifiers_t qualifiers, + entity_t *entry) +{ + assert(entry->kind == ENTITY_COMPOUND_MEMBER); + + check_deprecated(pos, entry); + + expression_t *select = allocate_expression_zero(EXPR_SELECT); + select->select.compound = addr; + select->select.compound_entry = entry; + + type_t *entry_type = entry->declaration.type; + type_t *res_type = get_qualified_type(entry_type, qualifiers); + + /* we always do the auto-type conversions; the & and sizeof parser contains + * code to revert this! */ + select->base.type = automatic_type_conversion(res_type); + if (res_type->kind == TYPE_BITFIELD) { + select->base.type = res_type->bitfield.base_type; + } + + return select; +} + +/** + * Find entry with symbol in compound. Search anonymous structs and unions and + * creates implicit select expressions for them. + * Returns the adress for the innermost compound. + */ +static expression_t *find_create_select(const source_position_t *pos, + expression_t *addr, + type_qualifiers_t qualifiers, + compound_t *compound, symbol_t *symbol) +{ + entity_t *iter = compound->members.entities; + for (; iter != NULL; iter = iter->base.next) { + if (iter->kind != ENTITY_COMPOUND_MEMBER) + continue; + + symbol_t *iter_symbol = iter->base.symbol; + if (iter_symbol == NULL) { + type_t *type = iter->declaration.type; + if (type->kind != TYPE_COMPOUND_STRUCT + && type->kind != TYPE_COMPOUND_UNION) + continue; + + compound_t *sub_compound = type->compound.compound; + + if (find_compound_entry(sub_compound, symbol) == NULL) + continue; + + expression_t *sub_addr = create_select(pos, addr, qualifiers, iter); + sub_addr->base.source_position = *pos; + sub_addr->select.implicit = true; + return find_create_select(pos, sub_addr, qualifiers, sub_compound, + symbol); + } + + if (iter_symbol == symbol) { + return create_select(pos, addr, qualifiers, iter); + } + } + + return NULL; +} + static void parse_compound_declarators(compound_t *compound, const declaration_specifiers_t *specifiers) { @@ -5936,7 +6095,7 @@ static void parse_compound_declarators(compound_t *compound, expression_t *size = parse_constant_expression(); type_t *type = make_bitfield_type(base_type, size, - &source_position, sym_anonymous); + &source_position, NULL); attribute_t *attributes = parse_attributes(NULL); if (attributes != NULL) { @@ -6410,29 +6569,6 @@ type_t *revert_automatic_type_conversion(const expression_t *expression) } } -static void check_deprecated(const source_position_t *source_position, - const entity_t *entity) -{ - if (!warning.deprecated_declarations) - return; - if (!is_declaration(entity)) - return; - if ((entity->declaration.modifiers & DM_DEPRECATED) == 0) - return; - - char const *const prefix = get_entity_kind_name(entity->kind); - const char *deprecated_string - = get_deprecated_string(entity->declaration.attributes); - if (deprecated_string != NULL) { - warningf(source_position, "%s '%Y' is deprecated (declared %P): \"%s\"", - prefix, entity->base.symbol, &entity->base.source_position, - deprecated_string); - } else { - warningf(source_position, "%s '%Y' is deprecated (declared %P)", prefix, - entity->base.symbol, &entity->base.source_position); - } -} - static expression_t *parse_reference(void) { symbol_t *const symbol = token.v.symbol; @@ -7355,29 +7491,26 @@ static expression_t *parse_alignof(void) return parse_typeprop(EXPR_ALIGNOF); } -static expression_t *parse_select_expression(expression_t *compound) +static expression_t *parse_select_expression(expression_t *addr) { - expression_t *select = allocate_expression_zero(EXPR_SELECT); - select->select.compound = compound; - assert(token.type == '.' || token.type == T_MINUSGREATER); - bool is_pointer = (token.type == T_MINUSGREATER); + bool select_left_arrow = (token.type == T_MINUSGREATER); next_token(); if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing select", T_IDENTIFIER, NULL); - return select; + return create_invalid_expression(); } symbol_t *symbol = token.v.symbol; next_token(); - type_t *const orig_type = compound->base.type; + type_t *const orig_type = addr->base.type; type_t *const type = skip_typeref(orig_type); type_t *type_left; bool saw_error = false; if (is_type_pointer(type)) { - if (!is_pointer) { + if (!select_left_arrow) { errorf(HERE, "request for member '%Y' in something not a struct or union, but '%T'", symbol, orig_type); @@ -7385,58 +7518,41 @@ static expression_t *parse_select_expression(expression_t *compound) } type_left = skip_typeref(type->pointer.points_to); } else { - if (is_pointer && is_type_valid(type)) { + if (select_left_arrow && is_type_valid(type)) { errorf(HERE, "left hand side of '->' is not a pointer, but '%T'", orig_type); saw_error = true; } type_left = type; } - entity_t *entry; - if (type_left->kind == TYPE_COMPOUND_STRUCT || - type_left->kind == TYPE_COMPOUND_UNION) { - compound_t *compound = type_left->compound.compound; + if (type_left->kind != TYPE_COMPOUND_STRUCT && + type_left->kind != TYPE_COMPOUND_UNION) { - if (!compound->complete) { - errorf(HERE, "request for member '%Y' of incomplete type '%T'", - symbol, type_left); - goto create_error_entry; - } - - entry = find_compound_entry(compound, symbol); - if (entry == NULL) { - errorf(HERE, "'%T' has no member named '%Y'", orig_type, symbol); - goto create_error_entry; - } - } else { if (is_type_valid(type_left) && !saw_error) { errorf(HERE, "request for member '%Y' in something not a struct or union, but '%T'", symbol, type_left); } -create_error_entry: - entry = create_error_entity(symbol, ENTITY_COMPOUND_MEMBER); + return create_invalid_expression(); } - assert(is_declaration(entry)); - select->select.compound_entry = entry; - - check_deprecated(HERE, entry); - - type_t *entry_type = entry->declaration.type; - type_t *res_type - = get_qualified_type(entry_type, type_left->base.qualifiers); + compound_t *compound = type_left->compound.compound; + if (!compound->complete) { + errorf(HERE, "request for member '%Y' in incomplete type '%T'", + symbol, type_left); + return create_invalid_expression(); + } - /* we always do the auto-type conversions; the & and sizeof parser contains - * code to revert this! */ - select->base.type = automatic_type_conversion(res_type); + type_qualifiers_t qualifiers = type_left->base.qualifiers; + expression_t *result + = find_create_select(HERE, addr, qualifiers, compound, symbol); - type_t *skipped = skip_typeref(res_type); - if (skipped->kind == TYPE_BITFIELD) { - select->base.type = skipped->bitfield.base_type; + if (result == NULL) { + errorf(HERE, "'%T' has no member named '%Y'", orig_type, symbol); + return create_invalid_expression(); } - return select; + return result; } static void check_call_argument(type_t *expected_type, @@ -8320,7 +8436,7 @@ static void warn_div_by_zero(binary_expression_t const *const expression) /* 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) { + !fold_constant_to_bool(right)) { warningf(&expression->base.source_position, "division by zero"); } } @@ -8371,7 +8487,7 @@ static bool semantic_shift(binary_expression_t *expression) type_left = promote_integer(type_left); if (is_constant_expression(right)) { - long count = fold_constant(right); + long count = fold_constant_to_int(right); if (count < 0) { warningf(&right->base.source_position, "shift count must be non-negative"); @@ -8520,7 +8636,7 @@ static bool maybe_negative(expression_t const *const expr) { return !is_constant_expression(expr) || - fold_constant(expr) < 0; + fold_constant_to_int(expr) < 0; } /** @@ -9378,7 +9494,7 @@ static statement_t *parse_case_statement(void) } statement->case_label.is_bad = true; } else { - long const val = fold_constant(expression); + long const val = fold_constant_to_int(expression); statement->case_label.first_case = val; statement->case_label.last_case = val; } @@ -9397,7 +9513,7 @@ static statement_t *parse_case_statement(void) } statement->case_label.is_bad = true; } else { - long const val = fold_constant(end_range); + long const val = fold_constant_to_int(end_range); statement->case_label.last_case = val; if (warning.other && val < statement->case_label.first_case) { @@ -9625,7 +9741,7 @@ static void check_enum_cases(const switch_statement_t *statement) for (; entry != NULL && entry->kind == ENTITY_ENUM_VALUE; entry = entry->base.next) { const expression_t *expression = entry->enum_value.value; - long value = expression != NULL ? fold_constant(expression) : last_value + 1; + long value = expression != NULL ? fold_constant_to_int(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)