Why does std::push_heap generate a -Wstrict-overflow=3 warning even if no signed types are involved?

165 Views Asked by At

According to the documentation of -Wstrict-overflow, level 3:

Also warn[s] about other cases where a comparison is simplified. For example: x + 1 > 1 is simplified to x > 0.

The MWE shown below throws the following warning on level 3 and up, but not below, AND if optimisation is set to -O2 and up but not below. g++ versions 9.3.0 and 10.2 exhibit this.

$ g++ -O3 -Wall -Wextra -pedantic -std=c++17 -Wstrict-overflow=3 a.cpp
a.cpp: In function ‘void std::push_heap(_RAIter, _RAIter) [with _RAIter = long unsigned int*]’: a.cpp:8:1: warning: assuming signed overflow does not occur when changing X +- C1 cmp C2 to X cmp C2 -+ C1 [-Wstrict-overflow]

Live demo

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)); // <---
}

Questions

  • Is this a bug in the library implementation? I don't see any signed types whatsoever.
  • How can I fix this while still keeping -Wstrict-overflow at its max level 5?
1

There are 1 best solutions below

0
On BEST ANSWER
  • Is this a bug in the library implementation? I don't see any signed types whatsoever.

No. The library implementation is correct. Using -fsanitize=undefined confirms there is no overflow.

The warning only tells you that the compiler is assuming no overflow occurs. It can optimise the code more aggressively if it assumes the code has no undefined behaviour, so it assumes the code is free from overflows. The warning is just telling you such an assumption was made, because that assumption might be wrong if you provide inputs to the function which actually do result in overflows.

So the warning means "you'd better not have provided bad input here, because that would make this optimisation produce incorrect results".

I've reported a compiler bug (PR 96658), but strictly speaking GCC is behaving as documented.

  • How can I fix this while still keeping -Wstrict-overflow at its max level 5?

The docs for -Wstrict-overflow are clear that is gives false positives, so don't combine it with -Werror, that's just silly.