diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index b2df0cd650ad7..e11d6cac7685e 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -2062,7 +2062,7 @@ bool equal(L &&LRange, R &&RRange, BinaryPredicate P) { template bool all_equal(R &&Range) { auto Begin = adl_begin(Range); auto End = adl_end(Range); - return Begin == End || std::equal(Begin + 1, End, Begin); + return Begin == End || std::equal(std::next(Begin), End, Begin); } /// Returns true if all Values in the initializer lists are equal or the list diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp index b7dc15bf60af5..ee8299c9b4861 100644 --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -831,6 +832,26 @@ TEST(STLExtrasTest, AllEqual) { EXPECT_FALSE(all_equal(V)); } +// Test to verify that all_equal works with a container that does not +// model the random access iterator concept. +TEST(STLExtrasTest, AllEqualNonRandomAccess) { + std::list V; + static_assert(!std::is_convertible_v< + std::iterator_traits::iterator_category, + std::random_access_iterator_tag>); + EXPECT_TRUE(all_equal(V)); + + V.push_back(1); + EXPECT_TRUE(all_equal(V)); + + V.push_back(1); + V.push_back(1); + EXPECT_TRUE(all_equal(V)); + + V.push_back(2); + EXPECT_FALSE(all_equal(V)); +} + TEST(STLExtrasTest, AllEqualInitializerList) { EXPECT_TRUE(all_equal({1})); EXPECT_TRUE(all_equal({1, 1}));