X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=d05f5c252a7cd22f7461e7c2d7b2e03875183122;hb=569c3410e7b645ac34e0a9a08ef5f0b068ecf606;hp=7e44886f46008e79158729be22a7f0faf84fa522;hpb=37f1ce3da5d6b4d308af26d117805fa8b357e277;p=cparser diff --git a/parser.c b/parser.c index 7e44886..d05f5c2 100644 --- a/parser.c +++ b/parser.c @@ -108,6 +108,7 @@ static bool in_gcc_extension = false; static struct obstack temp_obst; static entity_t *anonymous_entity; static declaration_t **incomplete_arrays; +static elf_visibility_tag_t default_visibility = ELF_VISIBILITY_DEFAULT; #define PUSH_PARENT(stmt) \ @@ -308,6 +309,7 @@ static size_t get_expression_struct_size(expression_kind_t kind) [EXPR_INVALID] = sizeof(expression_base_t), [EXPR_REFERENCE] = sizeof(reference_expression_t), [EXPR_REFERENCE_ENUM_VALUE] = sizeof(reference_expression_t), + [EXPR_LITERAL_BOOLEAN] = sizeof(literal_expression_t), [EXPR_LITERAL_INTEGER] = sizeof(literal_expression_t), [EXPR_LITERAL_INTEGER_OCTAL] = sizeof(literal_expression_t), [EXPR_LITERAL_INTEGER_HEXADECIMAL]= sizeof(literal_expression_t), @@ -1062,8 +1064,7 @@ static assign_error_t semantic_assign(type_t *orig_type_left, (is_type_atomic(type_left, ATOMIC_TYPE_BOOL) && is_type_pointer(type_right))) { return ASSIGN_SUCCESS; - } else if ((is_type_compound(type_left) && is_type_compound(type_right)) - || (is_type_builtin(type_left) && is_type_builtin(type_right))) { + } else if (is_type_compound(type_left) && is_type_compound(type_right)) { type_t *const unqual_type_left = get_unqualified_type(type_left); type_t *const unqual_type_right = get_unqualified_type(type_right); if (types_compatible(unqual_type_left, unqual_type_right)) { @@ -1268,24 +1269,25 @@ static attribute_t *parse_attribute_gnu_single(void) return NULL; } - const char *name = symbol->string; - next_token(); + attribute_kind_t kind; + char const *const name = symbol->string; + for (kind = ATTRIBUTE_GNU_FIRST;; ++kind) { + if (kind > ATTRIBUTE_GNU_LAST) { + if (warning.attribute) { + warningf(HERE, "unknown attribute '%s' ignored", name); + } + /* TODO: we should still save the attribute in the list... */ + kind = ATTRIBUTE_UNKNOWN; + break; + } - attribute_kind_t kind; - for (kind = ATTRIBUTE_GNU_FIRST; kind <= ATTRIBUTE_GNU_LAST; ++kind) { const char *attribute_name = get_attribute_name(kind); if (attribute_name != NULL && strcmp_underscore(attribute_name, name) == 0) break; } - if (kind >= ATTRIBUTE_GNU_LAST) { - if (warning.attribute) { - warningf(HERE, "unknown attribute '%s' ignored", name); - } - /* TODO: we should still save the attribute in the list... */ - kind = ATTRIBUTE_UNKNOWN; - } + next_token(); attribute_t *attribute = allocate_attribute_zero(kind); @@ -1332,6 +1334,8 @@ static attribute_t *parse_attributes(attribute_t *first) switch (token.type) { case T___attribute__: attribute = parse_attribute_gnu(); + if (attribute == NULL) + continue; break; case T_asm: @@ -1359,10 +1363,10 @@ static attribute_t *parse_attributes(attribute_t *first) break; case T___thiscall: - next_token(); /* TODO record modifier */ if (warning.other) warningf(HERE, "Ignoring declaration modifier %K", &token); + eat(T___thiscall); attribute = allocate_attribute_zero(ATTRIBUTE_MS_THISCALL); break; @@ -1751,12 +1755,13 @@ static initializer_t *parse_scalar_initializer(type_t *type, { /* there might be extra {} hierarchies */ int braces = 0; - if (next_if('{')) { + if (token.type == '{') { if (warning.other) warningf(HERE, "extra curly braces around scalar initializer"); do { + eat('{'); ++braces; - } while (next_if('{')); + } while (token.type == '{'); } expression_t *expression = parse_assignment_expression(); @@ -1962,7 +1967,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, if (iter == NULL) { errorf(&designator->source_position, "'%T' has no member named '%Y'", orig_type, symbol); - goto failed; + return false; } assert(iter->kind == ENTITY_COMPOUND_MEMBER); if (used_in_offsetof) { @@ -1971,7 +1976,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, errorf(&designator->source_position, "offsetof designator '%Y' must not specify bitfield", symbol); - goto failed; + return false; } } @@ -1989,7 +1994,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, "[%E] designator used for non-array type '%T'", array_index, orig_type); } - goto failed; + return false; } long index = fold_constant_to_int(array_index); @@ -2018,9 +2023,6 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, } } return true; - -failed: - return false; } static void advance_current_object(type_path_t *path, size_t top_path_level) @@ -2156,7 +2158,6 @@ finish_designator: if (type != NULL && is_type_scalar(type)) { sub = parse_scalar_initializer(type, env->must_be_constant); } else { - eat('{'); if (type == NULL) { if (env->entity != NULL) { errorf(HERE, @@ -2165,8 +2166,11 @@ finish_designator: } else { errorf(HERE, "extra brace group at end of initializer"); } - } else + eat('{'); + } else { + eat('{'); descend_into_subtype(path); + } add_anchor_token('}'); sub = parse_sub_initializer(path, orig_type, top_path_level+1, @@ -2198,10 +2202,19 @@ finish_designator: goto error_parse_next; type_t *const outer_type_skip = skip_typeref(outer_type); if (is_type_compound(outer_type_skip) && - !outer_type_skip->compound.compound->complete) { + !outer_type_skip->compound.compound->complete) { goto error_parse_next; } - goto error_excess; + + if (warning.other) { + source_position_t const* const pos = &expression->base.source_position; + if (env->entity != NULL) { + warningf(pos, "excess elements in initializer for '%Y'", env->entity->base.symbol); + } else { + warningf(pos, "excess elements in initializer"); + } + } + goto error_parse_next; } /* handle { "string" } special case */ @@ -2253,20 +2266,8 @@ finish_designator: path->max_index = index; } - if (type != NULL) { - /* append to initializers list */ - ARR_APP1(initializer_t*, initializers, sub); - } else { -error_excess: - if (warning.other) { - if (env->entity != NULL) { - warningf(HERE, "excess elements in initializer for '%Y'", - env->entity->base.symbol); - } else { - warningf(HERE, "excess elements in initializer"); - } - } - } + /* append to initializers list */ + ARR_APP1(initializer_t*, initializers, sub); error_parse_next: if (token.type == '}') { @@ -2350,6 +2351,7 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env) DEL_ARR_F(path.path); expect('}', end_error); +end_error:; } else { /* parse_scalar_initializer() also works in this case: we simply * have an expression without {} around it */ @@ -2395,8 +2397,6 @@ static initializer_t *parse_initializer(parse_initializer_env_t *env) } return result; -end_error: - return NULL; } static void append_entity(scope_t *scope, entity_t *entity) @@ -2413,10 +2413,11 @@ static void append_entity(scope_t *scope, entity_t *entity) static compound_t *parse_compound_type_specifier(bool is_struct) { + source_position_t const pos = *HERE; eat(is_struct ? T_struct : T_union); - symbol_t *symbol = NULL; - compound_t *compound = NULL; + symbol_t *symbol = NULL; + entity_t *entity = NULL; attribute_t *attributes = NULL; if (token.type == T___attribute__) { @@ -2427,46 +2428,37 @@ static compound_t *parse_compound_type_specifier(bool is_struct) if (token.type == T_IDENTIFIER) { /* the compound has a name, check if we have seen it already */ symbol = token.symbol; + entity = get_tag(symbol, kind); next_token(); - entity_t *entity = get_tag(symbol, kind); if (entity != NULL) { - compound = &entity->compound; - if (compound->base.parent_scope != current_scope && + if (entity->base.parent_scope != current_scope && (token.type == '{' || token.type == ';')) { /* we're in an inner scope and have a definition. Shadow * existing definition in outer scope */ - compound = NULL; - } else if (compound->complete && token.type == '{') { - assert(symbol != NULL); - errorf(HERE, "multiple definitions of '%s %Y' (previous definition %P)", + entity = NULL; + } else if (entity->compound.complete && token.type == '{') { + errorf(&pos, "multiple definitions of '%s %Y' (previous definition %P)", is_struct ? "struct" : "union", symbol, - &compound->base.source_position); + &entity->base.source_position); /* clear members in the hope to avoid further errors */ - compound->members.entities = NULL; + entity->compound.members.entities = NULL; } } } else if (token.type != '{') { - if (is_struct) { - parse_error_expected("while parsing struct type specifier", - T_IDENTIFIER, '{', NULL); - } else { - parse_error_expected("while parsing union type specifier", - T_IDENTIFIER, '{', NULL); - } + char const *const msg = + is_struct ? "while parsing struct type specifier" : + "while parsing union type specifier"; + parse_error_expected(msg, T_IDENTIFIER, '{', NULL); return NULL; } - if (compound == NULL) { - 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; - compound->base.parent_scope = current_scope; + if (entity == NULL) { + entity = allocate_entity_zero(kind, NAMESPACE_TAG, symbol); + entity->compound.alignment = 1; + entity->base.source_position = pos; + entity->base.parent_scope = current_scope; if (symbol != NULL) { environment_push(entity); } @@ -2474,20 +2466,20 @@ static compound_t *parse_compound_type_specifier(bool is_struct) } if (token.type == '{') { - parse_compound_type_entries(compound); + parse_compound_type_entries(&entity->compound); /* ISO/IEC 14882:1998(E) §7.1.3:5 */ if (symbol == NULL) { assert(anonymous_entity == NULL); - anonymous_entity = (entity_t*)compound; + anonymous_entity = entity; } } if (attributes != NULL) { - handle_entity_attributes(attributes, (entity_t*) compound); + handle_entity_attributes(attributes, entity); } - return compound; + return &entity->compound; } static void parse_enum_entries(type_t *const enum_type) @@ -2509,10 +2501,8 @@ static void parse_enum_entries(type_t *const enum_type) return; } - entity_t *entity = allocate_entity_zero(ENTITY_ENUM_VALUE); + entity_t *const entity = allocate_entity_zero(ENTITY_ENUM_VALUE, NAMESPACE_NORMAL, token.symbol); entity->enum_value.enum_type = enum_type; - entity->base.namespc = NAMESPACE_NORMAL; - entity->base.symbol = token.symbol; entity->base.source_position = token.source_position; next_token(); @@ -2537,16 +2527,17 @@ end_error: static type_t *parse_enum_specifier(void) { - entity_t *entity; - symbol_t *symbol; + source_position_t const pos = *HERE; + entity_t *entity; + symbol_t *symbol; eat(T_enum); switch (token.type) { case T_IDENTIFIER: symbol = token.symbol; + entity = get_tag(symbol, ENTITY_ENUM); next_token(); - entity = get_tag(symbol, ENTITY_ENUM); if (entity != NULL) { if (entity->base.parent_scope != current_scope && (token.type == '{' || token.type == ';')) { @@ -2554,7 +2545,7 @@ static type_t *parse_enum_specifier(void) * existing definition in outer scope */ entity = NULL; } else if (entity->enume.complete && token.type == '{') { - errorf(HERE, "multiple definitions of 'enum %Y' (previous definition %P)", + errorf(&pos, "multiple definitions of 'enum %Y' (previous definition %P)", symbol, &entity->base.source_position); } } @@ -2572,10 +2563,8 @@ static type_t *parse_enum_specifier(void) } if (entity == NULL) { - entity = allocate_entity_zero(ENTITY_ENUM); - entity->base.namespc = NAMESPACE_TAG; - entity->base.source_position = token.source_position; - entity->base.symbol = symbol; + entity = allocate_entity_zero(ENTITY_ENUM, NAMESPACE_TAG, symbol); + entity->base.source_position = pos; entity->base.parent_scope = current_scope; } @@ -2599,8 +2588,7 @@ static type_t *parse_enum_specifier(void) anonymous_entity = entity; } } else if (!entity->enume.complete && !(c_mode & _GNUC)) { - errorf(HERE, "'enum %Y' used before definition (incomplete enums are a GNU extension)", - symbol); + errorf(HERE, "'%T' used before definition (incomplete enums are a GNU extension)", type); } return type; @@ -2683,15 +2671,6 @@ typedef enum specifiers_t { SPECIFIER_IMAGINARY = 1 << 18, } specifiers_t; -static type_t *create_builtin_type(symbol_t *const symbol, - type_t *const real_type) -{ - type_t *type = allocate_type_zero(TYPE_BUILTIN); - type->builtin.symbol = symbol; - type->builtin.real_type = real_type; - return identify_new_type(type); -} - static type_t *get_typedef_type(symbol_t *symbol) { entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL); @@ -2718,28 +2697,25 @@ static attribute_t *parse_attribute_ms_property(attribute_t *attribute) goto end_error; } - bool is_put; - symbol_t *symbol = token.symbol; - next_token(); + symbol_t **prop; + symbol_t *symbol = token.symbol; if (strcmp(symbol->string, "put") == 0) { - is_put = true; + prop = &property->put_symbol; } else if (strcmp(symbol->string, "get") == 0) { - is_put = false; + prop = &property->get_symbol; } else { errorf(HERE, "expected put or get in property declspec"); - goto end_error; + prop = NULL; } + eat(T_IDENTIFIER); expect('=', end_error); if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing property declspec", T_IDENTIFIER, NULL); goto end_error; } - if (is_put) { - property->put_symbol = token.symbol; - } else { - property->get_symbol = token.symbol; - } + if (prop != NULL) + *prop = token.symbol; next_token(); } while (next_if(',')); @@ -2758,7 +2734,6 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void) kind = ATTRIBUTE_MS_RESTRICT; } else if (token.type == T_IDENTIFIER) { const char *name = token.symbol->string; - next_token(); for (attribute_kind_t k = ATTRIBUTE_MS_FIRST; k <= ATTRIBUTE_MS_LAST; ++k) { const char *attribute_name = get_attribute_name(k); @@ -2771,6 +2746,7 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void) if (kind == ATTRIBUTE_UNKNOWN && warning.attribute) { warningf(HERE, "unknown __declspec '%s' ignored", name); } + eat(T_IDENTIFIER); } else { parse_error_expected("while parsing __declspec", T_IDENTIFIER, NULL); return NULL; @@ -2825,10 +2801,8 @@ end_error: static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind) { - entity_t *entity = allocate_entity_zero(kind); - entity->base.namespc = NAMESPACE_NORMAL; + entity_t *const entity = allocate_entity_zero(kind, NAMESPACE_NORMAL, symbol); entity->base.source_position = *HERE; - entity->base.symbol = symbol; if (is_declaration(entity)) { entity->declaration.type = type_error_type; entity->declaration.implicit = true; @@ -2850,6 +2824,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) bool saw_error = false; bool old_gcc_extension = in_gcc_extension; + memset(specifiers, 0, sizeof(*specifiers)); specifiers->source_position = token.source_position; while (true) { @@ -2968,7 +2943,7 @@ wrong_thread_storage_class: case T_long: if (type_specifiers & SPECIFIER_LONG_LONG) { - errorf(HERE, "multiple type specifiers given"); + errorf(HERE, "too many long type specifiers given"); } else if (type_specifiers & SPECIFIER_LONG) { type_specifiers |= SPECIFIER_LONG_LONG; } else { @@ -3053,8 +3028,6 @@ wrong_thread_storage_class: next_token(); saw_error = true; - if (la1_type == '&' || la1_type == '*') - goto finish_specifiers; continue; } @@ -3217,32 +3190,33 @@ warn_about_long_long: case SPECIFIER_LONG | SPECIFIER_DOUBLE | SPECIFIER_IMAGINARY: atomic_type = ATOMIC_TYPE_LONG_DOUBLE; break; - default: + default: { /* invalid specifier combination, give an error message */ + source_position_t const* const pos = &specifiers->source_position; if (type_specifiers == 0) { - if (saw_error) - goto end_error; - - /* ISO/IEC 14882:1998(E) §C.1.5:4 */ - if (!(c_mode & _CXX) && !strict_mode) { - if (warning.implicit_int) { - warningf(HERE, "no type specifiers in declaration, using 'int'"); + if (!saw_error) { + /* ISO/IEC 14882:1998(E) §C.1.5:4 */ + if (!(c_mode & _CXX) && !strict_mode) { + if (warning.implicit_int) { + warningf(pos, "no type specifiers in declaration, using 'int'"); + } + atomic_type = ATOMIC_TYPE_INT; + break; + } else { + errorf(pos, "no type specifiers given in declaration"); } - atomic_type = ATOMIC_TYPE_INT; - break; - } else { - errorf(HERE, "no type specifiers given in declaration"); } } else if ((type_specifiers & SPECIFIER_SIGNED) && (type_specifiers & SPECIFIER_UNSIGNED)) { - errorf(HERE, "signed and unsigned specifiers given"); + errorf(pos, "signed and unsigned specifiers given"); } else if (type_specifiers & (SPECIFIER_SIGNED | SPECIFIER_UNSIGNED)) { - errorf(HERE, "only integer types can be signed or unsigned"); + errorf(pos, "only integer types can be signed or unsigned"); } else { - errorf(HERE, "multiple datatypes in declaration"); + errorf(pos, "multiple datatypes in declaration"); } goto end_error; } + } if (type_specifiers & SPECIFIER_COMPLEX) { type = allocate_type_zero(TYPE_COMPLEX); @@ -3256,7 +3230,7 @@ warn_about_long_long: } newtype = true; } else if (type_specifiers != 0) { - errorf(HERE, "multiple datatypes in declaration"); + errorf(&specifiers->source_position, "multiple datatypes in declaration"); } /* FIXME: check type qualifiers here */ @@ -3306,10 +3280,8 @@ static type_qualifiers_t parse_type_qualifiers(void) static void parse_identifier_list(scope_t *scope) { do { - entity_t *entity = allocate_entity_zero(ENTITY_PARAMETER); + entity_t *const entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, token.symbol); entity->base.source_position = token.source_position; - entity->base.namespc = NAMESPACE_NORMAL; - entity->base.symbol = token.symbol; /* a K&R parameter has no type, yet */ next_token(); @@ -3321,8 +3293,6 @@ static void parse_identifier_list(scope_t *scope) static entity_t *parse_parameter(void) { declaration_specifiers_t specifiers; - memset(&specifiers, 0, sizeof(specifiers)); - parse_declaration_specifiers(&specifiers); entity_t *entity = parse_declarator(&specifiers, @@ -3391,10 +3361,7 @@ static void parse_parameters(function_type_t *type, scope_t *scope) /* ISO/IEC 14882:1998(E) §C.1.6:1 */ if (!(c_mode & _CXX)) type->unspecified_parameters = true; - goto parameters_finished; - } - - if (has_parameters()) { + } else if (has_parameters()) { function_parameter_t **anchor = &type->parameters; do { switch (token.type) { @@ -3435,7 +3402,6 @@ static void parse_parameters(function_type_t *type, scope_t *scope) } while (next_if(',')); } - parameters_finished: rem_anchor_token(')'); expect(')', end_error); @@ -3456,6 +3422,7 @@ typedef union construct_type_t construct_type_t; typedef struct construct_type_base_t { construct_type_kind_t kind; + source_position_t pos; construct_type_t *next; } construct_type_base_t; @@ -3495,16 +3462,16 @@ static construct_type_t *allocate_declarator_zero(construct_type_kind_t const ki { construct_type_t *const cons = obstack_alloc(&temp_obst, size); memset(cons, 0, size); - cons->kind = kind; + cons->kind = kind; + cons->base.pos = *HERE; return cons; } /* §6.7.5.1 */ static construct_type_t *parse_pointer_declarator(void) { - eat('*'); - construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_POINTER, sizeof(parsed_pointer_t)); + eat('*'); cons->pointer.type_qualifiers = parse_type_qualifiers(); //cons->pointer.base_variable = base_variable; @@ -3514,12 +3481,11 @@ static construct_type_t *parse_pointer_declarator(void) /* ISO/IEC 14882:1998(E) §8.3.2 */ static construct_type_t *parse_reference_declarator(void) { - eat('&'); - if (!(c_mode & _CXX)) errorf(HERE, "references are only available for C++"); construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_REFERENCE, sizeof(parsed_reference_t)); + eat('&'); return cons; } @@ -3527,12 +3493,12 @@ static construct_type_t *parse_reference_declarator(void) /* §6.7.5.2 */ static construct_type_t *parse_array_declarator(void) { - eat('['); - add_anchor_token(']'); - construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_ARRAY, sizeof(parsed_array_t)); parsed_array_t *const array = &cons->array; + eat('['); + add_anchor_token(']'); + bool is_static = next_if(T_static); type_qualifiers_t type_qualifiers = parse_type_qualifiers(); @@ -3564,7 +3530,7 @@ static construct_type_t *parse_array_declarator(void) } if (is_static && size == NULL) - errorf(HERE, "static array parameters require a size"); + errorf(&array->base.pos, "static array parameters require a size"); rem_anchor_token(']'); expect(']', end_error); @@ -3576,6 +3542,8 @@ end_error: /* §6.7.5.3 */ static construct_type_t *parse_function_declarator(scope_t *scope) { + construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_FUNCTION, sizeof(construct_function_type_t)); + type_t *type = allocate_type_zero(TYPE_FUNCTION); function_type_t *ftype = &type->function; @@ -3584,7 +3552,6 @@ static construct_type_t *parse_function_declarator(scope_t *scope) parse_parameters(ftype, scope); - construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_FUNCTION, sizeof(construct_function_type_t)); cons->function.function_type = type; return cons; @@ -3651,30 +3618,48 @@ ptr_operator_end: ; } next_token(); break; - case '(': - /* §6.7.6:2 footnote 126: Empty parentheses in a type name are - * interpreted as ``function with no parameter specification'', rather - * than redundant parentheses around the omitted identifier. */ - if (look_ahead(1)->type != ')') { - next_token(); - add_anchor_token(')'); - inner_types = parse_inner_declarator(env); - if (inner_types != NULL) { - /* All later declarators only modify the return type */ - env->must_be_abstract = true; - } - rem_anchor_token(')'); - expect(')', end_error); - } else if (!env->may_be_abstract) { - errorf(HERE, "declarator must have a name"); - goto error_out; + + case '(': { + /* Parenthesized declarator or function declarator? */ + token_t const *const la1 = look_ahead(1); + switch (la1->type) { + case T_IDENTIFIER: + if (is_typedef_symbol(la1->symbol)) { + case ')': + /* §6.7.6:2 footnote 126: Empty parentheses in a type name are + * interpreted as ``function with no parameter specification'', rather + * than redundant parentheses around the omitted identifier. */ + default: + /* Function declarator. */ + if (!env->may_be_abstract) { + errorf(HERE, "function declarator must have a name"); + } + } else { + case '&': + case '(': + case '*': + case '[': + case T___attribute__: /* FIXME __attribute__ might also introduce a parameter of a function declarator. */ + /* Paranthesized declarator. */ + next_token(); + add_anchor_token(')'); + inner_types = parse_inner_declarator(env); + if (inner_types != NULL) { + /* All later declarators only modify the return type */ + env->must_be_abstract = true; + } + rem_anchor_token(')'); + expect(')', end_error); + } + break; } break; + } + default: if (env->may_be_abstract) break; parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL); -error_out: eat_until_anchor(); return NULL; } @@ -3722,6 +3707,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, { construct_type_t *iter = construct_list; for (; iter != NULL; iter = iter->base.next) { + source_position_t const* const pos = &iter->base.pos; switch (iter->kind) { case CONSTRUCT_INVALID: break; @@ -3734,13 +3720,12 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_t *skipped_return_type = skip_typeref(type); /* §6.7.5.3:1 */ if (is_type_function(skipped_return_type)) { - errorf(HERE, "function returning function is not allowed"); + errorf(pos, "function returning function is not allowed"); } else if (is_type_array(skipped_return_type)) { - errorf(HERE, "function returning array is not allowed"); + errorf(pos, "function returning array is not allowed"); } else { if (skipped_return_type->base.qualifiers != 0 && warning.other) { - warningf(HERE, - "type qualifiers in return type of function type are meaningless"); + warningf(pos, "type qualifiers in return type of function type are meaningless"); } } @@ -3752,7 +3737,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, case CONSTRUCT_POINTER: { if (is_type_reference(skip_typeref(type))) - errorf(HERE, "cannot declare a pointer to reference"); + errorf(pos, "cannot declare a pointer to reference"); parsed_pointer_t *pointer = &iter->pointer; type = make_based_pointer_type(type, pointer->type_qualifiers, pointer->base_variable); @@ -3761,14 +3746,14 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, case CONSTRUCT_REFERENCE: if (is_type_reference(skip_typeref(type))) - errorf(HERE, "cannot declare a reference to reference"); + errorf(pos, "cannot declare a reference to reference"); type = make_reference_type(type); continue; case CONSTRUCT_ARRAY: { if (is_type_reference(skip_typeref(type))) - errorf(HERE, "cannot declare an array of references"); + errorf(pos, "cannot declare an array of references"); parsed_array_t *array = &iter->array; type_t *array_type = allocate_type_zero(TYPE_ARRAY); @@ -3817,15 +3802,15 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, type_t *skipped_type = skip_typeref(type); /* §6.7.5.2:1 */ if (is_type_incomplete(skipped_type)) { - errorf(HERE, "array of incomplete type '%T' is not allowed", type); + errorf(pos, "array of incomplete type '%T' is not allowed", type); } else if (is_type_function(skipped_type)) { - errorf(HERE, "array of functions is not allowed"); + errorf(pos, "array of functions is not allowed"); } type = identify_new_type(array_type); continue; } } - internal_errorf(HERE, "invalid type construction found"); + internal_errorf(pos, "invalid type construction found"); } return type; @@ -3892,9 +3877,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, entity_t *entity; if (specifiers->storage_class == STORAGE_CLASS_TYPEDEF) { - entity = allocate_entity_zero(ENTITY_TYPEDEF); - entity->base.namespc = NAMESPACE_NORMAL; - entity->base.symbol = env.symbol; + entity = allocate_entity_zero(ENTITY_TYPEDEF, NAMESPACE_NORMAL, env.symbol); entity->base.source_position = env.source_position; entity->typedefe.type = orig_type; @@ -3915,7 +3898,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, } else { /* create a declaration type entity */ if (flags & DECL_CREATE_COMPOUND_MEMBER) { - entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER); + entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, env.symbol); if (env.symbol != NULL) { if (specifiers->is_inline && is_type_valid(type)) { @@ -3934,12 +3917,12 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, orig_type = semantic_parameter(&env.source_position, orig_type, specifiers, env.symbol); - entity = allocate_entity_zero(ENTITY_PARAMETER); + entity = allocate_entity_zero(ENTITY_PARAMETER, NAMESPACE_NORMAL, env.symbol); } else if (is_type_function(type)) { - entity = allocate_entity_zero(ENTITY_FUNCTION); - - entity->function.is_inline = specifiers->is_inline; - entity->function.parameters = env.parameters; + entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, env.symbol); + entity->function.is_inline = specifiers->is_inline; + entity->function.elf_visibility = default_visibility; + entity->function.parameters = env.parameters; if (env.symbol != NULL) { /* this needs fixes for C++ */ @@ -3955,9 +3938,9 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, } } } else { - entity = allocate_entity_zero(ENTITY_VARIABLE); - - entity->variable.thread_local = specifiers->thread_local; + entity = allocate_entity_zero(ENTITY_VARIABLE, NAMESPACE_NORMAL, env.symbol); + entity->variable.elf_visibility = default_visibility; + entity->variable.thread_local = specifiers->thread_local; if (env.symbol != NULL) { if (specifiers->is_inline && is_type_valid(type)) { @@ -3985,13 +3968,7 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, } } - if (env.symbol != NULL) { - entity->base.symbol = env.symbol; - entity->base.source_position = env.source_position; - } else { - entity->base.source_position = specifiers->source_position; - } - entity->base.namespc = NAMESPACE_NORMAL; + entity->base.source_position = env.symbol != NULL ? env.source_position : specifiers->source_position; entity->declaration.type = orig_type; entity->declaration.alignment = get_type_alignment(orig_type); entity->declaration.modifiers = env.modifiers; @@ -4000,7 +3977,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_function != NULL) + if (storage_class == STORAGE_CLASS_NONE && current_function != NULL) storage_class = STORAGE_CLASS_AUTO; entity->declaration.storage_class = storage_class; } @@ -4062,23 +4039,30 @@ static void check_main(const entity_t *entity) } const function_parameter_t *parm = func_type->parameters; if (parm != NULL) { - type_t *const first_type = parm->type; - if (!types_compatible(skip_typeref(first_type), type_int)) { + type_t *const first_type = skip_typeref(parm->type); + type_t *const first_type_unqual = get_unqualified_type(first_type); + if (!types_compatible(first_type_unqual, type_int)) { warningf(pos, "first argument of 'main' should be 'int', but is '%T'", - first_type); + parm->type); } parm = parm->next; if (parm != NULL) { - type_t *const second_type = parm->type; - if (!types_compatible(skip_typeref(second_type), type_char_ptr_ptr)) { - warningf(pos, "second argument of 'main' should be 'char**', but is '%T'", second_type); + type_t *const second_type = skip_typeref(parm->type); + type_t *const second_type_unqual + = get_unqualified_type(second_type); + if (!types_compatible(second_type_unqual, type_char_ptr_ptr)) { + warningf(pos, "second argument of 'main' should be 'char**', but is '%T'", + parm->type); } parm = parm->next; if (parm != NULL) { - type_t *const third_type = parm->type; - if (!types_compatible(skip_typeref(third_type), type_char_ptr_ptr)) { - warningf(pos, "third argument of 'main' should be 'char**', but is '%T'", third_type); + type_t *const third_type = skip_typeref(parm->type); + type_t *const third_type_unqual + = get_unqualified_type(third_type); + if (!types_compatible(third_type_unqual, type_char_ptr_ptr)) { + warningf(pos, "third argument of 'main' should be 'char**', but is '%T'", + parm->type); } parm = parm->next; if (parm != NULL) @@ -4107,14 +4091,14 @@ static void error_redefined_as_different_kind(const source_position_t *pos, get_entity_kind_name(new_kind), &old->base.source_position); } -static bool is_error_entity(entity_t *const ent) +static bool is_entity_valid(entity_t *const ent) { if (is_declaration(ent)) { - return !is_type_valid(skip_typeref(ent->declaration.type)); + return is_type_valid(skip_typeref(ent->declaration.type)); } else if (ent->kind == ENTITY_TYPEDEF) { - return !is_type_valid(skip_typeref(ent->typedefe.type)); + return is_type_valid(skip_typeref(ent->typedefe.type)); } - return false; + return true; } static bool contains_attribute(const attribute_t *list, const attribute_t *attr) @@ -4216,7 +4200,7 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) if (previous_entity->base.parent_scope == current_scope) { if (previous_entity->kind != entity->kind) { - if (!is_error_entity(previous_entity) && !is_error_entity(entity)) { + if (is_entity_valid(previous_entity) && is_entity_valid(entity)) { error_redefined_as_different_kind(pos, previous_entity, entity->kind); } @@ -4264,7 +4248,7 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) } else { unsigned old_storage_class = prev_decl->storage_class; - if (warning.redundant_decls && + if (warning.redundant_decls && is_definition && !prev_decl->used && !(prev_decl->modifiers & DM_USED) && @@ -4363,7 +4347,8 @@ error_redeclaration: return previous_entity; } - if (warning.shadow) { + if (warning.shadow || + (warning.shadow_local && previous_entity->base.parent_scope != file_scope)) { warningf(pos, "%s '%Y' shadows %s (declared %P)", get_entity_kind_name(entity->kind), symbol, get_entity_kind_name(previous_entity->kind), @@ -4397,7 +4382,6 @@ finish: assert(current_scope != NULL); entity->base.parent_scope = current_scope; - entity->base.namespc = NAMESPACE_NORMAL; environment_push(entity); append_entity(current_scope, entity); @@ -4432,19 +4416,26 @@ static bool is_declaration_specifier(const token_t *token, static void parse_init_declarator_rest(entity_t *entity) { - assert(is_declaration(entity)); - declaration_t *const declaration = &entity->declaration; + type_t *orig_type = type_error_type; - eat('='); + if (entity->base.kind == ENTITY_TYPEDEF) { + errorf(&entity->base.source_position, + "typedef '%Y' is initialized (use __typeof__ instead)", + entity->base.symbol); + } else { + assert(is_declaration(entity)); + orig_type = entity->declaration.type; + } - type_t *orig_type = declaration->type; - type_t *type = skip_typeref(orig_type); + type_t *type = skip_typeref(orig_type); if (entity->kind == ENTITY_VARIABLE && entity->variable.initializer != NULL) { parser_error_multiple_definition(entity, HERE); } + eat('='); + declaration_t *const declaration = &entity->declaration; bool must_be_constant = false; if (declaration->storage_class == STORAGE_CLASS_STATIC || entity->base.parent_scope == file_scope) { @@ -4585,16 +4576,14 @@ end_error: static entity_t *finished_kr_declaration(entity_t *entity, bool is_definition) { symbol_t *symbol = entity->base.symbol; - if (symbol == NULL) { - errorf(HERE, "anonymous declaration not valid as function parameter"); + if (symbol == NULL) return entity; - } assert(entity->base.namespc == NAMESPACE_NORMAL); entity_t *previous_entity = get_entity(symbol, NAMESPACE_NORMAL); if (previous_entity == NULL || previous_entity->base.parent_scope != current_scope) { - errorf(HERE, "expected declaration of a function parameter, found '%Y'", + errorf(&entity->base.source_position, "expected declaration of a function parameter, found '%Y'", symbol); return entity; } @@ -4609,10 +4598,8 @@ static entity_t *finished_kr_declaration(entity_t *entity, bool is_definition) static void parse_declaration(parsed_declaration_func finished_declaration, declarator_flags_t flags) { - declaration_specifiers_t specifiers; - memset(&specifiers, 0, sizeof(specifiers)); - add_anchor_token(';'); + declaration_specifiers_t specifiers; parse_declaration_specifiers(&specifiers); rem_anchor_token(';'); @@ -4719,14 +4706,13 @@ decl_list_end: type_t *parameter_type = parameter->declaration.type; if (parameter_type == NULL) { + source_position_t const* const pos = ¶meter->base.source_position; if (strict_mode) { - errorf(HERE, "no type specified for function parameter '%Y'", - parameter->base.symbol); + errorf(pos, "no type specified for function parameter '%Y'", parameter->base.symbol); parameter_type = type_error_type; } else { if (warning.implicit_int) { - warningf(HERE, "no type specified for function parameter '%Y', using 'int'", - parameter->base.symbol); + warningf(pos, "no type specified for function parameter '%Y', using 'int'", parameter->base.symbol); } parameter_type = type_int; } @@ -4764,7 +4750,7 @@ decl_list_end: if (warning.other && need_incompatible_warning) { type_t *proto_type_type = proto_type->declaration.type; - warningf(HERE, + warningf(&entity->base.source_position, "declaration '%#T' is incompatible with '%#T' (declared %P)", proto_type_type, proto_type->base.symbol, new_type, entity->base.symbol, @@ -4806,8 +4792,6 @@ static void check_labels(void) continue; label_t *label = goto_statement->label; - - label->used = true; if (label->base.source_position.input_name == NULL) { print_in_function(); errorf(&goto_statement->base.source_position, @@ -5506,10 +5490,8 @@ static void parse_external_declaration(void) { /* function-definitions and declarations both start with declaration * specifiers */ - declaration_specifiers_t specifiers; - memset(&specifiers, 0, sizeof(specifiers)); - add_anchor_token(';'); + declaration_specifiers_t specifiers; parse_declaration_specifiers(&specifiers); rem_anchor_token(';'); @@ -5571,15 +5553,15 @@ static void parse_external_declaration(void) if (warning.aggregate_return && is_type_compound(skip_typeref(type->function.return_type))) { - warningf(HERE, "function '%Y' returns an aggregate", + warningf(&ndeclaration->base.source_position, "function '%Y' returns an aggregate", ndeclaration->base.symbol); } if (warning.traditional && !type->function.unspecified_parameters) { - warningf(HERE, "traditional C rejects ISO C style function definition of function '%Y'", + warningf(&ndeclaration->base.source_position, "traditional C rejects ISO C style function definition of function '%Y'", ndeclaration->base.symbol); } if (warning.old_style_definition && type->function.unspecified_parameters) { - warningf(HERE, "old-style function definition '%Y'", + warningf(&ndeclaration->base.source_position, "old-style function definition '%Y'", ndeclaration->base.symbol); } @@ -5598,7 +5580,7 @@ static void parse_external_declaration(void) assert(entity->kind == ENTITY_FUNCTION); assert(ndeclaration->kind == ENTITY_FUNCTION); - function_t *function = &entity->function; + function_t *const function = &entity->function; if (ndeclaration != entity) { function->parameters = ndeclaration->function.parameters; } @@ -5633,7 +5615,7 @@ static void parse_external_declaration(void) function_t *old_current_function = current_function; entity_t *old_current_entity = current_entity; current_function = function; - current_entity = (entity_t*) function; + current_entity = entity; current_parent = NULL; goto_first = NULL; @@ -5665,7 +5647,7 @@ static void parse_external_declaration(void) assert(current_parent == NULL); assert(current_function == function); - assert(current_entity == (entity_t*) function); + assert(current_entity == entity); current_entity = old_current_entity; current_function = old_current_function; label_pop_to(label_stack_top); @@ -5688,8 +5670,7 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *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); + errorf(source_position, "bitfield base type '%T' is not an integer type", base_type); bit_size = 0; } else { bit_size = get_type_size(base_type) * 8; @@ -5854,8 +5835,7 @@ static void parse_compound_declarators(compound_t *compound, anchor = &(*anchor)->next; *anchor = specifiers->attributes; - entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER); - entity->base.namespc = NAMESPACE_NORMAL; + entity = allocate_entity_zero(ENTITY_COMPOUND_MEMBER, NAMESPACE_NORMAL, NULL); entity->base.source_position = source_position; entity->declaration.declared_storage_class = STORAGE_CLASS_NONE; entity->declaration.storage_class = STORAGE_CLASS_NONE; @@ -5938,9 +5918,7 @@ static void parse_compound_type_entries(compound_t *compound) break; } declaration_specifiers_t specifiers; - memset(&specifiers, 0, sizeof(specifiers)); parse_declaration_specifiers(&specifiers); - parse_compound_declarators(compound, &specifiers); } rem_anchor_token('}'); @@ -5953,14 +5931,13 @@ static void parse_compound_type_entries(compound_t *compound) static type_t *parse_typename(void) { declaration_specifiers_t specifiers; - memset(&specifiers, 0, sizeof(specifiers)); parse_declaration_specifiers(&specifiers); if (specifiers.storage_class != STORAGE_CLASS_NONE || specifiers.thread_local) { /* TODO: improve error message, user does probably not know what a * storage class is... */ - errorf(HERE, "typename must not have a storage class"); + errorf(&specifiers.source_position, "typename must not have a storage class"); } type_t *result = parse_abstract_declarator(specifiers.type); @@ -6188,7 +6165,7 @@ static expression_t *parse_character_constant(void) literal->literal.value = token.literal; size_t len = literal->literal.value.size; - if (len != 1) { + if (len > 1) { if (!GNU_MODE && !(c_mode & _C99)) { errorf(HERE, "more than 1 character in character constant"); } else if (warning.multichar) { @@ -6212,7 +6189,7 @@ static expression_t *parse_wide_character_constant(void) literal->literal.value = token.literal; size_t len = wstrlen(&literal->literal.value); - if (len != 1) { + if (len > 1) { warningf(HERE, "multi-character character constant"); } @@ -6229,13 +6206,11 @@ static entity_t *create_implicit_function(symbol_t *symbol, ntype->function.linkage = LINKAGE_C; type_t *type = identify_new_type(ntype); - entity_t *entity = allocate_entity_zero(ENTITY_FUNCTION); + entity_t *const entity = allocate_entity_zero(ENTITY_FUNCTION, NAMESPACE_NORMAL, symbol); entity->declaration.storage_class = STORAGE_CLASS_EXTERN; entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN; entity->declaration.type = type; entity->declaration.implicit = true; - entity->base.namespc = NAMESPACE_NORMAL; - entity->base.symbol = symbol; entity->base.source_position = *source_position; if (current_scope != NULL) { @@ -6423,7 +6398,8 @@ end_error: static expression_t *parse_reference(void) { - entity_t *entity = parse_qualified_identifier(); + source_position_t const pos = token.source_position; + entity_t *const entity = parse_qualified_identifier(); type_t *orig_type; if (is_declaration(entity)) { @@ -6442,9 +6418,10 @@ static expression_t *parse_reference(void) if (entity->kind == ENTITY_ENUM_VALUE) kind = EXPR_REFERENCE_ENUM_VALUE; - expression_t *expression = allocate_expression_zero(kind); - expression->reference.entity = entity; - expression->base.type = type; + expression_t *expression = allocate_expression_zero(kind); + expression->base.source_position = pos; + expression->base.type = type; + expression->reference.entity = entity; /* this declaration is used */ if (is_declaration(entity)) { @@ -6464,12 +6441,12 @@ static expression_t *parse_reference(void) current_function->need_closure = true; } - check_deprecated(HERE, entity); + check_deprecated(&pos, entity); if (warning.init_self && entity == current_init_decl && !in_type_prop && entity->kind == ENTITY_VARIABLE) { current_init_decl = NULL; - warningf(HERE, "variable '%#T' is initialized by itself", + warningf(&pos, "variable '%#T' is initialized by itself", entity->declaration.type, entity->base.symbol); } @@ -6547,10 +6524,11 @@ static expression_t *parse_compound_literal(type_t *type) */ static expression_t *parse_cast(void) { - add_anchor_token(')'); - source_position_t source_position = token.source_position; + eat('('); + add_anchor_token(')'); + type_t *type = parse_typename(); rem_anchor_token(')'); @@ -6581,10 +6559,11 @@ end_error: */ static expression_t *parse_statement_expression(void) { - add_anchor_token(')'); - expression_t *expression = allocate_expression_zero(EXPR_STATEMENT); + eat('('); + add_anchor_token(')'); + statement_t *statement = parse_compound_statement(true); statement->compound.stmt_expr = true; expression->statement.statement = statement; @@ -6616,22 +6595,21 @@ end_error: */ static expression_t *parse_parenthesized_expression(void) { - eat('('); - - switch (token.type) { + token_t const* const la1 = look_ahead(1); + switch (la1->type) { case '{': /* gcc extension: a statement expression */ return parse_statement_expression(); + case T_IDENTIFIER: + if (is_typedef_symbol(la1->symbol)) { TYPE_QUALIFIERS TYPE_SPECIFIERS - return parse_cast(); - case T_IDENTIFIER: - if (is_typedef_symbol(token.symbol)) { return parse_cast(); } } + eat('('); add_anchor_token(')'); expression_t *result = parse_expression(); result->base.parenthesized = true; @@ -7012,40 +6990,27 @@ end_error: } /** - * Return the declaration for a given label symbol or create a new one. - * - * @param symbol the symbol of the label + * Return the label for the current symbol or create a new one. */ -static label_t *get_label(symbol_t *symbol) +static label_t *get_label(void) { - entity_t *label; + assert(token.type == T_IDENTIFIER); assert(current_function != NULL); - label = get_entity(symbol, NAMESPACE_LABEL); - /* if we found a local label, we already created the declaration */ + entity_t *label = get_entity(token.symbol, NAMESPACE_LABEL); + /* If we find a local label, we already created the declaration. */ if (label != NULL && label->kind == ENTITY_LOCAL_LABEL) { if (label->base.parent_scope != current_scope) { assert(label->base.parent_scope->depth < current_scope->depth); current_function->goto_to_outer = true; } - return &label->label; - } - - label = get_entity(symbol, NAMESPACE_LABEL); - /* if we found a label in the same function, then we already created the - * declaration */ - if (label != NULL - && label->base.parent_scope == ¤t_function->parameters) { - return &label->label; + } else if (label == NULL || label->base.parent_scope != ¤t_function->parameters) { + /* There is no matching label in the same function, so create a new one. */ + label = allocate_entity_zero(ENTITY_LABEL, NAMESPACE_LABEL, token.symbol); + label_push(label); } - /* otherwise we need to create a new one */ - label = allocate_entity_zero(ENTITY_LABEL); - label->base.namespc = NAMESPACE_LABEL; - label->base.symbol = symbol; - - label_push(label); - + eat(T_IDENTIFIER); return &label->label; } @@ -7058,24 +7023,20 @@ static expression_t *parse_label_address(void) eat(T_ANDAND); if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing label address", T_IDENTIFIER, NULL); - goto end_error; + return create_invalid_expression(); } - symbol_t *symbol = token.symbol; - next_token(); - label_t *label = get_label(symbol); + label_t *const label = get_label(); label->used = true; label->address_taken = true; expression_t *expression = allocate_expression_zero(EXPR_LABEL_ADDRESS); expression->base.source_position = source_position; - /* label address is threaten as a void pointer */ + /* label address is treated as a void pointer */ expression->base.type = type_void_ptr; expression->label_address.label = label; return expression; -end_error: - return create_invalid_expression(); } /** @@ -7174,29 +7135,15 @@ static expression_t *parse_primary_expression(void) return create_invalid_expression(); } -/** - * Check if the expression has the character type and issue a warning then. - */ -static void check_for_char_index_type(const expression_t *expression) -{ - type_t *const type = expression->base.type; - const type_t *const base_type = skip_typeref(type); - - if (is_type_atomic(base_type, ATOMIC_TYPE_CHAR) && - warning.char_subscripts) { - warningf(&expression->base.source_position, - "array subscript has type '%T'", type); - } -} - static expression_t *parse_array_expression(expression_t *left) { - expression_t *expression = allocate_expression_zero(EXPR_ARRAY_ACCESS); + expression_t *const expr = allocate_expression_zero(EXPR_ARRAY_ACCESS); + array_access_expression_t *const arr = &expr->array_access; eat('['); add_anchor_token(']'); - expression_t *inside = parse_expression(); + expression_t *const inside = parse_expression(); type_t *const orig_type_left = left->base.type; type_t *const orig_type_inside = inside->base.type; @@ -7204,36 +7151,48 @@ static expression_t *parse_array_expression(expression_t *left) type_t *const type_left = skip_typeref(orig_type_left); type_t *const type_inside = skip_typeref(orig_type_inside); - type_t *return_type; - array_access_expression_t *array_access = &expression->array_access; + expression_t *ref; + expression_t *idx; + type_t *idx_type; + type_t *res_type; if (is_type_pointer(type_left)) { - return_type = type_left->pointer.points_to; - array_access->array_ref = left; - array_access->index = inside; - check_for_char_index_type(inside); + ref = left; + idx = inside; + idx_type = type_inside; + res_type = type_left->pointer.points_to; + goto check_idx; } else if (is_type_pointer(type_inside)) { - return_type = type_inside->pointer.points_to; - array_access->array_ref = inside; - array_access->index = left; - array_access->flipped = true; - check_for_char_index_type(left); + arr->flipped = true; + ref = inside; + idx = left; + idx_type = type_left; + res_type = type_inside->pointer.points_to; +check_idx: + res_type = automatic_type_conversion(res_type); + if (!is_type_integer(idx_type)) { + errorf(&idx->base.source_position, "array subscript must have integer type"); + } else if (is_type_atomic(idx_type, ATOMIC_TYPE_CHAR) && warning.char_subscripts) { + warningf(&idx->base.source_position, "array subscript has char type"); + } } else { if (is_type_valid(type_left) && is_type_valid(type_inside)) { - errorf(HERE, + errorf(&expr->base.source_position, "array access on object with non-pointer types '%T', '%T'", orig_type_left, orig_type_inside); } - return_type = type_error_type; - array_access->array_ref = left; - array_access->index = inside; + res_type = type_error_type; + ref = left; + idx = inside; } - expression->base.type = automatic_type_conversion(return_type); + arr->array_ref = ref; + arr->index = idx; + arr->base.type = res_type; rem_anchor_token(']'); expect(']', end_error); end_error: - return expression; + return expr; } static expression_t *parse_typeprop(expression_kind_t const kind) @@ -7424,8 +7383,8 @@ static void check_call_argument(type_t *expected_type, /* report exact scope in error messages (like "in argument 3") */ char buf[64]; snprintf(buf, sizeof(buf), "call argument %u", pos); - report_assign_error(error, expected_type, arg_expr, buf, - &arg_expr->base.source_position); + report_assign_error(error, expected_type, arg_expr, buf, + &arg_expr->base.source_position); } 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) && @@ -7558,9 +7517,9 @@ static expression_t *parse_call_expression(expression_t *expression) } if (parameter != NULL) { - errorf(HERE, "too few arguments to function '%E'", expression); + errorf(&expression->base.source_position, "too few arguments to function '%E'", expression); } else if (argument != NULL && !function_type->variadic) { - errorf(HERE, "too many arguments to function '%E'", expression); + errorf(&argument->expression->base.source_position, "too many arguments to function '%E'", expression); } } @@ -7578,16 +7537,16 @@ static expression_t *parse_call_expression(expression_t *expression) = create_implicit_cast(argument->expression, type); } - check_format(&result->call); + check_format(call); if (warning.aggregate_return && is_type_compound(skip_typeref(function_type->return_type))) { - warningf(&result->base.source_position, + warningf(&expression->base.source_position, "function call has aggregate value"); } - if (call->function->kind == EXPR_REFERENCE) { - reference_expression_t *reference = &call->function->reference; + if (expression->kind == EXPR_REFERENCE) { + reference_expression_t *reference = &expression->reference; if (reference->entity->kind == ENTITY_FUNCTION && reference->entity->function.btk != bk_none) handle_builtin_argument_restrictions(call); @@ -8076,8 +8035,8 @@ static void set_address_taken(expression_t *expression, bool may_be_register) if (entity->declaration.storage_class == STORAGE_CLASS_REGISTER && !may_be_register) { errorf(&expression->base.source_position, - "address of register %s '%Y' requested", - get_entity_kind_name(entity->kind), entity->base.symbol); + "address of register %s '%Y' requested", + get_entity_kind_name(entity->kind), entity->base.symbol); } if (entity->kind == ENTITY_VARIABLE) { @@ -8258,6 +8217,30 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression) expression->base.type = arithmetic_type; } +static void semantic_binexpr_integer(binary_expression_t *const expression) +{ + expression_t *const left = expression->left; + expression_t *const right = expression->right; + type_t *const orig_type_left = left->base.type; + type_t *const orig_type_right = right->base.type; + type_t *const type_left = skip_typeref(orig_type_left); + type_t *const type_right = skip_typeref(orig_type_right); + + if (!is_type_integer(type_left) || !is_type_integer(type_right)) { + /* TODO: improve error message */ + if (is_type_valid(type_left) && is_type_valid(type_right)) { + errorf(&expression->base.source_position, + "operation needs integer types"); + } + return; + } + + type_t *const result_type = semantic_arithmetic(type_left, type_right); + expression->left = create_implicit_cast(left, result_type); + expression->right = create_implicit_cast(right, result_type); + expression->base.type = result_type; +} + static void warn_div_by_zero(binary_expression_t const *const expression) { if (!warning.div_by_zero || @@ -8581,33 +8564,33 @@ static bool is_valid_assignment_lhs(expression_t const* const left) type_t *const type_left = skip_typeref(orig_type_left); if (!is_lvalue(left)) { - errorf(HERE, "left hand side '%E' of assignment is not an lvalue", + errorf(&left->base.source_position, "left hand side '%E' of assignment is not an lvalue", left); return false; } if (left->kind == EXPR_REFERENCE && left->reference.entity->kind == ENTITY_FUNCTION) { - errorf(HERE, "cannot assign to function '%E'", left); + errorf(&left->base.source_position, "cannot assign to function '%E'", left); return false; } if (is_type_array(type_left)) { - errorf(HERE, "cannot assign to array '%E'", left); + errorf(&left->base.source_position, "cannot assign to array '%E'", left); return false; } if (type_left->base.qualifiers & TYPE_QUALIFIER_CONST) { - errorf(HERE, "assignment to readonly location '%E' (type '%T')", left, + errorf(&left->base.source_position, "assignment to read-only location '%E' (type '%T')", left, orig_type_left); return false; } if (is_type_incomplete(type_left)) { - errorf(HERE, "left-hand side '%E' of assignment has incomplete type '%T'", + errorf(&left->base.source_position, "left-hand side '%E' of assignment has incomplete type '%T'", left, orig_type_left); return false; } if (is_type_compound(type_left) && has_const_fields(&type_left->compound)) { - errorf(HERE, "cannot assign to '%E' because compound type '%T' has readonly fields", + errorf(&left->base.source_position, "cannot assign to '%E' because compound type '%T' has read-only fields", left, orig_type_left); return false; } @@ -8959,9 +8942,9 @@ CREATE_BINEXPR_PARSER(T_LESSEQUAL, EXPR_BINARY_LESSEQUAL, PR CREATE_BINEXPR_PARSER(T_GREATEREQUAL, EXPR_BINARY_GREATEREQUAL, PREC_SHIFT, semantic_comparison) CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, EXPR_BINARY_NOTEQUAL, PREC_RELATIONAL, semantic_comparison) CREATE_BINEXPR_PARSER(T_EQUALEQUAL, EXPR_BINARY_EQUAL, PREC_RELATIONAL, semantic_comparison) -CREATE_BINEXPR_PARSER('&', EXPR_BINARY_BITWISE_AND, PREC_EQUALITY, semantic_binexpr_arithmetic) -CREATE_BINEXPR_PARSER('^', EXPR_BINARY_BITWISE_XOR, PREC_AND, semantic_binexpr_arithmetic) -CREATE_BINEXPR_PARSER('|', EXPR_BINARY_BITWISE_OR, PREC_XOR, semantic_binexpr_arithmetic) +CREATE_BINEXPR_PARSER('&', EXPR_BINARY_BITWISE_AND, PREC_EQUALITY, semantic_binexpr_integer) +CREATE_BINEXPR_PARSER('^', EXPR_BINARY_BITWISE_XOR, PREC_AND, semantic_binexpr_integer) +CREATE_BINEXPR_PARSER('|', EXPR_BINARY_BITWISE_OR, PREC_XOR, semantic_binexpr_integer) CREATE_BINEXPR_PARSER(T_ANDAND, EXPR_BINARY_LOGICAL_AND, PREC_OR, semantic_logical_op) CREATE_BINEXPR_PARSER(T_PIPEPIPE, EXPR_BINARY_LOGICAL_OR, PREC_LOGICAL_AND, semantic_logical_op) CREATE_BINEXPR_PARSER('=', EXPR_BINARY_ASSIGN, PREC_ASSIGNMENT, semantic_binexpr_assign) @@ -9052,7 +9035,7 @@ static void register_expression_parser(parse_expression_function parser, * @param precedence the precedence of the operator */ static void register_infix_parser(parse_expression_infix_function parser, - int token_type, precedence_t precedence) + int token_type, precedence_t precedence) { expression_parser_function_t *entry = &expression_parsers[token_type]; @@ -9308,17 +9291,17 @@ end_error: return create_invalid_statement(); } -static statement_t *parse_label_inner_statement(char const *const label, bool const eat_empty_stmt) +static statement_t *parse_label_inner_statement(statement_t const *const label, char const *const label_kind) { statement_t *inner_stmt; switch (token.type) { case '}': - errorf(HERE, "%s at end of compound statement", label); + errorf(&label->base.source_position, "%s at end of compound statement", label_kind); inner_stmt = create_invalid_statement(); break; case ';': - if (eat_empty_stmt) { + if (label->kind == STATEMENT_LABEL) { /* Eat an empty statement here, to avoid the warning about an empty * statement after a label. label:; is commonly used to have a label * before a closing brace. */ @@ -9330,8 +9313,9 @@ static statement_t *parse_label_inner_statement(char const *const label, bool co default: inner_stmt = parse_statement(); - if (inner_stmt->kind == STATEMENT_DECLARATION) { - errorf(&inner_stmt->base.source_position, "declaration after %s", label); + /* ISO/IEC 14882:1998(E) §6:1/§6.7 Declarations are statements */ + if (inner_stmt->kind == STATEMENT_DECLARATION && !(c_mode & _CXX)) { + errorf(&inner_stmt->base.source_position, "declaration after %s", label_kind); } break; } @@ -9416,7 +9400,7 @@ end_error: errorf(pos, "case label not within a switch statement"); } - statement->case_label.statement = parse_label_inner_statement("case label", false); + statement->case_label.statement = parse_label_inner_statement(statement, "case label"); POP_PARENT; return statement; @@ -9439,8 +9423,7 @@ end_error: if (current_switch != NULL) { const case_label_statement_t *def_label = current_switch->default_label; if (def_label != NULL) { - errorf(HERE, "multiple default labels in one switch (previous declared %P)", - &def_label->base.source_position); + errorf(&statement->base.source_position, "multiple default labels in one switch (previous declared %P)", &def_label->base.source_position); } else { current_switch->default_label = &statement->case_label; @@ -9457,7 +9440,7 @@ end_error: "'default' label not within a switch statement"); } - statement->case_label.statement = parse_label_inner_statement("default label", false); + statement->case_label.statement = parse_label_inner_statement(statement, "default label"); POP_PARENT; return statement; @@ -9468,31 +9451,26 @@ end_error: */ static statement_t *parse_label_statement(void) { - assert(token.type == T_IDENTIFIER); - symbol_t *symbol = token.symbol; - label_t *label = get_label(symbol); - statement_t *const statement = allocate_statement_zero(STATEMENT_LABEL); - statement->label.label = label; - - next_token(); + label_t *const label = get_label(); + statement->label.label = label; PUSH_PARENT(statement); /* if statement is already set then the label is defined twice, * otherwise it was just mentioned in a goto/local label declaration so far */ + source_position_t const* const pos = &statement->base.source_position; if (label->statement != NULL) { - errorf(HERE, "duplicate label '%Y' (declared %P)", - symbol, &label->base.source_position); + errorf(pos, "duplicate label '%Y' (declared %P)", label->base.symbol, &label->base.source_position); } else { - label->base.source_position = token.source_position; + label->base.source_position = *pos; label->statement = statement; } eat(':'); - statement->label.statement = parse_label_inner_statement("label", true); + statement->label.statement = parse_label_inner_statement(statement, "label"); /* remember the labels in a list for later checking */ *label_anchor = &statement->label; @@ -9830,9 +9808,9 @@ static statement_t *parse_goto(void) statement->gotos.expression = expression; } else if (token.type == T_IDENTIFIER) { - symbol_t *symbol = token.symbol; - next_token(); - statement->gotos.label = get_label(symbol); + label_t *const label = get_label(); + label->used = true; + statement->gotos.label = label; } else { if (GNU_MODE) parse_error_expected("while parsing goto", T_IDENTIFIER, '*', NULL); @@ -10003,13 +9981,13 @@ static statement_t *parse_return(void) } } else { assign_error_t error = semantic_assign(return_type, return_value); - report_assign_error(error, return_type, return_value, "'return'", - pos); + report_assign_error(error, return_type, return_value, "'return'", + pos); } return_value = create_implicit_cast(return_value, return_type); /* check for returning address of a local var */ if (warning.other && return_value != NULL - && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) { + && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) { const expression_t *expression = return_value->unary.value; if (expression_is_local_variable(expression)) { warningf(pos, "function returns address of local variable"); @@ -10019,10 +9997,10 @@ static statement_t *parse_return(void) /* ISO/IEC 14882:1998(E) §6.6.3:3 */ if (c_mode & _CXX || strict_mode) { errorf(pos, - "'return' without value, in function returning non-void"); + "'return' without value, in function returning non-void"); } else { warningf(pos, - "'return' without value, in function returning non-void"); + "'return' without value, in function returning non-void"); } } statement->returns.value = return_value; @@ -10150,12 +10128,9 @@ static statement_t *parse_local_label_declaration(void) errorf(HERE, "multiple definitions of '__label__ %Y' (previous definition %P)", symbol, &entity->base.source_position); } else { - entity = allocate_entity_zero(ENTITY_LOCAL_LABEL); - + entity = allocate_entity_zero(ENTITY_LOCAL_LABEL, NAMESPACE_LABEL, symbol); entity->base.parent_scope = current_scope; - entity->base.namespc = NAMESPACE_LABEL; entity->base.source_position = token.source_position; - entity->base.symbol = symbol; *anchor = entity; anchor = &entity->base.next; @@ -10187,7 +10162,7 @@ static void parse_namespace_definition(void) if (entity != NULL && entity->kind != ENTITY_NAMESPACE && entity->base.parent_scope == current_scope) { - if (!is_error_entity(entity)) { + if (is_entity_valid(entity)) { error_redefined_as_different_kind(&token.source_position, entity, ENTITY_NAMESPACE); } @@ -10196,10 +10171,8 @@ static void parse_namespace_definition(void) } if (entity == NULL) { - entity = allocate_entity_zero(ENTITY_NAMESPACE); - entity->base.symbol = symbol; + entity = allocate_entity_zero(ENTITY_NAMESPACE, NAMESPACE_NORMAL, symbol); entity->base.source_position = token.source_position; - entity->base.namespc = NAMESPACE_NORMAL; entity->base.parent_scope = current_scope; } @@ -10653,9 +10626,9 @@ end_error:; static void parse_linkage_specification(void) { eat(T_extern); - assert(token.type == T_STRING_LITERAL); - const char *linkage = parse_string_literals().begin; + source_position_t const pos = *HERE; + char const *const linkage = parse_string_literals().begin; linkage_kind_t old_linkage = current_linkage; linkage_kind_t new_linkage; @@ -10664,7 +10637,7 @@ static void parse_linkage_specification(void) } else if (strcmp(linkage, "C++") == 0) { new_linkage = LINKAGE_CXX; } else { - errorf(HERE, "linkage string \"%s\" not recognized", linkage); + errorf(&pos, "linkage string \"%s\" not recognized", linkage); new_linkage = LINKAGE_INVALID; } current_linkage = new_linkage; @@ -10735,6 +10708,7 @@ static void parse_externals(void) add_anchor_token(T_EOF); #ifndef NDEBUG + /* make a copy of the anchor set, so we can check if it is restored after parsing */ unsigned char token_anchor_copy[T_LAST_TOKEN]; memcpy(token_anchor_copy, token_anchor_set, sizeof(token_anchor_copy)); #endif @@ -10742,15 +10716,17 @@ static void parse_externals(void) while (token.type != T_EOF && token.type != '}') { #ifndef NDEBUG bool anchor_leak = false; - for (int i = 0; i != T_LAST_TOKEN; ++i) { + for (int i = 0; i < T_LAST_TOKEN; ++i) { unsigned char count = token_anchor_set[i] - token_anchor_copy[i]; if (count != 0) { - errorf(HERE, "Leaked anchor token %k %d times", i, count); + /* the anchor set and its copy differs */ + internal_errorf(HERE, "Leaked anchor token %k %d times", i, count); anchor_leak = true; } } if (in_gcc_extension) { - errorf(HERE, "Leaked __extension__"); + /* an gcc extension scope was not closed */ + internal_errorf(HERE, "Leaked __extension__"); anchor_leak = true; } @@ -10785,6 +10761,11 @@ static void parse_translation_unit(void) } } +void set_default_visibility(elf_visibility_tag_t visibility) +{ + default_visibility = visibility; +} + /** * Parse the input. * @@ -10916,9 +10897,6 @@ void init_parser(void) init_expression_parsers(); obstack_init(&temp_obst); - - symbol_t *const va_list_sym = symbol_table_insert("__builtin_va_list"); - type_valist = create_builtin_type(va_list_sym, type_void_ptr); } /**