80 Commits

Author SHA1 Message Date
Jakub Kuderski
c8f3d211fc
[ADT] Allow reverse to find free rbegin/rend functions (#87840)
Lift the requirement that rbegin/rend must be member functions. Also
allow the rbegin/rend to be found through Argument Dependent Lookup
(ADL) and add `adl_rbegin`/`adl_rend` to STLExtras.
2024-04-05 22:40:18 -04:00
Caroline Tice
19e71726ee [LLVM][unittests] Fix type issue in STLExtrasTest.cpp
Fixes a type error in UniqueNoPred test, that is causing the
ppc64le-lld-multistage-test buildbot to fail.
2024-02-20 12:12:16 -08:00
cmtice
d7a73c91b6
[LLVM][ADT] Put both vesions of 'unique' into STLExtras.h (#82312)
Currently there are two versions of llvm::unique, one that requires a
predicate, and is in STLExtras.h; and one that does not require a
predicate, and is in GenericUniformityImpl.h. This moves the one from
GenericUniformityImp.h to STlExtras.h, so they are both together, and
can both be easily called from other places inside LLVM.
2024-02-20 07:30:27 -08:00
Jakub Kuderski
4c28e666a7
[ADT] Support appending multiple values (#69891)
This is so that we can append multiple values at once without having to
create a temporary array or repeatedly call `push_back`.

Use the new function `append_values` to clean up the SPIR-V serializer
code. (NFC)
2023-10-24 13:20:05 -04:00
Jakub Kuderski
2e3d694018
[ADT] Add detection utility for incomplete types (#65495)
This allows us to produce better error messages for types that were only
forward-declared, but where a full definition was expected.

The first user will be https://reviews.llvm.org/D159013; this change is
sent to review separately to reduce the scope of the other patch.
2023-09-06 14:06:40 -04:00
Jakub Kuderski
2981832501 [ADT] Add llvm::range_size function for generic ranges
This function follows `std::ranges::size` from C++20. It is intended
mainly for generic code that does not know the exact range type.
I did not modify the existing `llvm::size` function because it has a strict
guarantee of O(1) running time, and we cannot guarantee that when we delegate
size check to user-defined size functions.

Use `range_size` to optimize size checks in `zip`* and `enumerate`
functions. Before that, we would have to perform linear scans for ranges
without random access iterators.

This is the last change I have planned in the series that overhauls
`zip`* and `enumerate`.

Reviewed By: dblaikie, zero9178

Differential Revision: https://reviews.llvm.org/D146231
2023-03-21 12:58:18 -04:00
Jakub Kuderski
a0a76804c4 [ADT] Allow llvm::enumerate to enumerate over multiple ranges
This does not work by a mere composition of `enumerate` and `zip_equal`,
because C++17 does not allow for recursive expansion of structured
bindings.

This implementation uses `zippy` to manage the iteratees and adds the
stream of indices as the first zipped range. Because we have an upfront
assertion that all input ranges are of the same length, we only need to
check if the second range has ended during iteration.

As a consequence of using `zippy`, `enumerate` will now follow the
reference and lifetime semantics of the `zip*` family of functions. The
main difference is that `enumerate` exposes each tuple of references
through a new tuple-like type `enumerate_result`, with the familiar
`.index()` and `.value()` member functions.

Because the `enumerate_result` returned on dereference is a
temporary, enumeration result can no longer be used through an
lvalue ref.

Reviewed By: dblaikie, zero9178

Differential Revision: https://reviews.llvm.org/D144503
2023-03-15 19:34:22 -04:00
Jakub Kuderski
0eaacc25bb [ADT] Make llvm::is_contained call member contains or find when available
This makes it so that calling `llvm::is_contained` no longer degrades
performance over member contains, even though both have almost identical
names. This would be the case in most set/map classes that can check for
an element being present in O(1) or O(log n) time vs. linear scan with
`std::find`. For C++17 maps/sets without `.contains`, use `.find` when available,
falling back to a linear scan with `std::find`.

I also considered detecting member contains and triggering a
`static_assert` instead, but decided against it because it's just as easy
to do the right thing and call `.contains`. This would also make some code fail
only when compiled in the C++20 mode when more container types come with
`.contains` member functions.

This was actually already the case with `CommandLine.h` calling `is_contained`
on `SmallPtrSet` and in a recent BOLT patch.

Reviewed By: kazu, dblaikie, MaskRay

Differential Revision: https://reviews.llvm.org/D146061
2023-03-15 12:07:56 -04:00
Florian Hahn
73f2a3b6a4
[STLExtras] Use std::get in less_first,less_second to support more types
Update less_first,less_second to use std::get to access the first and
second component. This extends support to any type implementing
std::get, like tuples.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D145489
2023-03-08 12:07:14 +01:00
Jakub Kuderski
010a97974a [ADT] Drop append_range test that doesn't compile with EXPENSIVE_CHECKS
The issue seems to be caused by the definition of `SafeIntIterator` and
is otherwise unrelated to the implementation of `append_range`.

We have a simialr test below, so this does not meaningfully decrease the
test coverage of `append_range`.

See the discussion in: https://reviews.llvm.org/D144420#4164373

Issue: https://github.com/llvm/llvm-project/issues/61122
2023-03-02 11:26:20 -05:00
Jakub Kuderski
1527a1bf70 [ADT] Use adl_begin/end in enumerate
This allows `enumerate` to work with range types that expose custom
`begin`/`end` functions.

This is a cleanup in preparation for future changes in
https://reviews.llvm.org/D144503.

Reviewed By: zero9178

Differential Revision: https://reviews.llvm.org/D145026
2023-03-01 11:15:19 -05:00
Jakub Kuderski
da0d816567 [ADT] Fix definition of adl_begin/adl_end and Iter/ValueOfRange
- Make `IterOfRange` and `ValueOfRange` work with types that require
  custom `begin`/`end` functions.
- Allow for `adl_begin`/`adl_end` to be used in constant-evaluated
  contexts.
- Use SFINAE-friendly trailing return type deductions `adl_begin`/`adl_end` so that they are useable in template argument deduction.
- Add missing documentation comments.

This is required for future work in https://reviews.llvm.org/D144503.

Reviewed By: dblaikie, zero9178

Differential Revision: https://reviews.llvm.org/D144583
2023-02-27 20:31:09 -05:00
Jakub Kuderski
d9f309c5c5 Reland "[ADT] Relax type requirements for is_contained" 2023-02-21 14:36:58 -05:00
Jakub Kuderski
a5aca5b2fd Revert "[ADT] Relax type requirements for is_contained"
This reverts commit 75272d5c1299db93aa619fc9e616832f578726c2.

This fails to compile on the clang-debian-cpp20 buildbot:
https://lab.llvm.org/buildbot#builders/249/builds/945.
2023-02-21 14:30:35 -05:00
Jakub Kuderski
93a971ccf8 [STLExtras] Allow for non-member begin/end in append_range
This makes `append_range` useable with, C arrays and types with custom
`begin`/`end` functions.

Reviewed By: kazu

Differential Revision: https://reviews.llvm.org/D144420
2023-02-21 13:35:19 -05:00
Jakub Kuderski
75272d5c12 [ADT] Relax type requirements for is_contained
- Do not require both the `Set` and `Element` to be exactly the same type and, instead, only require them to be comparable.
- Do not require `Element` to be copyable.
- Add missing documentation comment.

Reviewed By: beanz

Differential Revision: https://reviews.llvm.org/D144416
2023-02-21 13:12:50 -05:00
Kazu Hirata
6b49f30fca [llvm] Deprecate llvm::empty (NFC)
This patch deprecates llvm::empty as I've migrated all known uses of
llvm::empty(x) to x.empty().

Differential Revision: https://reviews.llvm.org/D134141
2022-09-18 22:01:32 -07:00
Jakub Kuderski
6fa87ec10f [ADT] Deprecate is_splat and replace all uses with all_equal
See the discussion thread for more details:
https://discourse.llvm.org/t/adt-is-splat-and-empty-ranges/64692

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D132335
2022-08-23 11:36:27 -04:00
Jakub Kuderski
c9e52fbe4d [ADT] Add all_equal predicate
`llvm::all_equal` checks if all values in the given range are equal, i.e., there are no two elements that are not equal.
Similar to `llvm::all_of`, it returns `true` when the range is empty.

`llvm::all_equal` is intended to supersede `llvm::is_splat`, which will be deprecated and removed in future patches.
See the discussion thread for more details:
https://discourse.llvm.org/t/adt-is-splat-and-empty-ranges/64692.

Reviewed By: dblaikie, shchenz

Differential Revision: https://reviews.llvm.org/D132334
2022-08-22 23:55:23 -04:00
Markus Böck
205701fd47 [llvm][ADT] Allow using structured bindings with llvm::enumerate
This patch adds the ability to deconstruct the `value_type` returned by `llvm::enumarate` into index and value of the wrapping range. Main use case is the common occurence of using it during loop iteration. After this patch it'd then be possible to write code such as:
```
for (auto [index, value] : enumerate(container)) {
   ...
}
```
where `index` is the current index and `value` a reference to elements in the given container.

Differential Revision: https://reviews.llvm.org/D131486
2022-08-09 18:12:40 +02:00
Benjamin Kramer
2960299986 [ADT] Retire llvm::apply_tuple in favor of C++17 std::apply 2022-08-08 18:23:38 +02:00
Jakub Kuderski
ba9dc5f577 [ADT] Add is_splat overload accepting initializer_list
Allow for `is_splat` to be used inline, similar to `is_contained`, e.g.,
```
if (is_splat({type1, type2, type3, type4}))
  ...
```

which is much more concise and less typo-prone than an equivalent chain of equality comparisons.

My immediate motivation is to clean up some code in the SPIR-V dialect that currently needs to either construct a temporary container or use `makeArrayRef` before calling `is_splat`.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D131289
2022-08-08 10:20:02 -04:00
Antonio Frighetto
7c3d8c8977 Fix warnings when -Wdeprecated-enum-enum-conversion is enabled
clang may throw the following warning:
include/clang/AST/DeclarationName.h:210:52: error: arithmetic between
different enumeration types ('clang::DeclarationName::StoredNameKind'
and 'clang::detail::DeclarationNameExtra::ExtraKind') is deprecated
when flags -Werror,-Wdeprecated-enum-enum-conversion are on.

This adds the `addEnumValues()` helper function to STLExtras.h to hide
the details of adding enumeration values together from two different
enumerations.
2022-04-07 08:20:54 -04:00
Chris Bieneman
b39f437757 [ADT] add initializer list specialization for is_contained
Adding an initializer list specialization for is_contained allows for
compile-time evaluation when called with a constant or runtime
evaluation for non-constant values.

This patch doesn't add any uses of this template, but that is coming in
a subsequent patch.

Reviewed By: pete

Differential Revision: https://reviews.llvm.org/D122079
2022-03-29 12:39:39 -05:00
Marek Kurdej
df4da5f37d [ADT] Add drop_end.
This patch adds drop_end that is analogical to drop_begin.
It tries to fill the functional gap where one could drop first elements but not the last ones.
The need for it came in when refactoring clang-format.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D122009
2022-03-21 09:43:19 +01:00
Scott Linder
78a26c7daf [ADT] Add new type traits for type pack indexes
Similar versions of these already exist, this effectively just just
factors them out into STLExtras. I plan to use these in future patches.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D100672
2021-12-15 19:25:14 +00:00
Geoffrey Martin-Noble
c92de29f8d [NFC] Add size inference to to_vector
A default calculated size for SmallVector was added in
https://reviews.llvm.org/D92522 after discussion in
https://groups.google.com/g/llvm-dev/c/Z-VwNCTRGSg, but to_vector still
requires an explicit size. This patch adds the default size to to_vector
as well, so that this case doesn't unnecessarily force users to pick an
arbitrary size.

Reviewed By: silvas, dblaikie

Differential Revision: https://reviews.llvm.org/D112968
2021-11-04 09:24:02 -07:00
Mehdi Amini
b70de61f48 Add all_of_zip to STLExtras
This takes two ranges and invokes a predicate on the element-wise pair in the
ranges. It returns true if all the pairs are matching the predicate and the ranges
have the same size.
It is useful with containers that aren't random iterator where we can't check the
sizes in O(1).

Differential Revision: https://reviews.llvm.org/D106605
2021-07-29 05:00:35 +00:00
Scott Linder
83887df155 [ADT] Follow up to fix bug in "Add makeVisitor to STLExtras.h"
Address mistakenly comparing the pointer values of two C-style strings
rather than comparing their contents in the unit tests for makeVisitor,
added in 6d6f35eb7b92c6dd4478834497752f4e963db16d
2021-07-01 18:24:49 +00:00
Scott Linder
6d6f35eb7b [ADT] Add makeVisitor to STLExtras.h
Relands patch reverted by 61242c0addb120294211d24a97ed89837418cb36
The original patch mistakenly included unrelated tests.

Adds a utility to combine multiple Callables into a single Callable.
This is useful to make constructing a visitor for `std::visit`-like
functions more natural; functions like this will be added in future
patches.

Intended to supercede https://reviews.llvm.org/D99560 by
perfectly-forwarding the combined Callables.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D100670
2021-06-28 20:07:11 +00:00
Scott Linder
61242c0add Revert "[ADT] Add makeVisitor to STLExtras.h"
This reverts commit 14a8aa615597ef0aa424ac9545906bf8b9865063.

Mistakenly landed this before a patch it should depend on was accepted.
2021-06-28 19:51:25 +00:00
Scott Linder
14a8aa6155 [ADT] Add makeVisitor to STLExtras.h
Adds a utility to combine multiple Callables into a single Callable.
This is useful to make constructing a visitor for `std::visit`-like
functions more natural; functions like this will be added in future
patches.

Intended to supercede https://reviews.llvm.org/D99560 by
perfectly-forwarding the combined Callables.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D100670
2021-06-28 19:35:42 +00:00
Scott Linder
e17610cf96 [ADT] Refactor enumerate unit tests
Preparation for landing the tests for llvm::makeVisitor, including
breaking out the a "Counted" base class and explicitly testing
the prvalue case as distinct from the rvalue case.

Differential Revision: https://reviews.llvm.org/D103206
2021-06-04 22:29:13 +00:00
David Blaikie
a08673d04a Add a range-based wrapper for std::unique(begin, end, binary_predicate) 2021-05-24 17:26:46 -07:00
Stella Stamenova
2d1f2ba7d5 Revert "[ADT] Add new type traits for type pack indexes"
This reverts commit a6d3987b8ef3b7616f0835b89515c4264f2a7a64.
2021-05-17 20:26:59 -07:00
Scott Linder
a6d3987b8e [ADT] Add new type traits for type pack indexes
Similar versions of these already exist, this effectively just just
factors them out into STLExtras. I plan to use these in future patches.

Differential Revision: https://reviews.llvm.org/D100672
2021-05-17 22:28:55 +00:00
Kazu Hirata
dc300beba7 [STLExtras] Add a default value to drop_begin
This patch adds the default value of 1 to drop_begin.

In the llvm codebase, 70% of calls to drop_begin have 1 as the second
argument.  The interface similar to with std::next should improve
readability.

This patch converts a couple of calls to drop_begin as examples.

Differential Revision: https://reviews.llvm.org/D94858
2021-01-18 10:16:34 -08:00
Florian Hahn
c701f85c45
[STLExtras] Use return type from operator* of the wrapped iter.
Currently make_early_inc_range cannot be used with iterators with
operator* implementations that do not return a reference.

Most notably in the LLVM codebase, this means the User iterator ranges
cannot be used with make_early_inc_range, which slightly simplifies
iterating over ranges while elements are removed.

Instead of directly using BaseT::reference as return type of operator*,
this patch uses decltype to get the actual return type of the operator*
implementation in WrappedIteratorT.

This patch also updates a few places to use make use of
make_early_inc_range.

Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D93992
2021-01-10 14:41:13 +00:00
Barry Revzin
92310454bf Make LLVM build in C++20 mode
Part of the <=> changes in C++20 make certain patterns of writing equality
operators ambiguous with themselves (sorry!).
This patch goes through and adjusts all the comparison operators such that
they should work in both C++17 and C++20 modes. It also makes two other small
C++20-specific changes (adding a constructor to a type that cases to be an
aggregate, and adding casts from u8 literals which no longer have type
const char*).

There were four categories of errors that this review fixes.
Here are canonical examples of them, ordered from most to least common:

// 1) Missing const
namespace missing_const {
    struct A {
    #ifndef FIXED
        bool operator==(A const&);
    #else
        bool operator==(A const&) const;
    #endif
    };

    bool a = A{} == A{}; // error
}

// 2) Type mismatch on CRTP
namespace crtp_mismatch {
    template <typename Derived>
    struct Base {
    #ifndef FIXED
        bool operator==(Derived const&) const;
    #else
        // in one case changed to taking Base const&
        friend bool operator==(Derived const&, Derived const&);
    #endif
    };

    struct D : Base<D> { };

    bool b = D{} == D{}; // error
}

// 3) iterator/const_iterator with only mixed comparison
namespace iter_const_iter {
    template <bool Const>
    struct iterator {
        using const_iterator = iterator<true>;

        iterator();

        template <bool B, std::enable_if_t<(Const && !B), int> = 0>
        iterator(iterator<B> const&);

    #ifndef FIXED
        bool operator==(const_iterator const&) const;
    #else
        friend bool operator==(iterator const&, iterator const&);
    #endif
    };

    bool c = iterator<false>{} == iterator<false>{} // error
          || iterator<false>{} == iterator<true>{}
          || iterator<true>{} == iterator<false>{}
          || iterator<true>{} == iterator<true>{};
}

// 4) Same-type comparison but only have mixed-type operator
namespace ambiguous_choice {
    enum Color { Red };

    struct C {
        C();
        C(Color);
        operator Color() const;
        bool operator==(Color) const;
        friend bool operator==(C, C);
    };

    bool c = C{} == C{}; // error
    bool d = C{} == Red;
}

Differential revision: https://reviews.llvm.org/D78938
2020-12-17 10:44:10 +00:00
Sean Silva
e9e2e3107d [STLExtras] Add append_range helper.
This is convenient in a lot of cases, such as when the thing you want
to append is `someReallyLongFunctionName()` that you'd rather not
write twice or assign to a variable for the paired begin/end calls.

Differential Revision: https://reviews.llvm.org/D90894
2020-11-05 16:20:02 -08:00
Nathan James
4363ea6105
Fix C2975 error under MSVC
Apparantly a constexpr value isn't a compile time constant under certain versions of MSVC.
2020-07-25 11:03:59 +01:00
Nathan James
6c25fc35e0
[ADT] Add a range-based version of std::move
Adds a range-based version of `std::move`, the version that moves a range, not the one that creates r-value references.

Reviewed By: dblaikie, gamesh411

Differential Revision: https://reviews.llvm.org/D83902
2020-07-25 10:37:34 +01:00
Rahul Joshi
0d9726bc3d - Add hasNItemsOrLess and container variants of hasNItems, hasNItemsOrMore, and hasNItemsOrLess
- Fixed a bug in hasNItems()
- Extend the STLExtras unit test to test hasSingleElement() and hasNItems() and friends.

Differential Revision: https://reviews.llvm.org/D82232
2020-06-22 15:07:36 -07:00
Justin Lebar
fb45968e62 Use C++14-style return type deduction in LLVM.
Summary:
Simplifies the C++11-style "-> decltype(...)" return-type deduction.

Note that you have to be careful about whether the function return type
is `auto` or `decltype(auto)`.  The difference is that bare `auto`
strips const and reference, just like lambda return type deduction.  In
some cases that's what we want (or more likely, we know that the return
type is a value type), but whenever we're wrapping a templated function
which might return a reference, we need to be sure that the return type
is decltype(auto).

No functional change.

Subscribers: dexonsmith, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D74383
2020-02-11 07:38:42 -08:00
Lang Hames
058bc4c8d4 [ADT] Move drop_begin from iterator_range.h into STLExtras.
Summary:
drop_begin depends on adl_begin/adl_end, which are defined in STLExtras.h,
but we can't just #include STLExtras.h in iterator_range.h as that would
introduce a circular reference (STLExtras.h already depends on
iterator_range.h). The simplest solution is to move drop_begin into
STLExtras.h, which is a reasonable home for it anyway.

Reviewers: dblaikie

Subscribers: dexonsmith, ributzka, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D70189
2019-11-14 08:10:59 -08:00
Jonas Devlieghere
0eaee545ee [llvm] Migrate llvm::make_unique to std::make_unique
Now that we've moved to C++14, we no longer need the llvm::make_unique
implementation from STLExtras.h. This patch is a mechanical replacement
of (hopefully) all the llvm::make_unique instances across the monorepo.

llvm-svn: 369013
2019-08-15 15:54:37 +00:00
Fangrui Song
78ee2fbf98 Cleanup: llvm::bsearch -> llvm::partition_point after r364719
llvm-svn: 364720
2019-06-30 11:19:56 +00:00
Fangrui Song
2d2cb77e45 [ADT] Implement llvm::bsearch() with std::partition_point()
Summary:
Delete the begin-end form because the standard std::partition_point
can be easily used as a replacement.

The ranges-style llvm::bsearch will be renamed to llvm::partition_point
in the next clean-up patch.

The name "bsearch" doesn't meet people's expectation because in C:

> If two or more members compare equal, which member is returned is unspecified.

Reviewed By: sammccall

Differential Revision: https://reviews.llvm.org/D63718

llvm-svn: 364719
2019-06-30 09:17:59 +00:00
Sam McCall
51389aad98 [ADT] Avoid warning in bsearch testcase
llvm-svn: 358811
2019-04-20 11:48:11 +00:00
Sam McCall
6b44291b5c [ADT] llvm::bsearch, binary search for mere mortals
Summary:
Add to STLExtras a binary search function with a simple mental model:
You provide a range and a predicate which is true above a certain point.
bsearch() tells you that point.
Overloads are provided for integers, iterators, and containers.

This is more suitable than std:: alternatives in many cases:
 - std::binary_search only indicates presence/absence
 - upper_bound/lower_bound give you the opportunity to pick the wrong one
 - all of the options have confusing names and definitions when your predicate
   doesn't have simple "less than" semantics
 - all of the options require iterators
 - we plumb around a useless `value` parameter that should be a lambda capture

The API is inspired by Go's standard library, but we add an extra parameter as
well as some overloads and templates to show how clever C++ is.

Reviewers: ilya-biryukov, gribozavr

Subscribers: dexonsmith, kristina, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D60779

llvm-svn: 358540
2019-04-16 23:53:28 +00:00