X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=1686f34e6c5a9a0de68a855211185b52b5831aee;hb=22d24ddd2209686fa723a62ccc19b7c2eea2d172;hp=ebecc3d9176f9742193429cfd07a538ca867babb;hpb=27040b8042ae6b0ac7974f52abd95d7562da6d9a;p=cparser diff --git a/parser.c b/parser.c index ebecc3d..1686f34 100644 --- a/parser.c +++ b/parser.c @@ -1,6 +1,6 @@ /* * This file is part of cparser. - * Copyright (C) 2007-2008 Matthias Braun + * Copyright (C) 2007-2009 Matthias Braun * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -58,7 +58,6 @@ struct declaration_specifiers_t { unsigned char alignment; /**< Alignment, 0 if not set. */ bool is_inline : 1; bool thread_local : 1; /**< GCC __thread */ - bool deprecated : 1; attribute_t *attributes; /**< list of attributes */ type_t *type; }; @@ -115,7 +114,7 @@ static declaration_t **incomplete_arrays; #define POP_PARENT ((void)(current_parent = prev_parent)) /** special symbol used for anonymous entities. */ -static const symbol_t *sym_anonymous = NULL; +static symbol_t *sym_anonymous = NULL; /** The token anchor set */ static unsigned char token_anchor_set[T_LAST_TOKEN]; @@ -797,7 +796,7 @@ static entity_t *get_entity(const symbol_t *const symbol, /* §6.2.3:1 24) There is only one name space for tags even though three are * possible. */ static entity_t *get_tag(symbol_t const *const symbol, - entity_kind_tag_t const kind) + entity_kind_tag_t const kind) { entity_t *entity = get_entity(symbol, NAMESPACE_TAG); if (entity != NULL && entity->kind != kind) { @@ -1002,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); } /** @@ -1307,6 +1306,7 @@ static symbol_t *get_symbol_from_token(void) { switch(token.type) { case T_IDENTIFIER: + return token.v.symbol; case T_auto: case T_char: case T_double: @@ -1336,7 +1336,7 @@ static symbol_t *get_symbol_from_token(void) case T_volatile: case T_inline: /* maybe we need more tokens ... add them on demand */ - return token.v.symbol; + return get_token_symbol(&token); default: return NULL; } @@ -1840,11 +1840,6 @@ static initializer_t *initializer_from_expression(type_t *orig_type, &expression->base.source_position); initializer_t *const result = allocate_initializer_zero(INITIALIZER_VALUE); -#if 0 - if (type->kind == TYPE_BITFIELD) { - type = type->bitfield.base_type; - } -#endif result->value.value = create_implicit_cast(expression, type); return result; @@ -1882,7 +1877,7 @@ static initializer_t *parse_scalar_initializer(type_t *type, mark_vars_read(expression, NULL); if (must_be_constant && !is_initializer_constant(expression)) { errorf(&expression->base.source_position, - "Initialisation expression '%E' is not constant", + "initialisation expression '%E' is not constant", expression); } @@ -2113,7 +2108,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, @@ -2382,10 +2377,10 @@ finish_designator: error_excess: if (warning.other) { if (env->entity != NULL) { - warningf(HERE, "excess elements in struct initializer for '%Y'", - env->entity->base.symbol); + warningf(HERE, "excess elements in initializer for '%Y'", + env->entity->base.symbol); } else { - warningf(HERE, "excess elements in struct initializer"); + warningf(HERE, "excess elements in initializer"); } } } @@ -2532,11 +2527,12 @@ static compound_t *parse_compound_type_specifier(bool is_struct) eat(T_union); } - symbol_t *symbol = NULL; - compound_t *compound = NULL; + symbol_t *symbol = NULL; + compound_t *compound = NULL; + attribute_t *attributes = NULL; if (token.type == T___attribute__) { - parse_attributes(NULL); + attributes = parse_attributes(NULL); } entity_kind_tag_t const kind = is_struct ? ENTITY_STRUCT : ENTITY_UNION; @@ -2578,6 +2574,7 @@ static compound_t *parse_compound_type_specifier(bool is_struct) entity_t *entity = allocate_entity_zero(kind); compound = &entity->compound; + compound->alignment = 1; compound->base.namespc = NAMESPACE_TAG; compound->base.source_position = token.source_position; compound->base.symbol = symbol; @@ -2590,7 +2587,6 @@ static compound_t *parse_compound_type_specifier(bool is_struct) if (token.type == '{') { parse_compound_type_entries(compound); - parse_attributes(NULL); /* ISO/IEC 14882:1998(E) §7.1.3:5 */ if (symbol == NULL) { @@ -2599,6 +2595,10 @@ static compound_t *parse_compound_type_specifier(bool is_struct) } } + if (attributes != NULL) { + handle_entity_attributes(attributes, (entity_t*) compound); + } + return compound; } @@ -2978,101 +2978,6 @@ static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) return entity; } -/** - * Finish the construction of a struct type by calculating its size, offsets, - * alignment. - */ -static void finish_struct_type(compound_type_t *type) -{ - assert(type->compound != NULL); - - compound_t *compound = type->compound; - if (!compound->complete) - return; - - il_size_t size = 0; - il_size_t offset; - 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) - continue; - - type_t *m_type = entry->declaration.type; - if (! is_type_valid(skip_typeref(m_type))) { - /* simply ignore errors here */ - continue; - } - il_alignment_t m_alignment = get_type_alignment(m_type); - if (m_alignment > alignment) - alignment = m_alignment; - - offset = (size + m_alignment - 1) & -m_alignment; - - if (offset > size) - need_pad = true; - entry->compound_member.offset = offset; - size = offset + get_type_size(m_type); - } - - offset = (size + alignment - 1) & -alignment; - if (offset > size) - need_pad = true; - - if (need_pad) { - if (warning.padded) { - warningf(&compound->base.source_position, "'%T' needs padding", - type); - } - } else if (compound->packed && warning.packed) { - warningf(&compound->base.source_position, - "superfluous packed attribute on '%T'", type); - } - - compound->size = offset; - compound->alignment = alignment; -} - -/** - * Finish the construction of an union type by calculating - * its size and alignment. - */ -static void finish_union_type(compound_type_t *type) -{ - assert(type->compound != NULL); - - compound_t *compound = type->compound; - if (! compound->complete) - return; - - il_size_t size = 0; - il_alignment_t alignment = compound->alignment; - - entity_t *entry = compound->members.entities; - for (; entry != NULL; entry = entry->base.next) { - if (entry->kind != ENTITY_COMPOUND_MEMBER) - continue; - - type_t *m_type = entry->declaration.type; - if (! is_type_valid(m_type)) - continue; - - entry->compound_member.offset = 0; - il_size_t m_size = get_type_size(m_type); - if (m_size > size) - size = m_size; - il_alignment_t m_alignment = get_type_alignment(m_type); - if (m_alignment > alignment) - alignment = m_alignment; - } - size = (size + alignment - 1) & -alignment; - - compound->size = size; - compound->alignment = alignment; -} - static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) { type_t *type = NULL; @@ -3218,13 +3123,11 @@ wrong_thread_stoarge_class: type = allocate_type_zero(TYPE_COMPOUND_STRUCT); type->compound.compound = parse_compound_type_specifier(true); - finish_struct_type(&type->compound); break; case T_union: CHECK_DOUBLE_TYPE(); type = allocate_type_zero(TYPE_COMPOUND_UNION); type->compound.compound = parse_compound_type_specifier(false); - finish_union_type(&type->compound); break; case T_enum: CHECK_DOUBLE_TYPE(); @@ -3621,8 +3524,7 @@ static void parse_parameters(function_type_t *type, scope_t *scope) !is_typedef_symbol(token.v.symbol)) { token_type_t la1_type = (token_type_t)look_ahead(1)->type; if (la1_type == ',' || la1_type == ')') { - type->kr_style_parameters = true; - type->unspecified_parameters = true; + type->kr_style_parameters = true; parse_identifier_list(scope); goto parameters_finished; } @@ -3816,21 +3718,8 @@ static construct_type_t *parse_function_declarator(scope_t *scope) type_t *type = allocate_type_zero(TYPE_FUNCTION); function_type_t *ftype = &type->function; - ftype->linkage = current_linkage; - -#if 0 - switch (modifiers & (DM_CDECL | DM_STDCALL | DM_FASTCALL | DM_THISCALL)) { - case DM_NONE: break; - case DM_CDECL: ftype->calling_convention = CC_CDECL; break; - case DM_STDCALL: ftype->calling_convention = CC_STDCALL; break; - case DM_FASTCALL: ftype->calling_convention = CC_FASTCALL; break; - case DM_THISCALL: ftype->calling_convention = CC_THISCALL; break; - - default: - errorf(HERE, "multiple calling conventions in declaration"); - break; - } -#endif + ftype->linkage = current_linkage; + ftype->calling_convention = CC_DEFAULT; parse_parameters(ftype, scope); @@ -4060,7 +3949,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 @@ -4268,7 +4158,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, storage_class_t storage_class = specifiers->storage_class; entity->declaration.declared_storage_class = storage_class; - if (storage_class == STORAGE_CLASS_NONE && current_scope != file_scope) + if (storage_class == STORAGE_CLASS_NONE && current_function != NULL) storage_class = STORAGE_CLASS_AUTO; entity->declaration.storage_class = storage_class; } @@ -4308,7 +4198,7 @@ static type_t *parse_abstract_declarator(type_t *base_type) * @param decl the declaration to check * @param type the function type of the declaration */ -static void check_type_of_main(const entity_t *entity) +static void check_main(const entity_t *entity) { const source_position_t *pos = &entity->base.source_position; if (entity->kind != ENTITY_FUNCTION) { @@ -4417,7 +4307,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) if (warning.main && current_scope == file_scope && is_sym_main(symbol)) { - check_type_of_main(entity); + check_main(entity); } } @@ -4490,6 +4380,7 @@ static entity_t *record_entity(entity_t *entity, const bool is_definition) &previous_entity->base.source_position); } else { unsigned old_storage_class = prev_decl->storage_class; + if (warning.redundant_decls && is_definition && !prev_decl->used && @@ -4870,7 +4761,6 @@ static void parse_kr_declaration_list(entity_t *entity) if (!type->function.kr_style_parameters) return; - add_anchor_token('{'); /* push function parameters */ @@ -4912,8 +4802,30 @@ decl_list_end: function_parameter_t *parameters = NULL; function_parameter_t **anchor = ¶meters; + /* did we have an earlier prototype? */ + entity_t *proto_type = get_entity(entity->base.symbol, NAMESPACE_NORMAL); + if (proto_type != NULL && proto_type->kind != ENTITY_FUNCTION) + proto_type = NULL; + + function_parameter_t *proto_parameter = NULL; + if (proto_type != NULL) { + type_t *proto_type_type = proto_type->declaration.type; + proto_parameter = proto_type_type->function.parameters; + /* If a K&R function definition has a variadic prototype earlier, then + * make the function definition variadic, too. This should conform to + * §6.7.5.3:15 and §6.9.1:8. */ + new_type->function.variadic = proto_type_type->function.variadic; + } else { + /* §6.9.1.7: A K&R style parameter list does NOT act as a function + * prototype */ + new_type->function.unspecified_parameters = true; + } + + bool need_incompatible_warning = false; parameter = entity->function.parameters.entities; - for (; parameter != NULL; parameter = parameter->base.next) { + for (; parameter != NULL; parameter = parameter->base.next, + proto_parameter = + proto_parameter == NULL ? NULL : proto_parameter->next) { if (parameter->kind != ENTITY_PARAMETER) continue; @@ -4935,25 +4847,42 @@ decl_list_end: semantic_parameter_incomplete(parameter); - /* - * we need the default promoted types for the function type - */ - parameter_type = get_default_promoted_type(parameter_type); - - function_parameter_t *const parameter = - allocate_parameter(parameter_type); + /* we need the default promoted types for the function type */ + type_t *not_promoted = parameter_type; + parameter_type = get_default_promoted_type(parameter_type); + + /* gcc special: if the type of the prototype matches the unpromoted + * type don't promote */ + if (!strict_mode && proto_parameter != NULL) { + type_t *proto_p_type = skip_typeref(proto_parameter->type); + type_t *promo_skip = skip_typeref(parameter_type); + type_t *param_skip = skip_typeref(not_promoted); + if (!types_compatible(proto_p_type, promo_skip) + && types_compatible(proto_p_type, param_skip)) { + /* don't promote */ + need_incompatible_warning = true; + parameter_type = not_promoted; + } + } + function_parameter_t *const parameter + = allocate_parameter(parameter_type); *anchor = parameter; anchor = ¶meter->next; } - /* §6.9.1.7: A K&R style parameter list does NOT act as a function - * prototype */ - new_type->function.parameters = parameters; - new_type->function.unspecified_parameters = true; - + new_type->function.parameters = parameters; new_type = identify_new_type(new_type); + if (warning.other && need_incompatible_warning) { + type_t *proto_type_type = proto_type->declaration.type; + warningf(HERE, + "declaration '%#T' is incompatible with '%#T' (declared %P)", + proto_type_type, proto_type->base.symbol, + new_type, entity->base.symbol, + &proto_type->base.source_position); + } + entity->declaration.type = new_type; rem_anchor_token('{'); @@ -5082,7 +5011,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 +5224,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) { @@ -5775,8 +5704,7 @@ static void parse_external_declaration(void) /* §6.7.5.3:14 a function definition with () means no * parameters (and not unspecified parameters) */ if (type->function.unspecified_parameters && - type->function.parameters == NULL && - !type->function.kr_style_parameters) { + type->function.parameters == NULL) { type_t *copy = duplicate_type(type); copy->function.unspecified_parameters = false; type = identify_new_type(copy); @@ -5882,14 +5810,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 +5840,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 +5854,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 +5960,17 @@ 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) { + attribute_t *last = attributes; + while (last->next != NULL) + last = last->next; + last->next = specifiers->attributes; + } else { + attributes = specifiers->attributes; + } entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER); entity->base.namespc = NAMESPACE_NORMAL; @@ -5944,6 +5978,11 @@ static void parse_compound_declarators(compound_t *compound, entity->declaration.declared_storage_class = STORAGE_CLASS_NONE; entity->declaration.storage_class = STORAGE_CLASS_NONE; entity->declaration.type = type; + entity->declaration.attributes = attributes; + + if (attributes != NULL) { + handle_entity_attributes(attributes, entity); + } append_entity(&compound->members, entity); } else { entity = parse_declarator(specifiers, @@ -5973,7 +6012,10 @@ static void parse_compound_declarators(compound_t *compound, type_t *type = entity->declaration.type; type_t *bitfield_type = make_bitfield_type(type, size, &source_position, entity->base.symbol); + + attribute_t *attributes = parse_attributes(NULL); entity->declaration.type = bitfield_type; + handle_entity_attributes(attributes, entity); } else { type_t *orig_type = entity->declaration.type; type_t *type = skip_typeref(orig_type); @@ -6228,10 +6270,12 @@ static entity_t *create_implicit_function(symbol_t *symbol, entity->base.symbol = symbol; entity->base.source_position = *source_position; - bool strict_prototypes_old = warning.strict_prototypes; - warning.strict_prototypes = false; - record_entity(entity, false); - warning.strict_prototypes = strict_prototypes_old; + if (current_scope != NULL) { + bool strict_prototypes_old = warning.strict_prototypes; + warning.strict_prototypes = false; + record_entity(entity, false); + warning.strict_prototypes = strict_prototypes_old; + } return entity; } @@ -6272,11 +6316,23 @@ static type_t *make_function_1_type(type_t *return_type, type_t *argument_type) return identify_new_type(type); } +/** + * Creates a return_type (func)(argument_type, ...) function type if not + * already exists. + * + * @param return_type the return type + * @param argument_type the argument type + */ static type_t *make_function_1_type_variadic(type_t *return_type, type_t *argument_type) { - type_t *res = make_function_1_type(return_type, argument_type); - res->function.variadic = 1; - return res; + function_parameter_t *const parameter = allocate_parameter(argument_type); + + type_t *type = allocate_type_zero(TYPE_FUNCTION); + type->function.return_type = return_type; + type->function.parameters = parameter; + type->function.variadic = true; + + return identify_new_type(type); } /** @@ -6392,14 +6448,73 @@ type_t *revert_automatic_type_conversion(const expression_t *expression) } } -static expression_t *parse_reference(void) +/** + * Find an entity matching a symbol in a scope. + * Uses current scope if scope is NULL + */ +static entity_t *lookup_entity(const scope_t *scope, symbol_t *symbol, + namespace_tag_t namespc) { - symbol_t *const symbol = token.v.symbol; + if (scope == NULL) { + return get_entity(symbol, namespc); + } - entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL); + /* we should optimize here, if scope grows above a certain size we should + construct a hashmap here... */ + entity_t *entity = scope->entities; + for ( ; entity != NULL; entity = entity->base.next) { + if (entity->base.symbol == symbol && entity->base.namespc == namespc) + break; + } + + return entity; +} + +static entity_t *parse_qualified_identifier(void) +{ + /* namespace containing the symbol */ + symbol_t *symbol; + const scope_t *lookup_scope = NULL; + + if (token.type == T_COLONCOLON) { + next_token(); + lookup_scope = &unit->scope; + } + + entity_t *entity; + while (true) { + if (token.type != T_IDENTIFIER) { + parse_error_expected("while parsing identifier", T_IDENTIFIER, NULL); + return create_error_entity(sym_anonymous, ENTITY_VARIABLE); + } + symbol = token.v.symbol; + next_token(); + + /* lookup entity */ + entity = lookup_entity(lookup_scope, symbol, NAMESPACE_NORMAL); + + if (token.type != T_COLONCOLON) + break; + next_token(); + + switch (entity->kind) { + case ENTITY_NAMESPACE: + lookup_scope = &entity->namespacee.members; + break; + case ENTITY_STRUCT: + case ENTITY_UNION: + case ENTITY_CLASS: + lookup_scope = &entity->compound.members; + break; + default: + errorf(HERE, "'%Y' must be a namespace, class, struct or union (but is a %s)", + symbol, get_entity_kind_name(entity->kind)); + goto end_error; + } + } if (entity == NULL) { - if (!strict_mode && look_ahead(1)->type == '(') { + if (!strict_mode && token.type == '(') { /* an implicitly declared function */ if (warning.error_implicit_function_declaration) { errorf(HERE, "implicit declaration of function '%Y'", symbol); @@ -6414,8 +6529,25 @@ static expression_t *parse_reference(void) } } - type_t *orig_type; + return entity; + +end_error: + /* skip further qualifications */ + while (token.type == T_IDENTIFIER) { + next_token(); + if (token.type != T_COLONCOLON) + break; + next_token(); + } + + return create_error_entity(sym_anonymous, ENTITY_VARIABLE); +} + +static expression_t *parse_reference(void) +{ + entity_t *entity = parse_qualified_identifier(); + type_t *orig_type; if (is_declaration(entity)) { orig_type = entity->declaration.type; } else if (entity->kind == ENTITY_ENUM_VALUE) { @@ -6442,8 +6574,9 @@ static expression_t *parse_reference(void) } if (entity->base.parent_scope != file_scope - && (current_function != NULL && entity->base.parent_scope->depth < current_function->parameters.depth) - && is_type_valid(orig_type) && !is_type_function(orig_type)) { + && (current_function != NULL + && entity->base.parent_scope->depth < current_function->parameters.depth) + && (entity->kind == ENTITY_VARIABLE || entity->kind == ENTITY_PARAMETER)) { if (entity->kind == ENTITY_VARIABLE) { /* access of a variable from an outer function */ entity->variable.address_taken = true; @@ -6453,24 +6586,7 @@ static expression_t *parse_reference(void) current_function->need_closure = true; } - /* check for deprecated functions */ - if (warning.deprecated_declarations - && is_declaration(entity) - && entity->declaration.modifiers & DM_DEPRECATED) { - - char const *const prefix = entity->kind == ENTITY_FUNCTION ? - "function" : "variable"; - const char *deprecated_string - = get_deprecated_string(entity->declaration.attributes); - if (deprecated_string != NULL) { - warningf(HERE, "%s '%Y' is deprecated (declared %P): \"%s\"", - prefix, entity->base.symbol, &entity->base.source_position, - deprecated_string); - } else { - warningf(HERE, "%s '%Y' is deprecated (declared %P)", prefix, - entity->base.symbol, &entity->base.source_position); - } - } + check_deprecated(HERE, entity); if (warning.init_self && entity == current_init_decl && !in_type_prop && entity->kind == ENTITY_VARIABLE) { @@ -6479,7 +6595,6 @@ static expression_t *parse_reference(void) entity->declaration.type, entity->base.symbol); } - next_token(); return expression; } @@ -6824,9 +6939,12 @@ static expression_t *parse_va_start(void) expression_t *const expr = parse_assignment_expression(); if (expr->kind == EXPR_REFERENCE) { entity_t *const entity = expr->reference.entity; - if (entity->base.parent_scope != ¤t_function->parameters - || entity->base.next != NULL - || entity->kind != ENTITY_PARAMETER) { + if (!current_function->base.type->function.variadic) { + errorf(&expr->base.source_position, + "'va_start' used in non-variadic function"); + } else if (entity->base.parent_scope != ¤t_function->parameters || + entity->base.next != NULL || + entity->kind != ENTITY_PARAMETER) { errorf(&expr->base.source_position, "second argument of 'va_start' must be last parameter of the current function"); } else { @@ -6996,31 +7114,6 @@ end_error: return create_invalid_expression(); } -#if 0 -/** - * Parses a __builtin_expect(, end_error) expression. - */ -static expression_t *parse_builtin_expect(void, end_error) -{ - expression_t *expression - = allocate_expression_zero(EXPR_BINARY_BUILTIN_EXPECT); - - eat(T___builtin_expect); - - expect('(', end_error); - expression->binary.left = parse_assignment_expression(); - expect(',', end_error); - expression->binary.right = parse_constant_expression(); - expect(')', end_error); - - expression->base.type = expression->binary.left->base.type; - - return expression; -end_error: - return create_invalid_expression(); -} -#endif - /** * Parses a MS assume() expression. */ @@ -7186,6 +7279,8 @@ static expression_t *parse_primary_expression(void) case T___noop: return parse_noop_expression(); /* Gracefully handle type names while parsing expressions. */ + case T_COLONCOLON: + return parse_reference(); case T_IDENTIFIER: if (!is_typedef_symbol(token.v.symbol)) { return parse_reference(); @@ -7331,29 +7426,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); @@ -7361,56 +7453,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 (!compound->complete) { - errorf(HERE, "request for member '%Y' of incomplete type '%T'", - symbol, type_left); - goto create_error_entry; - } + if (type_left->kind != TYPE_COMPOUND_STRUCT && + type_left->kind != TYPE_COMPOUND_UNION) { - 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; - - 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, @@ -8294,7 +8371,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"); } } @@ -8345,7 +8422,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"); @@ -8494,7 +8571,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; } /** @@ -9352,7 +9429,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; } @@ -9371,7 +9448,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) { @@ -9599,7 +9676,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) @@ -9765,6 +9842,12 @@ static statement_t *parse_for(void) size_t const top = environment_top(); scope_t *old_scope = scope_push(&statement->fors.scope); + bool old_gcc_extension = in_gcc_extension; + while (token.type == T___extension__) { + next_token(); + in_gcc_extension = true; + } + if (token.type == ';') { next_token(); } else if (is_declaration_specifier(&token, false)) { @@ -9781,6 +9864,7 @@ static statement_t *parse_for(void) rem_anchor_token(';'); expect(';', end_error2); } + in_gcc_extension = old_gcc_extension; if (token.type != ';') { add_anchor_token(';'); @@ -10897,6 +10981,36 @@ static void complete_incomplete_arrays(void) } } +void prepare_main_collect2(entity_t *entity) +{ + // create call to __main + symbol_t *symbol = symbol_table_insert("__main"); + entity_t *subsubmain_ent + = create_implicit_function(symbol, &builtin_source_position); + + expression_t *ref = allocate_expression_zero(EXPR_REFERENCE); + type_t *ftype = subsubmain_ent->declaration.type; + ref->base.source_position = builtin_source_position; + ref->base.type = make_pointer_type(ftype, TYPE_QUALIFIER_NONE); + ref->reference.entity = subsubmain_ent; + + expression_t *call = allocate_expression_zero(EXPR_CALL); + call->base.source_position = builtin_source_position; + call->base.type = type_void; + call->call.function = ref; + + statement_t *expr_statement = allocate_statement_zero(STATEMENT_EXPRESSION); + expr_statement->base.source_position = builtin_source_position; + expr_statement->expression.expression = call; + + statement_t *statement = entity->function.statement; + assert(statement->kind == STATEMENT_COMPOUND); + compound_statement_t *compounds = &statement->compound; + + expr_statement->base.next = compounds->statements; + compounds->statements = expr_statement; +} + void parse(void) { lookahead_bufpos = 0;