Код для void* корректен т.к. тип void** приводится к void*.
Код int* p = (int*) &p; сам по себе корректен, т.к. хотя &p имеет тип int**, но его можно привести к int* через reinterpret_cast (C-style cast в данном случае).
Однако разыменовывать p нельзя, т.к. это будет нарушением правил alising'а: p фактически указывает на объект с типом int*, а выражение *p трактует этот объект как int.
(И конечно же результат такого reinterpret_cast нельзя разыменовать из за правил самого reinterpret_cast, но вопрос был про aliasing.)
strict aliasingпоэтому засомневался. Хотя сам не вижу его. – Vladimir Gamalyan Aug 15 '16 at 14:31