Files
TheRock/math-libs/libhipcxx/.upstream-tests/test/std/ranges/range.access/begin.pass.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

456 lines
15 KiB
C++

//===----------------------------------------------------------------------===//
//
// 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
// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//
// std::ranges::begin
// std::ranges::cbegin
#include <cuda/std/cassert>
#include <cuda/std/ranges>
#include <cuda/std/utility>
#include "test_iterators.h"
#include "test_macros.h"
using RangeBeginT = decltype(cuda::std::ranges::begin);
using RangeCBeginT = decltype(cuda::std::ranges::cbegin);
TEST_GLOBAL_VARIABLE int globalBuff[8] = {};
// This has been made valid as a defect report for C++17 onwards, however both clang and gcc below 11.0 does not
// implement it
#if !TEST_COMPILER(GCC, <, 11)
static_assert(cuda::std::is_invocable_v<RangeBeginT, int (&)[]>, "");
static_assert(cuda::std::is_invocable_v<RangeCBeginT, int (&)[]>, "");
#endif // !TEST_COMPILER(GCC, <, 11)
static_assert(cuda::std::is_invocable_v<RangeBeginT, int (&)[10]>, "");
static_assert(cuda::std::is_invocable_v<RangeCBeginT, int (&)[10]>, "");
#if !TEST_COMPILER(MSVC, <, 19, 23)
// old MSVC has a bug where it doesn't properly handle rvalue arrays
static_assert(!cuda::std::is_invocable_v<RangeBeginT, int (&&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, int (&&)[10]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, int (&&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, int (&&)[10]>, "");
#endif // !TEST_COMPILER(MSVC, <, 19, 23)
struct Incomplete;
static_assert(!cuda::std::is_invocable_v<RangeBeginT, Incomplete (&&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, const Incomplete (&&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, Incomplete (&&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, const Incomplete (&&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, Incomplete (&&)[10]>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, const Incomplete (&&)[10]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, Incomplete (&&)[10]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, const Incomplete (&&)[10]>, "");
// This case is IFNDR; we handle it SFINAE-friendly.
static_assert(!cuda::std::is_invocable_v<RangeBeginT, Incomplete (&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, const Incomplete (&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, Incomplete (&)[]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, const Incomplete (&)[]>, "");
// This case is IFNDR; we handle it SFINAE-friendly.
static_assert(!cuda::std::is_invocable_v<RangeBeginT, Incomplete (&)[10]>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, const Incomplete (&)[10]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, Incomplete (&)[10]>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, const Incomplete (&)[10]>, "");
struct BeginMember
{
int x;
__host__ __device__ constexpr const int* begin() const
{
return &x;
}
};
// Ensure that we can't call with rvalues with borrowing disabled.
static_assert(cuda::std::is_invocable_v<RangeBeginT, BeginMember&>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginMember&&>, "");
static_assert(cuda::std::is_invocable_v<RangeBeginT, BeginMember const&>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginMember const&&>, "");
static_assert(cuda::std::is_invocable_v<RangeCBeginT, BeginMember&>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, BeginMember&&>, "");
static_assert(cuda::std::is_invocable_v<RangeCBeginT, BeginMember const&>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, BeginMember const&&>, "");
struct Different
{
__host__ __device__ char*& begin();
__host__ __device__ short*& begin() const;
};
__host__ __device__ constexpr bool testReturnTypes()
{
{
int* x[2] = {};
unused(x);
static_assert(cuda::std::same_as<decltype(cuda::std::ranges::begin(x)), int**>, "");
static_assert(cuda::std::same_as<decltype(cuda::std::ranges::cbegin(x)), int* const*>, "");
}
{
int x[2][2] = {};
unused(x);
static_assert(cuda::std::same_as<decltype(cuda::std::ranges::begin(x)), int(*)[2]>, "");
static_assert(cuda::std::same_as<decltype(cuda::std::ranges::cbegin(x)), const int(*)[2]>, "");
}
{
Different x{};
unused(x);
static_assert(cuda::std::same_as<decltype(cuda::std::ranges::begin(x)), char*>, "");
static_assert(cuda::std::same_as<decltype(cuda::std::ranges::cbegin(x)), short*>, "");
}
return true;
}
__host__ __device__ constexpr bool testArray()
{
int a[2] = {};
assert(cuda::std::ranges::begin(a) == a);
assert(cuda::std::ranges::cbegin(a) == a);
int b[2][2] = {};
assert(cuda::std::ranges::begin(b) == b);
assert(cuda::std::ranges::cbegin(b) == b);
BeginMember c[2] = {};
assert(cuda::std::ranges::begin(c) == c);
assert(cuda::std::ranges::cbegin(c) == c);
return true;
}
struct BeginMemberReturnsInt
{
__host__ __device__ int begin() const;
};
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginMemberReturnsInt const&>, "");
struct BeginMemberReturnsVoidPtr
{
__host__ __device__ const void* begin() const;
};
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginMemberReturnsVoidPtr const&>, "");
struct EmptyBeginMember
{
struct iterator
{};
__host__ __device__ iterator begin() const;
};
static_assert(!cuda::std::is_invocable_v<RangeBeginT, EmptyBeginMember const&>, "");
struct PtrConvertibleBeginMember
{
struct iterator
{
__host__ __device__ operator int*() const;
};
__host__ __device__ iterator begin() const;
};
static_assert(!cuda::std::is_invocable_v<RangeBeginT, PtrConvertibleBeginMember const&>, "");
struct NonConstBeginMember
{
int x;
__host__ __device__ constexpr int* begin()
{
return &x;
}
};
static_assert(cuda::std::is_invocable_v<RangeBeginT, NonConstBeginMember&>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, NonConstBeginMember const&>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, NonConstBeginMember&>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, NonConstBeginMember const&>, "");
struct EnabledBorrowingBeginMember
{
__host__ __device__ constexpr const int* begin() const
{
return &globalBuff[0];
}
};
namespace cuda
{
namespace std
{
namespace ranges
{
template <>
_CCCL_INLINE_VAR constexpr bool enable_borrowed_range<EnabledBorrowingBeginMember> = true;
}
} // namespace std
} // namespace cuda
struct BeginMemberFunction
{
int x;
__host__ __device__ constexpr const int* begin() const
{
return &x;
}
__host__ __device__ friend int* begin(BeginMemberFunction const&);
};
struct EmptyPtrBeginMember
{
struct Empty
{};
Empty x;
__host__ __device__ constexpr const Empty* begin() const
{
return &x;
}
};
__host__ __device__ constexpr bool testBeginMember()
{
BeginMember a{};
assert(cuda::std::ranges::begin(a) == &a.x);
assert(cuda::std::ranges::cbegin(a) == &a.x);
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginMember&&>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, BeginMember&&>, "");
NonConstBeginMember b{};
assert(cuda::std::ranges::begin(b) == &b.x);
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, NonConstBeginMember&>, "");
EnabledBorrowingBeginMember c{};
assert(cuda::std::ranges::begin(c) == &globalBuff[0]);
assert(cuda::std::ranges::cbegin(c) == &globalBuff[0]);
assert(cuda::std::ranges::begin(cuda::std::move(c)) == &globalBuff[0]);
assert(cuda::std::ranges::cbegin(cuda::std::move(c)) == &globalBuff[0]);
BeginMemberFunction d{};
assert(cuda::std::ranges::begin(d) == &d.x);
assert(cuda::std::ranges::cbegin(d) == &d.x);
EmptyPtrBeginMember e{};
assert(cuda::std::ranges::begin(e) == &e.x);
assert(cuda::std::ranges::cbegin(e) == &e.x);
return true;
}
struct BeginFunction
{
int x;
__host__ __device__ friend constexpr const int* begin(BeginFunction const& bf)
{
return &bf.x;
}
};
static_assert(cuda::std::is_invocable_v<RangeBeginT, BeginFunction const&>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginFunction&&>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginFunction&>, "");
static_assert(cuda::std::is_invocable_v<RangeCBeginT, BeginFunction const&>, "");
static_assert(cuda::std::is_invocable_v<RangeCBeginT, BeginFunction&>, "");
struct BeginFunctionReturnsInt
{
__host__ __device__ friend int begin(BeginFunctionReturnsInt const&);
};
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginFunctionReturnsInt const&>, "");
struct BeginFunctionReturnsVoidPtr
{
__host__ __device__ friend void* begin(BeginFunctionReturnsVoidPtr const&);
};
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginFunctionReturnsVoidPtr const&>, "");
struct BeginFunctionReturnsPtrConvertible
{
struct iterator
{
__host__ __device__ operator int*() const;
};
__host__ __device__ friend iterator begin(BeginFunctionReturnsPtrConvertible const&);
};
static_assert(!cuda::std::is_invocable_v<RangeBeginT, BeginFunctionReturnsPtrConvertible const&>, "");
struct BeginFunctionByValue
{
__host__ __device__ friend constexpr const int* begin(BeginFunctionByValue)
{
return &globalBuff[1];
}
};
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, BeginFunctionByValue>, "");
struct BeginFunctionEnabledBorrowing
{
__host__ __device__ friend constexpr const int* begin(BeginFunctionEnabledBorrowing)
{
return &globalBuff[2];
}
};
namespace cuda
{
namespace std
{
namespace ranges
{
template <>
_CCCL_INLINE_VAR constexpr bool enable_borrowed_range<BeginFunctionEnabledBorrowing> = true;
}
} // namespace std
} // namespace cuda
struct BeginFunctionReturnsEmptyPtr
{
struct Empty
{};
Empty x;
__host__ __device__ friend constexpr const Empty* begin(BeginFunctionReturnsEmptyPtr const& bf)
{
return &bf.x;
}
};
struct BeginFunctionWithDataMember
{
int x;
int begin;
__host__ __device__ friend constexpr const int* begin(BeginFunctionWithDataMember const& bf)
{
return &bf.x;
}
};
struct BeginFunctionWithPrivateBeginMember
{
int y;
__host__ __device__ friend constexpr const int* begin(BeginFunctionWithPrivateBeginMember const& bf)
{
return &bf.y;
}
private:
__host__ __device__ const int* begin() const;
};
__host__ __device__ constexpr bool testBeginFunction()
{
BeginFunction a{};
const BeginFunction aa{};
static_assert(!cuda::std::invocable<RangeBeginT, decltype((a))>, "");
assert(cuda::std::ranges::cbegin(a) == &a.x);
assert(cuda::std::ranges::begin(aa) == &aa.x);
assert(cuda::std::ranges::cbegin(aa) == &aa.x);
BeginFunctionByValue b{};
const BeginFunctionByValue bb{};
assert(cuda::std::ranges::begin(b) == &globalBuff[1]);
assert(cuda::std::ranges::cbegin(b) == &globalBuff[1]);
assert(cuda::std::ranges::begin(bb) == &globalBuff[1]);
assert(cuda::std::ranges::cbegin(bb) == &globalBuff[1]);
BeginFunctionEnabledBorrowing c{};
const BeginFunctionEnabledBorrowing cc{};
assert(cuda::std::ranges::begin(cuda::std::move(c)) == &globalBuff[2]);
assert(cuda::std::ranges::cbegin(cuda::std::move(c)) == &globalBuff[2]);
assert(cuda::std::ranges::begin(cuda::std::move(cc)) == &globalBuff[2]);
assert(cuda::std::ranges::cbegin(cuda::std::move(cc)) == &globalBuff[2]);
BeginFunctionReturnsEmptyPtr d{};
const BeginFunctionReturnsEmptyPtr dd{};
static_assert(!cuda::std::invocable<RangeBeginT, decltype((d))>, "");
assert(cuda::std::ranges::cbegin(d) == &d.x);
assert(cuda::std::ranges::begin(dd) == &dd.x);
assert(cuda::std::ranges::cbegin(dd) == &dd.x);
BeginFunctionWithDataMember e{};
const BeginFunctionWithDataMember ee{};
static_assert(!cuda::std::invocable<RangeBeginT, decltype((e))>, "");
assert(cuda::std::ranges::begin(ee) == &ee.x);
assert(cuda::std::ranges::cbegin(e) == &e.x);
assert(cuda::std::ranges::cbegin(ee) == &ee.x);
BeginFunctionWithPrivateBeginMember f{};
const BeginFunctionWithPrivateBeginMember ff{};
static_assert(!cuda::std::invocable<RangeBeginT, decltype((f))>, "");
assert(cuda::std::ranges::cbegin(f) == &f.y);
assert(cuda::std::ranges::begin(ff) == &ff.y);
assert(cuda::std::ranges::cbegin(ff) == &ff.y);
return true;
}
static_assert(noexcept(cuda::std::ranges::begin(cuda::std::declval<int (&)[10]>())));
static_assert(noexcept(cuda::std::ranges::cbegin(cuda::std::declval<int (&)[10]>())));
// needs c++17's guaranteed copy elision
#if !TEST_COMPILER(MSVC2019) // broken noexcept
_CCCL_GLOBAL_CONSTANT struct NoThrowMemberBegin
{
__host__ __device__ ThrowingIterator<int> begin() const noexcept; // auto(t.begin()) doesn't throw
} ntmb;
static_assert(noexcept(cuda::std::ranges::begin(ntmb)), "");
static_assert(noexcept(cuda::std::ranges::cbegin(ntmb)), "");
_CCCL_GLOBAL_CONSTANT struct NoThrowADLBegin
{
__host__ __device__ friend ThrowingIterator<int> begin(NoThrowADLBegin&) noexcept; // auto(begin(t)) doesn't throw
__host__ __device__ friend ThrowingIterator<int> begin(const NoThrowADLBegin&) noexcept;
} ntab;
static_assert(noexcept(cuda::std::ranges::begin(ntab)), "");
static_assert(noexcept(cuda::std::ranges::cbegin(ntab)), "");
#endif // !TEST_COMPILER(MSVC2019)
_CCCL_GLOBAL_CONSTANT struct NoThrowMemberBeginReturnsRef
{
__host__ __device__ ThrowingIterator<int>& begin() const noexcept; // auto(t.begin()) may throw
} ntmbrr;
static_assert(!noexcept(cuda::std::ranges::begin(ntmbrr)), "");
static_assert(!noexcept(cuda::std::ranges::cbegin(ntmbrr)), "");
_CCCL_GLOBAL_CONSTANT struct BeginReturnsArrayRef
{
__host__ __device__ auto begin() const noexcept -> int (&)[10];
} brar;
static_assert(noexcept(cuda::std::ranges::begin(brar)), "");
static_assert(noexcept(cuda::std::ranges::cbegin(brar)), "");
#if TEST_STD_VER > 2017
// Test ADL-proofing.
struct Incomplete;
template <class T>
struct Holder
{
T t;
};
static_assert(!cuda::std::is_invocable_v<RangeBeginT, Holder<Incomplete>*>, "");
static_assert(!cuda::std::is_invocable_v<RangeBeginT, Holder<Incomplete>*&>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, Holder<Incomplete>*>, "");
static_assert(!cuda::std::is_invocable_v<RangeCBeginT, Holder<Incomplete>*&>, "");
#endif // TEST_STD_VER > 2017
int main(int, char**)
{
static_assert(testReturnTypes(), "");
testArray();
static_assert(testArray(), "");
testBeginMember();
static_assert(testBeginMember(), "");
testBeginFunction();
static_assert(testBeginFunction(), "");
#if !TEST_COMPILER(MSVC2019) // broken noexcept
unused(ntmb);
unused(ntab);
#endif // !TEST_COMPILER(MSVC2019)
unused(ntmbrr);
unused(brar);
return 0;
}