Skip to content

Commit 0a0e0af

Browse files
committed
[libc++] span: Fix incorrect static asserts
The static asserts in span<T, N>::front() and span<T, N>::back() are incorrect as they may be triggered from valid code due to evaluation of a never taken branch: span<int, 0> foo; if (!foo.empty()) { auto x = foo.front(); } The problem is that the branch is always evaluated by the compiler, creating invalid compile errors for span<T, 0>. Thanks to Michael Schellenberger Costa for the patch. Differential Revision: https://reviews.llvm.org/D71995
1 parent 84240e0 commit 0a0e0af

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

libcxx/include/span

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,13 +307,13 @@ public:
307307

308308
_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
309309
{
310-
static_assert(_Extent > 0, "span<T,N>[].front() on empty span");
310+
_LIBCPP_ASSERT(!empty(), "span<T, N>::front() on empty span");
311311
return __data[0];
312312
}
313313

314314
_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
315315
{
316-
static_assert(_Extent > 0, "span<T,N>[].back() on empty span");
316+
_LIBCPP_ASSERT(!empty(), "span<T, N>::back() on empty span");
317317
return __data[size()-1];
318318
}
319319

libcxx/test/std/containers/views/span.elem/back.pass.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,19 @@ constexpr bool testConstexprSpan(Span sp)
3030
return std::addressof(sp.back()) == sp.data() + sp.size() - 1;
3131
}
3232

33-
3433
template <typename Span>
3534
void testRuntimeSpan(Span sp)
3635
{
3736
LIBCPP_ASSERT(noexcept(sp.back()));
3837
assert(std::addressof(sp.back()) == sp.data() + sp.size() - 1);
3938
}
4039

40+
template <typename Span>
41+
void testEmptySpan(Span sp)
42+
{
43+
if (!sp.empty())
44+
[[maybe_unused]] auto res = sp.back();
45+
}
4146

4247
struct A{};
4348
constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
@@ -71,5 +76,8 @@ int main(int, char**)
7176
testRuntimeSpan(std::span<std::string> (&s, 1));
7277
testRuntimeSpan(std::span<std::string, 1>(&s, 1));
7378

79+
std::span<int, 0> sp;
80+
testEmptySpan(sp);
81+
7482
return 0;
7583
}

libcxx/test/std/containers/views/span.elem/front.pass.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ void testRuntimeSpan(Span sp)
3838
assert(std::addressof(sp.front()) == sp.data());
3939
}
4040

41+
template <typename Span>
42+
void testEmptySpan(Span sp)
43+
{
44+
if (!sp.empty())
45+
[[maybe_unused]] auto res = sp.front();
46+
}
4147

4248
struct A{};
4349
constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
@@ -71,5 +77,8 @@ int main(int, char**)
7177
testRuntimeSpan(std::span<std::string> (&s, 1));
7278
testRuntimeSpan(std::span<std::string, 1>(&s, 1));
7379

80+
std::span<int, 0> sp;
81+
testEmptySpan(sp);
82+
7483
return 0;
7584
}

0 commit comments

Comments
 (0)