[libc++] Various cleanups in the ranges tests

- Rename test files to follow conventions better
- Split constructor tests that were in a single file
- Add missing tests for take_view and transform_view's default constructors
- Add missing tests for transform_view's view/function constructor
- Fix include guards
- Mark some tests as being specific to libc++

Differential Revision: https://reviews.llvm.org/D108829
This commit is contained in:
Louis Dionne 2021-08-27 12:04:12 -04:00
parent 9721197520
commit 770602cfa0
26 changed files with 322 additions and 90 deletions

View File

@ -9,8 +9,10 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// REQUIRES: libc++
// unspecified begin;
// Test the libc++ specific behavior that we provide a better diagnostic when calling
// std::ranges::begin on an array of incomplete type.
#include <ranges>
@ -18,21 +20,17 @@
using begin_t = decltype(std::ranges::begin);
template <class T>
requires(!std::invocable<begin_t&, T>)
void f() {}
template <class T> void f() requires std::invocable<begin_t&, T> { }
template <class T> void f() { }
void test() {
struct incomplete;
f<incomplete(&)[]>();
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@-2 {{no matching function for call to 'f'}}
f<incomplete(&)[10]>();
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@-2 {{no matching function for call to 'f'}}
f<incomplete(&)[2][2]>();
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@-2 {{no matching function for call to 'f'}}
// This is okay because calling `std::ranges::begin` on any rvalue is ill-formed.
f<incomplete(&&)[10]>();

View File

@ -9,8 +9,10 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// REQUIRES: libc++
// ranges::cbegin;
// Test the libc++ specific behavior that we provide a better diagnostic when calling
// std::ranges::cbegin on an array of incomplete type.
#include <ranges>
@ -18,15 +20,13 @@
using cbegin_t = decltype(std::ranges::cbegin);
template <class T>
requires(!std::invocable<cbegin_t&, T>)
void f() {}
template <class T> void f() requires std::invocable<cbegin_t&, T> { }
template <class T> void f() { }
void test() {
struct incomplete;
f<incomplete(&)[10]>();
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@-2 {{no matching function for call to 'f'}}
// This is okay because calling `std::ranges::end` on any rvalue is ill-formed.
f<incomplete(&&)[10]>();

View File

@ -9,8 +9,10 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// REQUIRES: libc++
// unspecified begin;
// Test the libc++ specific behavior that we provide a better diagnostic when calling
// std::ranges::cend on an array of incomplete type.
#include <ranges>
@ -18,9 +20,8 @@
using cend_t = decltype(std::ranges::cend);
template <class T>
requires(!std::invocable<cend_t&, T>)
void f() {}
template <class T> void f() requires std::invocable<cend_t&, T> { }
template <class T> void f() { }
void test() {
struct incomplete;
@ -30,10 +31,8 @@ void test() {
f<incomplete(&)[10]>();
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@*:* {{"`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@-3 {{no matching function for call to 'f'}}
f<incomplete(&)[2][2]>();
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@-2 {{no matching function for call to 'f'}}
// This is okay because calling `std::ranges::end` on any rvalue is ill-formed.
f<incomplete(&&)[10]>();

View File

@ -9,8 +9,10 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// REQUIRES: libc++
// unspecified begin;
// Test the libc++ specific behavior that we provide a better diagnostic when calling
// std::ranges::end on an array of incomplete type.
#include <ranges>
@ -18,9 +20,8 @@
using end_t = decltype(std::ranges::end);
template <class T>
requires(!std::invocable<end_t&, T>)
void f() {}
template <class T> void f() requires std::invocable<end_t&, T> { }
template <class T> void f() { }
void test() {
struct incomplete;
@ -30,10 +31,8 @@ void test() {
f<incomplete(&)[10]>();
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@*:* {{"`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@-3 {{no matching function for call to 'f'}}
f<incomplete(&)[2][2]>();
// expected-error@*:* {{"`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."}}
// expected-error@-2 {{no matching function for call to 'f'}}
// This is okay because calling `std::ranges::end` on any rvalue is ill-formed.
f<incomplete(&&)[10]>();

View File

@ -9,8 +9,10 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// REQUIRES: libc++
// std::ranges::data
// Test the libc++ specific behavior that we provide a better diagnostic when calling
// std::ranges::data on an array of incomplete type.
#include <ranges>

View File

@ -9,8 +9,10 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// REQUIRES: libc++
// std::ranges::empty
// Test the libc++ specific behavior that we provide a better diagnostic when calling
// std::ranges::empty on an array of incomplete type.
#include <ranges>

View File

@ -32,7 +32,7 @@ struct ZeroOnDestroy : std::ranges::view_base {
constexpr ForwardIter end() const { return ForwardIter(); }
~ZeroOnDestroy() {
memset(buff, 0, sizeof(buff));
std::memset(buff, 0, sizeof(buff));
}
static auto dropFirstFour() {

View File

@ -0,0 +1,56 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// take_view() requires default_initializable<V> = default;
#include <ranges>
#include <cassert>
int buff[8] = {1, 2, 3, 4, 5, 6, 7, 8};
struct DefaultConstructible : std::ranges::view_base {
constexpr DefaultConstructible() : begin_(buff), end_(buff + 8) { }
constexpr int const* begin() const { return begin_; }
constexpr int const* end() const { return end_; }
private:
int const* begin_;
int const* end_;
};
struct NonDefaultConstructible : std::ranges::view_base {
NonDefaultConstructible() = delete;
int* begin() const;
int* end() const;
};
constexpr bool test() {
{
std::ranges::take_view<DefaultConstructible> tv;
assert(tv.begin() == buff);
assert(tv.size() == 0);
}
// Test SFINAE-friendliness
{
static_assert( std::is_default_constructible_v<std::ranges::take_view<DefaultConstructible>>);
static_assert(!std::is_default_constructible_v<std::ranges::take_view<NonDefaultConstructible>>);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -10,7 +10,6 @@
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// take_view() requires default_initializable<V> = default;
// constexpr take_view(V base, range_difference_t<V> count);
#include <ranges>
@ -21,27 +20,6 @@
#include "test_range.h"
#include "types.h"
int globalBuffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
template<bool IsDefaultCtorable>
struct DefaultConstructible : std::ranges::view_base {
DefaultConstructible() requires IsDefaultCtorable = default;
DefaultConstructible(int*);
int* begin();
sentinel_wrapper<int*> end();
};
struct SizedRandomAccessViewToGlobal : std::ranges::view_base {
RandomAccessIter begin() { return RandomAccessIter(globalBuffer); }
RandomAccessIter begin() const { return RandomAccessIter(globalBuffer); }
sentinel_wrapper<RandomAccessIter> end() {
return sentinel_wrapper<RandomAccessIter>{RandomAccessIter(globalBuffer + 8)};
}
sentinel_wrapper<RandomAccessIter> end() const {
return sentinel_wrapper<RandomAccessIter>{RandomAccessIter(globalBuffer + 8)};
}
};
constexpr bool test() {
int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
@ -70,13 +48,5 @@ int main(int, char**) {
test();
static_assert(test());
// Tests for the default ctor.
static_assert( std::default_initializable<DefaultConstructible<true>>);
static_assert(!std::default_initializable<DefaultConstructible<false>>);
std::ranges::take_view<SizedRandomAccessViewToGlobal> tv;
assert(*tv.base().begin() == 1);
assert(tv.size() == 0);
return 0;
}

View File

@ -0,0 +1,78 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// transform_view() requires std::default_initializable<V> &&
// std::default_initializable<F> = default;
#include <ranges>
#include <cassert>
#include <type_traits>
constexpr int buff[] = {1, 2, 3};
struct DefaultConstructibleView : std::ranges::view_base {
constexpr DefaultConstructibleView() : begin_(buff), end_(buff + 3) { }
constexpr int const* begin() const { return begin_; }
constexpr int const* end() const { return end_; }
private:
int const* begin_;
int const* end_;
};
struct DefaultConstructibleFunction {
int state_;
constexpr DefaultConstructibleFunction() : state_(100) { }
constexpr int operator()(int i) const { return i + state_; }
};
struct NoDefaultView : std::ranges::view_base {
NoDefaultView() = delete;
int* begin() const;
int* end() const;
};
struct NoDefaultFunction {
NoDefaultFunction() = delete;
constexpr int operator()(int i) const;
};
constexpr bool test() {
{
std::ranges::transform_view<DefaultConstructibleView, DefaultConstructibleFunction> view;
assert(view.size() == 3);
assert(view[0] == 101);
assert(view[1] == 102);
assert(view[2] == 103);
}
{
std::ranges::transform_view<DefaultConstructibleView, DefaultConstructibleFunction> view = {};
assert(view.size() == 3);
assert(view[0] == 101);
assert(view[1] == 102);
assert(view[2] == 103);
}
static_assert(!std::is_default_constructible_v<std::ranges::transform_view<NoDefaultView, DefaultConstructibleFunction>>);
static_assert(!std::is_default_constructible_v<std::ranges::transform_view<DefaultConstructibleView, NoDefaultFunction>>);
static_assert(!std::is_default_constructible_v<std::ranges::transform_view<NoDefaultView, NoDefaultFunction>>);
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -0,0 +1,64 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// constexpr transform_view(View, F);
#include <ranges>
#include <cassert>
struct Range : std::ranges::view_base {
constexpr explicit Range(int* b, int* e) : begin_(b), end_(e) { }
constexpr int* begin() const { return begin_; }
constexpr int* end() const { return end_; }
private:
int* begin_;
int* end_;
};
struct F {
constexpr int operator()(int i) const { return i + 100; }
};
constexpr bool test() {
int buff[] = {1, 2, 3, 4, 5, 6, 7, 8};
{
Range range(buff, buff + 8);
F f;
std::ranges::transform_view<Range, F> view(range, f);
assert(view[0] == 101);
assert(view[1] == 102);
// ...
assert(view[7] == 108);
}
{
Range range(buff, buff + 8);
F f;
std::ranges::transform_view<Range, F> view = {range, f};
assert(view[0] == 101);
assert(view[1] == 102);
// ...
assert(view[7] == 108);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -1,3 +1,11 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_TRANSFORM_TYPES_H
#define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_TRANSFORM_TYPES_H

View File

@ -17,7 +17,7 @@
#include <cassert>
#include "test_macros.h"
#include "test_iterators.h"
#include "../subrange_test_types.h"
#include "types.h"
constexpr bool test() {
std::ranges::subrange<int*> a(globalBuff, globalBuff + 8, 8);

View File

@ -14,7 +14,7 @@
#include <ranges>
#include "../subrange_test_types.h"
#include "types.h"
#include <cassert>
#include "test_macros.h"
#include "test_iterators.h"

View File

@ -14,7 +14,7 @@
#include <ranges>
#include "../subrange_test_types.h"
#include "types.h"
#include <cassert>
#include "test_macros.h"
#include "test_iterators.h"

View File

@ -14,7 +14,7 @@
#include <ranges>
#include "../subrange_test_types.h"
#include "types.h"
#include <cassert>
#include "test_macros.h"
#include "test_iterators.h"

View File

@ -14,7 +14,7 @@
#include <ranges>
#include "../subrange_test_types.h"
#include "types.h"
#include <cassert>
#include "test_macros.h"
#include "test_iterators.h"

View File

@ -0,0 +1,79 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// template<borrowed_range R>
// requires convertible-to-non-slicing<iterator_t<R>, I> &&
// convertible_to<sentinel_t<R>, S>
// constexpr subrange(R&& r, make-unsigned-like-t<iter_difference_t<I>> n)
// requires (K == subrange_kind::sized);
#include <ranges>
#include <cassert>
struct BorrowedRange {
constexpr explicit BorrowedRange(int* b, int* e) : begin_(b), end_(e) { }
constexpr int* begin() const { return begin_; }
constexpr int* end() const { return end_; }
private:
int* begin_;
int* end_;
};
namespace std::ranges {
template <>
inline constexpr bool enable_borrowed_range<::BorrowedRange> = true;
}
constexpr bool test() {
int buff[] = {1, 2, 3, 4, 5, 6, 7, 8};
using Subrange = std::ranges::subrange<int*, int*, std::ranges::subrange_kind::sized>;
// Test with an empty range
{
BorrowedRange range(buff, buff);
Subrange subrange(range, 0);
assert(subrange.size() == 0);
}
// Test with non-empty ranges
{
BorrowedRange range(buff, buff + 1);
Subrange subrange(range, 1);
assert(subrange.size() == 1);
}
{
BorrowedRange range(buff, buff + 2);
Subrange subrange(range, 2);
assert(subrange[0] == 1);
assert(subrange[1] == 2);
assert(subrange.size() == 2);
}
{
BorrowedRange range(buff, buff + 8);
Subrange subrange(range, 8);
assert(subrange[0] == 1);
assert(subrange[1] == 2);
// ...
assert(subrange[7] == 8);
assert(subrange.size() == 8);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@ -1,21 +0,0 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// class std::ranges::subrange;
#include <ranges>
// Tested in pair_like_conv.pass.cpp.
int main(int, char**) {
return 0;
}

View File

@ -17,7 +17,7 @@
#include <cassert>
#include "test_macros.h"
#include "test_iterators.h"
#include "../subrange_test_types.h"
#include "types.h"
template<size_t I, class S>
concept GetInvocable = requires {

View File

@ -17,9 +17,7 @@
#include <cassert>
#include "test_macros.h"
#include "test_iterators.h"
#include "../subrange_test_types.h"
// Note: begin and end tested in range.subrange.ctor.pass.cpp.
#include "types.h"
constexpr bool test() {
std::ranges::subrange<MoveOnlyForwardIter, int*> a(MoveOnlyForwardIter(globalBuff), globalBuff + 8, 8);

View File

@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef SUBRANGE_TEST_TYPES_H
#define SUBRANGE_TEST_TYPES_H
#ifndef LIBCXX_TEST_STD_RANGES_RANGE_UTILITY_RANGE_SUBRANGE_TYPES_H
#define LIBCXX_TEST_STD_RANGES_RANGE_UTILITY_RANGE_SUBRANGE_TYPES_H
#include "test_macros.h"
#include "test_iterators.h"
@ -212,4 +212,4 @@ using DifferentSentinelWithSizeMemberSubrange = std::ranges::subrange<ForwardIte
DifferentSentinelWithSizeMember::sentinel,
std::ranges::subrange_kind::unsized>;
#endif // SUBRANGE_TEST_TYPES_H
#endif // LIBCXX_TEST_STD_RANGES_RANGE_UTILITY_RANGE_SUBRANGE_TYPES_H