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

            Bug ID: 93332
           Summary: target-dependent inaccurate range info for some
                    expressions
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

This bug captures the problem behind the test failures reported in bug 92829. 
The test should produce the same warnings in all three compilations but the
warnings depend on the different forms of the expressions that set the ranges
of the integer variables in the test case, and also on the target. 

$ (set -x && cat t.C && for d in ALWAYS_WORKS ALWAYS_FAILS xxx; do
/build/powerpc64le-linux/gcc-git-wt/gcc/xgcc -B
/build/powerpc64le-linux/gcc-git-wt/gcc -D$d -O2 -S -Wall
-ftrack-macro-expansion=0 t.C; done)
+ cat t.C
typedef __SIZE_TYPE__ size_t;

static size_t i;
extern size_t vals[];

static inline size_t r (size_t x, size_t y)
{
  size_t z = vals[i++];
  return z < x || y < z ? x : z;
}

extern "C" char* strcpy (char*, const char*);

void sink (void*);

#define T(src, alloc) do {                      \
    const char *s = src;                        \
    char *d = (char*)alloc;                     \
    strcpy (d, s);                              \
    sink (d);                                   \
  } while (0)

size_t r_1_2, r_2_3;

void f (size_t vals[])
{
#if ALWAYS_WORKS
  // Works on both powerpc64* and x86_64.
  int i = 0;
  size_t r_1_2 = (++i, vals[i] < 1 || 2 < vals[i] ? 1 : vals[i]);
  size_t r_2_3 = (++i, vals[i] < 2 || 3 < vals[i] ? 2 : vals[i]);
#elif ALWAYS_FAILS
  // Second test fails on both powerpc64* and x86_64.
  if (r_1_2 < 1 || 2 < r_1_2) r_1_2 = 1;
  if (r_2_3 < 2 || 3 < r_2_3) r_2_3 = 2;
#else
  // Second test fails only on powerpc64*.
  (void)&vals;
  size_t r_1_2 = r (1, 2);
  size_t r_2_3 = r (2, 3);
#endif

  T ("1234", new short[r_1_2]);     // { dg-warning "\\\[-Wstringop-overflow" }
  T ("12345678", new short[r_2_3]); // { dg-warning "\\\[-Wstringop-overflow" }
}
+ for d in ALWAYS_WORKS ALWAYS_FAILS xxx
+ /build/powerpc64le-linux/gcc-git-wt/gcc/xgcc -B
/build/powerpc64le-linux/gcc-git-wt/gcc -DALWAYS_WORKS -O2 -S -Wall
-ftrack-macro-expansion=0 t.C
t.C: In function 'void f(size_t*)':
t.C:43:3: warning: 'void* __builtin_memcpy(void*, const void*, long unsigned
int)' writing 5 bytes into a region of size between 2 and 4
[-Wstringop-overflow=]
   43 |   T ("1234", new short[r_1_2]);     // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
t.C:43:3: note: at offset 0 to an object with size between 2 and 4 allocated by
'operator new []' here
t.C:44:3: warning: 'void* __builtin_memcpy(void*, const void*, long unsigned
int)' writing 9 bytes into a region of size between 4 and 6
[-Wstringop-overflow=]
   44 |   T ("12345678", new short[r_2_3]); // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
t.C:44:3: note: at offset 0 to an object with size between 4 and 6 allocated by
'operator new []' here
+ for d in ALWAYS_WORKS ALWAYS_FAILS xxx
+ /build/powerpc64le-linux/gcc-git-wt/gcc/xgcc -B
/build/powerpc64le-linux/gcc-git-wt/gcc -DALWAYS_FAILS -O2 -S -Wall
-ftrack-macro-expansion=0 t.C
t.C: In function 'void f(size_t*)':
t.C:43:3: warning: 'void* __builtin_memcpy(void*, const void*, long unsigned
int)' forming offset 4 is out of the bounds [0, 4] [-Warray-bounds]
   43 |   T ("1234", new short[r_1_2]);     // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
+ for d in ALWAYS_WORKS ALWAYS_FAILS xxx
+ /build/powerpc64le-linux/gcc-git-wt/gcc/xgcc -B
/build/powerpc64le-linux/gcc-git-wt/gcc -Dxxx -O2 -S -Wall
-ftrack-macro-expansion=0 t.C
t.C: In function 'void f(size_t*)':
t.C:44:3: warning: 'void* __builtin_memcpy(void*, const void*, long unsigned
int)' writing 9 bytes into a region of size between 4 and 6
[-Wstringop-overflow=]
   44 |   T ("12345678", new short[r_2_3]); // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
t.C:44:3: note: at offset 0 to an object with size between 4 and 6 allocated by
'operator new []' here


The followings shows the output with a native x86_64-linux GCC.  The output
differs from the powerpc64le-linux cross in the third invocation.

$ (set -x && for d in ALWAYS_WORKS ALWAYS_FAILS xxx; do
/build/gcc-git-wt/gcc/xgcc -B /build/gcc-git-wt/gcc -D$d -O2 -S -Wall
-ftrack-macro-expansion=0 t.C; done)
+ for d in ALWAYS_WORKS ALWAYS_FAILS xxx
+ /build/gcc-git-wt/gcc/xgcc -B /build/gcc-git-wt/gcc -DALWAYS_WORKS -O2 -S
-Wall -ftrack-macro-expansion=0 t.C
t.C: In function ‘void f(size_t*)’:
t.C:43:3: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned
int)’ writing 5 bytes into a region of size between 2 and 4
[-Wstringop-overflow=]
   43 |   T ("1234", new short[r_1_2]);     // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
t.C:43:3: note: at offset 0 to an object with size between 2 and 4 allocated by
‘operator new []’ here
t.C:44:3: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned
int)’ writing 9 bytes into a region of size between 4 and 6
[-Wstringop-overflow=]
   44 |   T ("12345678", new short[r_2_3]); // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
t.C:44:3: note: at offset 0 to an object with size between 4 and 6 allocated by
‘operator new []’ here
+ for d in ALWAYS_WORKS ALWAYS_FAILS xxx
+ /build/gcc-git-wt/gcc/xgcc -B /build/gcc-git-wt/gcc -DALWAYS_FAILS -O2 -S
-Wall -ftrack-macro-expansion=0 t.C
t.C: In function ‘void f(size_t*)’:
t.C:43:3: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned
int)’ forming offset 4 is out of the bounds [0, 4] [-Warray-bounds]
   43 |   T ("1234", new short[r_1_2]);     // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
+ for d in ALWAYS_WORKS ALWAYS_FAILS xxx
+ /build/gcc-git-wt/gcc/xgcc -B /build/gcc-git-wt/gcc -Dxxx -O2 -S -Wall
-ftrack-macro-expansion=0 t.C
t.C: In function ‘void f(size_t*)’:
t.C:43:3: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned
int)’ writing 5 bytes into a region of size between 2 and 4
[-Wstringop-overflow=]
   43 |   T ("1234", new short[r_1_2]);     // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
t.C:43:3: note: at offset 0 to an object with size between 2 and 4 allocated by
‘operator new []’ here
t.C:44:3: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned
int)’ writing 9 bytes into a region of size between 4 and 6
[-Wstringop-overflow=]
   44 |   T ("12345678", new short[r_2_3]); // { dg-warning
"\\\[-Wstringop-overflow" }
      |   ^
t.C:44:3: note: at offset 0 to an object with size between 4 and 6 allocated by
‘operator new []’ here

Reply via email to