Почему std::push_heap генерирует предупреждение -Wstrict-overflow=3, даже если не используются подписанные типы?
Согласно документации -Wstrict-overflow
, Уровень 3:
Также предупредите о других случаях, когда сравнение упрощено. Например: x + 1 > 1 упрощается до x > 0.
Показанный ниже MWE выдает следующее предупреждение на уровне 3 и выше, но не ниже, И если для оптимизации установлено значение-O2
и выше, но не ниже. g++ версии 9.3.0 и 10.2 демонстрируют это.
$ g++ -O3 -Wall -Wextra -pedantic -std= C++17 -Wstrict-overflow=3 a.cpp
a.cpp: In function 'void std::push_heap(_RAIter, _RAIter) [с _RAIter = long unsigned int*] ': a.cpp:8:1: предупреждение: предполагается, что подписанное переполнение не происходит при изменении X +- C1 cmp C2 на X cmp C2 -+ C1 [-Wstrict-overflow]
MWE
#include <algorithm>
int main() {
std::size_t v[] = {0,10,3};
std::make_heap(std::begin(v),std::end(v));
std::pop_heap(std::begin(v),std::end(v));
std::push_heap(std::begin(v),std::end(v)); // <---
}
Вопросы
- Это ошибка в реализации библиотеки? Я не вижу каких - либо подписанных типов вообще.
- Как я могу это исправить, сохранив
-Wstrict-overflow
на максимальном уровне 5?
1 ответ
- Это ошибка в реализации библиотеки? Я вообще не вижу подписанных типов.
Нет. Реализация библиотеки правильная. С помощью-fsanitize=undefined
подтверждает отсутствие переполнения.
Предупреждение говорит только о том, что компилятор не предполагает переполнения. Он может оптимизировать код более агрессивно, если предполагает, что код не имеет неопределенного поведения, поэтому он предполагает, что код свободен от переполнений. Предупреждение просто сообщает вам, что такое предположение было сделано, потому что это предположение может быть неверным, если вы вводите в функцию входные данные, которые на самом деле приводят к переполнениям.
Таким образом, предупреждение означает, что "вам лучше не вводить здесь неверные данные, потому что это приведет к тому, что эта оптимизация даст неверные результаты".
Я сообщил об ошибке компилятора (PR 96658), но, строго говоря, GCC ведет себя, как описано в документации.
- Как я могу исправить это, сохранив максимальный уровень -Wstrict-overflow 5?
Документы для -Wstrict-overflow
ясно, что это дает ложные срабатывания, поэтому не объединяйте его с -Werror
, это просто глупо.