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;
}