2

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?
bitmask
  • 32,434
  • 14
  • 99
  • 159
  • Signed types are [used](https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_heap.h#L139) inside `std::__push_heap` for indices: `while (__holeIndex > __topIndex && ...)`. If this comparison is removed from `std::__push_heap` the warning disappears. – Evg Aug 14 '20 at 06:07
  • 1
    There's no bug in the library. The compiler is telling you it assumes there is no integer overflow, not that there actually is an overflow. Compiling with `-fsanitize=undefined` shows there is no overflow at runtime. – Jonathan Wakely Aug 14 '20 at 10:04
  • 1
    @JonathanWakely If it's simply mentioning that it's an assumption, shouldn't this be an "info" level diagnostic? Since this is emitted as a warning diagnostic, [it fails with `-Werror`](https://godbolt.org/z/czqd3P), which seems undesirable. – Human-Compiler Aug 15 '20 at 03:34
  • 1
    @Human-Compiler That is my assessment as well. The standard library should not throw warnings. Any warnings. Unless they originate in user code, which I don't think they do in this case. – bitmask Aug 15 '20 at 12:56
  • The docs are clear: "Therefore this warning can easily give a false positive: a warning about code that is not actually a problem." Combining this warning with `-Werror` is a bit silly. You get what you asked for. – Jonathan Wakely Aug 16 '20 at 07:50

1 Answers1

1
  • 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.

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521