Почему для этого кода не создается строгие предупреждения строгих псевдонимов?
-
26-09-2019 - |
Вопрос
У меня есть следующий код:
struct A
{
short b;
};
struct B
{
double a;
};
void foo (struct B* src)
{
struct B* b = src;
struct A* a = (struct A*)src;
b->a = sin(rand());
if(a->b == rand())
{
printf("Where are you strict aliasing warnings?\n");
}
}
Я составляю код со следующей командной строкой:
gcc -c -std=c99 -Wstrict-aliasing=2 -Wall -fstrict-aliasing -O3 foo.c
Я использую GCC 4.5.0. Я ожидал, что компилятор распечатает предупреждение:
warning: dereferencing type-punned pointer will break strict-aliasing rules
Но это никогда не есть. Я могу получить предупреждение для печати для других случаев, но мне интересно, почему в этом случае это не так. Разве это не очевидный пример нарушения строгих псевдонимов?
Решение
Документы GCC для -Wstrict-aliasing=2
говорит (упор мой):
Уровень 2: агрессивный, быстрый, не слишком точный. Может все еще иметь много ложных срабатываний (не так много, как уровень 1), а также несколько ложных негативов (но, возможно, более уровня 1). Отказ В отличие от уровня 1, он только предупреждает, когда предпринят адрес. Предупреждает о неполных типах. Пробегает только в интерфейсе.
Похоже, ваш код не слишком сложно, поэтому я не уверен, почему там будет ложный негатив, но, возможно, это потому, что вы не используете &
Адрес оператора для выполнения псевдонима (это может быть то, что подразумевается под «только предупреждает, когда взят адрес»)
Обновлять:
Он не использует адрес-оператор. Если я добавлю следующий код в файл foo.c.c:
int usefoo(void)
{
struct B myB = {0};
foo( &myB);
return 0;
}
Предупреждение выдается.
Если usefoo()
находится в отдельном устройстве компиляции, отсутствие предупреждения не выдано.