Mercurial > hg > CbC > CbC_llvm
view clang/test/SemaSYCL/unique_stable_name.cpp @ 222:81f6424ef0e3 llvm-original
LLVM original branch
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 18 Jul 2021 22:10:01 +0900 |
parents | 79ff65ed7e25 |
children | c4bab56944e8 |
line wrap: on
line source
// 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>(); }