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
4 template <typename KernelName
, typename KernelType
>
5 [[clang::sycl_kernel
]] void kernel_single_task(KernelType kernelFunc
) { // #kernelSingleTask
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
22 kernel1func([]() {}); // #kernel1func_call
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
>([]() {});
41 kernel2func([]() {}); // #kernel2func_call
44 template <template <typename
> typename Outer
, typename Inner
>
46 void operator()() const;
49 template <typename Ty
>
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
62 // kernel3 and kernel4 - expect no errors
63 void callkernel3_4() {
64 kernel3_4func([]() {});
68 static constexpr const char *output1
= __builtin_sycl_unique_stable_name(T
);
71 auto l14 = []() { return 1; }; \
72 constexpr const char *l14_output = \
73 __builtin_sycl_unique_stable_name(decltype(l14));
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
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
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
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
);
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
121 kernel_single_task
<class kernel8
>(l9
);
123 kernel_single_task
<class kernel9
>(l10
);
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
);
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
)>{});
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
151 kernel_single_task
<class kernel13
>(
153 MACRO(); // #USN_MACRO
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
);
167 // FIXME: warning about side-effects in an unevaluated context expected, but
168 // none currently emitted.
170 __builtin_sycl_unique_stable_name(decltype(i
++));
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
176 __builtin_sycl_unique_stable_name(int[++j
]); // expected-warning {{variable length arrays in C++ are a Clang extension}} \
177 expected
-note
{{a constant expression cannot modify an object that is visible outside that expression
}}
180 template <typename T
>
182 // expected-error@+1{{no type named 'bad_val' in 'St'}}
183 __builtin_sycl_unique_stable_name(typename
T::bad_val
);
184 // expected-error@+1{{no type named 'bad_type' in 'St'}}
185 __builtin_sycl_unique_stable_name(typename
T::bad_type
);
191 // expected-note@+1{{in instantiation of}}
195 // A previous implementation resulted in this being an example of the
196 // kernel-ordering and lexical lambda ordering issue.
197 void out_of_order_use() {
201 kernel_single_task
<decltype(y
)>(y
);
202 constexpr auto USN
=__builtin_sycl_unique_stable_name(decltype(y
));
204 kernel_single_task
<decltype(x
)>(x
);