On Mon, 18 Sept 2023, 08:03 Paul Floyd via Gcc, <gcc@gcc.gnu.org> wrote:
> > > On 17-09-23 22:51, Jonathan Wakely wrote: > > > > > Why would it be trapping? It's loading an int64_t, which might be > > uninitialised but it can't trap. > > In this context I think that Valgrind is considering that any memory > load could trap. > There are no padding bits in int64_t and all object representations are valid values, so it has no trap representations. > > *f on a std::optional is not like dereferencing a pointer, the int64_t > > memory location is always present as part of the object. > > For this > > movq 40(%rbx), %rax > > unless you know that what RBX+40 is pointing to is safe to dereference > it's not different to dereferencing a pointer. > If it isn't safe to load that integer then it isn't safe to call f.operator bool() either. GCC knows they are part of the same object. > So I think that the problem is that Valgrind is being cautious and not > allowing any loads but GCC is accepting what it considers safe loads > from the stack. > Yes, GCC assumes that the reference is bound to a valid object, because C++ requires that to be true. Of course memcheck can't assume that, because one of its main reasons to exist is to find undefined behaviour where that isn't true! I think what GCC is doing is a valid transformation, in the context of a valid C++ program. But I'm not sure that helps valgrind, which doesn't have the liberty of assuming a valid program.