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

            Bug ID: 104215
           Summary: bogus -Wuse-after-free=3 due to forwprop moving a
                    pointer test after realloc
           Product: gcc
           Version: 12.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 is to make a record of the false positive.  I don't expect GCC to avoid
reordering the statements.  I don't see a way to avoid the warning except to
suppress it when it's moved (the statement is moved in forwprop1).

As discussed in the libc-alpha thread at
https://sourceware.org/pipermail/libc-alpha/2022-January/135586.html, at level
3 the new -Wuse-after-free warning complains about the integer variable in the
controlling expression of the if statement below,  The IL explains why: GCC
moves the variable's definition after the realloc call.  Since the defintion
uses the pointer made invalid by the call the warning triggers as designed.

$ cat a.c && gcc -O1 -S -Wall -fdump-tree-waccess3=/dev/stdout
-Wuse-after-free=3 a.c
void *p, *q;

void f (void)
{
  int c = p == q;
  void *r = __builtin_realloc (q, 7);
  if (!r)
    return;

  if (!c)   // <<< -Wuse-after-free=3
    __builtin_memcpy (r, p, 3);

  q = p = r;
}

;; Function f (f, funcdef_no=0, decl_uid=1981, cgraph_uid=1, symbol_order=2)

a.c: In function ‘f’:
a.c:10:6: warning: pointer may be used after ‘__builtin_realloc’
[-Wuse-after-free]
   10 |   if (!c)   // <<< -Wuse-after-free=3
      |      ^
a.c:6:13: note: call to ‘__builtin_realloc’ here
    6 |   void *r = __builtin_realloc (q, 7);
      |             ^~~~~~~~~~~~~~~~~~~~~~~~
pointer_query counters:
  index cache size:   17
  index entries:      1
  access cache size:  2
  access entries:     1
  hits:               0
  misses:             11
  failures:           0
  max_depth:          1
void f ()
{
  void * r;
  void * p.0_1;
  void * q.1_2;
  void * p.3_3;

  <bb 2> [local count: 1073741824]:
  p.0_1 = p;
  q.1_2 = q;
  r_8 = __builtin_realloc (q.1_2, 7);
  if (r_8 == 0B)
    goto <bb 6>; [0.04%]
  else
    goto <bb 3>; [99.96%]

  <bb 3> [local count: 1073312329]:
  if (p.0_1 != q.1_2)                        <<< -Wuse-after-free=3
    goto <bb 4>; [53.47%]
  else
    goto <bb 5>; [46.53%]

  <bb 4> [local count: 573900101]:
  p.3_3 = p;
  __builtin_memcpy (r_8, p.3_3, 3);

  <bb 5> [local count: 1073312329]:
  p = r_8;
  q = r_8;

  <bb 6> [local count: 1073741824]:
  return;

}

Reply via email to