xref: /aosp_15_r20/external/clang/test/SemaCUDA/function-overload.cu (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // REQUIRES: x86-registered-target
2*67e74705SXin Li // REQUIRES: nvptx-registered-target
3*67e74705SXin Li 
4*67e74705SXin Li // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
5*67e74705SXin Li // RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s
6*67e74705SXin Li 
7*67e74705SXin Li #include "Inputs/cuda.h"
8*67e74705SXin Li 
9*67e74705SXin Li // Opaque return types used to check that we pick the right overloads.
10*67e74705SXin Li struct HostReturnTy {};
11*67e74705SXin Li struct HostReturnTy2 {};
12*67e74705SXin Li struct DeviceReturnTy {};
13*67e74705SXin Li struct DeviceReturnTy2 {};
14*67e74705SXin Li struct HostDeviceReturnTy {};
15*67e74705SXin Li struct TemplateReturnTy {};
16*67e74705SXin Li 
17*67e74705SXin Li typedef HostReturnTy (*HostFnPtr)();
18*67e74705SXin Li typedef DeviceReturnTy (*DeviceFnPtr)();
19*67e74705SXin Li typedef HostDeviceReturnTy (*HostDeviceFnPtr)();
20*67e74705SXin Li typedef void (*GlobalFnPtr)();  // __global__ functions must return void.
21*67e74705SXin Li 
22*67e74705SXin Li // CurrentReturnTy is {HostReturnTy,DeviceReturnTy} during {host,device}
23*67e74705SXin Li // compilation.
24*67e74705SXin Li #ifdef __CUDA_ARCH__
25*67e74705SXin Li typedef DeviceReturnTy CurrentReturnTy;
26*67e74705SXin Li #else
27*67e74705SXin Li typedef HostReturnTy CurrentReturnTy;
28*67e74705SXin Li #endif
29*67e74705SXin Li 
30*67e74705SXin Li // CurrentFnPtr is a function pointer to a {host,device} function during
31*67e74705SXin Li // {host,device} compilation.
32*67e74705SXin Li typedef CurrentReturnTy (*CurrentFnPtr)();
33*67e74705SXin Li 
34*67e74705SXin Li // Host and unattributed functions can't be overloaded.
hh()35*67e74705SXin Li __host__ void hh() {} // expected-note {{previous definition is here}}
hh()36*67e74705SXin Li void hh() {} // expected-error {{redefinition of 'hh'}}
37*67e74705SXin Li 
38*67e74705SXin Li // H/D overloading is OK.
dh()39*67e74705SXin Li __host__ HostReturnTy dh() { return HostReturnTy(); }
dh()40*67e74705SXin Li __device__ DeviceReturnTy dh() { return DeviceReturnTy(); }
41*67e74705SXin Li 
42*67e74705SXin Li // H/HD and D/HD are not allowed.
hdh()43*67e74705SXin Li __host__ __device__ int hdh() { return 0; } // expected-note {{previous definition is here}}
hdh()44*67e74705SXin Li __host__ int hdh() { return 0; }            // expected-error {{redefinition of 'hdh'}}
45*67e74705SXin Li 
hhd()46*67e74705SXin Li __host__ int hhd() { return 0; }            // expected-note {{previous definition is here}}
hhd()47*67e74705SXin Li __host__ __device__ int hhd() { return 0; } // expected-error {{redefinition of 'hhd'}}
48*67e74705SXin Li // expected-warning@-1 {{attribute declaration must precede definition}}
49*67e74705SXin Li // expected-note@-3 {{previous definition is here}}
50*67e74705SXin Li 
hdd()51*67e74705SXin Li __host__ __device__ int hdd() { return 0; } // expected-note {{previous definition is here}}
hdd()52*67e74705SXin Li __device__ int hdd() { return 0; }          // expected-error {{redefinition of 'hdd'}}
53*67e74705SXin Li 
dhd()54*67e74705SXin Li __device__ int dhd() { return 0; }          // expected-note {{previous definition is here}}
dhd()55*67e74705SXin Li __host__ __device__ int dhd() { return 0; } // expected-error {{redefinition of 'dhd'}}
56*67e74705SXin Li // expected-warning@-1 {{attribute declaration must precede definition}}
57*67e74705SXin Li // expected-note@-3 {{previous definition is here}}
58*67e74705SXin Li 
59*67e74705SXin Li // Same tests for extern "C" functions.
chh()60*67e74705SXin Li extern "C" __host__ int chh() { return 0; } // expected-note {{previous definition is here}}
chh()61*67e74705SXin Li extern "C" int chh() { return 0; }          // expected-error {{redefinition of 'chh'}}
62*67e74705SXin Li 
63*67e74705SXin Li // H/D overloading is OK.
cdh()64*67e74705SXin Li extern "C" __device__ DeviceReturnTy cdh() { return DeviceReturnTy(); }
cdh()65*67e74705SXin Li extern "C" __host__ HostReturnTy cdh() { return HostReturnTy(); }
66*67e74705SXin Li 
67*67e74705SXin Li // H/HD and D/HD overloading is not allowed.
chhd1()68*67e74705SXin Li extern "C" __host__ __device__ int chhd1() { return 0; } // expected-note {{previous definition is here}}
chhd1()69*67e74705SXin Li extern "C" __host__ int chhd1() { return 0; }            // expected-error {{redefinition of 'chhd1'}}
70*67e74705SXin Li 
chhd2()71*67e74705SXin Li extern "C" __host__ int chhd2() { return 0; }            // expected-note {{previous definition is here}}
chhd2()72*67e74705SXin Li extern "C" __host__ __device__ int chhd2() { return 0; } // expected-error {{redefinition of 'chhd2'}}
73*67e74705SXin Li // expected-warning@-1 {{attribute declaration must precede definition}}
74*67e74705SXin Li // expected-note@-3 {{previous definition is here}}
75*67e74705SXin Li 
76*67e74705SXin Li // Helper functions to verify calling restrictions.
d()77*67e74705SXin Li __device__ DeviceReturnTy d() { return DeviceReturnTy(); }
78*67e74705SXin Li // expected-note@-1 1+ {{'d' declared here}}
79*67e74705SXin Li // expected-note@-2 1+ {{candidate function not viable: call to __device__ function from __host__ function}}
80*67e74705SXin Li // expected-note@-3 0+ {{candidate function not viable: call to __device__ function from __host__ __device__ function}}
81*67e74705SXin Li 
h()82*67e74705SXin Li __host__ HostReturnTy h() { return HostReturnTy(); }
83*67e74705SXin Li // expected-note@-1 1+ {{'h' declared here}}
84*67e74705SXin Li // expected-note@-2 1+ {{candidate function not viable: call to __host__ function from __device__ function}}
85*67e74705SXin Li // expected-note@-3 0+ {{candidate function not viable: call to __host__ function from __host__ __device__ function}}
86*67e74705SXin Li // expected-note@-4 1+ {{candidate function not viable: call to __host__ function from __global__ function}}
87*67e74705SXin Li 
g()88*67e74705SXin Li __global__ void g() {}
89*67e74705SXin Li // expected-note@-1 1+ {{'g' declared here}}
90*67e74705SXin Li // expected-note@-2 1+ {{candidate function not viable: call to __global__ function from __device__ function}}
91*67e74705SXin Li // expected-note@-3 0+ {{candidate function not viable: call to __global__ function from __host__ __device__ function}}
92*67e74705SXin Li // expected-note@-4 1+ {{candidate function not viable: call to __global__ function from __global__ function}}
93*67e74705SXin Li 
cd()94*67e74705SXin Li extern "C" __device__ DeviceReturnTy cd() { return DeviceReturnTy(); }
95*67e74705SXin Li // expected-note@-1 1+ {{'cd' declared here}}
96*67e74705SXin Li // expected-note@-2 1+ {{candidate function not viable: call to __device__ function from __host__ function}}
97*67e74705SXin Li // expected-note@-3 0+ {{candidate function not viable: call to __device__ function from __host__ __device__ function}}
98*67e74705SXin Li 
ch()99*67e74705SXin Li extern "C" __host__ HostReturnTy ch() { return HostReturnTy(); }
100*67e74705SXin Li // expected-note@-1 1+ {{'ch' declared here}}
101*67e74705SXin Li // expected-note@-2 1+ {{candidate function not viable: call to __host__ function from __device__ function}}
102*67e74705SXin Li // expected-note@-3 0+ {{candidate function not viable: call to __host__ function from __host__ __device__ function}}
103*67e74705SXin Li // expected-note@-4 1+ {{candidate function not viable: call to __host__ function from __global__ function}}
104*67e74705SXin Li 
hostf()105*67e74705SXin Li __host__ void hostf() {
106*67e74705SXin Li   DeviceFnPtr fp_d = d;         // expected-error {{reference to __device__ function 'd' in __host__ function}}
107*67e74705SXin Li   DeviceReturnTy ret_d = d();   // expected-error {{no matching function for call to 'd'}}
108*67e74705SXin Li   DeviceFnPtr fp_cd = cd;       // expected-error {{reference to __device__ function 'cd' in __host__ function}}
109*67e74705SXin Li   DeviceReturnTy ret_cd = cd(); // expected-error {{no matching function for call to 'cd'}}
110*67e74705SXin Li 
111*67e74705SXin Li   HostFnPtr fp_h = h;
112*67e74705SXin Li   HostReturnTy ret_h = h();
113*67e74705SXin Li   HostFnPtr fp_ch = ch;
114*67e74705SXin Li   HostReturnTy ret_ch = ch();
115*67e74705SXin Li 
116*67e74705SXin Li   HostFnPtr fp_dh = dh;
117*67e74705SXin Li   HostReturnTy ret_dh = dh();
118*67e74705SXin Li   HostFnPtr fp_cdh = cdh;
119*67e74705SXin Li   HostReturnTy ret_cdh = cdh();
120*67e74705SXin Li 
121*67e74705SXin Li   GlobalFnPtr fp_g = g;
122*67e74705SXin Li   g(); // expected-error {{call to global function g not configured}}
123*67e74705SXin Li   g<<<0, 0>>>();
124*67e74705SXin Li }
125*67e74705SXin Li 
devicef()126*67e74705SXin Li __device__ void devicef() {
127*67e74705SXin Li   DeviceFnPtr fp_d = d;
128*67e74705SXin Li   DeviceReturnTy ret_d = d();
129*67e74705SXin Li   DeviceFnPtr fp_cd = cd;
130*67e74705SXin Li   DeviceReturnTy ret_cd = cd();
131*67e74705SXin Li 
132*67e74705SXin Li   HostFnPtr fp_h = h;         // expected-error {{reference to __host__ function 'h' in __device__ function}}
133*67e74705SXin Li   HostReturnTy ret_h = h();   // expected-error {{no matching function for call to 'h'}}
134*67e74705SXin Li   HostFnPtr fp_ch = ch;       // expected-error {{reference to __host__ function 'ch' in __device__ function}}
135*67e74705SXin Li   HostReturnTy ret_ch = ch(); // expected-error {{no matching function for call to 'ch'}}
136*67e74705SXin Li 
137*67e74705SXin Li   DeviceFnPtr fp_dh = dh;
138*67e74705SXin Li   DeviceReturnTy ret_dh = dh();
139*67e74705SXin Li   DeviceFnPtr fp_cdh = cdh;
140*67e74705SXin Li   DeviceReturnTy ret_cdh = cdh();
141*67e74705SXin Li 
142*67e74705SXin Li   GlobalFnPtr fp_g = g; // expected-error {{reference to __global__ function 'g' in __device__ function}}
143*67e74705SXin Li   g(); // expected-error {{no matching function for call to 'g'}}
144*67e74705SXin Li   g<<<0,0>>>(); // expected-error {{reference to __global__ function 'g' in __device__ function}}
145*67e74705SXin Li }
146*67e74705SXin Li 
globalf()147*67e74705SXin Li __global__ void globalf() {
148*67e74705SXin Li   DeviceFnPtr fp_d = d;
149*67e74705SXin Li   DeviceReturnTy ret_d = d();
150*67e74705SXin Li   DeviceFnPtr fp_cd = cd;
151*67e74705SXin Li   DeviceReturnTy ret_cd = cd();
152*67e74705SXin Li 
153*67e74705SXin Li   HostFnPtr fp_h = h;         // expected-error {{reference to __host__ function 'h' in __global__ function}}
154*67e74705SXin Li   HostReturnTy ret_h = h();   // expected-error {{no matching function for call to 'h'}}
155*67e74705SXin Li   HostFnPtr fp_ch = ch;       // expected-error {{reference to __host__ function 'ch' in __global__ function}}
156*67e74705SXin Li   HostReturnTy ret_ch = ch(); // expected-error {{no matching function for call to 'ch'}}
157*67e74705SXin Li 
158*67e74705SXin Li   DeviceFnPtr fp_dh = dh;
159*67e74705SXin Li   DeviceReturnTy ret_dh = dh();
160*67e74705SXin Li   DeviceFnPtr fp_cdh = cdh;
161*67e74705SXin Li   DeviceReturnTy ret_cdh = cdh();
162*67e74705SXin Li 
163*67e74705SXin Li   GlobalFnPtr fp_g = g; // expected-error {{reference to __global__ function 'g' in __global__ function}}
164*67e74705SXin Li   g(); // expected-error {{no matching function for call to 'g'}}
165*67e74705SXin Li   g<<<0,0>>>(); // expected-error {{reference to __global__ function 'g' in __global__ function}}
166*67e74705SXin Li }
167*67e74705SXin Li 
hostdevicef()168*67e74705SXin Li __host__ __device__ void hostdevicef() {
169*67e74705SXin Li   DeviceFnPtr fp_d = d;
170*67e74705SXin Li   DeviceReturnTy ret_d = d();
171*67e74705SXin Li   DeviceFnPtr fp_cd = cd;
172*67e74705SXin Li   DeviceReturnTy ret_cd = cd();
173*67e74705SXin Li 
174*67e74705SXin Li   HostFnPtr fp_h = h;
175*67e74705SXin Li   HostReturnTy ret_h = h();
176*67e74705SXin Li   HostFnPtr fp_ch = ch;
177*67e74705SXin Li   HostReturnTy ret_ch = ch();
178*67e74705SXin Li 
179*67e74705SXin Li   CurrentFnPtr fp_dh = dh;
180*67e74705SXin Li   CurrentReturnTy ret_dh = dh();
181*67e74705SXin Li   CurrentFnPtr fp_cdh = cdh;
182*67e74705SXin Li   CurrentReturnTy ret_cdh = cdh();
183*67e74705SXin Li 
184*67e74705SXin Li   GlobalFnPtr fp_g = g;
185*67e74705SXin Li #if defined(__CUDA_ARCH__)
186*67e74705SXin Li   // expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
187*67e74705SXin Li #endif
188*67e74705SXin Li   g();
189*67e74705SXin Li   g<<<0,0>>>();
190*67e74705SXin Li #if !defined(__CUDA_ARCH__)
191*67e74705SXin Li   // expected-error@-3 {{call to global function g not configured}}
192*67e74705SXin Li #else
193*67e74705SXin Li   // expected-error@-5 {{no matching function for call to 'g'}}
194*67e74705SXin Li   // expected-error@-5 {{reference to __global__ function 'g' in __host__ __device__ function}}
195*67e74705SXin Li #endif  // __CUDA_ARCH__
196*67e74705SXin Li }
197*67e74705SXin Li 
198*67e74705SXin Li // Test for address of overloaded function resolution in the global context.
199*67e74705SXin Li HostFnPtr fp_h = h;
200*67e74705SXin Li HostFnPtr fp_ch = ch;
201*67e74705SXin Li CurrentFnPtr fp_dh = dh;
202*67e74705SXin Li CurrentFnPtr fp_cdh = cdh;
203*67e74705SXin Li GlobalFnPtr fp_g = g;
204*67e74705SXin Li 
205*67e74705SXin Li 
206*67e74705SXin Li // Test overloading of destructors
207*67e74705SXin Li // Can't mix H and unattributed destructors
208*67e74705SXin Li struct d_h {
~d_hd_h209*67e74705SXin Li   ~d_h() {} // expected-note {{previous declaration is here}}
~d_hd_h210*67e74705SXin Li   __host__ ~d_h() {} // expected-error {{destructor cannot be redeclared}}
211*67e74705SXin Li };
212*67e74705SXin Li 
213*67e74705SXin Li // H/D overloading is OK
214*67e74705SXin Li struct d_dh {
~d_dhd_dh215*67e74705SXin Li   __device__ ~d_dh() {}
~d_dhd_dh216*67e74705SXin Li   __host__ ~d_dh() {}
217*67e74705SXin Li };
218*67e74705SXin Li 
219*67e74705SXin Li // HD is OK
220*67e74705SXin Li struct d_hd {
~d_hdd_hd221*67e74705SXin Li   __host__ __device__ ~d_hd() {}
222*67e74705SXin Li };
223*67e74705SXin Li 
224*67e74705SXin Li // Mixing H/D and HD is not allowed.
225*67e74705SXin Li struct d_dhhd {
~d_dhhdd_dhhd226*67e74705SXin Li   __device__ ~d_dhhd() {}
~d_dhhdd_dhhd227*67e74705SXin Li   __host__ ~d_dhhd() {} // expected-note {{previous declaration is here}}
~d_dhhdd_dhhd228*67e74705SXin Li   __host__ __device__ ~d_dhhd() {} // expected-error {{destructor cannot be redeclared}}
229*67e74705SXin Li };
230*67e74705SXin Li 
231*67e74705SXin Li struct d_hhd {
~d_hhdd_hhd232*67e74705SXin Li   __host__ ~d_hhd() {} // expected-note {{previous declaration is here}}
~d_hhdd_hhd233*67e74705SXin Li   __host__ __device__ ~d_hhd() {} // expected-error {{destructor cannot be redeclared}}
234*67e74705SXin Li };
235*67e74705SXin Li 
236*67e74705SXin Li struct d_hdh {
~d_hdhd_hdh237*67e74705SXin Li   __host__ __device__ ~d_hdh() {} // expected-note {{previous declaration is here}}
~d_hdhd_hdh238*67e74705SXin Li   __host__ ~d_hdh() {} // expected-error {{destructor cannot be redeclared}}
239*67e74705SXin Li };
240*67e74705SXin Li 
241*67e74705SXin Li struct d_dhd {
~d_dhdd_dhd242*67e74705SXin Li   __device__ ~d_dhd() {} // expected-note {{previous declaration is here}}
~d_dhdd_dhd243*67e74705SXin Li   __host__ __device__ ~d_dhd() {} // expected-error {{destructor cannot be redeclared}}
244*67e74705SXin Li };
245*67e74705SXin Li 
246*67e74705SXin Li struct d_hdd {
~d_hddd_hdd247*67e74705SXin Li   __host__ __device__ ~d_hdd() {} // expected-note {{previous declaration is here}}
~d_hddd_hdd248*67e74705SXin Li   __device__ ~d_hdd() {} // expected-error {{destructor cannot be redeclared}}
249*67e74705SXin Li };
250*67e74705SXin Li 
251*67e74705SXin Li // Test overloading of member functions
252*67e74705SXin Li struct m_h {
253*67e74705SXin Li   void operator delete(void *ptr); // expected-note {{previous declaration is here}}
254*67e74705SXin Li   __host__ void operator delete(void *ptr); // expected-error {{class member cannot be redeclared}}
255*67e74705SXin Li };
256*67e74705SXin Li 
257*67e74705SXin Li // D/H overloading is OK
258*67e74705SXin Li struct m_dh {
259*67e74705SXin Li   __device__ void operator delete(void *ptr);
260*67e74705SXin Li   __host__ void operator delete(void *ptr);
261*67e74705SXin Li };
262*67e74705SXin Li 
263*67e74705SXin Li // HD by itself is OK
264*67e74705SXin Li struct m_hd {
265*67e74705SXin Li   __device__ __host__ void operator delete(void *ptr);
266*67e74705SXin Li };
267*67e74705SXin Li 
268*67e74705SXin Li struct m_hhd {
operator deletem_hhd269*67e74705SXin Li   __host__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
operator deletem_hhd270*67e74705SXin Li   __host__ __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
271*67e74705SXin Li };
272*67e74705SXin Li 
273*67e74705SXin Li struct m_hdh {
operator deletem_hdh274*67e74705SXin Li   __host__ __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
operator deletem_hdh275*67e74705SXin Li   __host__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
276*67e74705SXin Li };
277*67e74705SXin Li 
278*67e74705SXin Li struct m_dhd {
operator deletem_dhd279*67e74705SXin Li   __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
operator deletem_dhd280*67e74705SXin Li   __host__ __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
281*67e74705SXin Li };
282*67e74705SXin Li 
283*67e74705SXin Li struct m_hdd {
operator deletem_hdd284*67e74705SXin Li   __host__ __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
operator deletem_hdd285*67e74705SXin Li   __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
286*67e74705SXin Li };
287*67e74705SXin Li 
288*67e74705SXin Li // __global__ functions can't be overloaded based on attribute
289*67e74705SXin Li // difference.
290*67e74705SXin Li struct G {
291*67e74705SXin Li   friend void friend_of_g(G &arg);
292*67e74705SXin Li private:
293*67e74705SXin Li   int x;
294*67e74705SXin Li };
friend_of_g(G & arg)295*67e74705SXin Li __global__ void friend_of_g(G &arg) { int x = arg.x; } // expected-note {{previous definition is here}}
friend_of_g(G & arg)296*67e74705SXin Li void friend_of_g(G &arg) { int x = arg.x; } // expected-error {{redefinition of 'friend_of_g'}}
297*67e74705SXin Li 
298*67e74705SXin Li // HD functions are sometimes allowed to call H or D functions -- this
299*67e74705SXin Li // is an artifact of the source-to-source splitting performed by nvcc
300*67e74705SXin Li // that we need to mimic. During device mode compilation in nvcc, host
301*67e74705SXin Li // functions aren't present at all, so don't participate in
302*67e74705SXin Li // overloading. But in clang, H and D functions are present in both
303*67e74705SXin Li // compilation modes. Clang normally uses the target attribute as a
304*67e74705SXin Li // tiebreaker between overloads with otherwise identical priority, but
305*67e74705SXin Li // in order to match nvcc's behavior, we sometimes need to wholly
306*67e74705SXin Li // discard overloads that would not be present during compilation
307*67e74705SXin Li // under nvcc.
308*67e74705SXin Li 
template_vs_function(T arg)309*67e74705SXin Li template <typename T> TemplateReturnTy template_vs_function(T arg) {
310*67e74705SXin Li   return TemplateReturnTy();
311*67e74705SXin Li }
template_vs_function(float arg)312*67e74705SXin Li __device__ DeviceReturnTy template_vs_function(float arg) {
313*67e74705SXin Li   return DeviceReturnTy();
314*67e74705SXin Li }
315*67e74705SXin Li 
316*67e74705SXin Li // Here we expect to call the templated function during host compilation, even
317*67e74705SXin Li // if -fcuda-disable-target-call-checks is passed, and even though C++ overload
318*67e74705SXin Li // rules prefer the non-templated function.
test_host_device_calls_template(void)319*67e74705SXin Li __host__ __device__ void test_host_device_calls_template(void) {
320*67e74705SXin Li #ifdef __CUDA_ARCH__
321*67e74705SXin Li   typedef DeviceReturnTy ExpectedReturnTy;
322*67e74705SXin Li #else
323*67e74705SXin Li   typedef TemplateReturnTy ExpectedReturnTy;
324*67e74705SXin Li #endif
325*67e74705SXin Li 
326*67e74705SXin Li   ExpectedReturnTy ret1 = template_vs_function(1.0f);
327*67e74705SXin Li   ExpectedReturnTy ret2 = template_vs_function(2.0);
328*67e74705SXin Li }
329*67e74705SXin Li 
330*67e74705SXin Li // Calls from __host__ and __device__ functions should always call the
331*67e74705SXin Li // overloaded function that matches their mode.
test_host_calls_template_fn()332*67e74705SXin Li __host__ void test_host_calls_template_fn() {
333*67e74705SXin Li   TemplateReturnTy ret1 = template_vs_function(1.0f);
334*67e74705SXin Li   TemplateReturnTy ret2 = template_vs_function(2.0);
335*67e74705SXin Li }
336*67e74705SXin Li 
test_device_calls_template_fn()337*67e74705SXin Li __device__ void test_device_calls_template_fn() {
338*67e74705SXin Li   DeviceReturnTy ret1 = template_vs_function(1.0f);
339*67e74705SXin Li   DeviceReturnTy ret2 = template_vs_function(2.0);
340*67e74705SXin Li }
341*67e74705SXin Li 
342*67e74705SXin Li // If we have a mix of HD and H-only or D-only candidates in the overload set,
343*67e74705SXin Li // normal C++ overload resolution rules apply first.
template_vs_hd_function(T arg)344*67e74705SXin Li template <typename T> TemplateReturnTy template_vs_hd_function(T arg) {
345*67e74705SXin Li   return TemplateReturnTy();
346*67e74705SXin Li }
template_vs_hd_function(float arg)347*67e74705SXin Li __host__ __device__ HostDeviceReturnTy template_vs_hd_function(float arg) {
348*67e74705SXin Li   return HostDeviceReturnTy();
349*67e74705SXin Li }
350*67e74705SXin Li 
test_host_device_calls_hd_template()351*67e74705SXin Li __host__ __device__ void test_host_device_calls_hd_template() {
352*67e74705SXin Li   HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
353*67e74705SXin Li   TemplateReturnTy ret2 = template_vs_hd_function(1);
354*67e74705SXin Li }
355*67e74705SXin Li 
test_host_calls_hd_template()356*67e74705SXin Li __host__ void test_host_calls_hd_template() {
357*67e74705SXin Li   HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
358*67e74705SXin Li   TemplateReturnTy ret2 = template_vs_hd_function(1);
359*67e74705SXin Li }
360*67e74705SXin Li 
test_device_calls_hd_template()361*67e74705SXin Li __device__ void test_device_calls_hd_template() {
362*67e74705SXin Li   HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
363*67e74705SXin Li   // Host-only function template is not callable with strict call checks,
364*67e74705SXin Li   // so for device side HD function will be the only choice.
365*67e74705SXin Li   HostDeviceReturnTy ret2 = template_vs_hd_function(1);
366*67e74705SXin Li }
367*67e74705SXin Li 
368*67e74705SXin Li // Check that overloads still work the same way on both host and
369*67e74705SXin Li // device side when the overload set contains only functions from one
370*67e74705SXin Li // side of compilation.
device_only_function(int arg)371*67e74705SXin Li __device__ DeviceReturnTy device_only_function(int arg) { return DeviceReturnTy(); }
device_only_function(float arg)372*67e74705SXin Li __device__ DeviceReturnTy2 device_only_function(float arg) { return DeviceReturnTy2(); }
host_only_function(int arg)373*67e74705SXin Li __host__ HostReturnTy host_only_function(int arg) { return HostReturnTy(); }
host_only_function(float arg)374*67e74705SXin Li __host__ HostReturnTy2 host_only_function(float arg) { return HostReturnTy2(); }
375*67e74705SXin Li 
test_host_device_single_side_overloading()376*67e74705SXin Li __host__ __device__ void test_host_device_single_side_overloading() {
377*67e74705SXin Li   DeviceReturnTy ret1 = device_only_function(1);
378*67e74705SXin Li   DeviceReturnTy2 ret2 = device_only_function(1.0f);
379*67e74705SXin Li   HostReturnTy ret3 = host_only_function(1);
380*67e74705SXin Li   HostReturnTy2 ret4 = host_only_function(1.0f);
381*67e74705SXin Li }
382