https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88771
Jeffrey A. Law <law at redhat dot com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |law at redhat dot com --- Comment #21 from Jeffrey A. Law <law at redhat dot com> --- Sorry, but when I look at this, the warning seems correct and valid to me. In the .fre1 dump we have: ;; basic block 2, loop depth 0, maybe hot ;; prev block 0, next block 3, flags: (NEW, VISITED) ;; pred: ENTRY (FALLTHRU,EXECUTABLE) f.1_1 = f; _10 = f.1_1 + 1; if (_10 != 0) goto <bb 3>; [INV] else goto <bb 4>; [INV] ;; succ: 3 (TRUE_VALUE,EXECUTABLE) ;; 4 (FALSE_VALUE,EXECUTABLE) ;; basic block 3, loop depth 0, maybe hot ;; prev block 2, next block 4, flags: (NEW, VISITED) ;; pred: 2 (TRUE_VALUE,EXECUTABLE) iftmp.0_11 = (char) _10; goto <bb 5>; [INV] ;; succ: 5 (FALLTHRU,EXECUTABLE) ;; basic block 4, loop depth 0, maybe hot ;; prev block 3, next block 5, flags: (NEW, VISITED) ;; pred: 2 (FALSE_VALUE,EXECUTABLE) iftmp.0_12 = (char) f.1_1; ;; succ: 5 (FALLTHRU,EXECUTABLE) ;; basic block 5, loop depth 0, maybe hot ;; prev block 4, next block 6, flags: (NEW, VISITED) ;; pred: 3 (FALLTHRU,EXECUTABLE) ;; 4 (FALLTHRU,EXECUTABLE) # iftmp.0_7 = PHI <iftmp.0_11(3), iftmp.0_12(4)> _4 = (long unsigned int) f.1_1; x.4_5 = x; c.5_6 = c; __builtin_strncpy (c.5_6, x.4_5, _4); In particular note the conditional at the end of bb2 and the dataflow when _10 is zero. WHen that occurs we'll go to bb4 and we'll know that f.1_1 must have the value -1. WHich in turn means iftmp_0.12 has the value -1 which flows into the PHI at the start of BB5. We see all this in the .evrp dump: ;; basic block 2, loop depth 0, maybe hot ;; prev block 0, next block 3, flags: (NEW, VISITED) ;; pred: ENTRY (FALLTHRU,EXECUTABLE) f.1_1 = f; _10 = f.1_1 + 1; if (_10 != 0) goto <bb 3>; [INV] else goto <bb 4>; [INV] ;; succ: 3 (TRUE_VALUE,EXECUTABLE) ;; 4 (FALSE_VALUE,EXECUTABLE) ;; basic block 3, loop depth 0, maybe hot ;; prev block 2, next block 4, flags: (NEW, VISITED) ;; pred: 2 (TRUE_VALUE,EXECUTABLE) iftmp.0_11 = (char) _10; ;; succ: 4 (FALLTHRU,EXECUTABLE) ;; basic block 4, loop depth 0, maybe hot ;; prev block 3, next block 5, flags: (NEW, VISITED) ;; pred: 3 (FALLTHRU,EXECUTABLE) ;; 2 (FALSE_VALUE,EXECUTABLE) # iftmp.0_7 = PHI <iftmp.0_11(3), -1(2)> _4 = (long unsigned int) f.1_1; x.4_5 = x; c.5_6 = c; __builtin_strncpy (c.5_6, x.4_5, _4); if (iftmp.0_7 != 0) goto <bb 5>; [INV] else goto <bb 6>; [INV] Jump threading will want to optimize away the test at the end of bb4, so it duplicates bb4 isolating each incoming edge. The duplicate for the edge 2->4 will look like: ;; basic block 6, loop depth 0, count 536870912 (estimated locally), maybe hot ;; prev block 5, next block 1, flags: (NEW, VISITED) ;; pred: 2 [50.0% (guessed)] count:536870912 (estimated locally) (FALSE_VALUE,EXECUTABLE) # _17 = PHI <-1(2)> iftmp.0_18 = (char) _17; _19 = (long unsigned int) f.1_1; x.4_20 = x; c.5_21 = c; __builtin_strncpy (c.5_21, x.4_20, _19); goto <bb 4>; [100.00%] ;; succ: 4 [always (guessed)] count:536870912 (estimated locally) (FALLTHRU) Which is exactly what we want and highlights the error in the original user code. Namely that when f+1 is zero we'll make a totally bogus call to strncpy. Suppressing warnings per Jakub's comment in c#10 would just hide the fact that the user's code is just plain broken. If you find yourself blaming threading for exposing a warning like this, you're barking up the wrong tree Jakub. Threading is just exposing what's already broken in the user's original code and we absolutely do want these warnings.