void foo(bar_t* p)
baz_t* q = &p->baz;
I suspect this is a recurring source of vociferous opponents of allowing any information to be used for optimization, regardless of how much compilers promise that this time is totally different and they'll definitely actually check that it's correct before using it.
Firstly, that's not (in general) true, unless you count denial of service as a vulnerability; reading from address zero and then panicking has the same security implications as segfaulting while trying to read, namely the software immediately halting.
More importantly, the above code does not dereference p (at all, though do_stuff presumably does). `&p->baz` adds a constant offset to the (register storing the) pointer, without touching memory at all. There is no vulnerability (assuming the obvious assumptions about how foo and do_stuff work and are used) until the compiler introduces one.
0: For example, you count the fact that someone can DDOS the machine it's running on as a vulnerability in any network software. Which is somewhat resonable in some contexts, but not the context of compiler bugs.
It is extremely common -- i.e., absolutely normal -- to write code after an assertion that would be UB if the assertion were false. Any worry about eliding checks should apply even moreso to all that UB code. But people who hate optimization based on assertions have implicitly chosen to ignore all the UB, and concentrate only on the elided checks.
It's like complaining you don't have a parachute when you know the doors couldn't be opened anyway.
In a language that doesn't seem to have UB, those worries might seem less. But every substantial library makes its own versions of UB that, while they may have less drastic effects on the runtime consistency of the process, equally impact the coherent behavior of the program.