https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103483
Jason Merrill <jason at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jason at gcc dot gnu.org See Also| |https://gcc.gnu.org/bugzill | |a/show_bug.cgi?id=102958 --- Comment #12 from Jason Merrill <jason at gcc dot gnu.org> --- (In reply to Martin Sebor from comment #3) > GCC 11 doesn't warn because it's unable to determine the range of the last > memcpy() argument. Thanks to the Ranger improvements GCC 12 is able to do > better. In some cases this should improve the S/N ratio of the middle end > diagnostics that depend on ranges. Unfortunately, in others like this one > where other optimizations are disabled it can make things worse. It seems to me that if we don't warn when we have no information about the range of the argument, we also shouldn't warn when we have only path-dependent information about the range of the argument. The testcase in comment #0 is definitely dubious for using an unbounded int d to index into a bounded array, so let's consider a more reasonable C testcase derived from PR102958 for which there is no missed-optimization issue. char *sink; /* Definitions unavailable to optimization. */ int secret_strlen (const char *p); void secret_memcpy (char *, const char *, int); inline void copy(const char *p) { int L = secret_strlen (p); if (L < 16) /* disabling this branch prevents the warning */ secret_memcpy (sink, p, L); else __builtin_memcpy (sink, p, L); } void f() { copy ("12"); // bogus warning } At the __builtin_memcpy we have a constant string "12" and an unknown length L, and we try to copy L bytes of the constant string into a buffer. We do this in different ways depending on whether L is less than 16; on the latter path we __builtin_memcpy L bytes from the constant string into the buffer. And so -Wstringop-overread warns that we're reading 16 or more bytes from a 3-byte string. But we still have no basis for concluding that L is actually >= 16, we don't know its value at all. That this path is only taken for L >= 16 doesn't tell us whether it's actually possible that L >= 16; we can't assume that just because we don't know the value of len, it could therefore have any value, and so all branches are reachable for a specific string argument. We're able to propagate one constant value, and warning because an unknown value might be incompatible with the known value. And with the recent changes we're able to do more of this asymmetric constant propagation. Perhaps it would be useful to have an optional mode for these (and other) warnings that does assume that all branches are reachable, but it can't be the default. -Wmaybe-stringop-overread? -Wstringop-overread=maybe? My testcase above has given a false positive since GCC 8. I'm nervous about people adding __builtin_unreachables to suppress these warnings; forced assumptions can be big foot-guns.