X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=parser.c;h=980d9f2eafaf5aa34deaf6cde7b43251cfeb68dc;hb=0ebbd3e65a57231db1c7346190cb4f04ea52b628;hp=cf9273e33c26beb7b2d8401af065c42d5f3ca1f2;hpb=70bbc66382fadfcc4af5c2525f7b8423d360a5a8;p=cparser diff --git a/parser.c b/parser.c index cf9273e..980d9f2 100644 --- a/parser.c +++ b/parser.c @@ -130,7 +130,7 @@ static unsigned char token_anchor_set[T_LAST_TOKEN]; static statement_t *parse_compound_statement(bool inside_expression_statement); static statement_t *parse_statement(void); -static expression_t *parse_sub_expression(precedence_t); +static expression_t *parse_subexpression(precedence_t); static expression_t *parse_expression(void); static type_t *parse_typename(void); static void parse_externals(void); @@ -658,7 +658,7 @@ static void type_error_incompatible(const char *msg, /** * Expect the current token is the expected token. * If not, generate an error, eat the current statement, - * and goto the end_error label. + * and goto the error_label label. */ #define expect(expected, error_label) \ do { \ @@ -702,6 +702,7 @@ static void scope_pop(scope_t *old_scope) static entity_t *get_entity(const symbol_t *const symbol, namespace_tag_t namespc) { + assert(namespc != NAMESPACE_INVALID); entity_t *entity = symbol->entity; for (; entity != NULL; entity = entity->base.symbol_next) { if (entity->base.namespc == namespc) @@ -823,7 +824,7 @@ static void stack_pop_to(stack_entry_t **stack_ptr, size_t new_top) } } - ARR_SHRINKLEN(*stack_ptr, (int) new_top); + ARR_SHRINKLEN(*stack_ptr, new_top); } /** @@ -916,10 +917,13 @@ static bool is_null_pointer_constant(const expression_t *expression) } type_t *const type = skip_typeref(expression->base.type); - return - is_type_integer(type) && - is_constant_expression(expression) && - !fold_constant_to_bool(expression); + if (!is_type_integer(type)) + return false; + switch (is_constant_expression(expression)) { + case EXPR_CLASS_ERROR: return true; + case EXPR_CLASS_CONSTANT: return !fold_constant_to_bool(expression); + default: return false; + } } /** @@ -1055,8 +1059,8 @@ static assign_error_t semantic_assign(type_t *orig_type_left, return ASSIGN_WARNING_POINTER_FROM_INT; } } else if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) || - (is_type_atomic(type_left, ATOMIC_TYPE_BOOL) - && is_type_pointer(type_right))) { + (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))) { @@ -1077,9 +1081,9 @@ static assign_error_t semantic_assign(type_t *orig_type_left, static expression_t *parse_constant_expression(void) { - expression_t *result = parse_sub_expression(PREC_CONDITIONAL); + expression_t *result = parse_subexpression(PREC_CONDITIONAL); - if (!is_constant_expression(result)) { + if (is_constant_expression(result) == EXPR_CLASS_VARIABLE) { errorf(&result->base.source_position, "expression '%E' is not constant", result); } @@ -1089,7 +1093,7 @@ static expression_t *parse_constant_expression(void) static expression_t *parse_assignment_expression(void) { - return parse_sub_expression(PREC_ASSIGNMENT); + return parse_subexpression(PREC_ASSIGNMENT); } static void warn_string_concat(const source_position_t *pos) @@ -1261,7 +1265,7 @@ static attribute_t *parse_attribute_gnu_single(void) symbol_t *symbol = get_symbol_from_token(); if (symbol == NULL) { parse_error_expected("while parsing attribute((", T_IDENTIFIER, NULL); - goto end_error; + return NULL; } const char *name = symbol->string; @@ -1290,9 +1294,6 @@ static attribute_t *parse_attribute_gnu_single(void) attribute->a.arguments = parse_attribute_arguments(); return attribute; - -end_error: - return NULL; } static attribute_t *parse_attribute_gnu(void) @@ -1735,8 +1736,9 @@ static initializer_t *initializer_from_expression(type_t *orig_type, */ static bool is_initializer_constant(const expression_t *expression) { - return is_constant_expression(expression) - || is_address_constant(expression); + return + is_constant_expression(expression) != EXPR_CLASS_VARIABLE || + is_address_constant(expression) != EXPR_CLASS_VARIABLE; } /** @@ -1967,7 +1969,7 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, type_t *real_type = skip_typeref(iter->declaration.type); if (real_type->kind == TYPE_BITFIELD) { errorf(&designator->source_position, - "offsetof designator '%Y' may not specify bitfield", + "offsetof designator '%Y' must not specify bitfield", symbol); goto failed; } @@ -1999,8 +2001,8 @@ static bool walk_designator(type_path_t *path, const designator_t *designator, long array_size = type->array.size; if (index >= array_size) { errorf(&designator->source_position, - "designator [%E] (%d) exceeds array size %d", - array_index, index, array_size); + "designator [%E] (%d) exceeds array size %d", + array_index, index, array_size); } } } @@ -2509,6 +2511,7 @@ static void parse_enum_entries(type_t *const enum_type) entity_t *entity = allocate_entity_zero(ENTITY_ENUM_VALUE); 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(); @@ -2634,21 +2637,14 @@ static type_t *parse_typeof(void) switch (token.type) { case T_IDENTIFIER: if (is_typedef_symbol(token.symbol)) { + TYPENAME_START type = parse_typename(); } else { + default: expression = parse_expression(); type = revert_automatic_type_conversion(expression); } break; - - TYPENAME_START - type = parse_typename(); - break; - - default: - expression = parse_expression(); - type = expression->base.type; - break; } in_type_prop = old_type_prop; in_gcc_extension = old_gcc_extension; @@ -2830,6 +2826,7 @@ 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->base.source_position = *HERE; entity->base.symbol = symbol; if (is_declaration(entity)) { @@ -2895,10 +2892,10 @@ check_thread_storage_class: break; char const* wrong; - case STORAGE_CLASS_AUTO: wrong = "auto"; goto wrong_thread_stoarge_class; - case STORAGE_CLASS_REGISTER: wrong = "register"; goto wrong_thread_stoarge_class; - case STORAGE_CLASS_TYPEDEF: wrong = "typedef"; goto wrong_thread_stoarge_class; -wrong_thread_stoarge_class: + case STORAGE_CLASS_AUTO: wrong = "auto"; goto wrong_thread_storage_class; + case STORAGE_CLASS_REGISTER: wrong = "register"; goto wrong_thread_storage_class; + case STORAGE_CLASS_TYPEDEF: wrong = "typedef"; goto wrong_thread_storage_class; +wrong_thread_storage_class: errorf(HERE, "'__thread' used with '%s'", wrong); break; } @@ -3494,54 +3491,64 @@ union construct_type_t { parsed_array_t array; }; +static construct_type_t *allocate_declarator_zero(construct_type_kind_t const kind, size_t const size) +{ + construct_type_t *const cons = obstack_alloc(&temp_obst, size); + memset(cons, 0, size); + cons->kind = kind; + return cons; +} + +/* §6.7.5.1 */ static construct_type_t *parse_pointer_declarator(void) { eat('*'); - parsed_pointer_t *pointer = obstack_alloc(&temp_obst, sizeof(pointer[0])); - memset(pointer, 0, sizeof(pointer[0])); - pointer->base.kind = CONSTRUCT_POINTER; - pointer->type_qualifiers = parse_type_qualifiers(); - //pointer->base_variable = base_variable; + construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_POINTER, sizeof(parsed_pointer_t)); + cons->pointer.type_qualifiers = parse_type_qualifiers(); + //cons->pointer.base_variable = base_variable; - return (construct_type_t*) pointer; + return cons; } +/* ISO/IEC 14882:1998(E) §8.3.2 */ static construct_type_t *parse_reference_declarator(void) { eat('&'); - construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->reference)); - parsed_reference_t *reference = &cons->reference; - memset(reference, 0, sizeof(*reference)); - cons->kind = CONSTRUCT_REFERENCE; + 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)); return cons; } +/* §6.7.5.2 */ static construct_type_t *parse_array_declarator(void) { eat('['); add_anchor_token(']'); - construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->array)); - parsed_array_t *array = &cons->array; - memset(array, 0, sizeof(*array)); - cons->kind = CONSTRUCT_ARRAY; + construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_ARRAY, sizeof(parsed_array_t)); + parsed_array_t *const array = &cons->array; - if (next_if(T_static)) - array->is_static = true; + bool is_static = next_if(T_static); type_qualifiers_t type_qualifiers = parse_type_qualifiers(); - if (type_qualifiers != 0 && next_if(T_static)) - array->is_static = true; + + if (!is_static) + is_static = next_if(T_static); + array->type_qualifiers = type_qualifiers; + array->is_static = is_static; + expression_t *size = NULL; if (token.type == '*' && look_ahead(1)->type == ']') { array->is_variable = true; next_token(); } else if (token.type != ']') { - expression_t *const size = parse_assignment_expression(); + size = parse_assignment_expression(); /* §6.7.5.2:1 Array size must have integer type */ type_t *const orig_type = size->base.type; @@ -3556,6 +3563,9 @@ static construct_type_t *parse_array_declarator(void) mark_vars_read(size, NULL); } + if (is_static && size == NULL) + errorf(HERE, "static array parameters require a size"); + rem_anchor_token(']'); expect(']', end_error); @@ -3563,6 +3573,7 @@ end_error: return cons; } +/* §6.7.5.3 */ static construct_type_t *parse_function_declarator(scope_t *scope) { type_t *type = allocate_type_zero(TYPE_FUNCTION); @@ -3573,11 +3584,8 @@ static construct_type_t *parse_function_declarator(scope_t *scope) parse_parameters(ftype, scope); - construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->function)); - construct_function_type_t *function = &cons->function; - memset(function, 0, sizeof(*function)); - cons->kind = CONSTRUCT_FUNCTION; - function->function_type = type; + construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_FUNCTION, sizeof(construct_function_type_t)); + cons->function.function_type = type; return cons; } @@ -3592,6 +3600,7 @@ typedef struct parse_declarator_env_t { attribute_t *attributes; } parse_declarator_env_t; +/* §6.7.5 */ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env) { /* construct a single linked list of construct_type_t's which describe @@ -3606,8 +3615,6 @@ static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env) //variable_t *based = NULL; /* MS __based extension */ switch (token.type) { case '&': - if (!(c_mode & _CXX)) - errorf(HERE, "references are only available for C++"); type = parse_reference_declarator(); break; @@ -3658,12 +3665,16 @@ ptr_operator_end: ; } rem_anchor_token(')'); expect(')', end_error); + } else if (!env->may_be_abstract) { + errorf(HERE, "declarator must have a name"); + goto error_out; } break; default: if (env->may_be_abstract) break; parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL); +error_out: eat_until_anchor(); return NULL; } @@ -3775,24 +3786,31 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, array_type->array.size_expression = size_expression; if (size_expression != NULL) { - if (is_constant_expression(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 - * have a value greater than zero. */ - if (size <= 0) { - if (size < 0 || !GNU_MODE) { - errorf(&size_expression->base.source_position, - "size of array must be greater than zero"); - } else if (warning.other) { - warningf(&size_expression->base.source_position, - "zero length arrays are a GCC extension"); + switch (is_constant_expression(size_expression)) { + case EXPR_CLASS_CONSTANT: { + 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 + * have a value greater than zero. */ + if (size <= 0) { + if (size < 0 || !GNU_MODE) { + errorf(&size_expression->base.source_position, + "size of array must be greater than zero"); + } else if (warning.other) { + warningf(&size_expression->base.source_position, + "zero length arrays are a GCC extension"); + } } + break; } - } else { - array_type->array.is_vla = true; + + case EXPR_CLASS_VARIABLE: + array_type->array.is_vla = true; + break; + + case EXPR_CLASS_ERROR: + break; } } @@ -3875,6 +3893,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->base.source_position = env.source_position; entity->typedefe.type = orig_type; @@ -3927,10 +3946,10 @@ static entity_t *parse_declarator(const declaration_specifiers_t *specifiers, bool in_function_scope = current_function != NULL; if (specifiers->thread_local || ( - specifiers->storage_class != STORAGE_CLASS_EXTERN && - specifiers->storage_class != STORAGE_CLASS_NONE && - (in_function_scope || specifiers->storage_class != STORAGE_CLASS_STATIC) - )) { + specifiers->storage_class != STORAGE_CLASS_EXTERN && + specifiers->storage_class != STORAGE_CLASS_NONE && + (in_function_scope || specifiers->storage_class != STORAGE_CLASS_STATIC) + )) { errorf(&env.source_position, "invalid storage class for function '%Y'", env.symbol); } @@ -4088,14 +4107,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)); } else if (ent->kind == ENTITY_TYPEDEF) { 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) @@ -4197,7 +4216,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); } @@ -4413,19 +4432,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; + 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; + } eat('='); - 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); } + declaration_t *const declaration = &entity->declaration; bool must_be_constant = false; if (declaration->storage_class == STORAGE_CLASS_STATIC || entity->base.parent_scope == file_scope) { @@ -4879,8 +4905,8 @@ static void check_declarations(void) static int determine_truth(expression_t const* const cond) { return - !is_constant_expression(cond) ? 0 : - fold_constant_to_bool(cond) ? 1 : + is_constant_expression(cond) != EXPR_CLASS_CONSTANT ? 0 : + fold_constant_to_bool(cond) ? 1 : -1; } @@ -5090,7 +5116,7 @@ static void check_reachable(statement_t *const stmt) if (!expression_returns(expr)) return; - if (is_constant_expression(expr)) { + if (is_constant_expression(expr) == EXPR_CLASS_CONSTANT) { 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) { @@ -5676,7 +5702,7 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size, bit_size = get_type_size(base_type) * 8; } - if (is_constant_expression(size)) { + if (is_constant_expression(size) == EXPR_CLASS_CONSTANT) { long v = fold_constant_to_int(size); const symbol_t *user_symbol = symbol == NULL ? sym_anonymous : symbol; @@ -5941,7 +5967,7 @@ static type_t *parse_typename(void) /* TODO: improve error message, user does probably not know what a * storage class is... */ - errorf(HERE, "typename may not have a storage class"); + errorf(HERE, "typename must not have a storage class"); } type_t *result = parse_abstract_declarator(specifiers.type); @@ -6119,14 +6145,17 @@ static expression_t *parse_number_literal(void) case T_INTEGER: kind = EXPR_LITERAL_INTEGER; check_integer_suffix(); + type = type_int; break; case T_INTEGER_OCTAL: kind = EXPR_LITERAL_INTEGER_OCTAL; check_integer_suffix(); + type = type_int; break; case T_INTEGER_HEXADECIMAL: kind = EXPR_LITERAL_INTEGER_HEXADECIMAL; check_integer_suffix(); + type = type_int; break; case T_FLOATINGPOINT: kind = EXPR_LITERAL_FLOATINGPOINT; @@ -6212,6 +6241,7 @@ static entity_t *create_implicit_function(symbol_t *symbol, 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; @@ -6540,7 +6570,7 @@ static expression_t *parse_cast(void) expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST); cast->base.source_position = source_position; - expression_t *value = parse_sub_expression(PREC_CAST); + expression_t *value = parse_subexpression(PREC_CAST); cast->base.type = type; cast->unary.value = value; @@ -7147,6 +7177,7 @@ static expression_t *parse_primary_expression(void) } errorf(HERE, "unexpected token %K, expected an expression", &token); + eat_until_anchor(); return create_invalid_expression(); } @@ -7239,7 +7270,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind) goto typeprop_expression; } } else { - expression = parse_sub_expression(PREC_UNARY); + expression = parse_subexpression(PREC_UNARY); typeprop_expression: tp_expression->typeprop.tp_expression = expression; @@ -7250,12 +7281,28 @@ typeprop_expression: tp_expression->typeprop.type = orig_type; type_t const* const type = skip_typeref(orig_type); - char const* const wrong_type = - GNU_MODE && is_type_atomic(type, ATOMIC_TYPE_VOID) ? NULL : - is_type_incomplete(type) ? "incomplete" : - type->kind == TYPE_FUNCTION ? "function designator" : - type->kind == TYPE_BITFIELD ? "bitfield" : - NULL; + char const* wrong_type = NULL; + if (is_type_incomplete(type)) { + if (!is_type_atomic(type, ATOMIC_TYPE_VOID) || !GNU_MODE) + wrong_type = "incomplete"; + } else if (type->kind == TYPE_FUNCTION) { + if (GNU_MODE) { + /* function types are allowed (and return 1) */ + if (warning.other) { + char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; + warningf(&tp_expression->base.source_position, + "%s expression with function argument returns invalid result", what); + } + } else { + wrong_type = "function"; + } + } else { + if (is_type_incomplete(type)) + wrong_type = "incomplete"; + } + if (type->kind == TYPE_BITFIELD) + wrong_type = "bitfield"; + if (wrong_type != NULL) { char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; errorf(&tp_expression->base.source_position, @@ -7282,6 +7329,7 @@ static expression_t *parse_select_expression(expression_t *addr) { assert(token.type == '.' || token.type == T_MINUSGREATER); bool select_left_arrow = (token.type == T_MINUSGREATER); + source_position_t const pos = *HERE; next_token(); if (token.type != T_IDENTIFIER) { @@ -7298,7 +7346,7 @@ static expression_t *parse_select_expression(expression_t *addr) bool saw_error = false; if (is_type_pointer(type)) { if (!select_left_arrow) { - errorf(HERE, + errorf(&pos, "request for member '%Y' in something not a struct or union, but '%T'", symbol, orig_type); saw_error = true; @@ -7306,7 +7354,7 @@ static expression_t *parse_select_expression(expression_t *addr) type_left = skip_typeref(type->pointer.points_to); } else { if (select_left_arrow && is_type_valid(type)) { - errorf(HERE, "left hand side of '->' is not a pointer, but '%T'", orig_type); + errorf(&pos, "left hand side of '->' is not a pointer, but '%T'", orig_type); saw_error = true; } type_left = type; @@ -7316,7 +7364,7 @@ static expression_t *parse_select_expression(expression_t *addr) type_left->kind != TYPE_COMPOUND_UNION) { if (is_type_valid(type_left) && !saw_error) { - errorf(HERE, + errorf(&pos, "request for member '%Y' in something not a struct or union, but '%T'", symbol, type_left); } @@ -7325,17 +7373,17 @@ static expression_t *parse_select_expression(expression_t *addr) compound_t *compound = type_left->compound.compound; if (!compound->complete) { - errorf(HERE, "request for member '%Y' in incomplete type '%T'", + errorf(&pos, "request for member '%Y' in incomplete type '%T'", symbol, type_left); return create_invalid_expression(); } type_qualifiers_t qualifiers = type_left->base.qualifiers; - expression_t *result - = find_create_select(HERE, addr, qualifiers, compound, symbol); + expression_t *result = + find_create_select(&pos, addr, qualifiers, compound, symbol); if (result == NULL) { - errorf(HERE, "'%T' has no member named '%Y'", orig_type, symbol); + errorf(&pos, "'%T' has no member named '%Y'", orig_type, symbol); return create_invalid_expression(); } @@ -7408,20 +7456,33 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) { /* argument must be constant */ call_argument_t *argument = call->arguments; - if (! is_constant_expression(argument->expression)) { + if (is_constant_expression(argument->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, "argument of '%Y' must be a constant expression", call->function->reference.entity->base.symbol); } break; } - case bk_gnu_builtin_prefetch: { + case bk_gnu_builtin_object_size: + if (call->arguments == NULL) + break; + + call_argument_t *arg = call->arguments->next; + if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) { + errorf(&call->base.source_position, + "second argument of '%Y' must be a constant expression", + call->function->reference.entity->base.symbol); + } + break; + case bk_gnu_builtin_prefetch: /* second and third argument must be constant if existent */ + if (call->arguments == NULL) + break; call_argument_t *rw = call->arguments->next; call_argument_t *locality = NULL; if (rw != NULL) { - if (! is_constant_expression(rw->expression)) { + if (is_constant_expression(rw->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, "second argument of '%Y' must be a constant expression", call->function->reference.entity->base.symbol); @@ -7429,7 +7490,7 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) { locality = rw->next; } if (locality != NULL) { - if (! is_constant_expression(locality->expression)) { + if (is_constant_expression(locality->expression) == EXPR_CLASS_VARIABLE) { errorf(&call->base.source_position, "third argument of '%Y' must be a constant expression", call->function->reference.entity->base.symbol); @@ -7437,7 +7498,6 @@ static void handle_builtin_argument_restrictions(call_expression_t *call) { locality = rw->next; } break; - } default: break; } @@ -7514,6 +7574,10 @@ static expression_t *parse_call_expression(expression_t *expression) /* do default promotion for other arguments */ for (; argument != NULL; argument = argument->next) { type_t *type = argument->expression->base.type; + if (!is_type_object(skip_typeref(type))) { + errorf(&argument->expression->base.source_position, + "call argument '%E' must not be void", argument->expression); + } type = get_default_promoted_type(type); @@ -7646,7 +7710,7 @@ static expression_t *parse_conditional_expression(expression_t *expression) expect(':', end_error); end_error:; expression_t *false_expression = - parse_sub_expression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL); + parse_subexpression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL); type_t *const orig_true_type = true_expression->base.type; type_t *const orig_false_type = false_expression->base.type; @@ -7675,13 +7739,6 @@ end_error:; } else if (is_type_arithmetic(true_type) && is_type_arithmetic(false_type)) { result_type = semantic_arithmetic(true_type, false_type); - - true_expression = create_implicit_cast(true_expression, result_type); - false_expression = create_implicit_cast(false_expression, result_type); - - conditional->true_expression = true_expression; - conditional->false_expression = false_expression; - conditional->base.type = result_type; } else if (same_compound_type(true_type, false_type)) { /* just take 1 of the 2 types */ result_type = true_type; @@ -7733,7 +7790,7 @@ end_error:; result_type = pointer_type; } else { if (is_type_valid(other_type)) { - type_error_incompatible("while parsing conditional", + type_error_incompatible("while parsing conditional", &expression->base.source_position, true_type, false_type); } result_type = type_error_type; @@ -7764,7 +7821,7 @@ static expression_t *parse_extension(void) bool old_gcc_extension = in_gcc_extension; in_gcc_extension = true; - expression_t *expression = parse_sub_expression(PREC_UNARY); + expression_t *expression = parse_subexpression(PREC_UNARY); in_gcc_extension = old_gcc_extension; return expression; } @@ -7808,7 +7865,7 @@ static expression_t *parse_delete(void) end_error:; } - expression_t *const value = parse_sub_expression(PREC_CAST); + expression_t *const value = parse_subexpression(PREC_CAST); result->unary.value = value; type_t *const type = skip_typeref(value->base.type); @@ -8072,7 +8129,7 @@ static expression_t *parse_##unexpression_type(void) \ expression_t *unary_expression \ = allocate_expression_zero(unexpression_type); \ eat(token_type); \ - unary_expression->unary.value = parse_sub_expression(PREC_UNARY); \ + unary_expression->unary.value = parse_subexpression(PREC_UNARY); \ \ sfunc(&unary_expression->unary); \ \ @@ -8216,8 +8273,8 @@ static void warn_div_by_zero(binary_expression_t const *const expression) expression_t const *const right = expression->right; /* The type of the right operand can be different for /= */ - if (is_type_integer(right->base.type) && - is_constant_expression(right) && + if (is_type_integer(right->base.type) && + is_constant_expression(right) == EXPR_CLASS_CONSTANT && !fold_constant_to_bool(right)) { warningf(&expression->base.source_position, "division by zero"); } @@ -8268,7 +8325,7 @@ static bool semantic_shift(binary_expression_t *expression) type_left = promote_integer(type_left); - if (is_constant_expression(right)) { + if (is_constant_expression(right) == EXPR_CLASS_CONSTANT) { long count = fold_constant_to_int(right); if (count < 0) { warningf(&right->base.source_position, @@ -8416,9 +8473,11 @@ static void warn_comparison_in_comparison(const expression_t *const expr) static bool maybe_negative(expression_t const *const expr) { - return - !is_constant_expression(expr) || - fold_constant_to_int(expr) < 0; + switch (is_constant_expression(expr)) { + case EXPR_CLASS_ERROR: return false; + case EXPR_CLASS_CONSTANT: return fold_constant_to_int(expr) < 0; + default: return true; + } } /** @@ -8886,7 +8945,7 @@ static expression_t *parse_##binexpression_type(expression_t *left) \ binexpr->binary.left = left; \ eat(token_type); \ \ - expression_t *right = parse_sub_expression(prec_r); \ + expression_t *right = parse_subexpression(prec_r); \ \ binexpr->binary.right = right; \ sfunc(&binexpr->binary); \ @@ -8926,7 +8985,7 @@ CREATE_BINEXPR_PARSER(T_CARETEQUAL, EXPR_BINARY_BITWISE_XOR_ASSIGN, PR CREATE_BINEXPR_PARSER(',', EXPR_BINARY_COMMA, PREC_ASSIGNMENT, semantic_comma) -static expression_t *parse_sub_expression(precedence_t precedence) +static expression_t *parse_subexpression(precedence_t precedence) { if (token.type < 0) { return expected_expression_error(); @@ -8971,7 +9030,7 @@ static expression_t *parse_sub_expression(precedence_t precedence) */ static expression_t *parse_expression(void) { - return parse_sub_expression(PREC_EXPRESSION); + return parse_subexpression(PREC_EXPRESSION); } /** @@ -9213,9 +9272,13 @@ static statement_t *parse_asm_statement(void) expect('(', end_error); add_anchor_token(')'); - add_anchor_token(':'); + if (token.type != T_STRING_LITERAL) { + parse_error_expected("after asm(", T_STRING_LITERAL, NULL); + goto end_of_asm; + } asm_statement->asm_text = parse_string_literals(); + add_anchor_token(':'); if (!next_if(':')) { rem_anchor_token(':'); goto end_of_asm; @@ -9252,6 +9315,37 @@ end_error: return create_invalid_statement(); } +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(&label->base.source_position, "%s at end of compound statement", label_kind); + inner_stmt = create_invalid_statement(); + break; + + case ';': + 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. */ + inner_stmt = create_empty_statement(); + next_token(); + break; + } + /* FALLTHROUGH */ + + default: + inner_stmt = parse_statement(); + /* 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; + } + return inner_stmt; +} + /** * Parse a case statement. */ @@ -9264,11 +9358,9 @@ static statement_t *parse_case_statement(void) expression_t *const expression = parse_expression(); statement->case_label.expression = expression; - if (!is_constant_expression(expression)) { - /* This check does not prevent the error message in all cases of an - * prior error while parsing the expression. At least it catches the - * common case of a mistyped enum entry. */ - if (is_type_valid(skip_typeref(expression->base.type))) { + expression_classification_t const expr_class = is_constant_expression(expression); + if (expr_class != EXPR_CLASS_CONSTANT) { + if (expr_class != EXPR_CLASS_ERROR) { errorf(pos, "case label does not reduce to an integer constant"); } statement->case_label.is_bad = true; @@ -9282,11 +9374,9 @@ static statement_t *parse_case_statement(void) if (next_if(T_DOTDOTDOT)) { expression_t *const end_range = parse_expression(); statement->case_label.end_range = end_range; - if (!is_constant_expression(end_range)) { - /* This check does not prevent the error message in all cases of an - * prior error while parsing the expression. At least it catches the - * common case of a mistyped enum entry. */ - if (is_type_valid(skip_typeref(end_range->base.type))) { + expression_classification_t const end_class = is_constant_expression(end_range); + if (end_class != EXPR_CLASS_CONSTANT) { + if (end_class != EXPR_CLASS_ERROR) { errorf(pos, "case range does not reduce to an integer constant"); } statement->case_label.is_bad = true; @@ -9334,11 +9424,7 @@ end_error: errorf(pos, "case label not within a switch statement"); } - statement_t *const inner_stmt = parse_statement(); - statement->case_label.statement = inner_stmt; - if (inner_stmt->kind == STATEMENT_DECLARATION) { - errorf(&inner_stmt->base.source_position, "declaration after case label"); - } + statement->case_label.statement = parse_label_inner_statement(statement, "case label"); POP_PARENT; return statement; @@ -9356,6 +9442,8 @@ static statement_t *parse_default_statement(void) PUSH_PARENT(statement); expect(':', end_error); +end_error: + if (current_switch != NULL) { const case_label_statement_t *def_label = current_switch->default_label; if (def_label != NULL) { @@ -9377,17 +9465,10 @@ static statement_t *parse_default_statement(void) "'default' label not within a switch statement"); } - statement_t *const inner_stmt = parse_statement(); - statement->case_label.statement = inner_stmt; - if (inner_stmt->kind == STATEMENT_DECLARATION) { - errorf(&inner_stmt->base.source_position, "declaration after default label"); - } + statement->case_label.statement = parse_label_inner_statement(statement, "default label"); POP_PARENT; return statement; -end_error: - POP_PARENT; - return create_invalid_statement(); } /** @@ -9419,28 +9500,7 @@ static statement_t *parse_label_statement(void) eat(':'); - if (token.type == '}') { - /* TODO only warn? */ - if (warning.other && false) { - warningf(HERE, "label at end of compound statement"); - statement->label.statement = create_empty_statement(); - } else { - errorf(HERE, "label at end of compound statement"); - statement->label.statement = create_invalid_statement(); - } - } else if (token.type == ';') { - /* 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. */ - statement->label.statement = create_empty_statement(); - next_token(); - } else { - statement_t *const inner_stmt = parse_statement(); - statement->label.statement = inner_stmt; - if (inner_stmt->kind == STATEMENT_DECLARATION) { - errorf(&inner_stmt->base.source_position, "declaration after label"); - } - } + statement->label.statement = parse_label_inner_statement(statement, "label"); /* remember the labels in a list for later checking */ *label_anchor = &statement->label; @@ -9787,7 +9847,7 @@ static statement_t *parse_goto(void) else parse_error_expected("while parsing goto", T_IDENTIFIER, NULL); eat_until_anchor(); - goto end_error; + return create_invalid_statement(); } /* remember the goto's in a list for later checking */ @@ -9796,9 +9856,8 @@ static statement_t *parse_goto(void) expect(';', end_error); - return statement; end_error: - return create_invalid_statement(); + return statement; } /** @@ -10084,8 +10143,9 @@ static statement_t *parse_local_label_declaration(void) eat(T___label__); - entity_t *begin = NULL, *end = NULL; - + entity_t *begin = NULL; + entity_t *end = NULL; + entity_t **anchor = &begin; do { if (token.type != T_IDENTIFIER) { parse_error_expected("while parsing local label declaration", @@ -10105,17 +10165,15 @@ static statement_t *parse_local_label_declaration(void) entity->base.source_position = token.source_position; entity->base.symbol = symbol; - if (end != NULL) - end->base.next = entity; - end = entity; - if (begin == NULL) - begin = entity; + *anchor = entity; + anchor = &entity->base.next; + end = entity; environment_push(entity); } next_token(); } while (next_if(',')); - eat(';'); + expect(';', end_error); end_error: statement->declaration.declarations_begin = begin; statement->declaration.declarations_end = end; @@ -10137,7 +10195,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); } @@ -10205,18 +10263,14 @@ static statement_t *intern_parse_statement(void) switch (la1_type) { case '&': case '*': - if (get_entity(token.symbol, NAMESPACE_NORMAL) != NULL) - goto expression_statment; - /* FALLTHROUGH */ - + if (get_entity(token.symbol, NAMESPACE_NORMAL) != NULL) { + default: + statement = parse_expression_statement(); + } else { DECLARATION_START case T_IDENTIFIER: - statement = parse_declaration_statement(); - break; - - default: -expression_statment: - statement = parse_expression_statement(); + statement = parse_declaration_statement(); + } break; } } @@ -10607,7 +10661,6 @@ end_error:; static void parse_linkage_specification(void) { eat(T_extern); - assert(token.type == T_STRING_LITERAL); const char *linkage = parse_string_literals().begin; @@ -10689,6 +10742,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 @@ -10696,14 +10750,16 @@ 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) { + /* the anchor set and its copy differs */ errorf(HERE, "Leaked anchor token %k %d times", i, count); anchor_leak = true; } } if (in_gcc_extension) { + /* an gcc extension scope was not closed */ errorf(HERE, "Leaked __extension__"); anchor_leak = true; }