https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100256
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Resolution|--- |WONTFIX Status|UNCONFIRMED |RESOLVED --- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- I can reproduce the warning (at -O2 and -O3) but I don't see it as a bug in GCC. A slightly simplified test case below. Using unsigned int for the size avoids the warning but using size_t brings it back again. The function is undefined when called with (n < 0 || n >= __INT_MAX__ / 2) (or j_degree in the original test case) and asserting that's not the case makes the warning go away and results in better code: if (n < 0 || n >= __INT_MAX__ / 2) __builtin_unreachable (); I suppose a possible improvement here that would avoid the warning is to teach GCC to derive the same precondition based on the absence of the undefined behavior and emit more optimal code. But that's orthogonal to the warning itself. The only thing I find puzzling is that the range for the memset() bound in the strlen dump (where the warning comes from) looks valid and would not trigger the warning but the one returned from vr_values::range_of_expr () the warning actually uses doesn't seem right:But the range returned from vr_values::range_of_expr () is: ;; basic block 12, loop depth 0, count 59461674 (estimated locally), maybe hot ;; prev block 11, next block 13, flags: (NEW, REACHABLE, VISITED) ;; pred: 8 [always] count:59055800 (estimated locally) (FALLTHRU,EXECUTABLE) ;; 5 [always] count:405874 (estimated locally) (FALLTHRU,EXECUTABLE) # .MEM_21 = PHI <.MEM_31(8), .MEM_40(5)> # VUSE <.MEM_21> return; ;; succ: EXIT [always] count:59461674 (estimated locally) (EXECUTABLE) ;; basic block 13, loop depth 0, count 52559662 (estimated locally), maybe hot ;; Invalid sum of incoming counts 55785408 (estimated locally), should be 52559662 (estimated locally) ;; prev block 12, next block 1, flags: (NEW, REACHABLE, VISITED) ;; pred: 6 [5.5% (guessed)] count:55785408 (estimated locally) (FALSE_VALUE,EXECUTABLE) # RANGE [0, 2147483647] NONZERO 2147483646 _12 = n_25(D) * 2; # RANGE [1, 2147483647] NONZERO 2147483647 _42 = _12 + 1; # RANGE [1, 2147483647] NONZERO 2147483647 _11 = (sizetype) _42; # RANGE [4, 8589934588] NONZERO 8589934588 _13 = _11 * 4; # .MEM_41 = VDEF <.MEM_38> # PT = { D.1985 } # ALIGN = 4, MISALIGN = 0 # USE = nonlocal { D.1983 } (escaped, escaped heap) # CLB = nonlocal { D.1983 } (escaped, escaped heap) a.0_43 = __builtin_alloca_with_alignD.1906 (_13, 32); # .MEM_45 = VDEF <.MEM_41> # USE = nonlocal { D.1983 } (escaped, escaped heap) # CLB = nonlocal { D.1983 } (escaped, escaped heap) memsetD.897 (a.0_43, 0, _13); goto <bb 9>; [100.00%] ;; succ: 9 [always] count:52559662 (estimated locally) (FALLTHRU,EXECUTABLE) } (gdb) p rng $22 = VR_RANGE (gdb) p debug_tree(vr.min()) <integer_cst 0x7fffea95f440 type <integer_type 0x7fffea80f000 sizetype> constant 18446744065119617028> $23 = void (gdb) p debug_tree(vr.max()) <integer_cst 0x7fffea939fa0 type <integer_type 0x7fffea80f000 sizetype> constant 18446744073709551612> $24 = void (gdb) The slightly reduced test case: $ cat pr100256.c && gcc -O2 -S -Wall pr100256.c void f (int n, int *q, int **p) { for (int i = 0; i < n + 1; i++) if (!(p[i] = __builtin_calloc (n + 1, sizeof (int)))) return; int a[n * 2 + 1]; __builtin_memset (a, 0, sizeof a); for (int i = 0; i < n * 2 + 1; i++) { a[i]++; if (i < n + 1) q[i]++; } } pr100256.c: In function ‘f’: pr100256.c:9:3: warning: ‘__builtin_memset’ writing between 18446744065119617028 and 18446744073709551612 bytes into a region of size 9223372036854775807 [-Wstringop-overflow=] 9 | __builtin_memset (a, 0, sizeof a); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pr100256.c:7:7: note: destination object ‘a’ of size 9223372036854775807 7 | int a[n * 2 + 1]; | ^