Это действительно нарушает правила строгого сглаживания?

Когда я скомпилирую этот пример кода с помощью g++, я получаю это предупреждение:

предупреждение: разыменованный тип-караульный указатель нарушит правила строгого сглаживания [-Wstrict-aliasing]

Код:

#include <iostream>

int main() 
{
   alignas(int) char data[sizeof(int)];
   int *myInt = new (data) int;
   *myInt = 34;

   std::cout << *reinterpret_cast<int*>(data);
}

В этом случае, не имеет ли data псевдоним int, и поэтому отбрасывание его обратно в int не будет нарушать строгие правила псевдонимов? Или я здесь что-то не хватает?

Изменить: странно, когда я определяю data следующим образом:

alignas(int) char* data = new char[sizeof(int)];

Предупреждение компилятора исчезает. Выделяет ли распределение стека значение со строгим псевдонимом? Означает ли факт, что это a char[], а не char* означает, что он не может на самом деле псевдоним какого-либо типа?

Ответ 1

Предупреждение абсолютно оправдано. Разложившийся указатель на data делает не ссылкой на объект типа int, а его литье не меняет этого. См. [basic.life]/7:

Если после окончания срока службы объекта и до хранения который занятый объект повторно используется или освобождается, новый объект созданный в месте хранения, в котором находился исходный объект, a указатель, указывающий на исходный объект, ссылка, ссылка на которую к исходному объекту, или имя исходного объекта будет автоматически ссылаются на новый объект и, как только время жизни новый объект запущен, может использоваться для управления новым объектом, , если:
(7.1) - [..]
(7.2) - новый объект имеет тот же тип, что и исходный объект (игнорируя cv-квалификаторы верхнего уровня),

Новый объект не является массивом char, а int. P0137, который формализует понятие указания, добавляет launder:

[Примечание: если эти условия не выполняются, указатель на новый объект может быть получен из указателя, который представляет адрес его путем вызова std::launder (18.6 [support.dynamic]). - конечная нота ]

т.е. ваш фрагмент можно исправить следующим образом:

std::cout << *std::launder(reinterpret_cast<int*>(data));

.. или просто инициализируйте новый указатель из результата размещения new, который также удаляет предупреждение.