X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=a859dc4601b3ddc2bed45dec81fef3e51be2097e;hb=152becd590dc065f730deea680aa32b7d1032286;hp=ba33164dbd9eb3e1840dc54e06485f6a79ac9203;hpb=6496958325046d8e57b6636cb34fe5c6172dbdf1;p=cparser diff --git a/parser.c b/parser.c index ba33164..a859dc4 100644 --- a/parser.c +++ b/parser.c @@ -34,6 +34,7 @@ #include "type_hash.h" #include "ast_t.h" #include "lang_features.h" +#include "walk_statements.h" #include "warning.h" #include "adt/bitfiddle.h" #include "adt/error.h" @@ -144,8 +145,6 @@ static struct obstack temp_obst; ((void)(current_parent = (stmt))) #define POP_PARENT ((void)(current_parent = prev_parent)) -static source_position_t null_position = { NULL, 0 }; - /** special symbol used for anonymous entities. */ static const symbol_t *sym_anonymous = NULL; @@ -183,7 +182,7 @@ static type_t *type_valist; static statement_t *parse_compound_statement(bool inside_expression_statement); static statement_t *parse_statement(void); -static expression_t *parse_sub_expression(unsigned precedence); +static expression_t *parse_sub_expression(precedence_t); static expression_t *parse_expression(void); static type_t *parse_typename(void); @@ -435,16 +434,14 @@ static size_t get_type_struct_size(type_kind_t kind) * fields with zero. * * @param kind type kind to allocate - * @param source_position the source position of the type definition */ -static type_t *allocate_type_zero(type_kind_t kind, const source_position_t *source_position) +static type_t *allocate_type_zero(type_kind_t kind) { size_t size = get_type_struct_size(kind); type_t *res = obstack_alloc(type_obst, size); memset(res, 0, size); + res->base.kind = kind; - res->base.kind = kind; - res->base.source_position = *source_position; return res; } @@ -1005,36 +1002,42 @@ static void report_assign_error(assign_error_t error, type_t *orig_type_left, return; case ASSIGN_ERROR_POINTER_QUALIFIER_MISSING: { - type_t *points_to_left - = skip_typeref(type_left->pointer.points_to); - type_t *points_to_right - = skip_typeref(type_right->pointer.points_to); - - /* the left type has all qualifiers from the right type */ - unsigned missing_qualifiers - = points_to_right->base.qualifiers & ~points_to_left->base.qualifiers; - warningf(source_position, - "destination type '%T' in %s from type '%T' lacks qualifiers '%Q' in pointer target type", - orig_type_left, context, orig_type_right, missing_qualifiers); + if (warning.other) { + type_t *points_to_left = skip_typeref(type_left->pointer.points_to); + type_t *points_to_right = skip_typeref(type_right->pointer.points_to); + + /* the left type has all qualifiers from the right type */ + unsigned missing_qualifiers + = points_to_right->base.qualifiers & ~points_to_left->base.qualifiers; + warningf(source_position, + "destination type '%T' in %s from type '%T' lacks qualifiers '%Q' in pointer target type", + orig_type_left, context, orig_type_right, missing_qualifiers); + } return; } case ASSIGN_WARNING_POINTER_INCOMPATIBLE: - warningf(source_position, - "destination type '%T' in %s is incompatible with '%E' of type '%T'", - orig_type_left, context, right, orig_type_right); + if (warning.other) { + warningf(source_position, + "destination type '%T' in %s is incompatible with '%E' of type '%T'", + orig_type_left, context, right, orig_type_right); + } return; case ASSIGN_WARNING_POINTER_FROM_INT: - warningf(source_position, - "%s makes pointer '%T' from integer '%T' without a cast", - context, orig_type_left, orig_type_right); + if (warning.other) { + warningf(source_position, + "%s makes pointer '%T' from integer '%T' without a cast", + context, orig_type_left, orig_type_right); + } return; case ASSIGN_WARNING_INT_FROM_POINTER: - warningf(source_position, - "%s makes integer '%T' from pointer '%T' without a cast", - context, orig_type_left, orig_type_right); + if (warning.other) { + warningf(source_position, + "%s makes integer '%T' from pointer '%T' without a cast", + context, orig_type_left, orig_type_right); + } return; default: @@ -1106,8 +1109,7 @@ static assign_error_t semantic_assign(type_t *orig_type_left, static expression_t *parse_constant_expression(void) { - /* start parsing at precedence 7 (conditional expression) */ - expression_t *result = parse_sub_expression(7); + expression_t *result = parse_sub_expression(PREC_CONDITIONAL); if (!is_constant_expression(result)) { errorf(&result->base.source_position, @@ -1119,8 +1121,7 @@ static expression_t *parse_constant_expression(void) static expression_t *parse_assignment_expression(void) { - /* start parsing at precedence 2 (assignment expression) */ - return parse_sub_expression(2); + return parse_sub_expression(PREC_ASSIGNMENT); } static type_t *make_global_typedef(const char *name, type_t *type) @@ -1138,7 +1139,7 @@ static type_t *make_global_typedef(const char *name, type_t *type) record_declaration(declaration, false); - type_t *typedef_type = allocate_type_zero(TYPE_TYPEDEF, &builtin_source_position); + type_t *typedef_type = allocate_type_zero(TYPE_TYPEDEF); typedef_type->typedeft.declaration = declaration; return typedef_type; @@ -1423,7 +1424,8 @@ static void parse_gnu_attribute_mode_arg(gnu_attribute_t *attribute) } else if (strcmp_underscore("DI", symbol_str) == 0) { attribute->u.akind = ATOMIC_TYPE_LONGLONG; } else { - warningf(HERE, "ignoring unknown mode '%s'", symbol_str); + if (warning.other) + warningf(HERE, "ignoring unknown mode '%s'", symbol_str); attribute->invalid = true; } next_token(); @@ -1861,7 +1863,8 @@ static decl_modifiers_t parse_attributes(gnu_attribute_t **attributes) case T___thiscall: /* TODO record modifier */ - warningf(HERE, "Ignoring declaration modifier %K", &token); + if (warning.other) + warningf(HERE, "Ignoring declaration modifier %K", &token); break; end_error: @@ -1885,9 +1888,11 @@ static declaration_t *determine_lhs_decl(expression_t *const expr, declaration_t case EXPR_ARRAY_ACCESS: { expression_t *const ref = expr->array_access.array_ref; declaration_t * decl = NULL; - if (is_type_array(skip_typeref(ref->base.type))) { + if (is_type_array(skip_typeref(revert_automatic_type_conversion(ref)))) { decl = determine_lhs_decl(ref, lhs_decl); lhs_decl = decl; + } else { + mark_decls_read(expr->select.compound, lhs_decl); } mark_decls_read(expr->array_access.index, lhs_decl); return decl; @@ -1960,6 +1965,8 @@ static void mark_decls_read(expression_t *const expr, declaration_t *lhs_decl) return; case EXPR_SELECT: + if (lhs_decl == DECL_ANY && !is_type_compound(skip_typeref(expr->base.type))) + lhs_decl = NULL; mark_decls_read(expr->select.compound, lhs_decl); return; @@ -1979,13 +1986,17 @@ static void mark_decls_read(expression_t *const expr, declaration_t *lhs_decl) /* Special case: Use void cast to mark a variable as "read" */ if (is_type_atomic(skip_typeref(expr->base.type), ATOMIC_TYPE_VOID)) lhs_decl = NULL; - /* FALLTHROUGH */ + goto unary; + + case EXPR_UNARY_DEREFERENCE: + if (lhs_decl == DECL_ANY) + lhs_decl = NULL; + goto unary; case EXPR_UNARY_NEGATE: case EXPR_UNARY_PLUS: case EXPR_UNARY_BITWISE_NEGATE: case EXPR_UNARY_NOT: - case EXPR_UNARY_DEREFERENCE: case EXPR_UNARY_TAKE_ADDRESS: case EXPR_UNARY_POSTFIX_INCREMENT: case EXPR_UNARY_POSTFIX_DECREMENT: @@ -1993,6 +2004,7 @@ static void mark_decls_read(expression_t *const expr, declaration_t *lhs_decl) case EXPR_UNARY_PREFIX_DECREMENT: case EXPR_UNARY_CAST_IMPLICIT: case EXPR_UNARY_ASSUME: +unary: mark_decls_read(expr->unary.value, lhs_decl); return; @@ -2221,7 +2233,8 @@ static initializer_t *parse_scalar_initializer(type_t *type, /* there might be extra {} hierarchies */ int braces = 0; if (token.type == '{') { - warningf(HERE, "extra curly braces around scalar initializer"); + if (warning.other) + warningf(HERE, "extra curly braces around scalar initializer"); do { ++braces; next_token(); @@ -2252,7 +2265,7 @@ static initializer_t *parse_scalar_initializer(type_t *type, next_token(); } if (token.type != '}') { - if (!additional_warning_displayed) { + if (!additional_warning_displayed && warning.other) { warningf(HERE, "additional elements in scalar initializer"); additional_warning_displayed = true; } @@ -2684,7 +2697,7 @@ finish_designator: if (token.type == ',') { next_token(); } - if (token.type != '}') { + if (token.type != '}' && warning.other) { warningf(HERE, "excessive elements in initializer for type '%T'", orig_type); } @@ -2731,11 +2744,14 @@ finish_designator: ARR_APP1(initializer_t*, initializers, sub); } else { error_excess: - if (env->declaration != NULL) - warningf(HERE, "excess elements in struct initializer for '%Y'", - env->declaration->symbol); - else - warningf(HERE, "excess elements in struct initializer"); + if (warning.other) { + if (env->declaration != NULL) { + warningf(HERE, "excess elements in struct initializer for '%Y'", + env->declaration->symbol); + } else { + warningf(HERE, "excess elements in struct initializer"); + } + } } error_parse_next: @@ -3013,7 +3029,7 @@ static type_t *parse_enum_specifier(void) declaration->parent_scope = scope; } - type_t *const type = allocate_type_zero(TYPE_ENUM, &declaration->source_position); + type_t *const type = allocate_type_zero(TYPE_ENUM); type->enumt.declaration = declaration; if (token.type == '{') { @@ -3090,7 +3106,7 @@ static type_t *parse_typeof(void) rem_anchor_token(')'); expect(')'); - type_t *typeof_type = allocate_type_zero(TYPE_TYPEOF, &expression->base.source_position); + type_t *typeof_type = allocate_type_zero(TYPE_TYPEOF); typeof_type->typeoft.expression = expression; typeof_type->typeoft.typeof_type = type; @@ -3123,7 +3139,7 @@ typedef enum 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, &builtin_source_position); + type_t *type = allocate_type_zero(TYPE_BUILTIN); type->builtin.symbol = symbol; type->builtin.real_type = real_type; @@ -3142,7 +3158,7 @@ static type_t *get_typedef_type(symbol_t *symbol) declaration->storage_class != STORAGE_CLASS_TYPEDEF) return NULL; - type_t *type = allocate_type_zero(TYPE_TYPEDEF, &declaration->source_position); + type_t *type = allocate_type_zero(TYPE_TYPEDEF); type->typedeft.declaration = declaration; return type; @@ -3167,7 +3183,7 @@ static bool check_alignment_value(long long intvalue) } #define DET_MOD(name, tag) do { \ - if (*modifiers & tag) warningf(HERE, #name " used more than once"); \ + if (*modifiers & tag && warning.other) warningf(HERE, #name " used more than once"); \ *modifiers |= tag; \ } while (0) @@ -3189,7 +3205,7 @@ static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *spe if (token.type != T_INTEGER) goto end_error; if (check_alignment_value(token.v.intvalue)) { - if (specifiers->alignment != 0) + if (specifiers->alignment != 0 && warning.other) warningf(HERE, "align used more than once"); specifiers->alignment = (unsigned char)token.v.intvalue; } @@ -3277,7 +3293,7 @@ static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *spe expect(')'); } else if (symbol == sym_deprecated) { next_token(); - if (specifiers->deprecated != 0) + if (specifiers->deprecated != 0 && warning.other) warningf(HERE, "deprecated used more than once"); specifiers->deprecated = 1; if (token.type == '(') { @@ -3294,7 +3310,8 @@ static void parse_microsoft_extended_decl_modifier(declaration_specifiers_t *spe next_token(); DET_MOD(noalias, DM_NOALIAS); } else { - warningf(HERE, "Unknown modifier %Y ignored", token.v.symbol); + if (warning.other) + warningf(HERE, "Unknown modifier %Y ignored", token.v.symbol); next_token(); if (token.type == '(') skip_until(')'); @@ -3554,14 +3571,14 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) break; case T_struct: { - type = allocate_type_zero(TYPE_COMPOUND_STRUCT, HERE); + type = allocate_type_zero(TYPE_COMPOUND_STRUCT); type->compound.declaration = parse_compound_type_specifier(true); finish_struct_type(&type->compound); break; } case T_union: { - type = allocate_type_zero(TYPE_COMPOUND_UNION, HERE); + type = allocate_type_zero(TYPE_COMPOUND_UNION); type->compound.declaration = parse_compound_type_specifier(false); if (type->compound.declaration->modifiers & DM_TRANSPARENT_UNION) modifiers |= TYPE_MODIFIER_TRANSPARENT_UNION; @@ -3619,7 +3636,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers) declaration_t *const decl = create_error_declaration(token.v.symbol, STORAGE_CLASS_TYPEDEF); - type = allocate_type_zero(TYPE_TYPEDEF, HERE); + type = allocate_type_zero(TYPE_TYPEDEF); type->typedeft.declaration = decl; next_token(); @@ -3810,13 +3827,13 @@ warn_about_long_long: } if (type_specifiers & SPECIFIER_COMPLEX) { - type = allocate_type_zero(TYPE_COMPLEX, &builtin_source_position); + type = allocate_type_zero(TYPE_COMPLEX); type->complex.akind = atomic_type; } else if (type_specifiers & SPECIFIER_IMAGINARY) { - type = allocate_type_zero(TYPE_IMAGINARY, &builtin_source_position); + type = allocate_type_zero(TYPE_IMAGINARY); type->imaginary.akind = atomic_type; } else { - type = allocate_type_zero(TYPE_ATOMIC, &builtin_source_position); + type = allocate_type_zero(TYPE_ATOMIC); type->atomic.akind = atomic_type; } newtype = true; @@ -4135,7 +4152,7 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration) { type_t *type; if (declaration != NULL) { - type = allocate_type_zero(TYPE_FUNCTION, &declaration->source_position); + type = allocate_type_zero(TYPE_FUNCTION); unsigned mask = declaration->modifiers & (DM_CDECL|DM_STDCALL|DM_FASTCALL|DM_THISCALL); @@ -4171,7 +4188,7 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration) else if (declaration->modifiers & DM_THISCALL) type->function.calling_convention = CC_THISCALL; } else { - type = allocate_type_zero(TYPE_FUNCTION, HERE); + type = allocate_type_zero(TYPE_FUNCTION); } declaration_t *last; @@ -4179,7 +4196,6 @@ static construct_type_t *parse_function_declarator(declaration_t *declaration) if (declaration != NULL) { declaration->scope.declarations = parameters; declaration->scope.last_declaration = last; - declaration->scope.is_parameter = true; } construct_function_type_t *construct_function_type = @@ -4375,7 +4391,7 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, } else if (is_type_array(skipped_return_type)) { errorf(HERE, "function returning array is not allowed"); } else { - if (skipped_return_type->base.qualifiers != 0) { + if (skipped_return_type->base.qualifiers != 0 && warning.other) { warningf(HERE, "type qualifiers in return type of function type are meaningless"); } @@ -4387,17 +4403,13 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, case CONSTRUCT_POINTER: { parsed_pointer_t *parsed_pointer = (parsed_pointer_t*) iter; - type_t *pointer_type = allocate_type_zero(TYPE_POINTER, &null_position); - pointer_type->pointer.points_to = type; - pointer_type->base.qualifiers = parsed_pointer->type_qualifiers; - - type = pointer_type; - break; + type = make_pointer_type(type, parsed_pointer->type_qualifiers); + continue; } case CONSTRUCT_ARRAY: { parsed_array_t *parsed_array = (parsed_array_t*) iter; - type_t *array_type = allocate_type_zero(TYPE_ARRAY, &null_position); + type_t *array_type = allocate_type_zero(TYPE_ARRAY); expression_t *size_expression = parsed_array->size; if (size_expression != NULL) { @@ -4604,7 +4616,7 @@ static declaration_t *record_declaration( assert(declaration != previous_declaration); if (previous_declaration != NULL && - previous_declaration->parent_scope->is_parameter && + previous_declaration->parent_scope == ¤t_function->scope && scope->depth == previous_declaration->parent_scope->depth + 1) { errorf(&declaration->source_position, "declaration '%#T' redeclares the parameter '%#T' (declared %P)", @@ -4828,28 +4840,30 @@ static void parse_anonymous_declaration_rest( { eat(';'); - if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) { - warningf(&specifiers->source_position, - "useless storage class in empty declaration"); - } + if (warning.other) { + if (specifiers->declared_storage_class != STORAGE_CLASS_NONE) { + warningf(&specifiers->source_position, + "useless storage class in empty declaration"); + } - type_t *type = specifiers->type; - switch (type->kind) { - case TYPE_COMPOUND_STRUCT: - case TYPE_COMPOUND_UNION: { - if (type->compound.declaration->symbol == NULL) { - warningf(&specifiers->source_position, - "unnamed struct/union that defines no instances"); + type_t *type = specifiers->type; + switch (type->kind) { + case TYPE_COMPOUND_STRUCT: + case TYPE_COMPOUND_UNION: { + if (type->compound.declaration->symbol == NULL) { + warningf(&specifiers->source_position, + "unnamed struct/union that defines no instances"); + } + break; } - break; - } - case TYPE_ENUM: - break; + case TYPE_ENUM: + break; - default: - warningf(&specifiers->source_position, "empty declaration"); - break; + default: + warningf(&specifiers->source_position, "empty declaration"); + break; + } } #ifdef RECORD_EMPTY_DECLARATIONS @@ -4877,8 +4891,9 @@ static void parse_declaration_rest(declaration_t *ndeclaration, type_t *orig_type = declaration->type; type_t *type = skip_typeref(orig_type); - if (type->kind != TYPE_FUNCTION && - declaration->is_inline && + if (warning.other && + type->kind != TYPE_FUNCTION && + declaration->is_inline && is_type_valid(type)) { warningf(&declaration->source_position, "variable '%Y' declared 'inline'\n", declaration->symbol); @@ -5136,77 +5151,24 @@ static void warn_unused_decl(declaration_t *decl, declaration_t *end, char const } } -static void check_unused_variables(statement_t const *const stmt) +static void check_unused_variables(statement_t *const stmt, void *const env) { - // TODO statement expressions - switch (stmt->kind) { - case STATEMENT_COMPOUND: - for (statement_t const *s = stmt->compound.statements; s != NULL; s = s->base.next) { - check_unused_variables(s); - } - return; - - case STATEMENT_FOR: { - warn_unused_decl(stmt->fors.scope.declarations, NULL, "variable"); - check_unused_variables(stmt->fors.body); - return; - } - - case STATEMENT_IF: - check_unused_variables(stmt->ifs.true_statement); - if (stmt->ifs.false_statement != NULL) - check_unused_variables(stmt->ifs.false_statement); - return; - - case STATEMENT_SWITCH: - check_unused_variables(stmt->switchs.body); - return; - - case STATEMENT_LABEL: - check_unused_variables(stmt->label.statement); - return; - - case STATEMENT_CASE_LABEL: - check_unused_variables(stmt->case_label.statement); - return; - - case STATEMENT_WHILE: - check_unused_variables(stmt->whiles.body); - return; - - case STATEMENT_DO_WHILE: - check_unused_variables(stmt->do_while.body); - return; + (void)env; + switch (stmt->kind) { case STATEMENT_DECLARATION: { declaration_statement_t const *const decls = &stmt->declaration; warn_unused_decl(decls->declarations_begin, decls->declarations_end, "variable"); return; } - case STATEMENT_EXPRESSION: - // TODO statement expressions - return; - - case STATEMENT_INVALID: - case STATEMENT_EMPTY: - case STATEMENT_RETURN: - case STATEMENT_CONTINUE: - case STATEMENT_BREAK: - case STATEMENT_GOTO: - case STATEMENT_ASM: - case STATEMENT_LEAVE: + case STATEMENT_FOR: + warn_unused_decl(stmt->fors.scope.declarations, NULL, "variable"); return; - case STATEMENT_MS_TRY: { - ms_try_statement_t const *const ms_try = &stmt->ms_try; - check_unused_variables(ms_try->try_statement); - check_unused_variables(ms_try->final_statement); + default: return; - } } - - panic("unhandled statement"); } /** @@ -5223,7 +5185,7 @@ static void check_declarations(void) } } if (warning.unused_variable) { - check_unused_variables(current_function->init.statement); + walk_statements(current_function->init.statement, check_unused_variables, NULL); } } @@ -5586,58 +5548,12 @@ continue_for:; check_reachable(next); } -static void check_unreachable(statement_t const* const stmt) +static void check_unreachable(statement_t* const stmt, void *const env) { - if (!stmt->base.reachable && - stmt->kind != STATEMENT_DO_WHILE && - stmt->kind != STATEMENT_FOR && - (stmt->kind != STATEMENT_COMPOUND || stmt->compound.statements == NULL)) { - warningf(&stmt->base.source_position, "statement is unreachable"); - } + (void)env; switch (stmt->kind) { - case STATEMENT_INVALID: - case STATEMENT_EMPTY: - case STATEMENT_RETURN: - case STATEMENT_DECLARATION: - case STATEMENT_EXPRESSION: - case STATEMENT_CONTINUE: - case STATEMENT_BREAK: - case STATEMENT_GOTO: - case STATEMENT_ASM: - case STATEMENT_LEAVE: - return; - - case STATEMENT_COMPOUND: - for (statement_t const *s = stmt->compound.statements; s != NULL; s = s->base.next) { - check_unreachable(s); - } - return; - - case STATEMENT_IF: - check_unreachable(stmt->ifs.true_statement); - if (stmt->ifs.false_statement != NULL) - check_unreachable(stmt->ifs.false_statement); - return; - - case STATEMENT_SWITCH: - check_unreachable(stmt->switchs.body); - return; - - case STATEMENT_LABEL: - check_unreachable(stmt->label.statement); - return; - - case STATEMENT_CASE_LABEL: - check_unreachable(stmt->case_label.statement); - return; - - case STATEMENT_WHILE: - check_unreachable(stmt->whiles.body); - return; - case STATEMENT_DO_WHILE: - check_unreachable(stmt->do_while.body); if (!stmt->base.reachable) { expression_t const *const cond = stmt->do_while.condition; if (determine_truth(cond) >= 0) { @@ -5669,20 +5585,19 @@ static void check_unreachable(statement_t const* const stmt) "step of for-statement is unreachable"); } } - - check_unreachable(fors->body); return; } - case STATEMENT_MS_TRY: { - ms_try_statement_t const *const ms_try = &stmt->ms_try; - check_unreachable(ms_try->try_statement); - check_unreachable(ms_try->final_statement); + case STATEMENT_COMPOUND: + if (stmt->compound.statements != NULL) + return; + /* FALLTHROUGH*/ + + default: + if (!stmt->base.reachable) + warningf(&stmt->base.source_position, "statement is unreachable"); return; - } } - - panic("unhandled statement"); } static void parse_external_declaration(void) @@ -5821,7 +5736,7 @@ static void parse_external_declaration(void) noreturn_candidate = true; check_reachable(body); if (warning.unreachable_code) - check_unreachable(body); + walk_statements(body, check_unreachable, NULL); if (warning.missing_noreturn && noreturn_candidate && !(declaration->modifiers & DM_NORETURN)) { @@ -5846,7 +5761,7 @@ static type_t *make_bitfield_type(type_t *base_type, expression_t *size, source_position_t *source_position, const symbol_t *symbol) { - type_t *type = allocate_type_zero(TYPE_BITFIELD, source_position); + type_t *type = allocate_type_zero(TYPE_BITFIELD); type->bitfield.base_type = base_type; type->bitfield.size_expression = size; @@ -6038,13 +5953,11 @@ static type_t *parse_typename(void) -typedef expression_t* (*parse_expression_function) (unsigned precedence); -typedef expression_t* (*parse_expression_infix_function) (unsigned precedence, - expression_t *left); +typedef expression_t* (*parse_expression_function)(void); +typedef expression_t* (*parse_expression_infix_function)(expression_t *left); typedef struct expression_parser_function_t expression_parser_function_t; struct expression_parser_function_t { - unsigned precedence; parse_expression_function parser; unsigned infix_precedence; parse_expression_infix_function infix_parser; @@ -6194,7 +6107,7 @@ static expression_t *parse_float_const(void) static declaration_t *create_implicit_function(symbol_t *symbol, const source_position_t *source_position) { - type_t *ntype = allocate_type_zero(TYPE_FUNCTION, source_position); + type_t *ntype = allocate_type_zero(TYPE_FUNCTION); ntype->function.return_type = type_int; ntype->function.unspecified_parameters = true; @@ -6237,7 +6150,7 @@ static type_t *make_function_2_type(type_t *return_type, type_t *argument_type1, parameter1->type = argument_type1; parameter1->next = parameter2; - type_t *type = allocate_type_zero(TYPE_FUNCTION, &builtin_source_position); + type_t *type = allocate_type_zero(TYPE_FUNCTION); type->function.return_type = return_type; type->function.parameters = parameter1; @@ -6263,7 +6176,7 @@ static type_t *make_function_1_type(type_t *return_type, type_t *argument_type) memset(parameter, 0, sizeof(parameter[0])); parameter->type = argument_type; - type_t *type = allocate_type_zero(TYPE_FUNCTION, &builtin_source_position); + type_t *type = allocate_type_zero(TYPE_FUNCTION); type->function.return_type = return_type; type->function.parameters = parameter; @@ -6277,7 +6190,7 @@ static type_t *make_function_1_type(type_t *return_type, type_t *argument_type) static type_t *make_function_0_type(type_t *return_type) { - type_t *type = allocate_type_zero(TYPE_FUNCTION, &builtin_source_position); + type_t *type = allocate_type_zero(TYPE_FUNCTION); type->function.return_type = return_type; type->function.parameters = NULL; @@ -6437,7 +6350,6 @@ static expression_t *parse_reference(void) is_type_valid(orig_type) && !is_type_function(orig_type)) { /* access of a variable from an outer function */ declaration->address_taken = true; - ref->is_outer_ref = true; current_function->need_closure = true; } @@ -6553,7 +6465,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(20); + expression_t *value = parse_sub_expression(PREC_CAST); cast->base.type = type; cast->unary.value = value; @@ -6589,7 +6501,7 @@ static expression_t *parse_statement_expression(void) if (stmt->kind == STATEMENT_EXPRESSION) { type = stmt->expression.expression->base.type; } - } else { + } else if (warning.other) { warningf(&expression->base.source_position, "empty statement expression ({})"); } expression->base.type = type; @@ -7184,11 +7096,8 @@ static void check_for_char_index_type(const expression_t *expression) } } -static expression_t *parse_array_expression(unsigned precedence, - expression_t *left) +static expression_t *parse_array_expression(expression_t *left) { - (void) precedence; - eat('['); add_anchor_token(']'); @@ -7239,8 +7148,7 @@ static expression_t *parse_array_expression(unsigned precedence, } static expression_t *parse_typeprop(expression_kind_t const kind, - source_position_t const pos, - unsigned const precedence) + source_position_t const pos) { expression_t *tp_expression = allocate_expression_zero(kind); tp_expression->base.type = type_size_t; @@ -7271,7 +7179,7 @@ static expression_t *parse_typeprop(expression_kind_t const kind, rem_anchor_token(')'); expect(')'); } else { - expression_t *expression = parse_sub_expression(precedence); + expression_t *expression = parse_sub_expression(PREC_UNARY); type_t* const orig_type = revert_automatic_type_conversion(expression); expression->base.type = orig_type; @@ -7295,24 +7203,22 @@ end_error: return tp_expression; } -static expression_t *parse_sizeof(unsigned precedence) +static expression_t *parse_sizeof(void) { source_position_t pos = *HERE; eat(T_sizeof); - return parse_typeprop(EXPR_SIZEOF, pos, precedence); + return parse_typeprop(EXPR_SIZEOF, pos); } -static expression_t *parse_alignof(unsigned precedence) +static expression_t *parse_alignof(void) { source_position_t pos = *HERE; eat(T___alignof__); - return parse_typeprop(EXPR_ALIGNOF, pos, precedence); + return parse_typeprop(EXPR_ALIGNOF, pos); } -static expression_t *parse_select_expression(unsigned precedence, - expression_t *compound) +static expression_t *parse_select_expression(expression_t *compound) { - (void) precedence; assert(token.type == '.' || token.type == T_MINUSGREATER); bool is_pointer = (token.type == T_MINUSGREATER); @@ -7457,10 +7363,8 @@ static void check_call_argument(const function_parameter_t *parameter, * * @param expression the function address */ -static expression_t *parse_call_expression(unsigned precedence, - expression_t *expression) +static expression_t *parse_call_expression(expression_t *expression) { - (void) precedence; expression_t *result = allocate_expression_zero(EXPR_CALL); result->base.source_position = expression->base.source_position; @@ -7567,8 +7471,7 @@ static bool same_compound_type(const type_t *type1, const type_t *type2) * * @param expression the conditional expression */ -static expression_t *parse_conditional_expression(unsigned precedence, - expression_t *expression) +static expression_t *parse_conditional_expression(expression_t *expression) { expression_t *result = allocate_expression_zero(EXPR_CONDITIONAL); @@ -7595,7 +7498,7 @@ static expression_t *parse_conditional_expression(unsigned precedence, true_expression = parse_expression(); rem_anchor_token(':'); expect(':'); - expression_t *false_expression = parse_sub_expression(precedence); + expression_t *false_expression = parse_sub_expression(PREC_CONDITIONAL); type_t *const orig_true_type = true_expression->base.type; type_t *const orig_false_type = false_expression->base.type; @@ -7604,10 +7507,12 @@ static expression_t *parse_conditional_expression(unsigned precedence, /* 6.5.15.3 */ type_t *result_type; - if (is_type_atomic(true_type, ATOMIC_TYPE_VOID) || - is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { - if (!is_type_atomic(true_type, ATOMIC_TYPE_VOID) - || !is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { + if (is_type_atomic(true_type, ATOMIC_TYPE_VOID) || + is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { + if (warning.other && ( + !is_type_atomic(true_type, ATOMIC_TYPE_VOID) || + !is_type_atomic(false_type, ATOMIC_TYPE_VOID) + )) { warningf(&conditional->base.source_position, "ISO C forbids conditional expression with only one void side"); } @@ -7654,9 +7559,11 @@ static expression_t *parse_conditional_expression(unsigned precedence, get_unqualified_type(to2))) { to = to1; } else { - warningf(&conditional->base.source_position, - "pointer types '%T' and '%T' in conditional expression are incompatible", - true_type, false_type); + if (warning.other) { + warningf(&conditional->base.source_position, + "pointer types '%T' and '%T' in conditional expression are incompatible", + true_type, false_type); + } to = type_void; } @@ -7664,8 +7571,10 @@ static expression_t *parse_conditional_expression(unsigned precedence, get_qualified_type(to, to1->base.qualifiers | to2->base.qualifiers); result_type = make_pointer_type(type, TYPE_QUALIFIER_NONE); } else if (is_type_integer(other_type)) { - warningf(&conditional->base.source_position, - "pointer/integer type mismatch in conditional expression ('%T' and '%T')", true_type, false_type); + if (warning.other) { + warningf(&conditional->base.source_position, + "pointer/integer type mismatch in conditional expression ('%T' and '%T')", true_type, false_type); + } result_type = pointer_type; } else { if (is_type_valid(other_type)) { @@ -7696,13 +7605,13 @@ end_error: /** * Parse an extension expression. */ -static expression_t *parse_extension(unsigned precedence) +static expression_t *parse_extension(void) { eat(T___extension__); bool old_gcc_extension = in_gcc_extension; in_gcc_extension = true; - expression_t *expression = parse_sub_expression(precedence); + expression_t *expression = parse_sub_expression(PREC_UNARY); in_gcc_extension = old_gcc_extension; return expression; } @@ -7710,7 +7619,7 @@ static expression_t *parse_extension(unsigned precedence) /** * Parse a __builtin_classify_type() expression. */ -static expression_t *parse_builtin_classify_type(const unsigned precedence) +static expression_t *parse_builtin_classify_type(void) { eat(T___builtin_classify_type); @@ -7719,7 +7628,7 @@ static expression_t *parse_builtin_classify_type(const unsigned precedence) expect('('); add_anchor_token(')'); - expression_t *expression = parse_sub_expression(precedence); + expression_t *expression = parse_expression(); rem_anchor_token(')'); expect(')'); result->classify_type.type_expression = expression; @@ -7953,18 +7862,18 @@ static void semantic_take_addr(unary_expression_t *expression) expression->base.type = make_pointer_type(orig_type, TYPE_QUALIFIER_NONE); } -#define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type, sfunc) \ -static expression_t *parse_##unexpression_type(unsigned precedence) \ -{ \ - expression_t *unary_expression \ - = allocate_expression_zero(unexpression_type); \ - unary_expression->base.source_position = *HERE; \ - eat(token_type); \ - unary_expression->unary.value = parse_sub_expression(precedence); \ - \ - sfunc(&unary_expression->unary); \ - \ - return unary_expression; \ +#define CREATE_UNARY_EXPRESSION_PARSER(token_type, unexpression_type, sfunc) \ +static expression_t *parse_##unexpression_type(void) \ +{ \ + expression_t *unary_expression \ + = allocate_expression_zero(unexpression_type); \ + unary_expression->base.source_position = *HERE; \ + eat(token_type); \ + unary_expression->unary.value = parse_sub_expression(PREC_UNARY); \ + \ + sfunc(&unary_expression->unary); \ + \ + return unary_expression; \ } CREATE_UNARY_EXPRESSION_PARSER('-', EXPR_UNARY_NEGATE, @@ -7986,11 +7895,8 @@ CREATE_UNARY_EXPRESSION_PARSER(T_MINUSMINUS, EXPR_UNARY_PREFIX_DECREMENT, #define CREATE_UNARY_POSTFIX_EXPRESSION_PARSER(token_type, unexpression_type, \ sfunc) \ -static expression_t *parse_##unexpression_type(unsigned precedence, \ - expression_t *left) \ +static expression_t *parse_##unexpression_type(expression_t *left) \ { \ - (void) precedence; \ - \ expression_t *unary_expression \ = allocate_expression_zero(unexpression_type); \ unary_expression->base.source_position = *HERE; \ @@ -8209,11 +8115,11 @@ static void semantic_sub(binary_expression_t *expression) "subtracting pointers to incompatible types '%T' and '%T'", orig_type_left, orig_type_right); } else if (!is_type_object(unqual_left)) { - if (is_type_atomic(unqual_left, ATOMIC_TYPE_VOID)) { - warningf(pos, "subtracting pointers to void"); - } else { + if (!is_type_atomic(unqual_left, ATOMIC_TYPE_VOID)) { errorf(pos, "subtracting pointers to non-object types '%T'", orig_type_left); + } else if (warning.other) { + warningf(pos, "subtracting pointers to void"); } } expression->base.type = type_ptrdiff_t; @@ -8642,78 +8548,58 @@ static void semantic_comma(binary_expression_t *expression) expression->base.type = expression->right->base.type; } -#define CREATE_BINEXPR_PARSER(token_type, binexpression_type, sfunc, lr) \ -static expression_t *parse_##binexpression_type(unsigned precedence, \ - expression_t *left) \ -{ \ - expression_t *binexpr = allocate_expression_zero(binexpression_type); \ - binexpr->base.source_position = *HERE; \ - binexpr->binary.left = left; \ - eat(token_type); \ - \ - expression_t *right = parse_sub_expression(precedence + lr); \ - \ - binexpr->binary.right = right; \ - sfunc(&binexpr->binary); \ - \ - return binexpr; \ -} - -CREATE_BINEXPR_PARSER(',', EXPR_BINARY_COMMA, semantic_comma, 1) -CREATE_BINEXPR_PARSER('*', EXPR_BINARY_MUL, semantic_binexpr_arithmetic, 1) -CREATE_BINEXPR_PARSER('/', EXPR_BINARY_DIV, semantic_divmod_arithmetic, 1) -CREATE_BINEXPR_PARSER('%', EXPR_BINARY_MOD, semantic_divmod_arithmetic, 1) -CREATE_BINEXPR_PARSER('+', EXPR_BINARY_ADD, semantic_add, 1) -CREATE_BINEXPR_PARSER('-', EXPR_BINARY_SUB, semantic_sub, 1) -CREATE_BINEXPR_PARSER('<', EXPR_BINARY_LESS, semantic_comparison, 1) -CREATE_BINEXPR_PARSER('>', EXPR_BINARY_GREATER, semantic_comparison, 1) -CREATE_BINEXPR_PARSER('=', EXPR_BINARY_ASSIGN, semantic_binexpr_assign, 0) - -CREATE_BINEXPR_PARSER(T_EQUALEQUAL, EXPR_BINARY_EQUAL, - semantic_comparison, 1) -CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, EXPR_BINARY_NOTEQUAL, - semantic_comparison, 1) -CREATE_BINEXPR_PARSER(T_LESSEQUAL, EXPR_BINARY_LESSEQUAL, - semantic_comparison, 1) -CREATE_BINEXPR_PARSER(T_GREATEREQUAL, EXPR_BINARY_GREATEREQUAL, - semantic_comparison, 1) - -CREATE_BINEXPR_PARSER('&', EXPR_BINARY_BITWISE_AND, - semantic_binexpr_arithmetic, 1) -CREATE_BINEXPR_PARSER('|', EXPR_BINARY_BITWISE_OR, - semantic_binexpr_arithmetic, 1) -CREATE_BINEXPR_PARSER('^', EXPR_BINARY_BITWISE_XOR, - semantic_binexpr_arithmetic, 1) -CREATE_BINEXPR_PARSER(T_ANDAND, EXPR_BINARY_LOGICAL_AND, - semantic_logical_op, 1) -CREATE_BINEXPR_PARSER(T_PIPEPIPE, EXPR_BINARY_LOGICAL_OR, - semantic_logical_op, 1) -CREATE_BINEXPR_PARSER(T_LESSLESS, EXPR_BINARY_SHIFTLEFT, - semantic_shift_op, 1) -CREATE_BINEXPR_PARSER(T_GREATERGREATER, EXPR_BINARY_SHIFTRIGHT, - semantic_shift_op, 1) -CREATE_BINEXPR_PARSER(T_PLUSEQUAL, EXPR_BINARY_ADD_ASSIGN, - semantic_arithmetic_addsubb_assign, 0) -CREATE_BINEXPR_PARSER(T_MINUSEQUAL, EXPR_BINARY_SUB_ASSIGN, - semantic_arithmetic_addsubb_assign, 0) -CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, EXPR_BINARY_MUL_ASSIGN, - semantic_arithmetic_assign, 0) -CREATE_BINEXPR_PARSER(T_SLASHEQUAL, EXPR_BINARY_DIV_ASSIGN, - semantic_divmod_assign, 0) -CREATE_BINEXPR_PARSER(T_PERCENTEQUAL, EXPR_BINARY_MOD_ASSIGN, - semantic_divmod_assign, 0) -CREATE_BINEXPR_PARSER(T_LESSLESSEQUAL, EXPR_BINARY_SHIFTLEFT_ASSIGN, - semantic_arithmetic_assign, 0) -CREATE_BINEXPR_PARSER(T_GREATERGREATEREQUAL, EXPR_BINARY_SHIFTRIGHT_ASSIGN, - semantic_arithmetic_assign, 0) -CREATE_BINEXPR_PARSER(T_ANDEQUAL, EXPR_BINARY_BITWISE_AND_ASSIGN, - semantic_arithmetic_assign, 0) -CREATE_BINEXPR_PARSER(T_PIPEEQUAL, EXPR_BINARY_BITWISE_OR_ASSIGN, - semantic_arithmetic_assign, 0) -CREATE_BINEXPR_PARSER(T_CARETEQUAL, EXPR_BINARY_BITWISE_XOR_ASSIGN, - semantic_arithmetic_assign, 0) - -static expression_t *parse_sub_expression(unsigned precedence) +/** + * @param prec_r precedence of the right operand + */ +#define CREATE_BINEXPR_PARSER(token_type, binexpression_type, prec_r, sfunc) \ +static expression_t *parse_##binexpression_type(expression_t *left) \ +{ \ + expression_t *binexpr = allocate_expression_zero(binexpression_type); \ + binexpr->base.source_position = *HERE; \ + binexpr->binary.left = left; \ + eat(token_type); \ + \ + expression_t *right = parse_sub_expression(prec_r); \ + \ + binexpr->binary.right = right; \ + sfunc(&binexpr->binary); \ + \ + return binexpr; \ +} + +CREATE_BINEXPR_PARSER('*', EXPR_BINARY_MUL, PREC_CAST, semantic_binexpr_arithmetic) +CREATE_BINEXPR_PARSER('/', EXPR_BINARY_DIV, PREC_CAST, semantic_divmod_arithmetic) +CREATE_BINEXPR_PARSER('%', EXPR_BINARY_MOD, PREC_CAST, semantic_divmod_arithmetic) +CREATE_BINEXPR_PARSER('+', EXPR_BINARY_ADD, PREC_MULTIPLICATIVE, semantic_add) +CREATE_BINEXPR_PARSER('-', EXPR_BINARY_SUB, PREC_MULTIPLICATIVE, semantic_sub) +CREATE_BINEXPR_PARSER(T_LESSLESS, EXPR_BINARY_SHIFTLEFT, PREC_ADDITIVE, semantic_shift_op) +CREATE_BINEXPR_PARSER(T_GREATERGREATER, EXPR_BINARY_SHIFTRIGHT, PREC_ADDITIVE, semantic_shift_op) +CREATE_BINEXPR_PARSER('<', EXPR_BINARY_LESS, PREC_SHIFT, semantic_comparison) +CREATE_BINEXPR_PARSER('>', EXPR_BINARY_GREATER, PREC_SHIFT, semantic_comparison) +CREATE_BINEXPR_PARSER(T_LESSEQUAL, EXPR_BINARY_LESSEQUAL, PREC_SHIFT, semantic_comparison) +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(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) +CREATE_BINEXPR_PARSER(T_PLUSEQUAL, EXPR_BINARY_ADD_ASSIGN, PREC_ASSIGNMENT, semantic_arithmetic_addsubb_assign) +CREATE_BINEXPR_PARSER(T_MINUSEQUAL, EXPR_BINARY_SUB_ASSIGN, PREC_ASSIGNMENT, semantic_arithmetic_addsubb_assign) +CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, EXPR_BINARY_MUL_ASSIGN, PREC_ASSIGNMENT, semantic_arithmetic_assign) +CREATE_BINEXPR_PARSER(T_SLASHEQUAL, EXPR_BINARY_DIV_ASSIGN, PREC_ASSIGNMENT, semantic_divmod_assign) +CREATE_BINEXPR_PARSER(T_PERCENTEQUAL, EXPR_BINARY_MOD_ASSIGN, PREC_ASSIGNMENT, semantic_divmod_assign) +CREATE_BINEXPR_PARSER(T_LESSLESSEQUAL, EXPR_BINARY_SHIFTLEFT_ASSIGN, PREC_ASSIGNMENT, semantic_arithmetic_assign) +CREATE_BINEXPR_PARSER(T_GREATERGREATEREQUAL, EXPR_BINARY_SHIFTRIGHT_ASSIGN, PREC_ASSIGNMENT, semantic_arithmetic_assign) +CREATE_BINEXPR_PARSER(T_ANDEQUAL, EXPR_BINARY_BITWISE_AND_ASSIGN, PREC_ASSIGNMENT, semantic_arithmetic_assign) +CREATE_BINEXPR_PARSER(T_PIPEEQUAL, EXPR_BINARY_BITWISE_OR_ASSIGN, PREC_ASSIGNMENT, semantic_arithmetic_assign) +CREATE_BINEXPR_PARSER(T_CARETEQUAL, EXPR_BINARY_BITWISE_XOR_ASSIGN, PREC_ASSIGNMENT, semantic_arithmetic_assign) +CREATE_BINEXPR_PARSER(',', EXPR_BINARY_COMMA, PREC_ASSIGNMENT, semantic_comma) + + +static expression_t *parse_sub_expression(precedence_t precedence) { if (token.type < 0) { return expected_expression_error(); @@ -8725,7 +8611,7 @@ static expression_t *parse_sub_expression(unsigned precedence) expression_t *left; if (parser->parser != NULL) { - left = parser->parser(parser->precedence); + left = parser->parser(); } else { left = parse_primary_expression(); } @@ -8743,7 +8629,7 @@ static expression_t *parse_sub_expression(unsigned precedence) if (parser->infix_precedence < precedence) break; - left = parser->infix_parser(parser->infix_precedence, left); + left = parser->infix_parser(left); assert(left != NULL); assert(left->kind != EXPR_UNKNOWN); @@ -8758,18 +8644,17 @@ static expression_t *parse_sub_expression(unsigned precedence) */ static expression_t *parse_expression(void) { - return parse_sub_expression(1); + return parse_sub_expression(PREC_EXPRESSION); } /** - * Register a parser for a prefix-like operator with given precedence. + * Register a parser for a prefix-like operator. * * @param parser the parser function * @param token_type the token type of the prefix token - * @param precedence the precedence of the operator */ static void register_expression_parser(parse_expression_function parser, - int token_type, unsigned precedence) + int token_type) { expression_parser_function_t *entry = &expression_parsers[token_type]; @@ -8777,8 +8662,7 @@ static void register_expression_parser(parse_expression_function parser, diagnosticf("for token '%k'\n", (token_type_t)token_type); panic("trying to register multiple expression parsers for a token"); } - entry->parser = parser; - entry->precedence = precedence; + entry->parser = parser; } /** @@ -8809,69 +8693,56 @@ static void init_expression_parsers(void) { memset(&expression_parsers, 0, sizeof(expression_parsers)); - register_infix_parser(parse_array_expression, '[', 30); - register_infix_parser(parse_call_expression, '(', 30); - register_infix_parser(parse_select_expression, '.', 30); - register_infix_parser(parse_select_expression, T_MINUSGREATER, 30); - register_infix_parser(parse_EXPR_UNARY_POSTFIX_INCREMENT, - T_PLUSPLUS, 30); - register_infix_parser(parse_EXPR_UNARY_POSTFIX_DECREMENT, - T_MINUSMINUS, 30); - - register_infix_parser(parse_EXPR_BINARY_MUL, '*', 17); - register_infix_parser(parse_EXPR_BINARY_DIV, '/', 17); - register_infix_parser(parse_EXPR_BINARY_MOD, '%', 17); - register_infix_parser(parse_EXPR_BINARY_ADD, '+', 16); - register_infix_parser(parse_EXPR_BINARY_SUB, '-', 16); - register_infix_parser(parse_EXPR_BINARY_SHIFTLEFT, T_LESSLESS, 15); - register_infix_parser(parse_EXPR_BINARY_SHIFTRIGHT, T_GREATERGREATER, 15); - register_infix_parser(parse_EXPR_BINARY_LESS, '<', 14); - register_infix_parser(parse_EXPR_BINARY_GREATER, '>', 14); - register_infix_parser(parse_EXPR_BINARY_LESSEQUAL, T_LESSEQUAL, 14); - register_infix_parser(parse_EXPR_BINARY_GREATEREQUAL, T_GREATEREQUAL, 14); - register_infix_parser(parse_EXPR_BINARY_EQUAL, T_EQUALEQUAL, 13); - register_infix_parser(parse_EXPR_BINARY_NOTEQUAL, - T_EXCLAMATIONMARKEQUAL, 13); - register_infix_parser(parse_EXPR_BINARY_BITWISE_AND, '&', 12); - register_infix_parser(parse_EXPR_BINARY_BITWISE_XOR, '^', 11); - register_infix_parser(parse_EXPR_BINARY_BITWISE_OR, '|', 10); - register_infix_parser(parse_EXPR_BINARY_LOGICAL_AND, T_ANDAND, 9); - register_infix_parser(parse_EXPR_BINARY_LOGICAL_OR, T_PIPEPIPE, 8); - register_infix_parser(parse_conditional_expression, '?', 7); - register_infix_parser(parse_EXPR_BINARY_ASSIGN, '=', 2); - register_infix_parser(parse_EXPR_BINARY_ADD_ASSIGN, T_PLUSEQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_SUB_ASSIGN, T_MINUSEQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_MUL_ASSIGN, T_ASTERISKEQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_DIV_ASSIGN, T_SLASHEQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_MOD_ASSIGN, T_PERCENTEQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_SHIFTLEFT_ASSIGN, - T_LESSLESSEQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_SHIFTRIGHT_ASSIGN, - T_GREATERGREATEREQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_BITWISE_AND_ASSIGN, - T_ANDEQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_BITWISE_OR_ASSIGN, - T_PIPEEQUAL, 2); - register_infix_parser(parse_EXPR_BINARY_BITWISE_XOR_ASSIGN, - T_CARETEQUAL, 2); - - register_infix_parser(parse_EXPR_BINARY_COMMA, ',', 1); - - register_expression_parser(parse_EXPR_UNARY_NEGATE, '-', 25); - register_expression_parser(parse_EXPR_UNARY_PLUS, '+', 25); - register_expression_parser(parse_EXPR_UNARY_NOT, '!', 25); - register_expression_parser(parse_EXPR_UNARY_BITWISE_NEGATE, '~', 25); - register_expression_parser(parse_EXPR_UNARY_DEREFERENCE, '*', 25); - register_expression_parser(parse_EXPR_UNARY_TAKE_ADDRESS, '&', 25); - register_expression_parser(parse_EXPR_UNARY_PREFIX_INCREMENT, - T_PLUSPLUS, 25); - register_expression_parser(parse_EXPR_UNARY_PREFIX_DECREMENT, - T_MINUSMINUS, 25); - register_expression_parser(parse_sizeof, T_sizeof, 25); - register_expression_parser(parse_alignof, T___alignof__, 25); - register_expression_parser(parse_extension, T___extension__, 25); - register_expression_parser(parse_builtin_classify_type, - T___builtin_classify_type, 25); + register_infix_parser(parse_array_expression, '[', PREC_POSTFIX); + register_infix_parser(parse_call_expression, '(', PREC_POSTFIX); + register_infix_parser(parse_select_expression, '.', PREC_POSTFIX); + register_infix_parser(parse_select_expression, T_MINUSGREATER, PREC_POSTFIX); + register_infix_parser(parse_EXPR_UNARY_POSTFIX_INCREMENT, T_PLUSPLUS, PREC_POSTFIX); + register_infix_parser(parse_EXPR_UNARY_POSTFIX_DECREMENT, T_MINUSMINUS, PREC_POSTFIX); + register_infix_parser(parse_EXPR_BINARY_MUL, '*', PREC_MULTIPLICATIVE); + register_infix_parser(parse_EXPR_BINARY_DIV, '/', PREC_MULTIPLICATIVE); + register_infix_parser(parse_EXPR_BINARY_MOD, '%', PREC_MULTIPLICATIVE); + register_infix_parser(parse_EXPR_BINARY_ADD, '+', PREC_ADDITIVE); + register_infix_parser(parse_EXPR_BINARY_SUB, '-', PREC_ADDITIVE); + register_infix_parser(parse_EXPR_BINARY_SHIFTLEFT, T_LESSLESS, PREC_SHIFT); + register_infix_parser(parse_EXPR_BINARY_SHIFTRIGHT, T_GREATERGREATER, PREC_SHIFT); + register_infix_parser(parse_EXPR_BINARY_LESS, '<', PREC_RELATIONAL); + register_infix_parser(parse_EXPR_BINARY_GREATER, '>', PREC_RELATIONAL); + register_infix_parser(parse_EXPR_BINARY_LESSEQUAL, T_LESSEQUAL, PREC_RELATIONAL); + register_infix_parser(parse_EXPR_BINARY_GREATEREQUAL, T_GREATEREQUAL, PREC_RELATIONAL); + register_infix_parser(parse_EXPR_BINARY_EQUAL, T_EQUALEQUAL, PREC_EQUALITY); + register_infix_parser(parse_EXPR_BINARY_NOTEQUAL, T_EXCLAMATIONMARKEQUAL, PREC_EQUALITY); + register_infix_parser(parse_EXPR_BINARY_BITWISE_AND, '&', PREC_AND); + register_infix_parser(parse_EXPR_BINARY_BITWISE_XOR, '^', PREC_XOR); + register_infix_parser(parse_EXPR_BINARY_BITWISE_OR, '|', PREC_OR); + register_infix_parser(parse_EXPR_BINARY_LOGICAL_AND, T_ANDAND, PREC_LOGICAL_AND); + register_infix_parser(parse_EXPR_BINARY_LOGICAL_OR, T_PIPEPIPE, PREC_LOGICAL_OR); + register_infix_parser(parse_conditional_expression, '?', PREC_CONDITIONAL); + register_infix_parser(parse_EXPR_BINARY_ASSIGN, '=', PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_ADD_ASSIGN, T_PLUSEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_SUB_ASSIGN, T_MINUSEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_MUL_ASSIGN, T_ASTERISKEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_DIV_ASSIGN, T_SLASHEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_MOD_ASSIGN, T_PERCENTEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_SHIFTLEFT_ASSIGN, T_LESSLESSEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_SHIFTRIGHT_ASSIGN, T_GREATERGREATEREQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_BITWISE_AND_ASSIGN, T_ANDEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_BITWISE_OR_ASSIGN, T_PIPEEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_BITWISE_XOR_ASSIGN, T_CARETEQUAL, PREC_ASSIGNMENT); + register_infix_parser(parse_EXPR_BINARY_COMMA, ',', PREC_EXPRESSION); + + register_expression_parser(parse_EXPR_UNARY_NEGATE, '-'); + register_expression_parser(parse_EXPR_UNARY_PLUS, '+'); + register_expression_parser(parse_EXPR_UNARY_NOT, '!'); + register_expression_parser(parse_EXPR_UNARY_BITWISE_NEGATE, '~'); + register_expression_parser(parse_EXPR_UNARY_DEREFERENCE, '*'); + register_expression_parser(parse_EXPR_UNARY_TAKE_ADDRESS, '&'); + register_expression_parser(parse_EXPR_UNARY_PREFIX_INCREMENT, T_PLUSPLUS); + register_expression_parser(parse_EXPR_UNARY_PREFIX_DECREMENT, T_MINUSMINUS); + register_expression_parser(parse_sizeof, T_sizeof); + register_expression_parser(parse_alignof, T___alignof__); + register_expression_parser(parse_extension, T___extension__); + register_expression_parser(parse_builtin_classify_type, T___builtin_classify_type); } /** @@ -9109,7 +8980,7 @@ static statement_t *parse_case_statement(void) long const val = fold_constant(end_range); statement->case_label.last_case = val; - if (val < statement->case_label.first_case) { + if (warning.other && val < statement->case_label.first_case) { statement->case_label.is_empty_range = true; warningf(pos, "empty range specified"); } @@ -9237,7 +9108,7 @@ static statement_t *parse_label_statement(void) if (token.type == '}') { /* TODO only warn? */ - if (false) { + if (warning.other && false) { warningf(HERE, "label at end of compound statement"); statement->label.statement = create_empty_statement(); } else { @@ -9566,7 +9437,7 @@ static statement_t *parse_goto(void) if (!is_type_pointer(type) && !is_type_integer(type)) { errorf(&expression->base.source_position, "cannot convert to a pointer type"); - } else if (type != type_void_ptr) { + } else if (warning.other && type != type_void_ptr) { warningf(&expression->base.source_position, "type of computed goto expression should be 'void*' not '%T'", type); } @@ -9587,10 +9458,6 @@ static statement_t *parse_goto(void) next_token(); statement->gotos.label = get_label(symbol); - - if (statement->gotos.label->parent_scope->depth < current_function->scope.depth) { - statement->gotos.outer_fkt_jmp = true; - } } /* remember the goto's in a list for later checking */ @@ -9743,10 +9610,12 @@ static statement_t *parse_return(void) if (return_value != NULL) { type_t *return_value_type = skip_typeref(return_value->base.type); - if (is_type_atomic(return_type, ATOMIC_TYPE_VOID) - && !is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) { - warningf(&statement->base.source_position, - "'return' with a value, in function returning void"); + if (is_type_atomic(return_type, ATOMIC_TYPE_VOID) && + !is_type_atomic(return_value_type, ATOMIC_TYPE_VOID)) { + if (warning.other) { + warningf(&statement->base.source_position, + "'return' with a value, in function returning void"); + } return_value = NULL; } else { assign_error_t error = semantic_assign(return_type, return_value); @@ -9755,7 +9624,8 @@ static statement_t *parse_return(void) return_value = create_implicit_cast(return_value, return_type); } /* check for returning address of a local var */ - if (return_value != NULL && + if (warning.other && + return_value != NULL && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) { const expression_t *expression = return_value->unary.value; if (is_local_variable(expression)) { @@ -9763,11 +9633,9 @@ static statement_t *parse_return(void) "function returns address of local variable"); } } - } else { - if (!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { - warningf(&statement->base.source_position, - "'return' without value, in function returning non-void"); - } + } else if (warning.other && !is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { + warningf(&statement->base.source_position, + "'return' without value, in function returning non-void"); } statement->returns.value = return_value; @@ -10180,7 +10048,7 @@ static void initialize_builtin_types(void) type_wchar_t_ptr = make_pointer_type(type_wchar_t, TYPE_QUALIFIER_NONE); /* const version of wchar_t */ - type_const_wchar_t = allocate_type_zero(TYPE_TYPEDEF, &builtin_source_position); + type_const_wchar_t = allocate_type_zero(TYPE_TYPEDEF); type_const_wchar_t->typedeft.declaration = type_wchar_t->typedeft.declaration; type_const_wchar_t->base.qualifiers |= TYPE_QUALIFIER_CONST; @@ -10285,7 +10153,8 @@ static void parse_translation_unit(void) case ';': if (!strict_mode) { - warningf(HERE, "stray ';' outside of function"); + if (warning.other) + warningf(HERE, "stray ';' outside of function"); next_token(); break; }