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

            Bug ID: 102291
           Summary: dubious overflow warning
           Product: gcc
           Version: 11.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: hv at crypt dot org
  Target Milestone: ---

The following code warns with gcc-11.2.0 (but not with 9.2.1-17ubuntu1~18.04.1)
in testera(), but not in testerb() which differs only by the removal of an
assert. I don't understand this, and cannot see what is overflowing.

This is reduced from a report against the UTF8_ACCUMULATE macro in perl source.
This build of gcc was configured as follows (including the error in prefix):
  ../gcc/configure --prefix=/opt/gcc-12 --disable-gcov --disable-multilib
--enable-languages=c --disable-nls --disable-decimal-float


% uname -a
Linux zen2 5.4.0-73-generic #82~18.04.1-Ubuntu SMP Fri Apr 16 15:10:02 UTC 2021
x86_64 x86_64 x86_64 GNU/Linux

% gcc --version | head -1
gcc (GCC) 11.2.0

% cat test.c
/* #include <assert.h> */
extern void __assert_fail (const char *__assertion, const char *__file,
      unsigned int __line, const char *__function)
    __attribute__ ((__nothrow__ , __leaf__))
            __attribute__ ((__noreturn__));
#define assert(expr)                          \
  ((void) sizeof ((expr) ? 1 : 0), __extension__ ({         \
      if (expr)                             \
        ; /* empty */                           \
      else                              \
        __assert_fail (#expr, __FILE__, __LINE__, __ASSERT_FUNCTION);   \
    }))
#define __ASSERT_FUNCTION    __extension__ __PRETTY_FUNCTION__
/* end assert.h */

typedef unsigned long ulong;
typedef unsigned char uchar;

#define FIT8(c) assert(((sizeof(c) == 1) || (((ulong) (c)) >> 8) == 0))
#define BE8a(c) (FIT8(c), ((uchar) (c)))
#define BE8b(c) (         ((uchar) (c)))
#define NUM(c) ((c) | 0)

#define TESTER(old, new) ((((ulong)(old)) << 6) | (((uchar) NUM(new)) & 0x3f))

ulong testera(ulong ul) {
    return TESTER(ul, BE8a(0x80));
}

ulong testerb(ulong ul) {
    return TESTER(ul, BE8b(0x80));
}

% gcc -c test.c 
test.c: In function 'testera':
test.c:24:49: warning: overflow in conversion from 'int' to 'long unsigned int'
changes value from '((((void)4, (({...}))), 128)) & 63' to '0' [-Woverflow]
   24 | #define TESTERa(old, new) ((((ulong)(old)) << 6) | (((uchar) NUM(new))
& 0x3f))
      |                                                  ^
test.c:27:12: note: in expansion of macro 'TESTERa'
   27 |     return TESTERa(ul, BE8a(0x80));
      |            ^~~~~~~
%

Reply via email to