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