3030#include < functional>
3131#include < vector>
3232
33+ #include " sized_allocator.h"
3334#include " test_iterators.h"
3435#include " test_macros.h"
3536#include " type_algorithms.h"
@@ -173,6 +174,90 @@ TEST_CONSTEXPR_CXX20 bool test() {
173174 test_vector_bool<256 >();
174175 }
175176
177+ // Make sure std::equal behaves properly with std::vector<bool> iterators with custom size types.
178+ // See issue: https://github.com/llvm/llvm-project/issues/126369.
179+ {
180+ // // Tests for std::equal with aligned bits
181+
182+ { // Test the first (partial) word for uint8_t
183+ using Alloc = sized_allocator<bool , std::uint8_t , std::int8_t >;
184+ std::vector<bool , Alloc> in (6 , true , Alloc (1 ));
185+ std::vector<bool , Alloc> expected (8 , true , Alloc (1 ));
186+ assert (std::equal (in.begin () + 4 , in.end (), expected.begin () + 4 ));
187+ }
188+ { // Test the last word for uint8_t
189+ using Alloc = sized_allocator<bool , std::uint8_t , std::int8_t >;
190+ std::vector<bool , Alloc> in (12 , true , Alloc (1 ));
191+ std::vector<bool , Alloc> expected (16 , true , Alloc (1 ));
192+ assert (std::equal (in.begin (), in.end (), expected.begin ()));
193+ }
194+ { // Test middle words for uint8_t
195+ using Alloc = sized_allocator<bool , std::uint8_t , std::int8_t >;
196+ std::vector<bool , Alloc> in (24 , true , Alloc (1 ));
197+ std::vector<bool , Alloc> expected (29 , true , Alloc (1 ));
198+ assert (std::equal (in.begin (), in.end (), expected.begin ()));
199+ }
200+
201+ { // Test the first (partial) word for uint16_t
202+ using Alloc = sized_allocator<bool , std::uint16_t , std::int16_t >;
203+ std::vector<bool , Alloc> in (12 , true , Alloc (1 ));
204+ std::vector<bool , Alloc> expected (16 , true , Alloc (1 ));
205+ assert (std::equal (in.begin () + 4 , in.end (), expected.begin () + 4 ));
206+ }
207+ { // Test the last word for uint16_t
208+ using Alloc = sized_allocator<bool , std::uint16_t , std::int16_t >;
209+ std::vector<bool , Alloc> in (24 , true , Alloc (1 ));
210+ std::vector<bool , Alloc> expected (32 , true , Alloc (1 ));
211+ assert (std::equal (in.begin (), in.end (), expected.begin ()));
212+ }
213+ { // Test middle words for uint16_t
214+ using Alloc = sized_allocator<bool , std::uint16_t , std::int16_t >;
215+ std::vector<bool , Alloc> in (48 , true , Alloc (1 ));
216+ std::vector<bool , Alloc> expected (55 , true , Alloc (1 ));
217+ assert (std::equal (in.begin (), in.end (), expected.begin ()));
218+ }
219+
220+ // // Tests for std::equal with unaligned bits
221+
222+ { // Test the first (partial) word for uint8_t
223+ using Alloc = sized_allocator<bool , std::uint8_t , std::int8_t >;
224+ std::vector<bool , Alloc> in (6 , true , Alloc (1 ));
225+ std::vector<bool , Alloc> expected (8 , true , Alloc (1 ));
226+ assert (std::equal (in.begin () + 4 , in.end (), expected.begin ()));
227+ }
228+ { // Test the last word for uint8_t
229+ using Alloc = sized_allocator<bool , std::uint8_t , std::int8_t >;
230+ std::vector<bool , Alloc> in (4 , true , Alloc (1 ));
231+ std::vector<bool , Alloc> expected (8 , true , Alloc (1 ));
232+ assert (std::equal (in.begin (), in.end (), expected.begin () + 3 ));
233+ }
234+ { // Test middle words for uint8_t
235+ using Alloc = sized_allocator<bool , std::uint8_t , std::int8_t >;
236+ std::vector<bool , Alloc> in (16 , true , Alloc (1 ));
237+ std::vector<bool , Alloc> expected (24 , true , Alloc (1 ));
238+ assert (std::equal (in.begin (), in.end (), expected.begin () + 4 ));
239+ }
240+
241+ { // Test the first (partial) word for uint16_t
242+ using Alloc = sized_allocator<bool , std::uint16_t , std::int16_t >;
243+ std::vector<bool , Alloc> in (12 , true , Alloc (1 ));
244+ std::vector<bool , Alloc> expected (16 , true , Alloc (1 ));
245+ assert (std::equal (in.begin () + 4 , in.end (), expected.begin ()));
246+ }
247+ { // Test the last word for uint16_t
248+ using Alloc = sized_allocator<bool , std::uint16_t , std::int16_t >;
249+ std::vector<bool , Alloc> in (12 , true , Alloc (1 ));
250+ std::vector<bool , Alloc> expected (16 , true , Alloc (1 ));
251+ assert (std::equal (in.begin (), in.end (), expected.begin () + 3 ));
252+ }
253+ { // Test the middle words for uint16_t
254+ using Alloc = sized_allocator<bool , std::uint16_t , std::int16_t >;
255+ std::vector<bool , Alloc> in (32 , true , Alloc (1 ));
256+ std::vector<bool , Alloc> expected (64 , true , Alloc (1 ));
257+ assert (std::equal (in.begin (), in.end (), expected.begin () + 4 ));
258+ }
259+ }
260+
176261 return true ;
177262}
178263
@@ -198,9 +283,9 @@ struct TestTypes {
198283
199284int main (int , char **) {
200285 test ();
201- #if TEST_STD_VER >= 20
202- static_assert (test ());
203- #endif
286+ #if TEST_STD_VER >= 20
287+ static_assert (test ());
288+ #endif
204289
205290 types::for_each (types::integer_types (), TestTypes ());
206291 types::for_each (types::as_pointers<types::cv_qualified_versions<int > >(),
0 commit comments