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