Bug 107116 - -Woverflow false alarm in unreachable code
Summary: -Woverflow false alarm in unreachable code
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 12.2.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2022-10-01 22:09 UTC by Paul Eggert
Modified: 2024-01-09 23:47 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Paul Eggert 2022-10-01 22:09:17 UTC
This bug is following up on a bug reported against coreutils <https://bugs.gnu.org/58163>. In the coreutils bug report, a build failed because of a false alarm generated by GCC. I simplified the source and came up with two different GCC test cases, shown in the shell transcript below. I generated this transcript on Fedora 36 x86-64, which has gcc (GCC) 12.2.1 20220819 (Red Hat 12.2.1-2).

In the first (shorter) test case v.i, gcc -O2 -Woverflow incorrectly complains about INT_MAX + 1900 in code that is unreachable because YEAR must be both negative and nonnegative to reach the expression, which is impossible.

The second (longer) test case t.c has the same false alarm; I'm including it mostly to give you a feel for the false alarm's context in coreutils, which is even more complicated than the second test case.


$ cat v.i
enum { INT_MAX = 0x7fffffff };
_Bool
to_tm_year (long year)
{
  return
    (year < 0
     && (year < 0
	 ? year + 1900 < 0
	 : INT_MAX + 1900 < year));
}
$ gcc -O2 -S -Woverflow v.i
v.i: In function ‘to_tm_year’:
v.i:9:20: warning: integer overflow in expression of type ‘int’ results in ‘-2147481749’ [-Woverflow]
    9 |          : INT_MAX + 1900 < year));
      |                    ^
$ cat t.c
enum { INT_MAX = 0x7fffffff, INT_MIN = -1 - INT_MAX };
#define _GL_INT_CONVERT(e, v) ((1 ? 0 : (e)) + (v))
#define _GL_INT_NEGATE_CONVERT(e, v) ((1 ? 0 : (e)) - (v))
#define _GL_EXPR_SIGNED(e) (_GL_INT_NEGATE_CONVERT (e, 1) < 0)
#define _GL_INT_SUBTRACT_RANGE_OVERFLOW(a, b, tmin, tmax) \
  (((a) < 0) == ((b) < 0) \
   ? ((a) < (b) \
      ? !(tmin) || -1 - (tmin) < (b) - (a) - 1 \
      : (tmax) < (a) - (b)) \
   : (a) < 0 \
   ? ((!_GL_EXPR_SIGNED (_GL_INT_CONVERT ((a) - (tmin), b)) && (a) - (tmin) < 0) \
      || (a) - (tmin) < (b)) \
   : ((! (_GL_EXPR_SIGNED (_GL_INT_CONVERT (tmax, b)) \
          && _GL_EXPR_SIGNED (_GL_INT_CONVERT ((tmax) + (b), a))) \
       && (tmax) <= -1 - (b)) \
      || (tmax) + (b) < (a)))
#define _GL_INT_OP_WRAPV_VIA_UNSIGNED(a, b, op, ut, t) \
  ((t) ((ut) (a) op (ut) (b)))
#define _GL_INT_OP_CALC(a, b, r, op, overflow, ut, t, tmin, tmax) \
  (overflow (a, b, tmin, tmax) \
   ? (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 1) \
   : (*(r) = _GL_INT_OP_WRAPV_VIA_UNSIGNED (a, b, op, ut, t), 0))
#define _GL_INT_OP_WRAPV(a, b, r, op, overflow) \
       _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
                        int, INT_MIN, INT_MAX)
#define _GL_INT_SUBTRACT_WRAPV(a, b, r) \
   _GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW)
#define INT_SUBTRACT_WRAPV(a, b, r) _GL_INT_SUBTRACT_WRAPV (a, b, r)

_Bool
year_out_of_range (long year)
{
  int i;
  return INT_SUBTRACT_WRAPV (year, 1900, &i);
}
$ gcc -O2 -S -Woverflow t.c
t.c: In function ‘year_out_of_range’:
t.c:16:17: warning: integer overflow in expression of type ‘int’ results in ‘-2147481749’ [-Woverflow]
   16 |       || (tmax) + (b) < (a)))
      |                 ^
t.c:20:4: note: in expansion of macro ‘_GL_INT_SUBTRACT_RANGE_OVERFLOW’
   20 |   (overflow (a, b, tmin, tmax) \
      |    ^~~~~~~~
t.c:24:8: note: in expansion of macro ‘_GL_INT_OP_CALC’
   24 |        _GL_INT_OP_CALC (a, b, r, op, overflow, unsigned int, \
      |        ^~~~~~~~~~~~~~~
t.c:27:4: note: in expansion of macro ‘_GL_INT_OP_WRAPV’
   27 |    _GL_INT_OP_WRAPV (a, b, r, -, _GL_INT_SUBTRACT_RANGE_OVERFLOW)
      |    ^~~~~~~~~~~~~~~~
t.c:28:37: note: in expansion of macro ‘_GL_INT_SUBTRACT_WRAPV’
   28 | #define INT_SUBTRACT_WRAPV(a, b, r) _GL_INT_SUBTRACT_WRAPV (a, b, r)
      |                                     ^~~~~~~~~~~~~~~~~~~~~~
t.c:34:10: note: in expansion of macro ‘INT_SUBTRACT_WRAPV’
   34 |   return INT_SUBTRACT_WRAPV (year, 1900, &i);
      |          ^~~~~~~~~~~~~~~~~~
$
Comment 1 Andrew Pinski 2022-10-01 22:13:35 UTC
I thought there was a much older duplicate of this bug but I can't find it right now.
When I saw older I mean under 1000.