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