From 1904e2efc1660d58629d70f2ce52ca19e448e412 Mon Sep 17 00:00:00 2001 From: Jakub Kuderski Date: Sun, 9 Mar 2025 18:03:55 -0400 Subject: [PATCH] [ADT] Use `adl_begin` in `make_first_range` and `make_second_range` This is to make sure that ADT helpers consistently use argument dependent lookup when dealing with input ranges. This was a part of #87936 but reverted due to buildbot failures. This PR is stacked on top of #130508. --- llvm/include/llvm/ADT/STLExtras.h | 4 ++-- llvm/unittests/ADT/STLExtrasTest.cpp | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index fa22e299d80a8..78b7e94c2b3a1 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -1434,7 +1434,7 @@ template class first_or_second_type { /// Given a container of pairs, return a range over the first elements. template auto make_first_range(ContainerTy &&c) { - using EltTy = decltype((*std::begin(c))); + using EltTy = decltype(*adl_begin(c)); return llvm::map_range(std::forward(c), [](EltTy elt) -> typename detail::first_or_second_type< EltTy, decltype((elt.first))>::type { @@ -1444,7 +1444,7 @@ template auto make_first_range(ContainerTy &&c) { /// Given a container of pairs, return a range over the second elements. template auto make_second_range(ContainerTy &&c) { - using EltTy = decltype((*std::begin(c))); + using EltTy = decltype(*adl_begin(c)); return llvm::map_range( std::forward(c), [](EltTy elt) -> diff --git a/llvm/unittests/ADT/STLExtrasTest.cpp b/llvm/unittests/ADT/STLExtrasTest.cpp index 086fa78bf1469..dbb094b0a3088 100644 --- a/llvm/unittests/ADT/STLExtrasTest.cpp +++ b/llvm/unittests/ADT/STLExtrasTest.cpp @@ -428,9 +428,17 @@ struct List { std::list::const_iterator begin(const List &list) { return list.data.begin(); } - std::list::const_iterator end(const List &list) { return list.data.end(); } +struct Pairs { + std::vector> data; + using const_iterator = + std::vector>::const_iterator; +}; + +Pairs::const_iterator begin(const Pairs &p) { return p.data.begin(); } +Pairs::const_iterator end(const Pairs &p) { return p.data.end(); } + struct requires_move {}; int *begin(requires_move &&) { return nullptr; } int *end(requires_move &&) { return nullptr; } @@ -524,6 +532,15 @@ TEST(STLExtrasTest, ConcatRangeADL) { EXPECT_THAT(concat(S0, S1), ElementsAre(1, 2, 3, 4)); } +TEST(STLExtrasTest, MakeFirstSecondRangeADL) { + // Make sure that we use the `begin`/`end` functions from `some_namespace`, + // using ADL. + some_namespace::Pairs Pairs; + Pairs.data = {{"foo", 1}, {"bar", 2}}; + EXPECT_THAT(make_first_range(Pairs), ElementsAre("foo", "bar")); + EXPECT_THAT(make_second_range(Pairs), ElementsAre(1, 2)); +} + template struct Iterator { int i = 0; T operator*() const { return i; }