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

            Bug ID: 101688
           Summary: g++.dg/warn/Wstringop-overflow-4.C fails on x86-32
                    with new jump threader
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: aldyh at gcc dot gnu.org
                CC: msebor at gcc dot gnu.org
  Target Milestone: ---

Created attachment 51223
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51223&action=edit
reduced testcase

FAIL: g++.dg/warn/Wstringop-overflow-4.C  -std=gnu++14 (test for excess errors)
FAIL: g++.dg/warn/Wstringop-overflow-4.C  -std=gnu++17 (test for excess errors)
FAIL: g++.dg/warn/Wstringop-overflow-4.C  -std=gnu++2a (test for excess errors)
FAIL: g++.dg/warn/Wstringop-overflow-4.C  -std=gnu++98 (test for excess errors)

Here are the new warnings:

b.C:129:3: note: destination object of size [4, 6] allocated by ‘operator new
[]’
b.C:148:3: warning: ‘void* __builtin_memcpy(void*, const void*, unsigned int)’
writing 2 bytes into a region of size 0 [-Wstringop-overflow=]
  148 |   T (S (1), new int16_t[r_0_imax]);
      |   ^
b.C:148:3: note: destination object of size 0 allocated by ‘operator new []’
b.C:149:3: warning: ‘void* __builtin_memcpy(void*, const void*, unsigned int)’
writing 3 bytes into a region of size 2 [-Wstringop-overflow=]
  149 |   T (S (2), new int16_t[r_0_imax + 1]);
      |   ^
b.C:149:3: note: destination object of size 2 allocated by ‘operator new []’

What happens is that the new code is threading bb2 -> bb4 -> bb5, and is
presumably confusing the -Wstringop-overflow pass.  The transformation is
correct as can be seen in the sequence below:

  <bb 2> :
  _34 ={v} signed_value_source;
  if (_34 < 0)
    goto <bb 4>; [50.00%]
  else
    goto <bb 3>; [50.00%]

  <bb 3> :

  <bb 4> :
  # iftmp.4_38 = PHI <0(2), _34(3)>
  r_0_imax.1_8 = (sizetype) iftmp.4_38;
  if (r_0_imax.1_8 <= 1073741822)
    goto <bb 5>; [INV]
  else
    goto <bb 6>; [INV]

  <bb 5> :
  iftmp.0_10 = r_0_imax.1_8 * 2;
  _12 = operator new [] (iftmp.0_10);
  __builtin_memcpy (_12, &MEM <const char[37]> [(void
*)"0123456789abcdefghijklmnopqrstuvwxyz" + 35B], 2);
  sink (_12);
  _1 = iftmp.4_38 + 1;
  _17 = (sizetype) _1;
  if (_17 <= 1073741822)
    goto <bb 7>; [INV]
  else
    goto <bb 8>; [INV]

The attached reduced testcase can be reproduced with:

./cc1plus a.ii -fdump-tree-all-details-graph -quiet -I/tmp -O2 -Wall
-Wno-array-bounds -ftrack-macro-expansion=0 -m32

a.ii: In function ‘void test_strcpy_new_int16_t(size_t, const size_t*)’:
a.ii:25:12: warning: ‘void* __builtin_memcpy(void*, const void*, unsigned int)’
writing 2 bytes into a region of size 0 [-Wstringop-overflow=]
   25 |     strcpy (d, s);
      |     ~~~~~~~^~~~~~
a.ii:24:42: note: destination object of size 0 allocated by ‘operator new []’
   24 |     char *d = (char*)new int16_t[r_0_imax]; //blah1
      |                                          ^
a.ii:32:12: warning: ‘void* __builtin_memcpy(void*, const void*, unsigned int)’
writing 3 bytes into a region of size 2 [-Wstringop-overflow=]
   32 |     strcpy (d, s);
      |     ~~~~~~~^~~~~~
a.ii:31:46: note: destination object of size 2 allocated by ‘operator new []’
   31 |     char *d = (char*)new int16_t[r_0_imax + 1]; //blah2
      |                                              ^

Reply via email to