X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=parser.c;h=90e8ca431f519c96bcdf4b163730018ec1050d9b;hb=bb8544d38aaa4c716603a5d565c3ff3840454ffc;hp=d9397d98992b4eca5a45fc8d01f09fb020dfce69;hpb=6a2564eda2e886dba330454545f3c71e49be852b;p=cparser diff --git a/parser.c b/parser.c index d9397d9..90e8ca4 100644 --- a/parser.c +++ b/parser.c @@ -950,10 +950,7 @@ typedef enum assign_error_t { ASSIGN_WARNING_INT_FROM_POINTER } assign_error_t; -static void report_assign_error(assign_error_t error, type_t *orig_type_left, - const expression_t *const right, - const char *context, - const source_position_t *source_position) +static void report_assign_error(assign_error_t error, type_t *orig_type_left, expression_t const *const right, char const *const context, source_position_t const *const pos) { type_t *const orig_type_right = right->base.type; type_t *const type_left = skip_typeref(orig_type_left); @@ -963,48 +960,29 @@ static void report_assign_error(assign_error_t error, type_t *orig_type_left, case ASSIGN_SUCCESS: return; case ASSIGN_ERROR_INCOMPATIBLE: - errorf(source_position, - "destination type '%T' in %s is incompatible with type '%T'", - orig_type_left, context, orig_type_right); + errorf(pos, "destination type '%T' in %s is incompatible with type '%T'", orig_type_left, context, orig_type_right); return; case ASSIGN_ERROR_POINTER_QUALIFIER_MISSING: { - 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); + 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); - } + /* the left type has all qualifiers from the right type */ + unsigned missing_qualifiers = points_to_right->base.qualifiers & ~points_to_left->base.qualifiers; + warningf(WARN_OTHER, pos, "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: - 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); - } + warningf(WARN_OTHER, pos, "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: - if (warning.other) { - warningf(source_position, - "%s makes pointer '%T' from integer '%T' without a cast", - context, orig_type_left, orig_type_right); - } + warningf(WARN_OTHER, pos, "%s makes pointer '%T' from integer '%T' without a cast", context, orig_type_left, orig_type_right); return; case ASSIGN_WARNING_INT_FROM_POINTER: - if (warning.other) { - warningf(source_position, - "%s makes integer '%T' from pointer '%T' without a cast", - context, orig_type_left, orig_type_right); - } + warningf(WARN_OTHER, pos, "%s makes integer '%T' from pointer '%T' without a cast", context, orig_type_left, orig_type_right); return; default: @@ -1095,9 +1073,7 @@ static expression_t *parse_assignment_expression(void) static void warn_string_concat(const source_position_t *pos) { - if (warning.traditional) { - warningf(pos, "traditional C rejects string constant concatenation"); - } + warningf(WARN_TRADITIONAL, pos, "traditional C rejects string constant concatenation"); } static string_t parse_string_literals(void) @@ -1269,9 +1245,7 @@ static attribute_t *parse_attribute_gnu_single(void) 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); - } + warningf(WARN_ATTRIBUTE, HERE, "unknown attribute '%s' ignored", name); /* TODO: we should still save the attribute in the list... */ kind = ATTRIBUTE_UNKNOWN; break; @@ -1360,8 +1334,7 @@ static attribute_t *parse_attributes(attribute_t *first) case T___thiscall: /* TODO record modifier */ - if (warning.other) - warningf(HERE, "Ignoring declaration modifier %K", &token); + warningf(WARN_OTHER, HERE, "Ignoring declaration modifier %K", &token); eat(T___thiscall); attribute = allocate_attribute_zero(ATTRIBUTE_MS_THISCALL); break; @@ -1751,8 +1724,7 @@ static initializer_t *parse_scalar_initializer(type_t *type, /* there might be extra {} hierarchies */ int braces = 0; if (token.type == '{') { - if (warning.other) - warningf(HERE, "extra curly braces around scalar initializer"); + warningf(WARN_OTHER, HERE, "extra curly braces around scalar initializer"); do { eat('{'); ++braces; @@ -1781,8 +1753,8 @@ static initializer_t *parse_scalar_initializer(type_t *type, while (braces > 0) { next_if(','); if (token.type != '}') { - if (!additional_warning_displayed && warning.other) { - warningf(HERE, "additional elements in scalar initializer"); + if (!additional_warning_displayed) { + warningf(WARN_OTHER, HERE, "additional elements in scalar initializer"); additional_warning_displayed = true; } } @@ -2201,13 +2173,11 @@ finish_designator: goto error_parse_next; } - 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"); - } + source_position_t const* const pos = &expression->base.source_position; + if (env->entity != NULL) { + warningf(WARN_OTHER, pos, "excess elements in initializer for '%Y'", env->entity->base.symbol); + } else { + warningf(WARN_OTHER, pos, "excess elements in initializer"); } goto error_parse_next; } @@ -2219,9 +2189,8 @@ finish_designator: sub = initializer_from_expression(outer_type, expression); if (sub != NULL) { next_if(','); - if (token.type != '}' && warning.other) { - warningf(HERE, "excessive elements in initializer for type '%T'", - orig_type); + if (token.type != '}') { + warningf(WARN_OTHER, HERE, "excessive elements in initializer for type '%T'", orig_type); } /* TODO: eat , ... */ return sub; @@ -2737,8 +2706,8 @@ static attribute_t *parse_microsoft_extended_decl_modifier_single(void) } } - if (kind == ATTRIBUTE_UNKNOWN && warning.attribute) { - warningf(HERE, "unknown __declspec '%s' ignored", name); + if (kind == ATTRIBUTE_UNKNOWN) { + warningf(WARN_ATTRIBUTE, HERE, "unknown __declspec '%s' ignored", name); } eat(T_IDENTIFIER); } else { @@ -3111,10 +3080,7 @@ finish_specifiers: | SPECIFIER_INT: atomic_type = ATOMIC_TYPE_ULONGLONG; warn_about_long_long: - if (warning.long_long) { - warningf(&specifiers->source_position, - "ISO C90 does not support 'long long'"); - } + warningf(WARN_LONG_LONG, &specifiers->source_position, "ISO C90 does not support 'long long'"); break; case SPECIFIER_UNSIGNED | SPECIFIER_INT8: @@ -3193,9 +3159,7 @@ warn_about_long_long: 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'"); - } + warningf(WARN_IMPLICIT_INT, pos, "no type specifiers in declaration, using 'int'"); atomic_type = ATOMIC_TYPE_INT; break; } else { @@ -3718,8 +3682,8 @@ static type_t *construct_declarator_type(construct_type_t *construct_list, } else if (is_type_array(skipped_return_type)) { errorf(pos, "function returning array is not allowed"); } else { - if (skipped_return_type->base.qualifiers != 0 && warning.other) { - warningf(pos, "type qualifiers in return type of function type are meaningless"); + if (skipped_return_type->base.qualifiers != 0) { + warningf(WARN_OTHER, pos, "type qualifiers in return type of function type are meaningless"); } } @@ -4008,30 +3972,28 @@ static void check_main(const entity_t *entity) { const source_position_t *pos = &entity->base.source_position; if (entity->kind != ENTITY_FUNCTION) { - warningf(pos, "'main' is not a function"); + warningf(WARN_MAIN, pos, "'main' is not a function"); return; } if (entity->declaration.storage_class == STORAGE_CLASS_STATIC) { - warningf(pos, "'main' is normally a non-static function"); + warningf(WARN_MAIN, pos, "'main' is normally a non-static function"); } type_t *type = skip_typeref(entity->declaration.type); assert(is_type_function(type)); - function_type_t *func_type = &type->function; - if (!types_compatible(skip_typeref(func_type->return_type), type_int)) { - warningf(pos, "return type of 'main' should be 'int', but is '%T'", - func_type->return_type); + function_type_t const *const func_type = &type->function; + type_t *const ret_type = func_type->return_type; + if (!types_compatible(skip_typeref(ret_type), type_int)) { + warningf(WARN_MAIN, pos, "return type of 'main' should be 'int', but is '%T'", ret_type); } const function_parameter_t *parm = func_type->parameters; if (parm != NULL) { 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'", - parm->type); + warningf(WARN_MAIN, pos, "first argument of 'main' should be 'int', but is '%T'", parm->type); } parm = parm->next; if (parm != NULL) { @@ -4039,8 +4001,7 @@ static void check_main(const entity_t *entity) 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); + warningf(WARN_MAIN, pos, "second argument of 'main' should be 'char**', but is '%T'", parm->type); } parm = parm->next; if (parm != NULL) { @@ -4048,8 +4009,7 @@ static void check_main(const entity_t *entity) 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); + warningf(WARN_MAIN, pos, "third argument of 'main' should be 'char**', but is '%T'", parm->type); } parm = parm->next; if (parm != NULL) @@ -4057,7 +4017,7 @@ static void check_main(const entity_t *entity) } } else { warn_arg_count: - warningf(pos, "'main' takes only zero, two or three arguments"); + warningf(WARN_MAIN, pos, "'main' takes only zero, two or three arguments"); } } } @@ -4153,24 +4113,21 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) assert(is_type_function(type)); if (type->function.unspecified_parameters && - warning.strict_prototypes && previous_entity == NULL && !entity->declaration.implicit) { - warningf(pos, "function declaration '%#N' is not a prototype", entity); + warningf(WARN_STRICT_PROTOTYPES, pos, "function declaration '%#N' is not a prototype", entity); } - if (warning.main && current_scope == file_scope - && is_sym_main(symbol)) { + if (current_scope == file_scope && is_sym_main(symbol)) { check_main(entity); } } if (is_declaration(entity) && - warning.nested_externs && entity->declaration.storage_class == STORAGE_CLASS_EXTERN && current_scope != file_scope && !entity->declaration.implicit) { - warningf(pos, "nested extern declaration of '%#N'", entity); + warningf(WARN_NESTED_EXTERNS, pos, "nested extern declaration of '%#N'", entity); } if (previous_entity != NULL) { @@ -4226,12 +4183,11 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) } else { unsigned old_storage_class = prev_decl->storage_class; - if (warning.redundant_decls && - is_definition && + if (is_definition && !prev_decl->used && !(prev_decl->modifiers & DM_USED) && prev_decl->storage_class == STORAGE_CLASS_STATIC) { - warningf(ppos, "unnecessary static forward declaration for '%#N'", previous_entity); + warningf(WARN_REDUNDANT_DECLS, ppos, "unnecessary static forward declaration for '%#N'", previous_entity); } storage_class_t new_storage_class = decl->storage_class; @@ -4252,10 +4208,8 @@ entity_t *record_entity(entity_t *entity, const bool is_definition) case STORAGE_CLASS_EXTERN: if (is_definition) { - if (warning.missing_prototypes && - prev_type->function.unspecified_parameters && - !is_sym_main(symbol)) { - warningf(pos, "no previous prototype for '%#N'", entity); + if (prev_type->function.unspecified_parameters && !is_sym_main(symbol)) { + warningf(WARN_MISSING_PROTOTYPES, pos, "no previous prototype for '%#N'", entity); } } else if (new_storage_class == STORAGE_CLASS_NONE) { new_storage_class = STORAGE_CLASS_EXTERN; @@ -4279,10 +4233,9 @@ warn_redundant_declaration: ; if (has_new_attrs) { merge_in_attributes(decl, prev_decl->attributes); } else if (!is_definition && - warning.redundant_decls && is_type_valid(prev_type) && strcmp(ppos->input_name, "") != 0) { - warningf(pos, "redundant declaration for '%Y' (declared %P)", symbol, ppos); + warningf(WARN_REDUNDANT_DECLS, pos, "redundant declaration for '%Y' (declared %P)", symbol, ppos); } } else if (current_function == NULL) { if (old_storage_class != STORAGE_CLASS_STATIC && @@ -4314,27 +4267,30 @@ error_redeclaration: return previous_entity; } - if (warning.shadow || - (warning.shadow_local && previous_entity->base.parent_scope != file_scope)) { + warning_t why; + if (is_warn_on(why = WARN_SHADOW) || + (is_warn_on(why = WARN_SHADOW_LOCAL) && previous_entity->base.parent_scope != file_scope)) { char const *const what = get_entity_kind_name(previous_entity->kind); - warningf(pos, "'%N' shadows %s (declared %P)", entity, what, ppos); + warningf(why, pos, "'%N' shadows %s (declared %P)", entity, what, ppos); } } if (entity->kind == ENTITY_FUNCTION) { if (is_definition && - entity->declaration.storage_class != STORAGE_CLASS_STATIC) { - if (warning.missing_prototypes && !is_sym_main(symbol)) { - warningf(pos, "no previous prototype for '%#N'", entity); - } else if (warning.missing_declarations && !is_sym_main(symbol)) { - warningf(pos, "no previous declaration for '%#N'", entity); + entity->declaration.storage_class != STORAGE_CLASS_STATIC && + !is_sym_main(symbol)) { + if (is_warn_on(WARN_MISSING_PROTOTYPES)) { + warningf(WARN_MISSING_PROTOTYPES, pos, "no previous prototype for '%#N'", entity); + } else { + goto warn_missing_declaration; } } } else if (entity->kind == ENTITY_VARIABLE) { - if (warning.missing_declarations && - current_scope == file_scope && - entity->declaration.storage_class == STORAGE_CLASS_NONE) { - warningf(pos, "no previous declaration for '%#N'", entity); + if (current_scope == file_scope && + entity->declaration.storage_class == STORAGE_CLASS_NONE && + !entity->declaration.implicit) { +warn_missing_declaration: + warningf(WARN_MISSING_DECLARATIONS, pos, "no previous declaration for '%#N'", entity); } } @@ -4426,31 +4382,28 @@ static void parse_anonymous_declaration_rest( eat(';'); anonymous_entity = NULL; - if (warning.other) { - if (specifiers->storage_class != STORAGE_CLASS_NONE || - specifiers->thread_local) { - warningf(&specifiers->source_position, - "useless storage class in empty declaration"); - } + source_position_t const *const pos = &specifiers->source_position; + if (specifiers->storage_class != STORAGE_CLASS_NONE || + specifiers->thread_local) { + warningf(WARN_OTHER, pos, "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.compound->base.symbol == NULL) { - warningf(&specifiers->source_position, - "unnamed struct/union that defines no instances"); - } - break; + type_t *type = specifiers->type; + switch (type->kind) { + case TYPE_COMPOUND_STRUCT: + case TYPE_COMPOUND_UNION: { + if (type->compound.compound->base.symbol == NULL) { + warningf(WARN_OTHER, pos, "unnamed struct/union that defines no instances"); } + break; + } - case TYPE_ENUM: - break; + case TYPE_ENUM: + break; - default: - warningf(&specifiers->source_position, "empty declaration"); - break; - } + default: + warningf(WARN_OTHER, pos, "empty declaration"); + break; } } @@ -4661,9 +4614,7 @@ decl_list_end: errorf(pos, "no type specified for function '%N'", parameter); parameter_type = type_error_type; } else { - if (warning.implicit_int) { - warningf(pos, "no type specified for function '%N', using 'int'", parameter); - } + warningf(WARN_IMPLICIT_INT, pos, "no type specified for function parameter '%N', using 'int'", parameter); parameter_type = type_int; } parameter->declaration.type = parameter_type; @@ -4698,11 +4649,11 @@ decl_list_end: new_type->function.parameters = parameters; new_type = identify_new_type(new_type); - if (warning.other && need_incompatible_warning) { + if (need_incompatible_warning) { + symbol_t const *const sym = entity->base.symbol; source_position_t const *const pos = &entity->base.source_position; source_position_t const *const ppos = &proto_type->base.source_position; - symbol_t const *const sym = entity->base.symbol; - warningf(pos, "declaration '%#N' is incompatible with '%#T' (declared %P)", proto_type, new_type, sym, ppos); + warningf(WARN_OTHER, pos, "declaration '%#N' is incompatible with '%#T' (declared %P)", proto_type, new_type, sym, ppos); } entity->declaration.type = new_type; @@ -4745,7 +4696,7 @@ static void check_labels(void) } } - if (warning.unused_label) { + if (is_warn_on(WARN_UNUSED_LABEL)) { for (const label_statement_t *label_statement = label_first; label_statement != NULL; label_statement = label_statement->next) { @@ -4754,13 +4705,13 @@ static void check_labels(void) if (! label->used) { print_in_function(); source_position_t const *const pos = &label_statement->base.source_position; - warningf(pos, "'%N' defined but not used", (entity_t const*)label); + warningf(WARN_UNUSED_LABEL, pos, "'%N' defined but not used", (entity_t const*)label); } } } } -static void warn_unused_entity(entity_t *entity, entity_t *last) +static void warn_unused_entity(warning_t const why, entity_t *entity, entity_t *const last) { entity_t const *const end = last != NULL ? last->base.next : NULL; for (; entity != end; entity = entity->base.next) { @@ -4773,10 +4724,10 @@ static void warn_unused_entity(entity_t *entity, entity_t *last) if (!declaration->used) { print_in_function(); - warningf(&entity->base.source_position, "'%N' is unused", entity); + warningf(why, &entity->base.source_position, "'%N' is unused", entity); } else if (entity->kind == ENTITY_VARIABLE && !entity->variable.read) { print_in_function(); - warningf(&entity->base.source_position, "'%N' is never read", entity); + warningf(why, &entity->base.source_position, "'%N' is never read", entity); } } } @@ -4788,13 +4739,12 @@ static void check_unused_variables(statement_t *const stmt, void *const env) switch (stmt->kind) { case STATEMENT_DECLARATION: { declaration_statement_t const *const decls = &stmt->declaration; - warn_unused_entity(decls->declarations_begin, - decls->declarations_end); + warn_unused_entity(WARN_UNUSED_VARIABLE, decls->declarations_begin, decls->declarations_end); return; } case STATEMENT_FOR: - warn_unused_entity(stmt->fors.scope.entities, NULL); + warn_unused_entity(WARN_UNUSED_VARIABLE, stmt->fors.scope.entities, NULL); return; default: @@ -4807,15 +4757,15 @@ static void check_unused_variables(statement_t *const stmt, void *const env) */ static void check_declarations(void) { - if (warning.unused_parameter) { + if (is_warn_on(WARN_UNUSED_PARAMETER)) { const scope_t *scope = ¤t_function->parameters; /* do not issue unused warnings for main */ if (!is_sym_main(current_function->base.base.symbol)) { - warn_unused_entity(scope->entities, NULL); + warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL); } } - if (warning.unused_variable) { + if (is_warn_on(WARN_UNUSED_VARIABLE)) { walk_statements(current_function->statement, check_unused_variables, NULL); } @@ -5228,12 +5178,11 @@ found_break_parent: type_t *const type = skip_typeref(current_function->base.type); assert(is_type_function(type)); type_t *const ret = skip_typeref(type->function.return_type); - if (warning.return_type && - !is_type_atomic(ret, ATOMIC_TYPE_VOID) && + if (!is_type_atomic(ret, ATOMIC_TYPE_VOID) && is_type_valid(ret) && !is_sym_main(current_function->base.base.symbol)) { - warningf(&stmt->base.source_position, - "control reaches end of non-void function"); + source_position_t const *const pos = &stmt->base.source_position; + warningf(WARN_RETURN_TYPE, pos, "control reaches end of non-void function"); } return; } @@ -5366,8 +5315,8 @@ static void check_unreachable(statement_t* const stmt, void *const env) if (!stmt->base.reachable) { expression_t const *const cond = stmt->do_while.condition; if (determine_truth(cond) >= 0) { - warningf(&cond->base.source_position, - "condition of do-while-loop is unreachable"); + source_position_t const *const pos = &cond->base.source_position; + warningf(WARN_UNREACHABLE_CODE, pos, "condition of do-while-loop is unreachable"); } } return; @@ -5377,21 +5326,21 @@ static void check_unreachable(statement_t* const stmt, void *const env) // if init and step are unreachable, cond is unreachable, too if (!stmt->base.reachable && !fors->step_reachable) { - warningf(&stmt->base.source_position, "statement is unreachable"); + goto warn_unreachable; } else { if (!stmt->base.reachable && fors->initialisation != NULL) { - warningf(&fors->initialisation->base.source_position, - "initialisation of for-statement is unreachable"); + source_position_t const *const pos = &fors->initialisation->base.source_position; + warningf(WARN_UNREACHABLE_CODE, pos, "initialisation of for-statement is unreachable"); } if (!fors->condition_reachable && fors->condition != NULL) { - warningf(&fors->condition->base.source_position, - "condition of for-statement is unreachable"); + source_position_t const *const pos = &fors->condition->base.source_position; + warningf(WARN_UNREACHABLE_CODE, pos, "condition of for-statement is unreachable"); } if (!fors->step_reachable && fors->step != NULL) { - warningf(&fors->step->base.source_position, - "step of for-statement is unreachable"); + source_position_t const *const pos = &fors->step->base.source_position; + warningf(WARN_UNREACHABLE_CODE, pos, "step of for-statement is unreachable"); } } return; @@ -5422,8 +5371,10 @@ static void check_unreachable(statement_t* const stmt, void *const env) default: warn_unreachable: - if (!stmt->base.reachable) - warningf(&stmt->base.source_position, "statement is unreachable"); + if (!stmt->base.reachable) { + source_position_t const *const pos = &stmt->base.source_position; + warningf(WARN_UNREACHABLE_CODE, pos, "statement is unreachable"); + } return; } } @@ -5493,15 +5444,13 @@ static void parse_external_declaration(void) errorf(pos, "type of function definition '%#N' is a typedef", ndeclaration); } - if (warning.aggregate_return && - is_type_compound(skip_typeref(type->function.return_type))) { - warningf(pos, "'%N' returns an aggregate", ndeclaration); + if (is_type_compound(skip_typeref(type->function.return_type))) { + warningf(WARN_AGGREGATE_RETURN, pos, "'%N' returns an aggregate", ndeclaration); } - if (warning.traditional && !type->function.unspecified_parameters) { - warningf(pos, "traditional C rejects ISO C style definition of '%N'", ndeclaration); - } - if (warning.old_style_definition && type->function.unspecified_parameters) { - warningf(pos, "old-style definition of '%N'", ndeclaration); + if (type->function.unspecified_parameters) { + warningf(WARN_OLD_STYLE_DEFINITION, pos, "old-style definition of '%N'", ndeclaration); + } else { + warningf(WARN_TRADITIONAL, pos, "traditional C rejects ISO C style definition of '%N'", ndeclaration); } /* §6.7.5.3:14 a function definition with () means no @@ -5567,19 +5516,17 @@ static void parse_external_declaration(void) first_err = true; check_labels(); check_declarations(); - if (warning.return_type || - warning.unreachable_code || - (warning.missing_noreturn - && !(function->base.modifiers & DM_NORETURN))) { + if (is_warn_on(WARN_RETURN_TYPE) || + is_warn_on(WARN_UNREACHABLE_CODE) || + (is_warn_on(WARN_MISSING_NORETURN) && !(function->base.modifiers & DM_NORETURN))) { noreturn_candidate = true; check_reachable(body); - if (warning.unreachable_code) + if (is_warn_on(WARN_UNREACHABLE_CODE)) walk_statements(body, check_unreachable, NULL); - if (warning.missing_noreturn && - noreturn_candidate && + if (noreturn_candidate && !(function->base.modifiers & DM_NORETURN)) { source_position_t const *const pos = &body->base.source_position; - warningf(pos, "function '%#N' is candidate for attribute 'noreturn'", entity); + warningf(WARN_MISSING_NORETURN, pos, "function '%#N' is candidate for attribute 'noreturn'", entity); } } @@ -5662,19 +5609,17 @@ static entity_t *find_compound_entry(compound_t *compound, symbol_t *symbol) static void check_deprecated(const source_position_t *source_position, const entity_t *entity) { - if (!warning.deprecated_declarations) - return; if (!is_declaration(entity)) return; if ((entity->declaration.modifiers & DM_DEPRECATED) == 0) return; - source_position_t const *const pos = &entity->base.source_position; - char const* const msg = get_deprecated_string(entity->declaration.attributes); + source_position_t const *const epos = &entity->base.source_position; + char const *const msg = get_deprecated_string(entity->declaration.attributes); if (msg != NULL) { - warningf(source_position, "'%N' is deprecated (declared %P): \"%s\"", entity, pos, msg); + warningf(WARN_DEPRECATED_DECLARATIONS, source_position, "'%N' is deprecated (declared %P): \"%s\"", entity, epos, msg); } else { - warningf(source_position, "'%N' is deprecated (declared %P)", entity, pos); + warningf(WARN_DEPRECATED_DECLARATIONS, source_position, "'%N' is deprecated (declared %P)", entity, epos); } } @@ -5905,12 +5850,12 @@ static expression_t *expected_expression_error(void) static type_t *get_string_type(void) { - return warning.write_strings ? type_const_char_ptr : type_char_ptr; + return is_warn_on(WARN_WRITE_STRINGS) ? type_const_char_ptr : type_char_ptr; } static type_t *get_wide_string_type(void) { - return warning.write_strings ? type_const_wchar_t_ptr : type_wchar_t_ptr; + return is_warn_on(WARN_WRITE_STRINGS) ? type_const_wchar_t_ptr : type_wchar_t_ptr; } /** @@ -5962,10 +5907,7 @@ static expression_t *parse_boolean_literal(bool value) static void warn_traditional_suffix(void) { - if (!warning.traditional) - return; - warningf(&token.source_position, "traditional C rejects the '%Y' suffix", - token.symbol); + warningf(WARN_TRADITIONAL, HERE, "traditional C rejects the '%Y' suffix", token.symbol); } static void check_integer_suffix(void) @@ -6097,9 +6039,9 @@ static expression_t *parse_character_constant(void) if (len > 1) { if (!GNU_MODE && !(c_mode & _C99)) { errorf(HERE, "more than 1 character in character constant"); - } else if (warning.multichar) { + } else { literal->base.type = type_int; - warningf(HERE, "multi-character character constant"); + warningf(WARN_MULTICHAR, HERE, "multi-character character constant"); } } @@ -6119,7 +6061,7 @@ static expression_t *parse_wide_character_constant(void) size_t len = wstrlen(&literal->literal.value); if (len > 1) { - warningf(HERE, "multi-character character constant"); + warningf(WARN_MULTICHAR, HERE, "multi-character character constant"); } next_token(); @@ -6304,12 +6246,7 @@ static entity_t *parse_qualified_identifier(void) if (entity == NULL) { if (!strict_mode && token.type == '(') { /* an implicitly declared function */ - if (warning.error_implicit_function_declaration) { - errorf(&pos, "implicit declaration of function '%Y'", symbol); - } else if (warning.implicit_function_declaration) { - warningf(&pos, "implicit declaration of function '%Y'", symbol); - } - + warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, "implicit declaration of function '%Y'", symbol); entity = create_implicit_function(symbol, &pos); } else { errorf(&pos, "unknown identifier '%Y' found.", symbol); @@ -6367,10 +6304,9 @@ static expression_t *parse_reference(void) check_deprecated(&pos, entity); - if (warning.init_self && entity == current_init_decl && !in_type_prop - && entity->kind == ENTITY_VARIABLE) { + if (entity == current_init_decl && !in_type_prop && entity->kind == ENTITY_VARIABLE) { current_init_decl = NULL; - warningf(&pos, "variable '%#N' is initialized by itself", entity); + warningf(WARN_INIT_SELF, &pos, "variable '%#N' is initialized by itself", entity); } return expression; @@ -6408,17 +6344,13 @@ static bool semantic_cast(expression_t *cast) return false; } - if (warning.cast_qual && - is_type_pointer(src_type) && - is_type_pointer(dst_type)) { + if (is_type_pointer(src_type) && is_type_pointer(dst_type)) { type_t *src = skip_typeref(src_type->pointer.points_to); type_t *dst = skip_typeref(dst_type->pointer.points_to); unsigned missing_qualifiers = src->base.qualifiers & ~dst->base.qualifiers; if (missing_qualifiers != 0) { - warningf(pos, - "cast discards qualifiers '%Q' in pointer target type of '%T'", - missing_qualifiers, orig_type_right); + warningf(WARN_CAST_QUAL, pos, "cast discards qualifiers '%Q' in pointer target type of '%T'", missing_qualifiers, orig_type_right); } } return true; @@ -6501,8 +6433,9 @@ static expression_t *parse_statement_expression(void) if (stmt->kind == STATEMENT_EXPRESSION) { type = stmt->expression.expression->base.type; } - } else if (warning.other) { - warningf(&expression->base.source_position, "empty statement expression ({})"); + } else { + source_position_t const *const pos = &expression->base.source_position; + warningf(WARN_OTHER, pos, "empty statement expression ({})"); } expression->base.type = type; @@ -7095,8 +7028,9 @@ 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_atomic(idx_type, ATOMIC_TYPE_CHAR)) { + source_position_t const *const pos = &idx->base.source_position; + warningf(WARN_CHAR_SUBSCRIPTS, pos, "array subscript has char type"); } } else { if (is_type_valid(type_left) && is_type_valid(type_inside)) { @@ -7162,11 +7096,9 @@ typeprop_expression: } 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); - } + source_position_t const *const pos = &tp_expression->base.source_position; + char const *const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof"; + warningf(WARN_OTHER, pos, "%s expression with function argument returns invalid result", what); } else { wrong_type = "function"; } @@ -7307,15 +7239,14 @@ static void check_call_argument(type_t *expected_type, snprintf(buf, sizeof(buf), "call argument %u", pos); report_assign_error(error, expected_type, arg_expr, buf, &arg_expr->base.source_position); - } else if (warning.traditional || warning.conversion) { + } else { type_t *const promoted_type = get_default_promoted_type(arg_type); if (!types_compatible(expected_type_skip, promoted_type) && !types_compatible(expected_type_skip, type_void_ptr) && !types_compatible(type_void_ptr, promoted_type)) { /* Deliberately show the skipped types in this warning */ - warningf(&arg_expr->base.source_position, - "passing call argument %u as '%T' rather than '%T' due to prototype", - pos, expected_type_skip, promoted_type); + source_position_t const *const apos = &arg_expr->base.source_position; + warningf(WARN_TRADITIONAL, apos, "passing call argument %u as '%T' rather than '%T' due to prototype", pos, expected_type_skip, promoted_type); } } } @@ -7461,10 +7392,9 @@ static expression_t *parse_call_expression(expression_t *expression) check_format(call); - if (warning.aggregate_return && - is_type_compound(skip_typeref(function_type->return_type))) { - warningf(&expression->base.source_position, - "function call has aggregate value"); + if (is_type_compound(skip_typeref(function_type->return_type))) { + source_position_t const *const pos = &expression->base.source_position; + warningf(WARN_AGGREGATE_RETURN, pos, "function call has aggregate value"); } if (expression->kind == EXPR_REFERENCE) { @@ -7519,27 +7449,22 @@ static expression_t const *get_reference_address(expression_t const *expr) static void warn_reference_address_as_bool(expression_t const* expr) { - if (!warning.address) - return; - expr = get_reference_address(expr); if (expr != NULL) { source_position_t const *const pos = &expr->base.source_position; entity_t const *const ent = expr->reference.entity; - warningf(pos, "the address of '%N' will always evaluate as 'true'", ent); + warningf(WARN_ADDRESS, pos, "the address of '%N' will always evaluate as 'true'", ent); } } static void warn_assignment_in_condition(const expression_t *const expr) { - if (!warning.parentheses) - return; if (expr->base.kind != EXPR_BINARY_ASSIGN) return; if (expr->base.parenthesized) return; - warningf(&expr->base.source_position, - "suggest parentheses around assignment used as truth value"); + source_position_t const *const pos = &expr->base.source_position; + warningf(WARN_PARENTHESES, pos, "suggest parentheses around assignment used as truth value"); } static void semantic_condition(expression_t const *const expr, @@ -7592,7 +7517,8 @@ end_error:; type_t *const false_type = skip_typeref(orig_false_type); /* 6.5.15.3 */ - type_t *result_type; + source_position_t const *const pos = &conditional->base.source_position; + type_t *result_type; if (is_type_atomic(true_type, ATOMIC_TYPE_VOID) || is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { /* ISO/IEC 14882:1998(E) §5.16:2 */ @@ -7601,12 +7527,9 @@ end_error:; } else if (false_expression->kind == EXPR_UNARY_THROW) { result_type = true_type; } else { - 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"); + if (!is_type_atomic(true_type, ATOMIC_TYPE_VOID) || + !is_type_atomic(false_type, ATOMIC_TYPE_VOID)) { + warningf(WARN_OTHER, pos, "ISO C forbids conditional expression with only one void side"); } result_type = type_void; } @@ -7645,11 +7568,7 @@ end_error:; get_unqualified_type(to2))) { to = to1; } else { - if (warning.other) { - warningf(&conditional->base.source_position, - "pointer types '%T' and '%T' in conditional expression are incompatible", - true_type, false_type); - } + warningf(WARN_OTHER, pos, "pointer types '%T' and '%T' in conditional expression are incompatible", true_type, false_type); to = type_void; } @@ -7657,10 +7576,7 @@ end_error:; 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)) { - if (warning.other) { - warningf(&conditional->base.source_position, - "pointer/integer type mismatch in conditional expression ('%T' and '%T')", true_type, false_type); - } + warningf(WARN_OTHER, pos, "pointer/integer type mismatch in conditional expression ('%T' and '%T')", true_type, false_type); result_type = pointer_type; } else { goto types_incompatible; @@ -7668,9 +7584,7 @@ end_error:; } else { types_incompatible: if (is_type_valid(true_type) && is_type_valid(false_type)) { - type_error_incompatible("while parsing conditional", - &conditional->base.source_position, true_type, - false_type); + type_error_incompatible("while parsing conditional", pos, true_type, false_type); } result_type = type_error_type; } @@ -7745,10 +7659,9 @@ end_error:; errorf(&value->base.source_position, "operand of delete must have pointer type"); } - } else if (warning.other && - is_type_atomic(skip_typeref(type->pointer.points_to), ATOMIC_TYPE_VOID)) { - warningf(&value->base.source_position, - "deleting 'void*' is undefined"); + } else if (is_type_atomic(skip_typeref(type->pointer.points_to), ATOMIC_TYPE_VOID)) { + source_position_t const *const pos = &value->base.source_position; + warningf(WARN_OTHER, pos, "deleting 'void*' is undefined"); } return result; @@ -7806,10 +7719,8 @@ static bool check_pointer_arithmetic(const source_position_t *source_position, "arithmetic with pointer to incomplete type '%T' not allowed", orig_pointer_type); return false; - } else if (warning.pointer_arith) { - warningf(source_position, - "pointer of type '%T' used in arithmetic", - orig_pointer_type); + } else { + warningf(WARN_POINTER_ARITH, source_position, "pointer of type '%T' used in arithmetic", orig_pointer_type); } } else if (is_type_function(points_to)) { if (!GNU_MODE) { @@ -7817,10 +7728,8 @@ static bool check_pointer_arithmetic(const source_position_t *source_position, "arithmetic with pointer to function type '%T' not allowed", orig_pointer_type); return false; - } else if (warning.pointer_arith) { - warningf(source_position, - "pointer to a function '%T' used in arithmetic", - orig_pointer_type); + } else { + warningf(WARN_POINTER_ARITH, source_position, "pointer to a function '%T' used in arithmetic", orig_pointer_type); } } return true; @@ -7891,9 +7800,8 @@ static void semantic_unexpr_arithmetic(unary_expression_t *expression) static void semantic_unexpr_plus(unary_expression_t *expression) { semantic_unexpr_arithmetic(expression); - if (warning.traditional) - warningf(&expression->base.source_position, - "traditional C rejects the unary plus operator"); + source_position_t const *const pos = &expression->base.source_position; + warningf(WARN_TRADITIONAL, pos, "traditional C rejects the unary plus operator"); } static void semantic_not(unary_expression_t *expression) @@ -8161,8 +8069,7 @@ static void semantic_binexpr_integer(binary_expression_t *const expression) static void warn_div_by_zero(binary_expression_t const *const expression) { - if (!warning.div_by_zero || - !is_type_integer(expression->base.type)) + if (!is_type_integer(expression->base.type)) return; expression_t const *const right = expression->right; @@ -8170,7 +8077,8 @@ static void warn_div_by_zero(binary_expression_t const *const expression) 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"); + source_position_t const *const pos = &expression->base.source_position; + warningf(WARN_DIV_BY_ZERO, pos, "division by zero"); } } @@ -8195,8 +8103,8 @@ static void warn_addsub_in_shift(const expression_t *const expr) default: return; } - warningf(&expr->base.source_position, - "suggest parentheses around '%c' inside shift", op); + source_position_t const *const pos = &expr->base.source_position; + warningf(WARN_PARENTHESES, pos, "suggest parentheses around '%c' inside shift", op); } static bool semantic_shift(binary_expression_t *expression) @@ -8220,14 +8128,13 @@ static bool semantic_shift(binary_expression_t *expression) type_left = promote_integer(type_left); if (is_constant_expression(right) == EXPR_CLASS_CONSTANT) { - long count = fold_constant_to_int(right); + source_position_t const *const pos = &right->base.source_position; + long const count = fold_constant_to_int(right); if (count < 0) { - warningf(&right->base.source_position, - "shift count must be non-negative"); + warningf(WARN_OTHER, pos, "shift count must be non-negative"); } else if ((unsigned long)count >= get_atomic_type_size(type_left->atomic.akind) * 8) { - warningf(&right->base.source_position, - "shift count must be less than type width"); + warningf(WARN_OTHER, pos, "shift count must be less than type width"); } } @@ -8245,10 +8152,8 @@ static void semantic_shift_op(binary_expression_t *expression) if (!semantic_shift(expression)) return; - if (warning.parentheses) { - warn_addsub_in_shift(left); - warn_addsub_in_shift(right); - } + warn_addsub_in_shift(left); + warn_addsub_in_shift(right); type_t *const orig_type_left = left->base.type; type_t * type_left = skip_typeref(orig_type_left); @@ -8319,8 +8224,8 @@ static void semantic_sub(binary_expression_t *expression) 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"); + } else { + warningf(WARN_OTHER, pos, "subtracting pointers to void"); } } expression->base.type = type_ptrdiff_t; @@ -8341,8 +8246,8 @@ static void warn_string_literal_address(expression_t const* expr) if (expr->kind == EXPR_STRING_LITERAL || expr->kind == EXPR_WIDE_STRING_LITERAL) { - warningf(&expr->base.source_position, - "comparison with string literal results in unspecified behaviour"); + source_position_t const *const pos = &expr->base.source_position; + warningf(WARN_ADDRESS, pos, "comparison with string literal results in unspecified behaviour"); } } @@ -8357,17 +8262,15 @@ static bool maybe_negative(expression_t const *const expr) static void warn_comparison(source_position_t const *const pos, expression_t const *const expr, expression_t const *const other) { - if (warning.address) { - warn_string_literal_address(expr); + warn_string_literal_address(expr); - expression_t const* const ref = get_reference_address(expr); - if (ref != NULL && is_null_pointer_constant(other)) { - entity_t const *const ent = ref->reference.entity; - warningf(pos, "the address of '%N' will never be NULL", ent); - } + expression_t const* const ref = get_reference_address(expr); + if (ref != NULL && is_null_pointer_constant(other)) { + entity_t const *const ent = ref->reference.entity; + warningf(WARN_ADDRESS, pos, "the address of '%N' will never be NULL", ent); } - if (warning.parentheses && !expr->base.parenthesized) { + if (!expr->base.parenthesized) { switch (expr->base.kind) { case EXPR_BINARY_LESS: case EXPR_BINARY_GREATER: @@ -8375,7 +8278,7 @@ static void warn_comparison(source_position_t const *const pos, expression_t con case EXPR_BINARY_GREATEREQUAL: case EXPR_BINARY_NOTEQUAL: case EXPR_BINARY_EQUAL: - warningf(pos, "comparisons like 'x <= y < z' do not have their mathematical meaning"); + warningf(WARN_PARENTHESES, pos, "comparisons like 'x <= y < z' do not have their mathematical meaning"); break; default: break; @@ -8407,7 +8310,7 @@ static void semantic_comparison(binary_expression_t *expression) type_t *arithmetic_type = semantic_arithmetic(type_left, type_right); /* test for signed vs unsigned compares */ - if (warning.sign_compare && is_type_integer(arithmetic_type)) { + if (is_type_integer(arithmetic_type)) { bool const signed_left = is_type_signed(type_left); bool const signed_right = is_type_signed(type_right); if (signed_left != signed_right) { @@ -8415,7 +8318,7 @@ static void semantic_comparison(binary_expression_t *expression) /* TODO check whether constant value can be represented by other type */ if ((signed_left && maybe_negative(left)) || (signed_right && maybe_negative(right))) { - warningf(pos, "comparison between signed and unsigned"); + warningf(WARN_SIGN_COMPARE, pos, "comparison between signed and unsigned"); } } } @@ -8423,11 +8326,10 @@ static void semantic_comparison(binary_expression_t *expression) expression->left = create_implicit_cast(left, arithmetic_type); expression->right = create_implicit_cast(right, arithmetic_type); expression->base.type = arithmetic_type; - if (warning.float_equal && - (expression->base.kind == EXPR_BINARY_EQUAL || + if ((expression->base.kind == EXPR_BINARY_EQUAL || expression->base.kind == EXPR_BINARY_NOTEQUAL) && is_type_float(arithmetic_type)) { - warningf(pos, "comparing floating point with == or != is unsafe"); + warningf(WARN_FLOAT_EQUAL, pos, "comparing floating point with == or != is unsafe"); } } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) { /* TODO check compatibility */ @@ -8619,8 +8521,8 @@ static void warn_logical_and_within_or(const expression_t *const expr) return; if (expr->base.parenthesized) return; - warningf(&expr->base.source_position, - "suggest parentheses around && within ||"); + source_position_t const *const pos = &expr->base.source_position; + warningf(WARN_PARENTHESES, pos, "suggest parentheses around && within ||"); } /** @@ -8632,8 +8534,7 @@ static void semantic_logical_op(binary_expression_t *expression) * §6.5.14:2 Each of the operands shall have scalar type. */ semantic_condition(expression->left, "left operand of logical operator"); semantic_condition(expression->right, "right operand of logical operator"); - if (expression->base.kind == EXPR_BINARY_LOGICAL_OR && - warning.parentheses) { + if (expression->base.kind == EXPR_BINARY_LOGICAL_OR) { warn_logical_and_within_or(expression->left); warn_logical_and_within_or(expression->right); } @@ -8804,12 +8705,10 @@ static bool expression_has_effect(const expression_t *const expr) static void semantic_comma(binary_expression_t *expression) { - if (warning.unused_value) { - const expression_t *const left = expression->left; - if (!expression_has_effect(left)) { - warningf(&left->base.source_position, - "left-hand operand of comma expression has no effect"); - } + const expression_t *const left = expression->left; + if (!expression_has_effect(left)) { + source_position_t const *const pos = &left->base.source_position; + warningf(WARN_UNUSED_VALUE, pos, "left-hand operand of comma expression has no effect"); } expression->base.type = expression->right->base.type; } @@ -9263,9 +9162,9 @@ static statement_t *parse_case_statement(void) long const val = fold_constant_to_int(end_range); statement->case_label.last_case = val; - if (warning.other && val < statement->case_label.first_case) { + if (val < statement->case_label.first_case) { statement->case_label.is_empty_range = true; - warningf(pos, "empty range specified"); + warningf(WARN_OTHER, pos, "empty range specified"); } } } @@ -9417,11 +9316,10 @@ end_error: if (next_if(T_else)) { statement->ifs.false_statement = parse_statement(); - } else if (warning.parentheses && - true_stmt->kind == STATEMENT_IF && + } else if (true_stmt->kind == STATEMENT_IF && true_stmt->ifs.false_statement != NULL) { - warningf(&true_stmt->base.source_position, - "suggest explicit braces to avoid ambiguous 'else'"); + source_position_t const *const pos = &true_stmt->base.source_position; + warningf(WARN_PARENTHESES, pos, "suggest explicit braces to avoid ambiguous 'else'"); } POP_PARENT; @@ -9435,6 +9333,8 @@ end_error: */ static void check_enum_cases(const switch_statement_t *statement) { + if (!is_warn_on(WARN_SWITCH_ENUM)) + return; const type_t *type = skip_typeref(statement->expression->base.type); if (! is_type_enum(type)) return; @@ -9462,7 +9362,8 @@ static void check_enum_cases(const switch_statement_t *statement) } } if (!found) { - warningf(&statement->base.source_position, "'%N' not handled in switch", entry); + source_position_t const *const pos = &statement->base.source_position; + warningf(WARN_SWITCH_ENUM, pos, "'%N' not handled in switch", entry); } last_value = value; } @@ -9486,12 +9387,8 @@ static statement_t *parse_switch(void) type_t * type = skip_typeref(expr->base.type); if (is_type_integer(type)) { type = promote_integer(type); - if (warning.traditional) { - if (get_rank(type) >= get_akind_rank(ATOMIC_TYPE_LONG)) { - warningf(&expr->base.source_position, - "'%T' switch expression not converted to '%T' in ISO C", - type, type_int); - } + if (get_rank(type) >= get_akind_rank(ATOMIC_TYPE_LONG)) { + warningf(WARN_TRADITIONAL, &expr->base.source_position, "'%T' switch expression not converted to '%T' in ISO C", type, type_int); } } else if (is_type_valid(type)) { errorf(&expr->base.source_position, @@ -9507,12 +9404,10 @@ static statement_t *parse_switch(void) statement->switchs.body = parse_statement(); current_switch = rem; - if (warning.switch_default && - statement->switchs.default_label == NULL) { - warningf(&statement->base.source_position, "switch has no default case"); + if (statement->switchs.default_label == NULL) { + warningf(WARN_SWITCH_DEFAULT, &statement->base.source_position, "switch has no default case"); } - if (warning.switch_enum) - check_enum_cases(&statement->switchs); + check_enum_cases(&statement->switchs); POP_PARENT; return statement; @@ -9628,9 +9523,8 @@ static statement_t *parse_for(void) expression_t *const init = parse_expression(); statement->fors.initialisation = init; mark_vars_read(init, ENT_ANY); - if (warning.unused_value && !expression_has_effect(init)) { - warningf(&init->base.source_position, - "initialisation of 'for'-statement has no effect"); + if (!expression_has_effect(init)) { + warningf(WARN_UNUSED_VALUE, &init->base.source_position, "initialisation of 'for'-statement has no effect"); } rem_anchor_token(';'); expect(';', end_error2); @@ -9652,9 +9546,8 @@ static statement_t *parse_for(void) expression_t *const step = parse_expression(); statement->fors.step = step; mark_vars_read(step, ENT_ANY); - if (warning.unused_value && !expression_has_effect(step)) { - warningf(&step->base.source_position, - "step of 'for'-statement has no effect"); + if (!expression_has_effect(step)) { + warningf(WARN_UNUSED_VALUE, &step->base.source_position, "step of 'for'-statement has no effect"); } } expect(')', end_error2); @@ -9700,9 +9593,8 @@ 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 (warning.other && type != type_void_ptr) { - warningf(&expression->base.source_position, - "type of computed goto expression should be 'void*' not '%T'", type); + } else if (type != type_void_ptr) { + warningf(WARN_OTHER, &expression->base.source_position, "type of computed goto expression should be 'void*' not '%T'", type); } expression = create_implicit_cast(expression, type_void_ptr); } @@ -9866,18 +9758,16 @@ static statement_t *parse_return(void) if (c_mode & _CXX || strict_mode) { errorf(pos, "'return' with a value, in function returning 'void'"); - } else if (warning.other) { - warningf(pos, - "'return' with a value, in function returning 'void'"); + } else { + warningf(WARN_OTHER, pos, "'return' with a value, in function returning 'void'"); } } else if (!(c_mode & _CXX)) { /* ISO/IEC 14882:1998(E) §6.6.3:3 */ /* Only warn in C mode, because GCC does the same */ if (strict_mode) { errorf(pos, "'return' with expression in function returning 'void'"); - } else if (warning.other) { - warningf(pos, - "'return' with expression in function returning 'void'"); + } else { + warningf(WARN_OTHER, pos, "'return' with expression in function returning 'void'"); } } } else { @@ -9887,21 +9777,19 @@ static statement_t *parse_return(void) } 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) { + if (return_value != NULL && 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"); + warningf(WARN_OTHER, pos, "function returns address of local variable"); } } - } else if (warning.other && !is_type_atomic(return_type, ATOMIC_TYPE_VOID)) { + } else if (!is_type_atomic(return_type, ATOMIC_TYPE_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"); } else { - warningf(pos, - "'return' without value, in function returning non-void"); + warningf(WARN_OTHER, pos, "'return' without value, in function returning non-void"); } } statement->returns.value = return_value; @@ -10000,9 +9888,7 @@ end_error: static statement_t *parse_empty_statement(void) { - if (warning.empty_statement) { - warningf(HERE, "statement is empty"); - } + warningf(WARN_EMPTY_STATEMENT, HERE, "statement is empty"); statement_t *const statement = create_empty_statement(); eat(';'); return statement; @@ -10207,11 +10093,10 @@ static statement_t *parse_statement(void) { statement_t *statement = intern_parse_statement(); - if (statement->kind == STATEMENT_EXPRESSION && warning.unused_value) { + if (statement->kind == STATEMENT_EXPRESSION) { expression_t *expression = statement->expression.expression; if (!expression_has_effect(expression)) { - warningf(&expression->base.source_position, - "statement has no effect"); + warningf(WARN_UNUSED_VALUE, &expression->base.source_position, "statement has no effect"); } } @@ -10337,13 +10222,11 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) continue; } - if (warning.declaration_after_statement) { - if (sub_statement->kind != STATEMENT_DECLARATION) { - only_decls_so_far = false; - } else if (!only_decls_so_far) { - warningf(&sub_statement->base.source_position, - "ISO C90 forbids mixed declarations and code"); - } + if (sub_statement->kind != STATEMENT_DECLARATION) { + only_decls_so_far = false; + } else if (!only_decls_so_far) { + source_position_t const *const pos = &sub_statement->base.source_position; + warningf(WARN_DECLARATION_AFTER_STATEMENT, pos, "ISO C90 forbids mixed declarations and code"); } *anchor = sub_statement; @@ -10356,7 +10239,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) next_token(); /* look over all statements again to produce no effect warnings */ - if (warning.unused_value) { + if (is_warn_on(WARN_UNUSED_VALUE)) { statement_t *sub_statement = statement->compound.statements; for (; sub_statement != NULL; sub_statement = sub_statement->base.next) { if (sub_statement->kind != STATEMENT_EXPRESSION) @@ -10368,8 +10251,7 @@ static statement_t *parse_compound_statement(bool inside_expression_statement) expression_t *expression = sub_statement->expression.expression; if (!expression_has_effect(expression)) { - warningf(&expression->base.source_position, - "statement has no effect"); + warningf(WARN_UNUSED_VALUE, &expression->base.source_position, "statement has no effect"); } } } @@ -10475,7 +10357,7 @@ end_error: */ static void check_unused_globals(void) { - if (!warning.unused_function && !warning.unused_variable) + if (!is_warn_on(WARN_UNUSED_FUNCTION) && !is_warn_on(WARN_UNUSED_VARIABLE)) return; for (const entity_t *entity = file_scope->entities; entity != NULL; @@ -10490,18 +10372,21 @@ static void check_unused_globals(void) declaration->storage_class != STORAGE_CLASS_STATIC) continue; - const char *s; + warning_t why; + char const *s; if (entity->kind == ENTITY_FUNCTION) { /* inhibit warning for static inline functions */ if (entity->function.is_inline) continue; - s = entity->function.statement != NULL ? "defined" : "declared"; + why = WARN_UNUSED_FUNCTION; + s = entity->function.statement != NULL ? "defined" : "declared"; } else { - s = "defined"; + why = WARN_UNUSED_VARIABLE; + s = "defined"; } - warningf(&declaration->base.source_position, "'%#N' %s but not used", entity); + warningf(why, &declaration->base.source_position, "'%#N' %s but not used", entity); } } @@ -10585,8 +10470,7 @@ static void parse_external(void) case ';': if (!strict_mode) { - if (warning.other) - warningf(HERE, "stray ';' outside of function"); + warningf(WARN_OTHER, HERE, "stray ';' outside of function"); next_token(); return; } @@ -10717,10 +10601,8 @@ static void complete_incomplete_arrays(void) if (!is_type_incomplete(type)) continue; - if (warning.other) { - source_position_t const *const pos = &decl->base.source_position; - warningf(pos, "array '%#N' assumed to have one element", (entity_t const*)decl); - } + source_position_t const *const pos = &decl->base.source_position; + warningf(WARN_OTHER, pos, "array '%#N' assumed to have one element", (entity_t const*)decl); type_t *const new_type = duplicate_type(type); new_type->array.size_constant = true;