[libcxx-commits] [libcxx] [libc++] Fix implementation of iota_view::size (PR #67819)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Sep 29 08:26:17 PDT 2023


https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/67819

We were incorrectly deducing the return type of size() because we were not using ternary operators in the implementation (as the spec says). Instead of deducing the common type of the expressions in the spec, we would deduce potentially different return types and fail to compile.

Fixes #67551

>From 98bd219618f8283474cdd0c54adcd4182b1374ae Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 29 Sep 2023 11:21:03 -0400
Subject: [PATCH] [libc++] Fix implementation of iota_view::size

We were incorrectly deducing the return type of size() because we were
not using ternary operators in the implementation (as the spec says).
Instead of deducing the common type of the expressions in the spec, we
would deduce potentially different return types and fail to compile.

Fixes #67551
---
 libcxx/include/__ranges/iota_view.h               | 15 +++++++--------
 .../range.factories/range.iota.view/size.pass.cpp | 12 +++++++++++-
 2 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index f372688abfdaf32..ccf0c7a8e8d50e4 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -363,15 +363,14 @@ namespace ranges {
               (integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
     {
       if constexpr (__integer_like<_Start> && __integer_like<_BoundSentinel>) {
-        if (__value_ < 0) {
-          if (__bound_sentinel_ < 0) {
-            return std::__to_unsigned_like(-__value_) - std::__to_unsigned_like(-__bound_sentinel_);
-          }
-          return std::__to_unsigned_like(__bound_sentinel_) + std::__to_unsigned_like(-__value_);
-        }
-        return std::__to_unsigned_like(__bound_sentinel_) - std::__to_unsigned_like(__value_);
+        return (__value_ < 0)
+                 ? ((__bound_sentinel_ < 0)
+                        ? std::__to_unsigned_like(-__value_) - std::__to_unsigned_like(-__bound_sentinel_)
+                        : std::__to_unsigned_like(__bound_sentinel_) + std::__to_unsigned_like(-__value_))
+                 : std::__to_unsigned_like(__bound_sentinel_) - std::__to_unsigned_like(__value_);
+      } else {
+        return std::__to_unsigned_like(__bound_sentinel_ - __value_);
       }
-      return std::__to_unsigned_like(__bound_sentinel_ - __value_);
     }
   };
 
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
index 07092b74be87389..b894bc542be10b6 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/size.pass.cpp
@@ -10,9 +10,10 @@
 
 // constexpr auto size() const requires see below;
 
-#include <ranges>
 #include <cassert>
+#include <concepts>
 #include <limits>
+#include <ranges>
 
 #include "test_macros.h"
 #include "types.h"
@@ -89,6 +90,15 @@ constexpr bool test() {
     assert(io.size() == 0);
   }
 
+  // Make sure iota_view<short, short> works properly. For details,
+  // see https://github.com/llvm/llvm-project/issues/67551.
+  {
+    static_assert(std::ranges::sized_range<std::ranges::iota_view<short, short>>);
+    std::ranges::iota_view<short, short> io(10, 20);
+    std::same_as<unsigned int> auto sz = io.size();
+    assert(sz == 10);
+  }
+
   return true;
 }
 



More information about the libcxx-commits mailing list