1 // RUN: %clang_cc1 %s -std=c++17 -triple x86_64-pc-windows-msvc -fsycl-is-device -verify -fsyntax-only -Wno-unused 2 // RUN: %clang_cc1 %s -std=c++17 -triple x86_64-linux-gnu -fsycl-is-device -verify -fsyntax-only -Wno-unused 3 4 template <typename KernelName, typename KernelType> 5 [[clang::sycl_kernel]] void kernel_single_task(KernelType kernelFunc) { // #kernelSingleTask 6 kernelFunc(); 7 } 8 9 // kernel1 - expect error 10 // The current function is named with a lambda (i.e., takes a lambda as a 11 // template parameter. Call the builtin on the current function then it is 12 // passed to a kernel. Test that passing the given function to the unique 13 // stable name builtin and then to the kernel throws an error because the 14 // latter causes its name mangling to change. 15 template <typename Func> 16 void kernel1func(const Func &F1) { 17 constexpr const char *F1_output = __builtin_sycl_unique_stable_name(Func); // #USN_F1 18 // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}} 19 // expected-note@#kernel1func_call{{in instantiation of function template specialization}} 20 // expected-note@#USN_F1{{'__builtin_sycl_unique_stable_name' evaluated here}} 21 // expected-note@+1{{in instantiation of function template specialization}} 22 kernel_single_task<class kernel1>(F1); // #kernel1_call 23 } 24 25 void callkernel1() { 26 kernel1func([]() {}); // #kernel1func_call 27 } 28 29 // kernel2 - expect error 30 // The current function is named with a lambda (i.e., takes a lambda as a 31 // template parameter). Call the builtin on the given function, 32 // then an empty lambda is passed to kernel. 33 // Test that passing the given function to the unique stable name builtin and 34 // then passing a different lambda to the kernel still throws an error because 35 // the calling context is part of naming the kernel. Even though the given 36 // function (F2) is not passed to the kernel, its mangling changes due to 37 // kernel call with the unrelated lambda. 38 template <typename Func> 39 void kernel2func(const Func &F2) { 40 constexpr const char *F2_output = __builtin_sycl_unique_stable_name(Func); // #USN_F2 41 // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}} 42 // expected-note@#kernel2func_call{{in instantiation of function template specialization}} 43 // expected-note@#USN_F2{{'__builtin_sycl_unique_stable_name' evaluated here}} 44 // expected-note@+1{{in instantiation of function template specialization}} 45 kernel_single_task<class kernel2>([]() {}); 46 } 47 48 void callkernel2() { 49 kernel2func([]() {}); // #kernel2func_call 50 } 51 52 template <template <typename> typename Outer, typename Inner> 53 struct S { 54 void operator()() const; 55 }; 56 57 template <typename Ty> 58 struct Tangerine {}; 59 60 template <typename Func> 61 void kernel3_4func(const Func &F) { 62 // Test that passing the same lambda to two kernels does not cause an error 63 // because the kernel uses do not interfere with each other or invalidate 64 // the stable name in any way. 65 kernel_single_task<class kernel3>(F); 66 kernel_single_task<class kernel4>(F); 67 // Using the same functor twice should be fine 68 } 69 70 // kernel3 and kernel4 - expect no errors 71 void callkernel3_4() { 72 kernel3_4func([]() {}); 73 } 74 75 template <typename T> 76 static constexpr const char *output1 = __builtin_sycl_unique_stable_name(T); 77 78 #define MACRO() \ 79 auto l14 = []() { return 1; }; \ 80 constexpr const char *l14_output = \ 81 __builtin_sycl_unique_stable_name(decltype(l14)); 82 83 int main() { 84 85 // kernel5 - expect no error 86 // Test that passing the lambda to the unique stable name builtin and then 87 // using the lambda in a way that does not contribute to the kernel name 88 // does not cause an error because the stable name is not invalidated in 89 // this situation. 90 auto l5 = []() {}; 91 constexpr const char *l5_output = 92 __builtin_sycl_unique_stable_name(decltype(l5)); 93 kernel_single_task<class kernel5>( 94 [=]() { l5(); }); // Used in the kernel, but not the kernel name itself 95 96 // kernel6 - expect error 97 // Test that passing the lambda to the unique stable name builtin and then 98 // using the same lambda in the naming of a kernel causes a diagnostic on the 99 // kernel use due to the change in results to the stable name. 100 auto l6 = []() { return 1; }; 101 constexpr const char *l6_output = 102 __builtin_sycl_unique_stable_name(decltype(l6)); // #USN_l6 103 // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}} 104 // expected-note@#USN_l6{{'__builtin_sycl_unique_stable_name' evaluated here}} 105 // expected-note@+1{{in instantiation of function template specialization}} 106 kernel_single_task<class kernel6>(l6); // Used in the kernel name after builtin 107 108 // kernel7 - expect error 109 // Same as kernel11 (below) except make the lambda part of naming the kernel. 110 // Test that passing a lambda to the unique stable name builtin and then 111 // passing a second lambda to the kernel throws an error because the first 112 // lambda is included in the signature of the second lambda, hence it changes 113 // the mangling of the kernel. 114 auto l7 = []() { return 1; }; 115 auto l8 = [](decltype(l7) *derp = nullptr) { return 2; }; 116 constexpr const char *l7_output = 117 __builtin_sycl_unique_stable_name(decltype(l7)); // #USN_l7 118 // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}} 119 // expected-note@#USN_l7{{'__builtin_sycl_unique_stable_name' evaluated here}} 120 // expected-note@+1{{in instantiation of function template specialization}} 121 kernel_single_task<class kernel7>(l8); 122 123 // kernel8 and kernel9 - expect error 124 // Tests that passing a lambda to the unique stable name builtin and passing it 125 // to a kernel called with an if constexpr branch causes a diagnostic on the 126 // kernel9 use due to the change in the results to the stable name. This happens 127 // even though the use of kernel9 happens in the false branch of a constexpr if 128 // because both the true and the false branches cause the instantiation of 129 // kernel_single_task. 130 auto l9 = []() { return 1; }; 131 auto l10 = []() { return 2; }; 132 constexpr const char *l10_output = 133 __builtin_sycl_unique_stable_name(decltype(l10)); // #USN_l10 134 if constexpr (1) { 135 kernel_single_task<class kernel8>(l9); 136 } else { 137 // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}} 138 // expected-note@#USN_l10{{'__builtin_sycl_unique_stable_name' evaluated here}} 139 // expected-note@+1{{in instantiation of function template specialization}} 140 kernel_single_task<class kernel9>(l10); 141 } 142 143 // kernel11 - expect no error 144 // Test that passing a lambda to the unique stable name builtin and then 145 // passing a second lambda capturing the first one to the kernel does not 146 // throw an error because the first lambda is not involved in naming the 147 // kernel i.e., the mangling does not change. 148 auto l11 = []() { return 1; }; 149 auto l12 = [l11]() { return 2; }; 150 constexpr const char *l11_output = 151 __builtin_sycl_unique_stable_name(decltype(l11)); 152 kernel_single_task<class kernel11>(l12); 153 154 // kernel12 - expect an error 155 // Test that passing a lambda to the unique stable name builtin and then 156 // passing it to the kernel as a template template parameter causes a 157 // diagnostic on the kernel use due to template template parameter being 158 // involved in the mangling of the kernel name. 159 auto l13 = []() { return 1; }; 160 constexpr const char *l13_output = 161 __builtin_sycl_unique_stable_name(decltype(l13)); // #USN_l13 162 // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}} 163 // expected-note@#USN_l13{{'__builtin_sycl_unique_stable_name' evaluated here}} 164 // expected-note@+1{{in instantiation of function template specialization}} 165 kernel_single_task<class kernel12>(S<Tangerine, decltype(l13)>{}); 166 167 // kernel13 - expect an error 168 // Test that passing a lambda to the unique stable name builtin within a macro 169 // and then calling the macro within the kernel causes an error on the kernel 170 // and diagnoses in all the expected places despite the use of a macro. 171 // expected-error@#kernelSingleTask{{kernel instantiation changes the result of an evaluated '__builtin_sycl_unique_stable_name'}} 172 // expected-note@#USN_MACRO{{'__builtin_sycl_unique_stable_name' evaluated here}} 173 // expected-note@+1{{in instantiation of function template specialization}} 174 kernel_single_task<class kernel13>( 175 []() { 176 MACRO(); // #USN_MACRO 177 }); 178 } 179 180 namespace NS {} 181 182 void f() { 183 // expected-error@+1{{unknown type name 'bad_var'}} 184 __builtin_sycl_unique_stable_name(bad_var); 185 // expected-error@+1{{use of undeclared identifier 'bad'}} 186 __builtin_sycl_unique_stable_name(bad::type); 187 // expected-error@+1{{no type named 'still_bad' in namespace 'NS'}} 188 __builtin_sycl_unique_stable_name(NS::still_bad); 189 190 // FIXME: warning about side-effects in an unevaluated context expected, but 191 // none currently emitted. 192 int i = 0; 193 __builtin_sycl_unique_stable_name(decltype(i++)); 194 195 // Tests that use within a VLA does not diagnose as a side-effecting use in 196 // an unevaluated context because the use within a VLA extent forces 197 // evaluation. 198 int j = 55; 199 __builtin_sycl_unique_stable_name(int[++j]); // no warning expected 200 } 201 202 template <typename T> 203 void f2() { 204 // expected-error@+1{{no type named 'bad_val' in 'St'}} 205 __builtin_sycl_unique_stable_name(typename T::bad_val); 206 // expected-error@+1{{no type named 'bad_type' in 'St'}} 207 __builtin_sycl_unique_stable_name(typename T::bad_type); 208 } 209 210 struct St {}; 211 212 void use() { 213 // expected-note@+1{{in instantiation of}} 214 f2<St>(); 215 } 216