diff options
author | Jason Merrill <jason@redhat.com> | 2020-01-07 12:20:26 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2020-01-21 18:40:19 -0500 |
commit | c77074d05691053ee7347d9e44ab89b3adb23fb1 (patch) | |
tree | 589e55a7c74bb1c0ec4c46ac228f20340158909a /gcc/c-family | |
parent | 731dbfc3f3b586e78f2ccdca24561ea3369c6338 (diff) | |
download | gcc-c77074d05691053ee7347d9e44ab89b3adb23fb1.zip gcc-c77074d05691053ee7347d9e44ab89b3adb23fb1.tar.gz gcc-c77074d05691053ee7347d9e44ab89b3adb23fb1.tar.bz2 |
PR c++/40752 - useless -Wconversion with short +=.
This is a longstanding issue with lots of duplicates; people are not
interested in a -Wconversion warning about mychar += 1. So now that warning
depends on -Warith-conversion; otherwise we only warn if operands of the
arithmetic have conversion issues.
* c.opt (-Warith-conversion): New.
* c-warn.c (conversion_warning): Recurse for operands of
operators. Only warn about the whole expression with
-Warith-conversion.
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/c-family/c-warn.c | 70 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 4 |
3 files changed, 74 insertions, 9 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index fbbc924..3a9ce24 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,4 +1,13 @@ 2020-01-21 Jason Merrill <jason@redhat.com> + Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR c++/40752 - useless -Wconversion with short +=. + * c.opt (-Warith-conversion): New. + * c-warn.c (conversion_warning): Recurse for operands of + operators. Only warn about the whole expression with + -Warith-conversion. + +2020-01-21 Jason Merrill <jason@redhat.com> * c-common.c (unsafe_conversion_p): Don't warn, return UNSAFE_SIGN. * c-warn.c (conversion_warning): Warn about UNSAFE_SIGN. diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 6dbc660..d8f0ad6 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -1155,17 +1155,18 @@ check_main_parameter_types (tree decl) "%q+D declared as variadic function", decl); } -/* Warns if the conversion of EXPR to TYPE may alter a value. +/* Warns and returns true if the conversion of EXPR to TYPE may alter a value. This is a helper function for warnings_for_convert_and_check. */ -static void +static bool conversion_warning (location_t loc, tree type, tree expr, tree result) { tree expr_type = TREE_TYPE (expr); enum conversion_safety conversion_kind; + bool is_arith = false; if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion) - return; + return false; /* This may happen, because for LHS op= RHS we preevaluate RHS and create C_MAYBE_CONST_EXPR <SAVE_EXPR <RHS>>, which @@ -1195,7 +1196,7 @@ conversion_warning (location_t loc, tree type, tree expr, tree result) if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) warning_at (loc, OPT_Wconversion, "conversion to %qT from boolean expression", type); - return; + return true; case REAL_CST: case INTEGER_CST: @@ -1250,8 +1251,48 @@ conversion_warning (location_t loc, tree type, tree expr, tree result) warning_at (loc, warnopt, "conversion from %qT to %qT changes the value of %qE", expr_type, type, expr); - break; + return true; } + + case PLUS_EXPR: + case MINUS_EXPR: + case MULT_EXPR: + case MAX_EXPR: + case MIN_EXPR: + case TRUNC_MOD_EXPR: + case FLOOR_MOD_EXPR: + case TRUNC_DIV_EXPR: + case FLOOR_DIV_EXPR: + case CEIL_DIV_EXPR: + case EXACT_DIV_EXPR: + case RDIV_EXPR: + { + tree op0 = TREE_OPERAND (expr, 0); + tree op1 = TREE_OPERAND (expr, 1); + if (conversion_warning (loc, type, op0, result) + || conversion_warning (loc, type, op1, result)) + return true; + goto arith_op; + } + + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case LSHIFT_EXPR: + case RSHIFT_EXPR: + case FIX_TRUNC_EXPR: + case NON_LVALUE_EXPR: + case NEGATE_EXPR: + case BIT_NOT_EXPR: + { + /* Unary ops or binary ops for which we only care about the lhs. */ + tree op0 = TREE_OPERAND (expr, 0); + if (conversion_warning (loc, type, op0, result)) + return true; + goto arith_op; + } + case COND_EXPR: { /* In case of COND_EXPR, we do not care about the type of @@ -1259,12 +1300,16 @@ conversion_warning (location_t loc, tree type, tree expr, tree result) tree op1 = TREE_OPERAND (expr, 1); tree op2 = TREE_OPERAND (expr, 2); - conversion_warning (loc, type, op1, result); - conversion_warning (loc, type, op2, result); - return; + return (conversion_warning (loc, type, op1, result) + || conversion_warning (loc, type, op2, result)); } - default: /* 'expr' is not a constant. */ + arith_op: + /* We didn't warn about the operands, we might still want to warn if + -Warith-conversion. */ + is_arith = true; + gcc_fallthrough (); + default: conversion_kind = unsafe_conversion_p (loc, type, expr, result, true); { int warnopt; @@ -1276,6 +1321,11 @@ conversion_warning (location_t loc, tree type, tree expr, tree result) warnopt = OPT_Wconversion; else break; + if (is_arith + && global_dc->option_enabled (warnopt, + global_dc->lang_mask, + global_dc->option_state)) + warnopt = OPT_Warith_conversion; if (conversion_kind == UNSAFE_SIGN) warning_at (loc, warnopt, "conversion to %qT from %qT " "may change the sign of the result", @@ -1288,8 +1338,10 @@ conversion_warning (location_t loc, tree type, tree expr, tree result) warning_at (loc, warnopt, "conversion from %qT to %qT may change value", expr_type, type); + return true; } } + return false; } /* Produce warnings after a conversion. RESULT is the result of diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index aa0fa5d..814ed17 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1107,6 +1107,10 @@ Wshift-negative-value C ObjC C++ ObjC++ Var(warn_shift_negative_value) Init(-1) Warning Warn if left shifting a negative value. +Warith-conversion +C ObjC C++ ObjC++ Var(warn_arith_conv) Warning +Warn if conversion of the result of arithmetic might change the value even though converting the operands cannot. + Wsign-compare C ObjC C++ ObjC++ Var(warn_sign_compare) Warning LangEnabledBy(C++ ObjC++,Wall) Warn about signed-unsigned comparisons. |