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.