So, the pointer arguments of memcpy shall (a violation of a shall clause is UB, per §4/2) have valid values, even though the function will copy zero characters.
So this puts a bound on what LLVM can do, right? However, (also judging
from the other answers) LLVM sometimes guarantees more than C does.
Here's the thread I read about it:
http://lists.llvm.org/pipermail/cfe-dev/2017-January/052066.html . As
I recall, the tl;dr was "optimizing these assumptions to death doesn't
realistically buy us much of anything, and there's a nontrivial amount
of real-world code that depends on this behavior."
Yeah, I recall that thread. The issue is that the current question comes
from Rust whereas the previous discussion was freely mixing C/C++ and
middle-end issues. We need to separate these.
Ah, I wanted to link to that thread but couldn't find it; thanks.
Right, so this is specifically about the llvm intrinsics that Rust uses,
and *not* about the C/C++ frontend.
I propose documenting in the LangRef
Documenting such issues in the LangRef would be great. That's always
the place I go to with corner cases like this, but often I don't find
the answer there either. (Btw, when I come up with such a corner case
-- is there a bugtracker where "please clarify LangRef"-kind of issues
can be submitted to, or is the mailing list the best venue?)
that memcpy and related intrinsics
are defined even when src and dst don't refer to valid storage as long
as the length argument is zero. Then we commit to implementing that
behavior. Is that OK with everyone? If so I can update the doc.
Please also clarify the behavior for NULL or unaligned pointers. (There
seems to be an entire lattice of "validity levels" for a pointer:
Completely broken, non-NULL and/or aligned, as well as aligned and
pointing to valid storage.)
Judging from "memcpy(NULL, _, 0) is okay", I suppose NULL is okay (both
for src and dest), which only leaves open the question of alignment.