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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2020-02-09
                 CC|                            |msebor at gcc dot gnu.org
          Component|other                       |middle-end
            Summary|-Wreturn-local-addr July    |[10 Regression]
                   |regression: new             |-Wreturn-local-addr July
                   |false-positive warning      |regression: new
                   |                            |false-positive warning
     Ever confirmed|0                           |1

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning is issued because a PHI operand of the the return statement
references another PHI node one of whose operands is yet another PHI node that
includes the local variable stack_buf among its operands:

  <bb 6> [local count: 79230146]:
  # buffer_17 = PHI <&stack_buf(4), buffer_38(D)(5)>
  ...
  <bb 7> [local count: 1073741824]:
  # buf_20 = PHI <buffer_17(6), buf_57(25)>
  ...
  <bb 29> [local count: 79230145]:
  # _25 = PHI <0B(10), buf_20(15), 0B(24), 0B(28), b_63(14), b_61(17), 0B(9),
buf_20(16), buf_20(18)>
  stack_buf ={v} {CLOBBER};
  return _25;

A simplified test case is below.  It warns for the same reason (but with fewer
indirections):

  # buffer_2 = PHI <&stack_buf(2), buffer_7(D)(3)>
  ...
  # _4 = PHI <0B(4), _11(7), 0B(5), buffer_2(6)>
  return _4;


There's no way to tell from the IL in either of these test cases that one of
the final PHI operands cannot point to stack_buf so the warning triggers. 
Short of not considering PHI arguments that are themselves PHIs  and trading
off false positives for false negatives I don't see how to avoid the warning in
this case.


$ cat pr93644.c && gcc -O2 -S -Wall -fdump-tree-isolate-paths=/dev/stdout
pr93644.c
typedef __SIZE_TYPE__ size_t;

char *
careadlinkat (char *buffer, size_t buffer_size)
{
  char stack_buf[1024];
  if (!buffer_size)
    {
      buffer = stack_buf;
      buffer_size = sizeof stack_buf;
    }

  char *buf = buffer;
  size_t buf_size = buffer_size;

  extern int link_length;
  if (link_length < 0)
    return 0;

  size_t link_size = link_length;
  if (link_size < buf_size)
    {
      if (buf == stack_buf)
        return __builtin_malloc (link_size);

      return buf;
    }

  return 0;
}

;; Function careadlinkat (careadlinkat, funcdef_no=0, decl_uid=1932,
cgraph_uid=1, symbol_order=0)

pr93644.c: In function ‘careadlinkat’:
cc1: warning: function may return address of local variable
[-Wreturn-local-addr]
pr93644.c:6:8: note: declared here
    6 |   char stack_buf[1024];
      |        ^~~~~~~~~
careadlinkat (char * buffer, size_t buffer_size)
{
  size_t link_size;
  char stack_buf[1024];
  int link_length.0_1;
  char * _4;
  char * _11;

  <bb 2> [local count: 1073741824]:
  if (buffer_size_6(D) == 0)
    goto <bb 4>; [50.00%]
  else
    goto <bb 3>; [50.00%]

  <bb 3> [local count: 536870912]:

  <bb 4> [local count: 1073741824]:
  # buffer_2 = PHI <&stack_buf(2), buffer_7(D)(3)>
  # buffer_size_3 = PHI <1024(2), buffer_size_6(D)(3)>
  link_length.0_1 = link_length;
  if (link_length.0_1 < 0)
    goto <bb 8>; [12.76%]
  else
    goto <bb 5>; [87.24%]

  <bb 5> [local count: 936732369]:
  link_size_9 = (size_t) link_length.0_1;
  if (buffer_size_3 > link_size_9)
    goto <bb 6>; [71.00%]
  else
    goto <bb 8>; [29.00%]

  <bb 6> [local count: 665079983]:
  if (&stack_buf == buffer_2)
    goto <bb 7>; [17.43%]
  else
    goto <bb 8>; [82.57%]

  <bb 7> [local count: 115923441]:
  _11 = __builtin_malloc (link_size_9);

  <bb 8> [local count: 1073741824]:
  # _4 = PHI <0B(4), _11(7), 0B(5), buffer_2(6)>
  stack_buf ={v} {CLOBBER};
  return _4;

}

Reply via email to