-
Notifications
You must be signed in to change notification settings - Fork 15.1k
Description
When using std::equal with vector<bool>::iterator in libc++, the function fails to compare vectors correctly for vector<bool> using storage types smaller than int, e.g., unsigned char, unsigned short, uint8_t and uint16_t. The issue arises when these small integral types are used as the underlying storage types for vector<bool>, where intermediate bitwise operations involving these small integral types are subject to integral promotions, leading to incorrect final equality comparison results.
Bug Reproduction
I have prepared a carefully written demo that illustrates the incorrect equality comparisons of std::equal when comparing two vector<bool> instances. With carefully chosen storage types, input sizes, and bit offsets for the two input vectors, we've captured incorrect comparisons in every possible code path:
- Error processing in the first, last, or middle words;
- Error processing in aligned or unaligned code paths.
For comparison purposes, the demo also provides the correct equality comparisons obtained from the standard general-form std::equal which works with all general input_iterators. To ensure that the standard std::equal is invoked, I wrap the input vector<bool>::iterators into standard input_iterators before calling std::equal (iterator unwrapping currently doesn't work, which is another issue to be fixed). Furthermore, we also provide the comparison results obtained from other implementations like MSVC-STL or libstdc++.
Key observations
-
While the
std::equaloptimization forvector<bool>::iteratorfails with small integral types in libc++, the problem does not appear in other implementations such as MSVC-STL or libstdc++, nor does it occur with the standardstd::equalimplementation in libc++. -
The same issue also carries over to the
std::ranges::equalalgorithm with the__bit_iteratoroptimization in libc++, as the range version algorithm boils down to calling the non-range version.
This behavior is clearly a bug in libc++. It is crucial to address this issue to ensure correct functionality across all storage types for vector<bool>.