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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
          Component|c                           |middle-end
                 CC|                            |msebor at gcc dot gnu.org
         Resolution|---                         |INVALID
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning behaves as designed.  There's no way for it tell from the IL that
the function cannot return the address of x:

  <bb 7> [local count: 375809640]:
  # msg_21 = PHI <"Error w/code"(6), msg_19(10)>
  if (&MEM <char[128]> [(void *)&x + 128B] > msg_21)
    goto <bb 9>; [50.00%]
  else
    goto <bb 8>; [50.00%]

  <bb 8> [local count: 187904820]:

  <bb 9> [local count: 1073741824]:
  # err_3 = PHI <msg_21(8), "Invalid argument"(4), "Error detected"(7), "Error
w/code"(6)>
  x ={v} {CLOBBER};
  return err_3;                              <<< -Wreturn-local-addr

  <bb 10> [local count: 375809641]:
  # msg_19 = PHI <&x.r.text(5), &x.rec(3)>   <<< x is on stack
  __builtin_puts (msg_19);
  goto <bb 7>; [100.00%]

}

As Andrew explained, the pointer relational expression is undefined if msg
points to the string literal (changing it to equality avoids the warning).  In
addition, and arguably more important, GCC's ability to extract useful
information from pointer relationships is quite limited so it doesn't "see
through" the expression.  The underlying problem (and the limitation) can be
reduced to the failure to fold and the false positive for the much simpler test
case below.  For a + n to be valid n must be zero or one, and so the function
must return null.  If GCC used that to fold the function the warning wouldn't
trigger.

With that, I think the report can be resolved as invalid (I'm sure the pointer
range optimization has its own bug.)

$ cat z.c && gcc -O2 -S -Wall -fdump-tree-isolate-paths=/dev/stdout z.c
void* f (int n)
{
  char a[1], *p = a + n;
  if (p <= a + 1)
    p = 0;
  return p;
}

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

z.c: In function ‘f’:
z.c:6:10: warning: function may return address of local variable
[-Wreturn-local-addr]
    6 |   return p;
      |          ^
z.c:3:8: note: declared here
    3 |   char a[1], *p = a + n;
      |        ^

SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j

p_7 -> { p_2 }
.MEM_8 -> { .MEM_6 }
Incremental SSA update started at block: 2
Number of blocks in CFG: 6
Number of blocks to update: 2 ( 33%)


Removing basic block 3
void * f (int n)
{
  char * p;
  char a[1];
  sizetype _1;

  <bb 2> [local count: 1073741824]:
  _1 = (sizetype) n_3(D);
  p_4 = &a + _1;
  if (&MEM <char[1]> [(void *)&a + 1B] >= p_4)
    goto <bb 3>; [100.00%]
  else
    goto <bb 4>; [0.00%]

  <bb 3> [local count: 311385128]:
  # p_2 = PHI <0B(2)>
  a ={v} {CLOBBER};
  return p_2;

  <bb 4> [count: 0]:
  # p_7 = PHI <p_4(2)>
  a ={v} {CLOBBER};
  return 0B;

}

Reply via email to