Sequence.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- Sequence.h - Utility for producing sequences of values ---*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. /// \file
  14. /// Provides some synthesis utilities to produce sequences of values. The names
  15. /// are intentionally kept very short as they tend to occur in common and
  16. /// widely used contexts.
  17. ///
  18. /// The `seq(A, B)` function produces a sequence of values from `A` to up to
  19. /// (but not including) `B`, i.e., [`A`, `B`), that can be safely iterated over.
  20. /// `seq` supports both integral (e.g., `int`, `char`, `uint32_t`) and enum
  21. /// types. `seq_inclusive(A, B)` produces a sequence of values from `A` to `B`,
  22. /// including `B`.
  23. ///
  24. /// Examples with integral types:
  25. /// ```
  26. /// for (int x : seq(0, 3))
  27. /// outs() << x << " ";
  28. /// ```
  29. ///
  30. /// Prints: `0 1 2 `.
  31. ///
  32. /// ```
  33. /// for (int x : seq_inclusive(0, 3))
  34. /// outs() << x << " ";
  35. /// ```
  36. ///
  37. /// Prints: `0 1 2 3 `.
  38. ///
  39. /// Similar to `seq` and `seq_inclusive`, the `enum_seq` and
  40. /// `enum_seq_inclusive` functions produce sequences of enum values that can be
  41. /// iterated over.
  42. /// To enable iteration with enum types, you need to either mark enums as safe
  43. /// to iterate on by specializing `enum_iteration_traits`, or opt into
  44. /// potentially unsafe iteration at every callsite by passing
  45. /// `force_iteration_on_noniterable_enum`.
  46. ///
  47. /// Examples with enum types:
  48. /// ```
  49. /// namespace X {
  50. /// enum class MyEnum : unsigned {A = 0, B, C};
  51. /// } // namespace X
  52. ///
  53. /// template <> struct enum_iteration_traits<X::MyEnum> {
  54. /// static contexpr bool is_iterable = true;
  55. /// };
  56. ///
  57. /// class MyClass {
  58. /// public:
  59. /// enum Safe { D = 3, E, F };
  60. /// enum MaybeUnsafe { G = 1, H = 2, I = 4 };
  61. /// };
  62. ///
  63. /// template <> struct enum_iteration_traits<MyClass::Safe> {
  64. /// static contexpr bool is_iterable = true;
  65. /// };
  66. /// ```
  67. ///
  68. /// ```
  69. /// for (auto v : enum_seq(MyClass::Safe::D, MyClass::Safe::F))
  70. /// outs() << int(v) << " ";
  71. /// ```
  72. ///
  73. /// Prints: `3 4 `.
  74. ///
  75. /// ```
  76. /// for (auto v : enum_seq(MyClass::MaybeUnsafe::H, MyClass::MaybeUnsafe::I,
  77. /// force_iteration_on_noniterable_enum))
  78. /// outs() << int(v) << " ";
  79. /// ```
  80. ///
  81. /// Prints: `2 3 `.
  82. ///
  83. //===----------------------------------------------------------------------===//
  84. #ifndef LLVM_ADT_SEQUENCE_H
  85. #define LLVM_ADT_SEQUENCE_H
  86. #include <cassert> // assert
  87. #include <iterator> // std::random_access_iterator_tag
  88. #include <limits> // std::numeric_limits
  89. #include <type_traits> // std::is_integral, std::is_enum, std::underlying_type,
  90. // std::enable_if
  91. #include "llvm/Support/MathExtras.h" // AddOverflow / SubOverflow
  92. namespace llvm {
  93. // Enum traits that marks enums as safe or unsafe to iterate over.
  94. // By default, enum types are *not* considered safe for iteration.
  95. // To allow iteration for your enum type, provide a specialization with
  96. // `is_iterable` set to `true` in the `llvm` namespace.
  97. // Alternatively, you can pass the `force_iteration_on_noniterable_enum` tag
  98. // to `enum_seq` or `enum_seq_inclusive`.
  99. template <typename EnumT> struct enum_iteration_traits {
  100. static constexpr bool is_iterable = false;
  101. };
  102. struct force_iteration_on_noniterable_enum_t {
  103. explicit force_iteration_on_noniterable_enum_t() = default;
  104. };
  105. // TODO: Make this `inline` once we update to C++17 to avoid ORD violations.
  106. constexpr force_iteration_on_noniterable_enum_t
  107. force_iteration_on_noniterable_enum;
  108. namespace detail {
  109. // Returns whether a value of type U can be represented with type T.
  110. template <typename T, typename U> bool canTypeFitValue(const U Value) {
  111. const intmax_t BotT = intmax_t(std::numeric_limits<T>::min());
  112. const intmax_t BotU = intmax_t(std::numeric_limits<U>::min());
  113. const uintmax_t TopT = uintmax_t(std::numeric_limits<T>::max());
  114. const uintmax_t TopU = uintmax_t(std::numeric_limits<U>::max());
  115. return !((BotT > BotU && Value < static_cast<U>(BotT)) ||
  116. (TopT < TopU && Value > static_cast<U>(TopT)));
  117. }
  118. // An integer type that asserts when:
  119. // - constructed from a value that doesn't fit into intmax_t,
  120. // - casted to a type that cannot hold the current value,
  121. // - its internal representation overflows.
  122. struct CheckedInt {
  123. // Integral constructor, asserts if Value cannot be represented as intmax_t.
  124. template <typename Integral, typename std::enable_if_t<
  125. std::is_integral<Integral>::value, bool> = 0>
  126. static CheckedInt from(Integral FromValue) {
  127. if (!canTypeFitValue<intmax_t>(FromValue))
  128. assertOutOfBounds();
  129. CheckedInt Result;
  130. Result.Value = static_cast<intmax_t>(FromValue);
  131. return Result;
  132. }
  133. // Enum constructor, asserts if Value cannot be represented as intmax_t.
  134. template <typename Enum,
  135. typename std::enable_if_t<std::is_enum<Enum>::value, bool> = 0>
  136. static CheckedInt from(Enum FromValue) {
  137. using type = typename std::underlying_type<Enum>::type;
  138. return from<type>(static_cast<type>(FromValue));
  139. }
  140. // Equality
  141. bool operator==(const CheckedInt &O) const { return Value == O.Value; }
  142. bool operator!=(const CheckedInt &O) const { return Value != O.Value; }
  143. CheckedInt operator+(intmax_t Offset) const {
  144. CheckedInt Result;
  145. if (AddOverflow(Value, Offset, Result.Value))
  146. assertOutOfBounds();
  147. return Result;
  148. }
  149. intmax_t operator-(CheckedInt Other) const {
  150. intmax_t Result;
  151. if (SubOverflow(Value, Other.Value, Result))
  152. assertOutOfBounds();
  153. return Result;
  154. }
  155. // Convert to integral, asserts if Value cannot be represented as Integral.
  156. template <typename Integral, typename std::enable_if_t<
  157. std::is_integral<Integral>::value, bool> = 0>
  158. Integral to() const {
  159. if (!canTypeFitValue<Integral>(Value))
  160. assertOutOfBounds();
  161. return static_cast<Integral>(Value);
  162. }
  163. // Convert to enum, asserts if Value cannot be represented as Enum's
  164. // underlying type.
  165. template <typename Enum,
  166. typename std::enable_if_t<std::is_enum<Enum>::value, bool> = 0>
  167. Enum to() const {
  168. using type = typename std::underlying_type<Enum>::type;
  169. return Enum(to<type>());
  170. }
  171. private:
  172. static void assertOutOfBounds() { assert(false && "Out of bounds"); }
  173. intmax_t Value;
  174. };
  175. template <typename T, bool IsReverse> struct SafeIntIterator {
  176. using iterator_category = std::random_access_iterator_tag;
  177. using value_type = T;
  178. using difference_type = intmax_t;
  179. using pointer = T *;
  180. using reference = T &;
  181. // Construct from T.
  182. explicit SafeIntIterator(T Value) : SI(CheckedInt::from<T>(Value)) {}
  183. // Construct from other direction.
  184. SafeIntIterator(const SafeIntIterator<T, !IsReverse> &O) : SI(O.SI) {}
  185. // Dereference
  186. value_type operator*() const { return SI.to<T>(); }
  187. // Indexing
  188. value_type operator[](intmax_t Offset) const { return *(*this + Offset); }
  189. // Can be compared for equivalence using the equality/inequality operators.
  190. bool operator==(const SafeIntIterator &O) const { return SI == O.SI; }
  191. bool operator!=(const SafeIntIterator &O) const { return SI != O.SI; }
  192. // Comparison
  193. bool operator<(const SafeIntIterator &O) const { return (*this - O) < 0; }
  194. bool operator>(const SafeIntIterator &O) const { return (*this - O) > 0; }
  195. bool operator<=(const SafeIntIterator &O) const { return (*this - O) <= 0; }
  196. bool operator>=(const SafeIntIterator &O) const { return (*this - O) >= 0; }
  197. // Pre Increment/Decrement
  198. void operator++() { offset(1); }
  199. void operator--() { offset(-1); }
  200. // Post Increment/Decrement
  201. SafeIntIterator operator++(int) {
  202. const auto Copy = *this;
  203. ++*this;
  204. return Copy;
  205. }
  206. SafeIntIterator operator--(int) {
  207. const auto Copy = *this;
  208. --*this;
  209. return Copy;
  210. }
  211. // Compound assignment operators
  212. void operator+=(intmax_t Offset) { offset(Offset); }
  213. void operator-=(intmax_t Offset) { offset(-Offset); }
  214. // Arithmetic
  215. SafeIntIterator operator+(intmax_t Offset) const { return add(Offset); }
  216. SafeIntIterator operator-(intmax_t Offset) const { return add(-Offset); }
  217. // Difference
  218. intmax_t operator-(const SafeIntIterator &O) const {
  219. return IsReverse ? O.SI - SI : SI - O.SI;
  220. }
  221. private:
  222. SafeIntIterator(const CheckedInt &SI) : SI(SI) {}
  223. static intmax_t getOffset(intmax_t Offset) {
  224. return IsReverse ? -Offset : Offset;
  225. }
  226. CheckedInt add(intmax_t Offset) const { return SI + getOffset(Offset); }
  227. void offset(intmax_t Offset) { SI = SI + getOffset(Offset); }
  228. CheckedInt SI;
  229. // To allow construction from the other direction.
  230. template <typename, bool> friend struct SafeIntIterator;
  231. };
  232. } // namespace detail
  233. template <typename T> struct iota_range {
  234. using value_type = T;
  235. using reference = T &;
  236. using const_reference = const T &;
  237. using iterator = detail::SafeIntIterator<value_type, false>;
  238. using const_iterator = iterator;
  239. using reverse_iterator = detail::SafeIntIterator<value_type, true>;
  240. using const_reverse_iterator = reverse_iterator;
  241. using difference_type = intmax_t;
  242. using size_type = std::size_t;
  243. explicit iota_range(T Begin, T End, bool Inclusive)
  244. : BeginValue(Begin), PastEndValue(End) {
  245. assert(Begin <= End && "Begin must be less or equal to End.");
  246. if (Inclusive)
  247. ++PastEndValue;
  248. }
  249. size_t size() const { return PastEndValue - BeginValue; }
  250. bool empty() const { return BeginValue == PastEndValue; }
  251. auto begin() const { return const_iterator(BeginValue); }
  252. auto end() const { return const_iterator(PastEndValue); }
  253. auto rbegin() const { return const_reverse_iterator(PastEndValue - 1); }
  254. auto rend() const { return const_reverse_iterator(BeginValue - 1); }
  255. private:
  256. static_assert(std::is_integral<T>::value || std::is_enum<T>::value,
  257. "T must be an integral or enum type");
  258. static_assert(std::is_same<T, std::remove_cv_t<T>>::value,
  259. "T must not be const nor volatile");
  260. iterator BeginValue;
  261. iterator PastEndValue;
  262. };
  263. /// Iterate over an integral type from Begin up to - but not including - End.
  264. /// Note: Begin and End values have to be within [INTMAX_MIN, INTMAX_MAX] for
  265. /// forward iteration (resp. [INTMAX_MIN + 1, INTMAX_MAX] for reverse
  266. /// iteration).
  267. template <typename T, typename = std::enable_if_t<std::is_integral<T>::value &&
  268. !std::is_enum<T>::value>>
  269. auto seq(T Begin, T End) {
  270. return iota_range<T>(Begin, End, false);
  271. }
  272. /// Iterate over an integral type from Begin to End inclusive.
  273. /// Note: Begin and End values have to be within [INTMAX_MIN, INTMAX_MAX - 1]
  274. /// for forward iteration (resp. [INTMAX_MIN + 1, INTMAX_MAX - 1] for reverse
  275. /// iteration).
  276. template <typename T, typename = std::enable_if_t<std::is_integral<T>::value &&
  277. !std::is_enum<T>::value>>
  278. auto seq_inclusive(T Begin, T End) {
  279. return iota_range<T>(Begin, End, true);
  280. }
  281. /// Iterate over an enum type from Begin up to - but not including - End.
  282. /// Note: `enum_seq` will generate each consecutive value, even if no
  283. /// enumerator with that value exists.
  284. /// Note: Begin and End values have to be within [INTMAX_MIN, INTMAX_MAX] for
  285. /// forward iteration (resp. [INTMAX_MIN + 1, INTMAX_MAX] for reverse
  286. /// iteration).
  287. template <typename EnumT,
  288. typename = std::enable_if_t<std::is_enum<EnumT>::value>>
  289. auto enum_seq(EnumT Begin, EnumT End) {
  290. static_assert(enum_iteration_traits<EnumT>::is_iterable,
  291. "Enum type is not marked as iterable.");
  292. return iota_range<EnumT>(Begin, End, false);
  293. }
  294. /// Iterate over an enum type from Begin up to - but not including - End, even
  295. /// when `EnumT` is not marked as safely iterable by `enum_iteration_traits`.
  296. /// Note: `enum_seq` will generate each consecutive value, even if no
  297. /// enumerator with that value exists.
  298. /// Note: Begin and End values have to be within [INTMAX_MIN, INTMAX_MAX] for
  299. /// forward iteration (resp. [INTMAX_MIN + 1, INTMAX_MAX] for reverse
  300. /// iteration).
  301. template <typename EnumT,
  302. typename = std::enable_if_t<std::is_enum<EnumT>::value>>
  303. auto enum_seq(EnumT Begin, EnumT End, force_iteration_on_noniterable_enum_t) {
  304. return iota_range<EnumT>(Begin, End, false);
  305. }
  306. /// Iterate over an enum type from Begin to End inclusive.
  307. /// Note: `enum_seq_inclusive` will generate each consecutive value, even if no
  308. /// enumerator with that value exists.
  309. /// Note: Begin and End values have to be within [INTMAX_MIN, INTMAX_MAX - 1]
  310. /// for forward iteration (resp. [INTMAX_MIN + 1, INTMAX_MAX - 1] for reverse
  311. /// iteration).
  312. template <typename EnumT,
  313. typename = std::enable_if_t<std::is_enum<EnumT>::value>>
  314. auto enum_seq_inclusive(EnumT Begin, EnumT End) {
  315. static_assert(enum_iteration_traits<EnumT>::is_iterable,
  316. "Enum type is not marked as iterable.");
  317. return iota_range<EnumT>(Begin, End, true);
  318. }
  319. /// Iterate over an enum type from Begin to End inclusive, even when `EnumT`
  320. /// is not marked as safely iterable by `enum_iteration_traits`.
  321. /// Note: `enum_seq_inclusive` will generate each consecutive value, even if no
  322. /// enumerator with that value exists.
  323. /// Note: Begin and End values have to be within [INTMAX_MIN, INTMAX_MAX - 1]
  324. /// for forward iteration (resp. [INTMAX_MIN + 1, INTMAX_MAX - 1] for reverse
  325. /// iteration).
  326. template <typename EnumT,
  327. typename = std::enable_if_t<std::is_enum<EnumT>::value>>
  328. auto enum_seq_inclusive(EnumT Begin, EnumT End,
  329. force_iteration_on_noniterable_enum_t) {
  330. return iota_range<EnumT>(Begin, End, true);
  331. }
  332. } // end namespace llvm
  333. #endif // LLVM_ADT_SEQUENCE_H
  334. #ifdef __GNUC__
  335. #pragma GCC diagnostic pop
  336. #endif