@The real problem(s)
>"The first, and most critical problem, is a bug in GCC, where it optimizes away null pointer checks in some cases where it should be giving a fatal compile time error."
It's not a bug. It is an explicitly documented feature in the manual, which also warns you to take care with it:
> >" `-fdelete-null-pointer-checks'
> >Assume that programs cannot safely dereference null pointers, and that no code or data element resides there. This enables simple constant folding optimizations at all optimization levels. In addition, other optimization passes in GCC use this flag to control global dataflow analyses that eliminate useless checks for null pointers; these assume that if a pointer is checked after it has already been dereferenced, it cannot be null.
> >Note however that in some environments this assumption is not true. Use `-fno-delete-null-pointer-checks' to disable this optimization for programs which depend on that behavior.
> >Some targets, especially embedded ones, disable this option at all levels. Otherwise it is enabled at all levels: `-O0', `-O1', `-O2', `-O3', `-Os'. Passes that use the information are enabled independently at different optimization levels. "
>"That's right. I'm saying GCC should bomb on this code, complaining that the pointer is used before the null pointer check."
I'm saying that when the user explicitly tells GCC to assume that it can do this, GCC should assume that it can do this, and if it is not true, the user should not have told lies to the compiler, and the compiler should do what the user tells it. Maybe you *want* to get a SEGV if the pointer is NULL because you plan to handle that elsewhere? The compiler can't second guess you. You told it that control flow cannot possibly reach that test if the pointer is NULL; it would be stupid of the compiler to bother inserting it.
>"Note: I think GCC can safely optimize away redundant null pointer checks - and I've certainly seen code that has those. But optimizing away a null pointer check simply because it's already seen broken code is stupid."
It's not stupid. The vast majority of these checks are not going to come from buggy code like this, but from places where any/and/or/all of macro expansion, inlining and templating have combined to generate inefficient code. If the compiler wasn't very aggressive with optimising this stuff, C++ templates would still be the hideous bloated monstrosities they used to be back in the 90s - i.e. practically unusable in anything that has to be the least bit efficient.
You can argue about whether this is a "dangerous optimisation", and should only go in -O3 by default (I might agree with you), or whether it shouldn't be turned on by default at all but always left to the user to request (I'd probably disagree), and you can argue that it should generate a warning (I'd certainly agree with you, but I might consider that sufficient reason to leave it enabled at lower -O levels), but calling it "stupid" is simplistic and lacks insight into the issues. As I think I mentioned once before, GCC is a general purpose tool that must work for a huge range of different applications from small realtime embedded to overnight number crunching batch jobs. No single set of optimisations is ever going to be completely right for all those applications, and the -O levels are crude guidelines, but if you have a very specialised need, you need to take control of how you use your compiler.