blob: 3c78600b174e373629f6fc86c8bf237f9e32a84b [file] [log] [blame]
Artem Belevich94a55e82015-09-22 17:22:59 +00001// REQUIRES: x86-registered-target
2// REQUIRES: nvptx-registered-target
3
Justin Lebar25c4a812016-03-29 16:24:16 +00004// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
5// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s
Artem Belevich94a55e82015-09-22 17:22:59 +00006
7#include "Inputs/cuda.h"
8
Justin Lebare5eed042016-03-23 22:42:30 +00009// Opaque return types used to check that we pick the right overloads.
10struct HostReturnTy {};
11struct HostReturnTy2 {};
12struct DeviceReturnTy {};
13struct DeviceReturnTy2 {};
14struct HostDeviceReturnTy {};
15struct TemplateReturnTy {};
16
17typedef HostReturnTy (*HostFnPtr)();
18typedef DeviceReturnTy (*DeviceFnPtr)();
19typedef HostDeviceReturnTy (*HostDeviceFnPtr)();
20typedef void (*GlobalFnPtr)(); // __global__ functions must return void.
21
22// CurrentReturnTy is {HostReturnTy,DeviceReturnTy} during {host,device}
23// compilation.
24#ifdef __CUDA_ARCH__
25typedef DeviceReturnTy CurrentReturnTy;
26#else
27typedef HostReturnTy CurrentReturnTy;
28#endif
29
30// CurrentFnPtr is a function pointer to a {host,device} function during
31// {host,device} compilation.
32typedef CurrentReturnTy (*CurrentFnPtr)();
Artem Belevich94a55e82015-09-22 17:22:59 +000033
Justin Lebare82caa32016-03-23 22:42:28 +000034// Host and unattributed functions can't be overloaded.
35__host__ void hh() {} // expected-note {{previous definition is here}}
36void hh() {} // expected-error {{redefinition of 'hh'}}
Artem Belevich94a55e82015-09-22 17:22:59 +000037
Justin Lebare82caa32016-03-23 22:42:28 +000038// H/D overloading is OK.
Justin Lebare5eed042016-03-23 22:42:30 +000039__host__ HostReturnTy dh() { return HostReturnTy(); }
40__device__ DeviceReturnTy dh() { return DeviceReturnTy(); }
Artem Belevich94a55e82015-09-22 17:22:59 +000041
Justin Lebare82caa32016-03-23 22:42:28 +000042// H/HD and D/HD are not allowed.
Justin Lebare5eed042016-03-23 22:42:30 +000043__host__ __device__ int hdh() { return 0; } // expected-note {{previous definition is here}}
44__host__ int hdh() { return 0; } // expected-error {{redefinition of 'hdh'}}
Artem Belevich94a55e82015-09-22 17:22:59 +000045
Justin Lebare5eed042016-03-23 22:42:30 +000046__host__ int hhd() { return 0; } // expected-note {{previous definition is here}}
47__host__ __device__ int hhd() { return 0; } // expected-error {{redefinition of 'hhd'}}
Artem Belevich94a55e82015-09-22 17:22:59 +000048// expected-warning@-1 {{attribute declaration must precede definition}}
49// expected-note@-3 {{previous definition is here}}
50
Justin Lebare5eed042016-03-23 22:42:30 +000051__host__ __device__ int hdd() { return 0; } // expected-note {{previous definition is here}}
52__device__ int hdd() { return 0; } // expected-error {{redefinition of 'hdd'}}
Artem Belevich94a55e82015-09-22 17:22:59 +000053
Justin Lebare5eed042016-03-23 22:42:30 +000054__device__ int dhd() { return 0; } // expected-note {{previous definition is here}}
55__host__ __device__ int dhd() { return 0; } // expected-error {{redefinition of 'dhd'}}
Artem Belevich94a55e82015-09-22 17:22:59 +000056// expected-warning@-1 {{attribute declaration must precede definition}}
57// expected-note@-3 {{previous definition is here}}
58
Justin Lebare82caa32016-03-23 22:42:28 +000059// Same tests for extern "C" functions.
Justin Lebare5eed042016-03-23 22:42:30 +000060extern "C" __host__ int chh() { return 0; } // expected-note {{previous definition is here}}
61extern "C" int chh() { return 0; } // expected-error {{redefinition of 'chh'}}
Artem Belevich94a55e82015-09-22 17:22:59 +000062
Justin Lebare82caa32016-03-23 22:42:28 +000063// H/D overloading is OK.
Justin Lebare5eed042016-03-23 22:42:30 +000064extern "C" __device__ DeviceReturnTy cdh() { return DeviceReturnTy(); }
65extern "C" __host__ HostReturnTy cdh() { return HostReturnTy(); }
Artem Belevich94a55e82015-09-22 17:22:59 +000066
67// H/HD and D/HD overloading is not allowed.
Justin Lebare5eed042016-03-23 22:42:30 +000068extern "C" __host__ __device__ int chhd1() { return 0; } // expected-note {{previous definition is here}}
69extern "C" __host__ int chhd1() { return 0; } // expected-error {{redefinition of 'chhd1'}}
Artem Belevich94a55e82015-09-22 17:22:59 +000070
Justin Lebare5eed042016-03-23 22:42:30 +000071extern "C" __host__ int chhd2() { return 0; } // expected-note {{previous definition is here}}
72extern "C" __host__ __device__ int chhd2() { return 0; } // expected-error {{redefinition of 'chhd2'}}
Artem Belevich94a55e82015-09-22 17:22:59 +000073// expected-warning@-1 {{attribute declaration must precede definition}}
74// expected-note@-3 {{previous definition is here}}
75
76// Helper functions to verify calling restrictions.
Justin Lebare5eed042016-03-23 22:42:30 +000077__device__ DeviceReturnTy d() { return DeviceReturnTy(); }
Justin Lebare82caa32016-03-23 22:42:28 +000078// expected-note@-1 1+ {{'d' declared here}}
79// expected-note@-2 1+ {{candidate function not viable: call to __device__ function from __host__ function}}
80// expected-note@-3 0+ {{candidate function not viable: call to __device__ function from __host__ __device__ function}}
Artem Belevich94a55e82015-09-22 17:22:59 +000081
Justin Lebare5eed042016-03-23 22:42:30 +000082__host__ HostReturnTy h() { return HostReturnTy(); }
Justin Lebare82caa32016-03-23 22:42:28 +000083// expected-note@-1 1+ {{'h' declared here}}
84// expected-note@-2 1+ {{candidate function not viable: call to __host__ function from __device__ function}}
85// expected-note@-3 0+ {{candidate function not viable: call to __host__ function from __host__ __device__ function}}
86// expected-note@-4 1+ {{candidate function not viable: call to __host__ function from __global__ function}}
87
88__global__ void g() {}
89// expected-note@-1 1+ {{'g' declared here}}
90// expected-note@-2 1+ {{candidate function not viable: call to __global__ function from __device__ function}}
91// expected-note@-3 0+ {{candidate function not viable: call to __global__ function from __host__ __device__ function}}
92// expected-note@-4 1+ {{candidate function not viable: call to __global__ function from __global__ function}}
93
Justin Lebare5eed042016-03-23 22:42:30 +000094extern "C" __device__ DeviceReturnTy cd() { return DeviceReturnTy(); }
Justin Lebare82caa32016-03-23 22:42:28 +000095// expected-note@-1 1+ {{'cd' declared here}}
96// expected-note@-2 1+ {{candidate function not viable: call to __device__ function from __host__ function}}
97// expected-note@-3 0+ {{candidate function not viable: call to __device__ function from __host__ __device__ function}}
98
Justin Lebare5eed042016-03-23 22:42:30 +000099extern "C" __host__ HostReturnTy ch() { return HostReturnTy(); }
Justin Lebare82caa32016-03-23 22:42:28 +0000100// expected-note@-1 1+ {{'ch' declared here}}
101// expected-note@-2 1+ {{candidate function not viable: call to __host__ function from __device__ function}}
102// expected-note@-3 0+ {{candidate function not viable: call to __host__ function from __host__ __device__ function}}
103// expected-note@-4 1+ {{candidate function not viable: call to __host__ function from __global__ function}}
104
105__host__ void hostf() {
Justin Lebare5eed042016-03-23 22:42:30 +0000106 DeviceFnPtr fp_d = d; // expected-error {{reference to __device__ function 'd' in __host__ function}}
107 DeviceReturnTy ret_d = d(); // expected-error {{no matching function for call to 'd'}}
108 DeviceFnPtr fp_cd = cd; // expected-error {{reference to __device__ function 'cd' in __host__ function}}
109 DeviceReturnTy ret_cd = cd(); // expected-error {{no matching function for call to 'cd'}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000110
Justin Lebare5eed042016-03-23 22:42:30 +0000111 HostFnPtr fp_h = h;
112 HostReturnTy ret_h = h();
113 HostFnPtr fp_ch = ch;
114 HostReturnTy ret_ch = ch();
115
116 HostFnPtr fp_dh = dh;
117 HostReturnTy ret_dh = dh();
118 HostFnPtr fp_cdh = cdh;
119 HostReturnTy ret_cdh = cdh();
120
121 GlobalFnPtr fp_g = g;
Artem Belevich94a55e82015-09-22 17:22:59 +0000122 g(); // expected-error {{call to global function g not configured}}
Justin Lebare5eed042016-03-23 22:42:30 +0000123 g<<<0, 0>>>();
Artem Belevich94a55e82015-09-22 17:22:59 +0000124}
125
Justin Lebare82caa32016-03-23 22:42:28 +0000126__device__ void devicef() {
Justin Lebare5eed042016-03-23 22:42:30 +0000127 DeviceFnPtr fp_d = d;
128 DeviceReturnTy ret_d = d();
129 DeviceFnPtr fp_cd = cd;
130 DeviceReturnTy ret_cd = cd();
Artem Belevich94a55e82015-09-22 17:22:59 +0000131
Justin Lebare5eed042016-03-23 22:42:30 +0000132 HostFnPtr fp_h = h; // expected-error {{reference to __host__ function 'h' in __device__ function}}
133 HostReturnTy ret_h = h(); // expected-error {{no matching function for call to 'h'}}
134 HostFnPtr fp_ch = ch; // expected-error {{reference to __host__ function 'ch' in __device__ function}}
135 HostReturnTy ret_ch = ch(); // expected-error {{no matching function for call to 'ch'}}
136
137 DeviceFnPtr fp_dh = dh;
138 DeviceReturnTy ret_dh = dh();
139 DeviceFnPtr fp_cdh = cdh;
140 DeviceReturnTy ret_cdh = cdh();
141
142 GlobalFnPtr fp_g = g; // expected-error {{reference to __global__ function 'g' in __device__ function}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000143 g(); // expected-error {{no matching function for call to 'g'}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000144 g<<<0,0>>>(); // expected-error {{reference to __global__ function 'g' in __device__ function}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000145}
146
Justin Lebare82caa32016-03-23 22:42:28 +0000147__global__ void globalf() {
Justin Lebare5eed042016-03-23 22:42:30 +0000148 DeviceFnPtr fp_d = d;
149 DeviceReturnTy ret_d = d();
150 DeviceFnPtr fp_cd = cd;
151 DeviceReturnTy ret_cd = cd();
Artem Belevich94a55e82015-09-22 17:22:59 +0000152
Justin Lebare5eed042016-03-23 22:42:30 +0000153 HostFnPtr fp_h = h; // expected-error {{reference to __host__ function 'h' in __global__ function}}
154 HostReturnTy ret_h = h(); // expected-error {{no matching function for call to 'h'}}
155 HostFnPtr fp_ch = ch; // expected-error {{reference to __host__ function 'ch' in __global__ function}}
156 HostReturnTy ret_ch = ch(); // expected-error {{no matching function for call to 'ch'}}
157
158 DeviceFnPtr fp_dh = dh;
159 DeviceReturnTy ret_dh = dh();
160 DeviceFnPtr fp_cdh = cdh;
161 DeviceReturnTy ret_cdh = cdh();
162
163 GlobalFnPtr fp_g = g; // expected-error {{reference to __global__ function 'g' in __global__ function}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000164 g(); // expected-error {{no matching function for call to 'g'}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000165 g<<<0,0>>>(); // expected-error {{reference to __global__ function 'g' in __global__ function}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000166}
167
Justin Lebare82caa32016-03-23 22:42:28 +0000168__host__ __device__ void hostdevicef() {
Justin Lebare5eed042016-03-23 22:42:30 +0000169 DeviceFnPtr fp_d = d;
170 DeviceReturnTy ret_d = d();
171 DeviceFnPtr fp_cd = cd;
172 DeviceReturnTy ret_cd = cd();
Justin Lebare82caa32016-03-23 22:42:28 +0000173
Justin Lebare5eed042016-03-23 22:42:30 +0000174 HostFnPtr fp_h = h;
175 HostReturnTy ret_h = h();
176 HostFnPtr fp_ch = ch;
177 HostReturnTy ret_ch = ch();
Justin Lebare82caa32016-03-23 22:42:28 +0000178
Justin Lebare5eed042016-03-23 22:42:30 +0000179 CurrentFnPtr fp_dh = dh;
180 CurrentReturnTy ret_dh = dh();
181 CurrentFnPtr fp_cdh = cdh;
182 CurrentReturnTy ret_cdh = cdh();
183
184 GlobalFnPtr fp_g = g;
Artem Belevich94a55e82015-09-22 17:22:59 +0000185#if defined(__CUDA_ARCH__)
186 // expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000187#endif
Artem Belevich94a55e82015-09-22 17:22:59 +0000188 g();
189 g<<<0,0>>>();
190#if !defined(__CUDA_ARCH__)
191 // expected-error@-3 {{call to global function g not configured}}
192#else
193 // expected-error@-5 {{no matching function for call to 'g'}}
Justin Lebare82caa32016-03-23 22:42:28 +0000194 // expected-error@-5 {{reference to __global__ function 'g' in __host__ __device__ function}}
Artem Belevich94a55e82015-09-22 17:22:59 +0000195#endif // __CUDA_ARCH__
196}
197
198// Test for address of overloaded function resolution in the global context.
Justin Lebare5eed042016-03-23 22:42:30 +0000199HostFnPtr fp_h = h;
200HostFnPtr fp_ch = ch;
201CurrentFnPtr fp_dh = dh;
202CurrentFnPtr fp_cdh = cdh;
203GlobalFnPtr fp_g = g;
Artem Belevich94a55e82015-09-22 17:22:59 +0000204
205
206// Test overloading of destructors
207// Can't mix H and unattributed destructors
208struct d_h {
209 ~d_h() {} // expected-note {{previous declaration is here}}
210 __host__ ~d_h() {} // expected-error {{destructor cannot be redeclared}}
211};
212
213// H/D overloading is OK
214struct d_dh {
215 __device__ ~d_dh() {}
216 __host__ ~d_dh() {}
217};
218
219// HD is OK
220struct d_hd {
221 __host__ __device__ ~d_hd() {}
222};
223
224// Mixing H/D and HD is not allowed.
225struct d_dhhd {
226 __device__ ~d_dhhd() {}
227 __host__ ~d_dhhd() {} // expected-note {{previous declaration is here}}
228 __host__ __device__ ~d_dhhd() {} // expected-error {{destructor cannot be redeclared}}
229};
230
231struct d_hhd {
232 __host__ ~d_hhd() {} // expected-note {{previous declaration is here}}
233 __host__ __device__ ~d_hhd() {} // expected-error {{destructor cannot be redeclared}}
234};
235
236struct d_hdh {
237 __host__ __device__ ~d_hdh() {} // expected-note {{previous declaration is here}}
238 __host__ ~d_hdh() {} // expected-error {{destructor cannot be redeclared}}
239};
240
241struct d_dhd {
242 __device__ ~d_dhd() {} // expected-note {{previous declaration is here}}
243 __host__ __device__ ~d_dhd() {} // expected-error {{destructor cannot be redeclared}}
244};
245
246struct d_hdd {
247 __host__ __device__ ~d_hdd() {} // expected-note {{previous declaration is here}}
248 __device__ ~d_hdd() {} // expected-error {{destructor cannot be redeclared}}
249};
250
251// Test overloading of member functions
252struct m_h {
253 void operator delete(void *ptr); // expected-note {{previous declaration is here}}
254 __host__ void operator delete(void *ptr); // expected-error {{class member cannot be redeclared}}
255};
256
257// D/H overloading is OK
258struct m_dh {
259 __device__ void operator delete(void *ptr);
260 __host__ void operator delete(void *ptr);
261};
262
263// HD by itself is OK
264struct m_hd {
265 __device__ __host__ void operator delete(void *ptr);
266};
267
268struct m_hhd {
269 __host__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
270 __host__ __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
271};
272
273struct m_hdh {
274 __host__ __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
275 __host__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
276};
277
278struct m_dhd {
279 __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
280 __host__ __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
281};
282
283struct m_hdd {
284 __host__ __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
285 __device__ void operator delete(void *ptr) {} // expected-error {{class member cannot be redeclared}}
286};
Artem Belevich1ef9b592016-02-24 21:54:45 +0000287
288// __global__ functions can't be overloaded based on attribute
289// difference.
290struct G {
291 friend void friend_of_g(G &arg);
292private:
293 int x;
294};
295__global__ void friend_of_g(G &arg) { int x = arg.x; } // expected-note {{previous definition is here}}
296void friend_of_g(G &arg) { int x = arg.x; } // expected-error {{redefinition of 'friend_of_g'}}
Justin Lebare5eed042016-03-23 22:42:30 +0000297
298// HD functions are sometimes allowed to call H or D functions -- this
299// is an artifact of the source-to-source splitting performed by nvcc
300// that we need to mimic. During device mode compilation in nvcc, host
301// functions aren't present at all, so don't participate in
302// overloading. But in clang, H and D functions are present in both
303// compilation modes. Clang normally uses the target attribute as a
304// tiebreaker between overloads with otherwise identical priority, but
305// in order to match nvcc's behavior, we sometimes need to wholly
306// discard overloads that would not be present during compilation
307// under nvcc.
308
309template <typename T> TemplateReturnTy template_vs_function(T arg) {
310 return TemplateReturnTy();
311}
312__device__ DeviceReturnTy template_vs_function(float arg) {
313 return DeviceReturnTy();
314}
315
316// Here we expect to call the templated function during host compilation, even
317// if -fcuda-disable-target-call-checks is passed, and even though C++ overload
318// rules prefer the non-templated function.
319__host__ __device__ void test_host_device_calls_template(void) {
320#ifdef __CUDA_ARCH__
321 typedef DeviceReturnTy ExpectedReturnTy;
322#else
323 typedef TemplateReturnTy ExpectedReturnTy;
324#endif
325
326 ExpectedReturnTy ret1 = template_vs_function(1.0f);
327 ExpectedReturnTy ret2 = template_vs_function(2.0);
328}
329
330// Calls from __host__ and __device__ functions should always call the
331// overloaded function that matches their mode.
332__host__ void test_host_calls_template_fn() {
333 TemplateReturnTy ret1 = template_vs_function(1.0f);
334 TemplateReturnTy ret2 = template_vs_function(2.0);
335}
336
337__device__ void test_device_calls_template_fn() {
338 DeviceReturnTy ret1 = template_vs_function(1.0f);
339 DeviceReturnTy ret2 = template_vs_function(2.0);
340}
341
342// If we have a mix of HD and H-only or D-only candidates in the overload set,
343// normal C++ overload resolution rules apply first.
344template <typename T> TemplateReturnTy template_vs_hd_function(T arg) {
345 return TemplateReturnTy();
346}
347__host__ __device__ HostDeviceReturnTy template_vs_hd_function(float arg) {
348 return HostDeviceReturnTy();
349}
350
351__host__ __device__ void test_host_device_calls_hd_template() {
352 HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
Justin Lebar25c4a812016-03-29 16:24:16 +0000353 TemplateReturnTy ret2 = template_vs_hd_function(1);
Justin Lebare5eed042016-03-23 22:42:30 +0000354}
355
356__host__ void test_host_calls_hd_template() {
357 HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
358 TemplateReturnTy ret2 = template_vs_hd_function(1);
359}
360
361__device__ void test_device_calls_hd_template() {
362 HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
363 // Host-only function template is not callable with strict call checks,
364 // so for device side HD function will be the only choice.
365 HostDeviceReturnTy ret2 = template_vs_hd_function(1);
366}
367
368// Check that overloads still work the same way on both host and
369// device side when the overload set contains only functions from one
370// side of compilation.
371__device__ DeviceReturnTy device_only_function(int arg) { return DeviceReturnTy(); }
372__device__ DeviceReturnTy2 device_only_function(float arg) { return DeviceReturnTy2(); }
373__host__ HostReturnTy host_only_function(int arg) { return HostReturnTy(); }
374__host__ HostReturnTy2 host_only_function(float arg) { return HostReturnTy2(); }
375
Justin Lebar25c4a812016-03-29 16:24:16 +0000376__host__ __device__ void test_host_device_single_side_overloading() {
Justin Lebare5eed042016-03-23 22:42:30 +0000377 DeviceReturnTy ret1 = device_only_function(1);
378 DeviceReturnTy2 ret2 = device_only_function(1.0f);
379 HostReturnTy ret3 = host_only_function(1);
380 HostReturnTy2 ret4 = host_only_function(1.0f);
Justin Lebare5eed042016-03-23 22:42:30 +0000381}