https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83642
Bug ID: 83642 Summary: excessive strlen range after a strcat of non-empty string Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: enhancement Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- The test case below (derived from bug 83640, comment #4) highlights a possible optimization opportunity in the strlen pass. So that the difference between pointers to the first and just past the last byte of any array must be at most PTRDIFF_MAX bytes the size of the largest array is PTRDIFF_MAX bytes. Since the length of the string literal appended to the DST array by the first strcat call below is known to be 2, then length of the DST string must be less than PTRDIFF_MAX - 2. Therefore the test can be assumed to never evaluate to true and the call to abort can be eliminated. $ cat a.c && gcc -O2 -S -fdump-tree-vrp=/dev/stdout a.c char *foo (void); void bar (char *dst, char *src) { __SIZE_TYPE__ n = __builtin_strlen (dst); __builtin_strcat (dst, "*/"); // implies n < PTRDIFF_MAX - 3 __builtin_strcat (dst, src); if (n >= __PTRDIFF_MAX__ - 2) // must be false __builtin_abort (); // can be eliminated } ... Value ranges after VRP: dst_2(D): VARYING n_3: [0, 9223372036854775806] _4: VARYING _9: [2, 9223372036854775808] _10: VARYING dst_11: ~[0B, 0B] EQUIVALENCES: { dst_2(D) } (1 elements) bar (char * dst, char * src) { long unsigned int n; char * _4; long unsigned int _9; char * _10; <bb 2> [local count: 1073741825]: n_3 = __builtin_strlen (dst_2(D)); _4 = dst_2(D) + n_3; __builtin_memcpy (_4, "*/", 2); _9 = n_3 + 2; _10 = dst_2(D) + _9; __builtin_strcpy (_10, src_6(D)); if (n_3 > 9223372036854775804) goto <bb 3>; [0.00%] else goto <bb 4>; [99.96%] <bb 3> [count: 0]: __builtin_abort (); <bb 4> [local count: 1073312327]: return; }