On Mon, Sep 08, 2025 at 01:22:17PM +0100, Iain Sandoe wrote: > For the testcase attached to the patch. > > Do we consider that the addition to x is considered observable?
I don't think so, it isn't any kind of barrier for moving statements around in either direction. I think a non-const/pure call (with the exception of some builtins where we know what they are doing) where we don't know what the body does is (or should be, anything else would be a bug). Because such a call can exit or say throw (unless marked nothrow and if it doesn't need to run anything on throw locally, there wouldn't be an edge for it) or loop forever and in all those cases, valid program with UB after that point shouldn't observe the UB earlier. So I think std::observable_checkpoint() needs to be handled as a barrier for such movements. const/pure calls (except for looping ones?) can be CSEd or removed entirely, so don't act as such barriers. > we can also have things like > > char *p = something; > if (p == nullptr) > { > __builtin_printf (“bad pointer\n”); > __builtin_abort (); > } > > …. > some UB…. > > which gets reduced to an unconditional print and abort. > (I agree that this is allowed, but it is unexpected to many users) > that kind of check can also be guarded. I don't think we do such optimizations. We do optimize char *p = something; *p = 1; // or read from it if (p == nullptr) // into if (false) or I think even char *p = something; int a = 0; if (p == nullptr) // into if (false) a++; *p = 1; but shouldn't be doing it exactly if there is some call that could not return or loop forever that would make the change observable. Jakub