class Widget
{
public:
Widget() {
cout<<\"~Widget()\"<
First of all, this can really be simplified down to delete (Widget*)0 - everything else in your main() is unnecessary to repro this.
It's a code generation artefact that happens because 1) user-defined operator delete must be able to handle NULL values, and 2) compiler tries to generate the most optimal code possible.
First let's consider the case when no user-defined destructor is involved. If that's the case, there's no code to run on the instance, except for operator delete. There's no point in checking for null before transferring control to operator delete, because the latter should do a check anyway; and so the compiler just generates unconditional call of operator delete (and you see the latter print a message).
Now the second case - destructor was defined. This means that your delete statement actually expands into two calls - destructor, and operator delete. But destructor cannot be safely called on a null pointer, because it could try to access class fields (the compiler could figure out that your particular destructor doesn't really do it and so is safe to call with null this, but looks like they don't bother in practice). So it inserts a null check in there before the destructor call. And once the check is already there, it might as well use it skip the call to operator delete, too - after all it's required to be a no-op anyway, and it will spare an extra meaningless check for null inside operator delete itself in case the pointer actually is null.
So far as I can see, nothing in this is in any way guaranteed by ISO C++ spec. It's just that both compilers do the same optimization here.