[Bug c/95141] [8/9/10/11 Regression] Incorrect integer overflow warning message for bitand expression

rguenth at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Mon May 18 13:28:01 GMT 2020


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95141

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #2)
> So there's already (OVF) at
> 
> ((long unsigned int) IA1 & 158(OVF)) & 1
> 
> but we only check
> 
> 375           if (TREE_OVERFLOW_P (ret)
> 376               && !TREE_OVERFLOW_P (op0)
> 377               && !TREE_OVERFLOW_P (op1))
> 378             overflow_warning (EXPR_LOC_OR_LOC (expr, input_location),
> ret, expr);
> 
> which doesn't catch the pre-existing overflow on op0 which then propagates.
> 
> The original overflow is introduced folding short 158 to signed char -98(OVF)
> via convert.c:do_narrow:
> 
> 437           /* We should do away with all this once we have a proper
> 438              type promotion/demotion pass, see PR45397.  */
> 439           expr = maybe_fold_build2_loc (dofold, loc, ex_form, typex,
> 440                                         convert (typex, arg0),
> 441                                         convert (typex, arg1));
> 
> specifically the convert (typex, arg1).
> 
> Now TREE_OVERFLOW in general is quite a fragile thing, but it's tempting to
> adjust the overflow_warning guard for this case ...
> 
> The do_narrow code also specifically looks for overflow cases that matter
> and does not perform narrowing then so clearing TREE_OVERFLOW there would
> also look reasonable.
> 
> Thus like the following?  Should be cheaper than adding walk_tree to the
> diagnostic guard.
> 
> diff --git a/gcc/convert.c b/gcc/convert.c
> index 42509c518a9..ed00ded1a89 100644
> --- a/gcc/convert.c
> +++ b/gcc/convert.c
> @@ -436,9 +436,16 @@ do_narrow (location_t loc,
>         }
>        /* We should do away with all this once we have a proper
>          type promotion/demotion pass, see PR45397.  */
> +      /* Above we checked for all cases where overflow matters, avoid
> +        geneating overflowed constants here which otherwise propagate
> +        and cause spurious warnings, see PR95141.  */
> +      tree converted_arg1 = convert (typex, arg1);
> +      if (TREE_OVERFLOW_P (converted_arg1)
> +         && !TREE_OVERFLOW_P (arg1))
> +       converted_arg1 = drop_tree_overflow (converted_arg1);
>        expr = maybe_fold_build2_loc (dofold, loc, ex_form, typex,
>                                     convert (typex, arg0),
> -                                   convert (typex, arg1));
> +                                   converted_arg1);
>        return convert (type, expr);
>      }

Regresses

FAIL: gcc.dg/overflow-warn-5.c  (test for warnings, line 6)

which looks like a useful warning to preserve.  Lame "walk-tree" variant
catching this case:

diff --git a/gcc/c/c-fold.c b/gcc/c/c-fold.c
index 63becfeaf2c..bd21d247051 100644
--- a/gcc/c/c-fold.c
+++ b/gcc/c/c-fold.c
@@ -374,6 +374,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool
*maybe_const_operands,
        ret = fold (expr);
       if (TREE_OVERFLOW_P (ret)
          && !TREE_OVERFLOW_P (op0)
+         && !(BINARY_CLASS_P (op0) && TREE_OVERFLOW_P (TREE_OPERAND (op0, 1)))
          && !TREE_OVERFLOW_P (op1))
        overflow_warning (EXPR_LOC_OR_LOC (expr, input_location), ret, expr);
       if (code == LSHIFT_EXPR


More information about the Gcc-bugs mailing list