forked from OSchip/llvm-project
216 lines
9.7 KiB
C++
216 lines
9.7 KiB
C++
// RUN: %clang_cc1 %s -std=c++17 -triple x86_64-pc-windows-msvc -fsycl-is-device -verify -fsyntax-only -Wno-unused
|
|
// RUN: %clang_cc1 %s -std=c++17 -triple x86_64-linux-gnu -fsycl-is-device -verify -fsyntax-only -Wno-unused
|
|
|
|
template <typename KernelName, typename KernelType>
|
|
[[clang::sycl_kernel]] void kernel_single_task(KernelType kernelFunc) { // #kernelSingleTask
|
|
kernelFunc();
|
|
}
|
|
|
|
// kernel1 - expect error
|
|
// The current function is named with a lambda (i.e., takes a lambda as a
|
|
// template parameter. Call the builtin on the current function then it is
|
|
// passed to a kernel. Test that passing the given function to the unique
|
|
// stable name builtin and then to the kernel throws an error because the
|
|
// latter causes its name mangling to change.
|
|
template <typename Func>
|
|
void kernel1func(const Func &F1) {
|
|
constexpr const char *F1_output = __builtin_sycl_unique_stable_name(Func); // #USN_F1
|
|
// expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
|
|
// expected-note@#kernel1func_call{{in instantiation of function template specialization}}
|
|
// expected-note@#USN_F1{{'__builtin_sycl_unique_stable_name' evaluated here}}
|
|
// expected-note@+1{{in instantiation of function template specialization}}
|
|
kernel_single_task<class kernel1>(F1); // #kernel1_call
|
|
}
|
|
|
|
void callkernel1() {
|
|
kernel1func([]() {}); // #kernel1func_call
|
|
}
|
|
|
|
// kernel2 - expect error
|
|
// The current function is named with a lambda (i.e., takes a lambda as a
|
|
// template parameter). Call the builtin on the given function,
|
|
// then an empty lambda is passed to kernel.
|
|
// Test that passing the given function to the unique stable name builtin and
|
|
// then passing a different lambda to the kernel still throws an error because
|
|
// the calling context is part of naming the kernel. Even though the given
|
|
// function (F2) is not passed to the kernel, its mangling changes due to
|
|
// kernel call with the unrelated lambda.
|
|
template <typename Func>
|
|
void kernel2func(const Func &F2) {
|
|
constexpr const char *F2_output = __builtin_sycl_unique_stable_name(Func); // #USN_F2
|
|
// expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
|
|
// expected-note@#kernel2func_call{{in instantiation of function template specialization}}
|
|
// expected-note@#USN_F2{{'__builtin_sycl_unique_stable_name' evaluated here}}
|
|
// expected-note@+1{{in instantiation of function template specialization}}
|
|
kernel_single_task<class kernel2>([]() {});
|
|
}
|
|
|
|
void callkernel2() {
|
|
kernel2func([]() {}); // #kernel2func_call
|
|
}
|
|
|
|
template <template <typename> typename Outer, typename Inner>
|
|
struct S {
|
|
void operator()() const;
|
|
};
|
|
|
|
template <typename Ty>
|
|
struct Tangerine {};
|
|
|
|
template <typename Func>
|
|
void kernel3_4func(const Func &F) {
|
|
// Test that passing the same lambda to two kernels does not cause an error
|
|
// because the kernel uses do not interfere with each other or invalidate
|
|
// the stable name in any way.
|
|
kernel_single_task<class kernel3>(F);
|
|
kernel_single_task<class kernel4>(F);
|
|
// Using the same functor twice should be fine
|
|
}
|
|
|
|
// kernel3 and kernel4 - expect no errors
|
|
void callkernel3_4() {
|
|
kernel3_4func([]() {});
|
|
}
|
|
|
|
template <typename T>
|
|
static constexpr const char *output1 = __builtin_sycl_unique_stable_name(T);
|
|
|
|
#define MACRO() \
|
|
auto l14 = []() { return 1; }; \
|
|
constexpr const char *l14_output = \
|
|
__builtin_sycl_unique_stable_name(decltype(l14));
|
|
|
|
int main() {
|
|
|
|
// kernel5 - expect no error
|
|
// Test that passing the lambda to the unique stable name builtin and then
|
|
// using the lambda in a way that does not contribute to the kernel name
|
|
// does not cause an error because the stable name is not invalidated in
|
|
// this situation.
|
|
auto l5 = []() {};
|
|
constexpr const char *l5_output =
|
|
__builtin_sycl_unique_stable_name(decltype(l5));
|
|
kernel_single_task<class kernel5>(
|
|
[=]() { l5(); }); // Used in the kernel, but not the kernel name itself
|
|
|
|
// kernel6 - expect error
|
|
// Test that passing the lambda to the unique stable name builtin and then
|
|
// using the same lambda in the naming of a kernel causes a diagnostic on the
|
|
// kernel use due to the change in results to the stable name.
|
|
auto l6 = []() { return 1; };
|
|
constexpr const char *l6_output =
|
|
__builtin_sycl_unique_stable_name(decltype(l6)); // #USN_l6
|
|
// expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
|
|
// expected-note@#USN_l6{{'__builtin_sycl_unique_stable_name' evaluated here}}
|
|
// expected-note@+1{{in instantiation of function template specialization}}
|
|
kernel_single_task<class kernel6>(l6); // Used in the kernel name after builtin
|
|
|
|
// kernel7 - expect error
|
|
// Same as kernel11 (below) except make the lambda part of naming the kernel.
|
|
// Test that passing a lambda to the unique stable name builtin and then
|
|
// passing a second lambda to the kernel throws an error because the first
|
|
// lambda is included in the signature of the second lambda, hence it changes
|
|
// the mangling of the kernel.
|
|
auto l7 = []() { return 1; };
|
|
auto l8 = [](decltype(l7) *derp = nullptr) { return 2; };
|
|
constexpr const char *l7_output =
|
|
__builtin_sycl_unique_stable_name(decltype(l7)); // #USN_l7
|
|
// expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
|
|
// expected-note@#USN_l7{{'__builtin_sycl_unique_stable_name' evaluated here}}
|
|
// expected-note@+1{{in instantiation of function template specialization}}
|
|
kernel_single_task<class kernel7>(l8);
|
|
|
|
// kernel8 and kernel9 - expect error
|
|
// Tests that passing a lambda to the unique stable name builtin and passing it
|
|
// to a kernel called with an if constexpr branch causes a diagnostic on the
|
|
// kernel9 use due to the change in the results to the stable name. This happens
|
|
// even though the use of kernel9 happens in the false branch of a constexpr if
|
|
// because both the true and the false branches cause the instantiation of
|
|
// kernel_single_task.
|
|
auto l9 = []() { return 1; };
|
|
auto l10 = []() { return 2; };
|
|
constexpr const char *l10_output =
|
|
__builtin_sycl_unique_stable_name(decltype(l10)); // #USN_l10
|
|
if constexpr (1) {
|
|
kernel_single_task<class kernel8>(l9);
|
|
} else {
|
|
// expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
|
|
// expected-note@#USN_l10{{'__builtin_sycl_unique_stable_name' evaluated here}}
|
|
// expected-note@+1{{in instantiation of function template specialization}}
|
|
kernel_single_task<class kernel9>(l10);
|
|
}
|
|
|
|
// kernel11 - expect no error
|
|
// Test that passing a lambda to the unique stable name builtin and then
|
|
// passing a second lambda capturing the first one to the kernel does not
|
|
// throw an error because the first lambda is not involved in naming the
|
|
// kernel i.e., the mangling does not change.
|
|
auto l11 = []() { return 1; };
|
|
auto l12 = [l11]() { return 2; };
|
|
constexpr const char *l11_output =
|
|
__builtin_sycl_unique_stable_name(decltype(l11));
|
|
kernel_single_task<class kernel11>(l12);
|
|
|
|
// kernel12 - expect an error
|
|
// Test that passing a lambda to the unique stable name builtin and then
|
|
// passing it to the kernel as a template template parameter causes a
|
|
// diagnostic on the kernel use due to template template parameter being
|
|
// involved in the mangling of the kernel name.
|
|
auto l13 = []() { return 1; };
|
|
constexpr const char *l13_output =
|
|
__builtin_sycl_unique_stable_name(decltype(l13)); // #USN_l13
|
|
// expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
|
|
// expected-note@#USN_l13{{'__builtin_sycl_unique_stable_name' evaluated here}}
|
|
// expected-note@+1{{in instantiation of function template specialization}}
|
|
kernel_single_task<class kernel12>(S<Tangerine, decltype(l13)>{});
|
|
|
|
// kernel13 - expect an error
|
|
// Test that passing a lambda to the unique stable name builtin within a macro
|
|
// and then calling the macro within the kernel causes an error on the kernel
|
|
// and diagnoses in all the expected places despite the use of a macro.
|
|
// expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}}
|
|
// expected-note@#USN_MACRO{{'__builtin_sycl_unique_stable_name' evaluated here}}
|
|
// expected-note@+1{{in instantiation of function template specialization}}
|
|
kernel_single_task<class kernel13>(
|
|
[]() {
|
|
MACRO(); // #USN_MACRO
|
|
});
|
|
}
|
|
|
|
namespace NS {}
|
|
|
|
void f() {
|
|
// expected-error@+1{{unknown type name 'bad_var'}}
|
|
__builtin_sycl_unique_stable_name(bad_var);
|
|
// expected-error@+1{{use of undeclared identifier 'bad'}}
|
|
__builtin_sycl_unique_stable_name(bad::type);
|
|
// expected-error@+1{{no type named 'still_bad' in namespace 'NS'}}
|
|
__builtin_sycl_unique_stable_name(NS::still_bad);
|
|
|
|
// FIXME: warning about side-effects in an unevaluated context expected, but
|
|
// none currently emitted.
|
|
int i = 0;
|
|
__builtin_sycl_unique_stable_name(decltype(i++));
|
|
|
|
// Tests that use within a VLA does not diagnose as a side-effecting use in
|
|
// an unevaluated context because the use within a VLA extent forces
|
|
// evaluation.
|
|
int j = 55;
|
|
__builtin_sycl_unique_stable_name(int[++j]); // no warning expected
|
|
}
|
|
|
|
template <typename T>
|
|
void f2() {
|
|
// expected-error@+1{{no type named 'bad_val' in 'St'}}
|
|
__builtin_sycl_unique_stable_name(typename T::bad_val);
|
|
// expected-error@+1{{no type named 'bad_type' in 'St'}}
|
|
__builtin_sycl_unique_stable_name(typename T::bad_type);
|
|
}
|
|
|
|
struct St {};
|
|
|
|
void use() {
|
|
// expected-note@+1{{in instantiation of}}
|
|
f2<St>();
|
|
}
|