Well, first off, it's not valid as it invokes undefined behavior. You are really asking why the compiler allows it, and the answer is because that is boneheaded code that simply won't occur in a real application, so why bother? The real problem comes when the pointer is made invalid at runtime in a way that cannot be anticipated by static code analysis.
The compiler is not there to hold your hand, it is there to compile your code according to the standard. If it offers useful warnings then great, but there is nothing syntactically or semantically illegal there, you are simply writing code which causes undefined behavior.