Как избежать недопустимого предупреждения из-за ошибки компилятора?

Вырезанный воспроизводимый тестовый пример, для обновления VS2015 2, следующий. Мы пытались построить с "Уровнем предупреждения 4", и мы рассматриваем предупреждения как фатальные ошибки, чтобы улучшить шансы заметить указанные предупреждения. Я надеюсь, что кто-то из сообщества уже столкнулся с этим и нашел разумное решение.

Это может оказаться слишком локализованным, если никто другой не видел эквивалентную проблему, поэтому я хотел бы отметить, что основной вопрос заключается в том, "как плохо следует калечить кодовую базу, чтобы избежать слабых предупреждений компилятора" или, что то же самое, как следует сообщать об ошибках компилятору, который теряет отчеты об ошибках ".

#ifdef _WIN32
#pragma warning( push )
#pragma warning( disable : 4702 ) // As suggested by comments
#endif
template <class Type>
void func (Type t)
{
    t.func ();
    t.func ();
}
#ifdef _WIN32
#pragma warning( pop )
#endif

struct NoThrow
{
    void func () {}
};

struct Throws
{
    void func () {throw 1;}
};

int main ()
{
    NoThrow nt;
    func (nt);

    Throws t;
    func (t);
}

Это вызывает недопустимые предупреждения кода. Шаблонная функция выглядит разумной сама по себе, но для одного конкретного экземпляра компилятор может определить, что второй t.func() мертв, поэтому он предупреждает о недоступном коде.

Это похоже на довольно четкое качество выполнения проблемы для VS2015, поэтому мы открыли отчет об ошибке здесь.

Мы получили некоторые рекомендации от Microsoft,

К сожалению, бэкэнд компилятора (откуда возникло это предупреждение) не имеет реальной концепции создания экземпляров шаблонов в качестве экземпляров одной функции шаблона. Они все просто функции с похожими именами, если они когда-либо потрудились сравнить (украшенные) имена друг с другом. Который никогда не делает. Таким образом, он видит здесь одну функцию с некоторым недостижимым кодом, о котором он предупреждает, и другую функцию без недостижимого кода, чего нет. Эта концепция "предупреждения о перекрестных функциях", которую вы предлагаете, где мы собираем и сравниваем данные по различным установкам шаблонов и только предупреждаем, что это или нет, является чрезвычайно сложным в чистом двоичном коде LTCG и невозможным в противном случае.

Рассмотрим шаблон Foo в заголовке foo.h. Предположим, что a.cpp включает в себя и создает Foo с недостижимым кодом, а затем b.cpp включает его и создает Foo без недостижимого кода. Вы предполагаете, что в a.cpp Foo не следует предупреждать, удалите недостижимый код, потому что Foo существует без недостижимого кода. Но Foo скомпилирован в другом файле, в другом процессе, в другом вызове cl.exe и наиболее неудобно в будущем. Очевидно, что компилятор не имеет возможности достичь в будущем еще нерожденного процесса и извлекать информацию, необходимую для расчета, если он должен предупреждать или нет.

Единственный реальный жизнеспособный вариант, который мы имеем здесь, заключается в том, чтобы отключить недопустимое предупреждение для всех шаблонов, которое я буду честным, не произойдет, пока мы не убедимся, что нанесенный вред больше, чем хорошее (это чистая плохая). Предупреждения имеют ложные срабатывания, это происходит. Я попытаюсь подумать о других параметрах и посмотреть номер строки/файла.

Вышеуказанная ссылка может быть недоступна, но поскольку Интернет поставляется с кешами, вы можете увидеть копию здесь или найти свой собственный, используя 2744730 и создание некорректно-недостижимого кода-предупреждения-в-шаблоне.

Итак, если мы предположим, что базовая модель создания экземпляра шаблона предназначена для удаления копий функций, то подвергает их анализу тех же самых предупреждений, что и любой другой, как мы можем избежать предупреждения о мертвом коде? Я в настоящее время разрывается между добавлением тегов на десятки или около того шаблонов, которые в настоящее время затронуты или отключены предупреждения по всему миру.

edit: Прямая ссылка, похоже, снова живая.

Ответ 1

Я бы сказал, что это правильное поведение, раздражающее, как это может быть. Разработчик

template <class Type>
void func (Type t)
{
    t.func ();
    t.func ();
}

может быть очень доволен этим предупреждением. Кроме того, не всегда возможно, чтобы компилятор разобрался, если не будет никаких, некоторые, все Type, которые будут приводить к неверному или действительному коду. Поэтому он ждет, пока не будет указан Type и будет продолжаться в основном так, как если бы код был введен с этим фиксированным типом.