2015-09-23 01:22:59 +08:00
|
|
|
// REQUIRES: x86-registered-target
|
|
|
|
// REQUIRES: nvptx-registered-target
|
|
|
|
|
2016-03-30 00:24:16 +08:00
|
|
|
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -verify %s
|
|
|
|
// RUN: %clang_cc1 -triple nvptx64-nvidia-cuda -fsyntax-only -fcuda-is-device -verify %s
|
2015-09-23 01:22:59 +08:00
|
|
|
|
|
|
|
#include "Inputs/cuda.h"
|
|
|
|
|
2016-03-24 06:42:30 +08:00
|
|
|
// Opaque return types used to check that we pick the right overloads.
|
|
|
|
struct HostReturnTy {};
|
|
|
|
struct HostReturnTy2 {};
|
|
|
|
struct DeviceReturnTy {};
|
|
|
|
struct DeviceReturnTy2 {};
|
|
|
|
struct HostDeviceReturnTy {};
|
|
|
|
struct TemplateReturnTy {};
|
|
|
|
|
|
|
|
typedef HostReturnTy (*HostFnPtr)();
|
|
|
|
typedef DeviceReturnTy (*DeviceFnPtr)();
|
|
|
|
typedef HostDeviceReturnTy (*HostDeviceFnPtr)();
|
|
|
|
typedef void (*GlobalFnPtr)(); // __global__ functions must return void.
|
|
|
|
|
|
|
|
// CurrentReturnTy is {HostReturnTy,DeviceReturnTy} during {host,device}
|
|
|
|
// compilation.
|
|
|
|
#ifdef __CUDA_ARCH__
|
|
|
|
typedef DeviceReturnTy CurrentReturnTy;
|
|
|
|
#else
|
|
|
|
typedef HostReturnTy CurrentReturnTy;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// CurrentFnPtr is a function pointer to a {host,device} function during
|
|
|
|
// {host,device} compilation.
|
|
|
|
typedef CurrentReturnTy (*CurrentFnPtr)();
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-03-24 06:42:28 +08:00
|
|
|
// Host and unattributed functions can't be overloaded.
|
|
|
|
__host__ void hh() {} // expected-note {{previous definition is here}}
|
|
|
|
void hh() {} // expected-error {{redefinition of 'hh'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-03-24 06:42:28 +08:00
|
|
|
// H/D overloading is OK.
|
2016-03-24 06:42:30 +08:00
|
|
|
__host__ HostReturnTy dh() { return HostReturnTy(); }
|
|
|
|
__device__ DeviceReturnTy dh() { return DeviceReturnTy(); }
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-03-24 06:42:28 +08:00
|
|
|
// H/HD and D/HD are not allowed.
|
2016-12-08 03:27:16 +08:00
|
|
|
__host__ __device__ int hdh() { return 0; } // expected-note {{previous declaration is here}}
|
|
|
|
__host__ int hdh() { return 0; }
|
|
|
|
// expected-error@-1 {{__host__ function 'hdh' cannot overload __host__ __device__ function 'hdh'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-12-08 03:27:16 +08:00
|
|
|
__host__ int hhd() { return 0; } // expected-note {{previous declaration is here}}
|
|
|
|
__host__ __device__ int hhd() { return 0; }
|
|
|
|
// expected-error@-1 {{__host__ __device__ function 'hhd' cannot overload __host__ function 'hhd'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-12-08 03:27:16 +08:00
|
|
|
__host__ __device__ int hdd() { return 0; } // expected-note {{previous declaration is here}}
|
|
|
|
__device__ int hdd() { return 0; }
|
|
|
|
// expected-error@-1 {{__device__ function 'hdd' cannot overload __host__ __device__ function 'hdd'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-12-08 03:27:16 +08:00
|
|
|
__device__ int dhd() { return 0; } // expected-note {{previous declaration is here}}
|
|
|
|
__host__ __device__ int dhd() { return 0; }
|
|
|
|
// expected-error@-1 {{__host__ __device__ function 'dhd' cannot overload __device__ function 'dhd'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-03-24 06:42:28 +08:00
|
|
|
// Same tests for extern "C" functions.
|
2016-03-24 06:42:30 +08:00
|
|
|
extern "C" __host__ int chh() { return 0; } // expected-note {{previous definition is here}}
|
|
|
|
extern "C" int chh() { return 0; } // expected-error {{redefinition of 'chh'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-03-24 06:42:28 +08:00
|
|
|
// H/D overloading is OK.
|
2016-03-24 06:42:30 +08:00
|
|
|
extern "C" __device__ DeviceReturnTy cdh() { return DeviceReturnTy(); }
|
|
|
|
extern "C" __host__ HostReturnTy cdh() { return HostReturnTy(); }
|
2015-09-23 01:22:59 +08:00
|
|
|
|
|
|
|
// H/HD and D/HD overloading is not allowed.
|
2016-12-08 03:27:16 +08:00
|
|
|
extern "C" __host__ __device__ int chhd1() { return 0; } // expected-note {{previous declaration is here}}
|
|
|
|
extern "C" __host__ int chhd1() { return 0; }
|
|
|
|
// expected-error@-1 {{__host__ function 'chhd1' cannot overload __host__ __device__ function 'chhd1'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
|
2016-12-08 03:27:16 +08:00
|
|
|
extern "C" __host__ int chhd2() { return 0; } // expected-note {{previous declaration is here}}
|
|
|
|
extern "C" __host__ __device__ int chhd2() { return 0; }
|
|
|
|
// expected-error@-1 {{__host__ __device__ function 'chhd2' cannot overload __host__ function 'chhd2'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
|
|
|
|
// Helper functions to verify calling restrictions.
|
2016-03-24 06:42:30 +08:00
|
|
|
__device__ DeviceReturnTy d() { return DeviceReturnTy(); }
|
2016-03-24 06:42:28 +08:00
|
|
|
// expected-note@-1 1+ {{'d' declared here}}
|
|
|
|
// expected-note@-2 1+ {{candidate function not viable: call to __device__ function from __host__ function}}
|
|
|
|
// expected-note@-3 0+ {{candidate function not viable: call to __device__ function from __host__ __device__ function}}
|
|
|
|
|
2016-03-24 06:42:30 +08:00
|
|
|
__host__ HostReturnTy h() { return HostReturnTy(); }
|
2016-03-24 06:42:28 +08:00
|
|
|
// expected-note@-1 1+ {{'h' declared here}}
|
|
|
|
// expected-note@-2 1+ {{candidate function not viable: call to __host__ function from __device__ function}}
|
|
|
|
// expected-note@-3 0+ {{candidate function not viable: call to __host__ function from __host__ __device__ function}}
|
|
|
|
// expected-note@-4 1+ {{candidate function not viable: call to __host__ function from __global__ function}}
|
|
|
|
|
|
|
|
__global__ void g() {}
|
|
|
|
// expected-note@-1 1+ {{'g' declared here}}
|
|
|
|
// expected-note@-2 1+ {{candidate function not viable: call to __global__ function from __device__ function}}
|
|
|
|
// expected-note@-3 0+ {{candidate function not viable: call to __global__ function from __host__ __device__ function}}
|
|
|
|
// expected-note@-4 1+ {{candidate function not viable: call to __global__ function from __global__ function}}
|
|
|
|
|
2016-03-24 06:42:30 +08:00
|
|
|
extern "C" __device__ DeviceReturnTy cd() { return DeviceReturnTy(); }
|
2016-03-24 06:42:28 +08:00
|
|
|
// expected-note@-1 1+ {{'cd' declared here}}
|
|
|
|
// expected-note@-2 1+ {{candidate function not viable: call to __device__ function from __host__ function}}
|
|
|
|
// expected-note@-3 0+ {{candidate function not viable: call to __device__ function from __host__ __device__ function}}
|
|
|
|
|
2016-03-24 06:42:30 +08:00
|
|
|
extern "C" __host__ HostReturnTy ch() { return HostReturnTy(); }
|
2016-03-24 06:42:28 +08:00
|
|
|
// expected-note@-1 1+ {{'ch' declared here}}
|
|
|
|
// expected-note@-2 1+ {{candidate function not viable: call to __host__ function from __device__ function}}
|
|
|
|
// expected-note@-3 0+ {{candidate function not viable: call to __host__ function from __host__ __device__ function}}
|
|
|
|
// expected-note@-4 1+ {{candidate function not viable: call to __host__ function from __global__ function}}
|
|
|
|
|
|
|
|
__host__ void hostf() {
|
2016-03-24 06:42:30 +08:00
|
|
|
DeviceFnPtr fp_d = d; // expected-error {{reference to __device__ function 'd' in __host__ function}}
|
|
|
|
DeviceReturnTy ret_d = d(); // expected-error {{no matching function for call to 'd'}}
|
|
|
|
DeviceFnPtr fp_cd = cd; // expected-error {{reference to __device__ function 'cd' in __host__ function}}
|
|
|
|
DeviceReturnTy ret_cd = cd(); // expected-error {{no matching function for call to 'cd'}}
|
|
|
|
|
|
|
|
HostFnPtr fp_h = h;
|
|
|
|
HostReturnTy ret_h = h();
|
|
|
|
HostFnPtr fp_ch = ch;
|
|
|
|
HostReturnTy ret_ch = ch();
|
|
|
|
|
|
|
|
HostFnPtr fp_dh = dh;
|
|
|
|
HostReturnTy ret_dh = dh();
|
|
|
|
HostFnPtr fp_cdh = cdh;
|
|
|
|
HostReturnTy ret_cdh = cdh();
|
|
|
|
|
|
|
|
GlobalFnPtr fp_g = g;
|
2018-03-28 12:16:13 +08:00
|
|
|
g(); // expected-error {{call to global function 'g' not configured}}
|
2016-03-24 06:42:30 +08:00
|
|
|
g<<<0, 0>>>();
|
2015-09-23 01:22:59 +08:00
|
|
|
}
|
|
|
|
|
2016-03-24 06:42:28 +08:00
|
|
|
__device__ void devicef() {
|
2016-03-24 06:42:30 +08:00
|
|
|
DeviceFnPtr fp_d = d;
|
|
|
|
DeviceReturnTy ret_d = d();
|
|
|
|
DeviceFnPtr fp_cd = cd;
|
|
|
|
DeviceReturnTy ret_cd = cd();
|
|
|
|
|
|
|
|
HostFnPtr fp_h = h; // expected-error {{reference to __host__ function 'h' in __device__ function}}
|
|
|
|
HostReturnTy ret_h = h(); // expected-error {{no matching function for call to 'h'}}
|
|
|
|
HostFnPtr fp_ch = ch; // expected-error {{reference to __host__ function 'ch' in __device__ function}}
|
|
|
|
HostReturnTy ret_ch = ch(); // expected-error {{no matching function for call to 'ch'}}
|
|
|
|
|
|
|
|
DeviceFnPtr fp_dh = dh;
|
|
|
|
DeviceReturnTy ret_dh = dh();
|
|
|
|
DeviceFnPtr fp_cdh = cdh;
|
|
|
|
DeviceReturnTy ret_cdh = cdh();
|
|
|
|
|
|
|
|
GlobalFnPtr fp_g = g; // expected-error {{reference to __global__ function 'g' in __device__ function}}
|
2015-09-23 01:22:59 +08:00
|
|
|
g(); // expected-error {{no matching function for call to 'g'}}
|
|
|
|
g<<<0,0>>>(); // expected-error {{reference to __global__ function 'g' in __device__ function}}
|
|
|
|
}
|
|
|
|
|
2016-03-24 06:42:28 +08:00
|
|
|
__global__ void globalf() {
|
2016-03-24 06:42:30 +08:00
|
|
|
DeviceFnPtr fp_d = d;
|
|
|
|
DeviceReturnTy ret_d = d();
|
|
|
|
DeviceFnPtr fp_cd = cd;
|
|
|
|
DeviceReturnTy ret_cd = cd();
|
|
|
|
|
|
|
|
HostFnPtr fp_h = h; // expected-error {{reference to __host__ function 'h' in __global__ function}}
|
|
|
|
HostReturnTy ret_h = h(); // expected-error {{no matching function for call to 'h'}}
|
|
|
|
HostFnPtr fp_ch = ch; // expected-error {{reference to __host__ function 'ch' in __global__ function}}
|
|
|
|
HostReturnTy ret_ch = ch(); // expected-error {{no matching function for call to 'ch'}}
|
|
|
|
|
|
|
|
DeviceFnPtr fp_dh = dh;
|
|
|
|
DeviceReturnTy ret_dh = dh();
|
|
|
|
DeviceFnPtr fp_cdh = cdh;
|
|
|
|
DeviceReturnTy ret_cdh = cdh();
|
|
|
|
|
|
|
|
GlobalFnPtr fp_g = g; // expected-error {{reference to __global__ function 'g' in __global__ function}}
|
2015-09-23 01:22:59 +08:00
|
|
|
g(); // expected-error {{no matching function for call to 'g'}}
|
|
|
|
g<<<0,0>>>(); // expected-error {{reference to __global__ function 'g' in __global__ function}}
|
|
|
|
}
|
|
|
|
|
2016-03-24 06:42:28 +08:00
|
|
|
__host__ __device__ void hostdevicef() {
|
2016-03-24 06:42:30 +08:00
|
|
|
DeviceFnPtr fp_d = d;
|
|
|
|
DeviceReturnTy ret_d = d();
|
|
|
|
DeviceFnPtr fp_cd = cd;
|
|
|
|
DeviceReturnTy ret_cd = cd();
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
#if !defined(__CUDA_ARCH__)
|
|
|
|
// expected-error@-5 {{reference to __device__ function 'd' in __host__ __device__ function}}
|
|
|
|
// expected-error@-5 {{reference to __device__ function 'd' in __host__ __device__ function}}
|
|
|
|
// expected-error@-5 {{reference to __device__ function 'cd' in __host__ __device__ function}}
|
|
|
|
// expected-error@-5 {{reference to __device__ function 'cd' in __host__ __device__ function}}
|
|
|
|
#endif
|
2016-03-24 06:42:28 +08:00
|
|
|
|
2016-03-24 06:42:30 +08:00
|
|
|
HostFnPtr fp_h = h;
|
|
|
|
HostReturnTy ret_h = h();
|
|
|
|
HostFnPtr fp_ch = ch;
|
|
|
|
HostReturnTy ret_ch = ch();
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
#if defined(__CUDA_ARCH__)
|
|
|
|
// expected-error@-5 {{reference to __host__ function 'h' in __host__ __device__ function}}
|
|
|
|
// expected-error@-5 {{reference to __host__ function 'h' in __host__ __device__ function}}
|
|
|
|
// expected-error@-5 {{reference to __host__ function 'ch' in __host__ __device__ function}}
|
|
|
|
// expected-error@-5 {{reference to __host__ function 'ch' in __host__ __device__ function}}
|
|
|
|
#endif
|
2016-03-24 06:42:28 +08:00
|
|
|
|
2016-03-24 06:42:30 +08:00
|
|
|
CurrentFnPtr fp_dh = dh;
|
|
|
|
CurrentReturnTy ret_dh = dh();
|
|
|
|
CurrentFnPtr fp_cdh = cdh;
|
|
|
|
CurrentReturnTy ret_cdh = cdh();
|
|
|
|
|
2016-10-19 08:06:49 +08:00
|
|
|
GlobalFnPtr fp_g = g;
|
|
|
|
#if defined(__CUDA_ARCH__)
|
|
|
|
// expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
|
|
|
|
#endif
|
|
|
|
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
g();
|
|
|
|
#if defined (__CUDA_ARCH__)
|
|
|
|
// expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
|
|
|
|
#else
|
2018-03-28 12:16:13 +08:00
|
|
|
// expected-error@-4 {{call to global function 'g' not configured}}
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
#endif
|
2016-10-19 08:06:49 +08:00
|
|
|
|
|
|
|
g<<<0,0>>>();
|
|
|
|
#if defined(__CUDA_ARCH__)
|
|
|
|
// expected-error@-2 {{reference to __global__ function 'g' in __host__ __device__ function}}
|
|
|
|
#endif
|
2015-09-23 01:22:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Test for address of overloaded function resolution in the global context.
|
2016-03-24 06:42:30 +08:00
|
|
|
HostFnPtr fp_h = h;
|
|
|
|
HostFnPtr fp_ch = ch;
|
|
|
|
CurrentFnPtr fp_dh = dh;
|
|
|
|
CurrentFnPtr fp_cdh = cdh;
|
|
|
|
GlobalFnPtr fp_g = g;
|
2015-09-23 01:22:59 +08:00
|
|
|
|
|
|
|
|
|
|
|
// Test overloading of destructors
|
|
|
|
// Can't mix H and unattributed destructors
|
|
|
|
struct d_h {
|
2017-08-12 09:46:03 +08:00
|
|
|
~d_h() {} // expected-note {{previous definition is here}}
|
2015-09-23 01:22:59 +08:00
|
|
|
__host__ ~d_h() {} // expected-error {{destructor cannot be redeclared}}
|
|
|
|
};
|
|
|
|
|
|
|
|
// HD is OK
|
|
|
|
struct d_hd {
|
|
|
|
__host__ __device__ ~d_hd() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Test overloading of member functions
|
|
|
|
struct m_h {
|
|
|
|
void operator delete(void *ptr); // expected-note {{previous declaration is here}}
|
|
|
|
__host__ void operator delete(void *ptr); // expected-error {{class member cannot be redeclared}}
|
|
|
|
};
|
|
|
|
|
|
|
|
// D/H overloading is OK
|
|
|
|
struct m_dh {
|
|
|
|
__device__ void operator delete(void *ptr);
|
|
|
|
__host__ void operator delete(void *ptr);
|
|
|
|
};
|
|
|
|
|
|
|
|
// HD by itself is OK
|
|
|
|
struct m_hd {
|
|
|
|
__device__ __host__ void operator delete(void *ptr);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct m_hhd {
|
|
|
|
__host__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
|
2016-12-08 03:27:16 +08:00
|
|
|
__host__ __device__ void operator delete(void *ptr) {}
|
|
|
|
// expected-error@-1 {{__host__ __device__ function 'operator delete' cannot overload __host__ function 'operator delete'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct m_hdh {
|
|
|
|
__host__ __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
|
2016-12-08 03:27:16 +08:00
|
|
|
__host__ void operator delete(void *ptr) {}
|
|
|
|
// expected-error@-1 {{__host__ function 'operator delete' cannot overload __host__ __device__ function 'operator delete'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct m_dhd {
|
|
|
|
__device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
|
2016-12-08 03:27:16 +08:00
|
|
|
__host__ __device__ void operator delete(void *ptr) {}
|
|
|
|
// expected-error@-1 {{__host__ __device__ function 'operator delete' cannot overload __device__ function 'operator delete'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct m_hdd {
|
|
|
|
__host__ __device__ void operator delete(void *ptr) {} // expected-note {{previous declaration is here}}
|
2016-12-08 03:27:16 +08:00
|
|
|
__device__ void operator delete(void *ptr) {}
|
|
|
|
// expected-error@-1 {{__device__ function 'operator delete' cannot overload __host__ __device__ function 'operator delete'}}
|
2015-09-23 01:22:59 +08:00
|
|
|
};
|
2016-02-25 05:54:45 +08:00
|
|
|
|
|
|
|
// __global__ functions can't be overloaded based on attribute
|
|
|
|
// difference.
|
|
|
|
struct G {
|
2016-12-08 03:27:16 +08:00
|
|
|
friend void friend_of_g(G &arg); // expected-note {{previous declaration is here}}
|
2016-02-25 05:54:45 +08:00
|
|
|
private:
|
2016-12-08 03:27:16 +08:00
|
|
|
int x; // expected-note {{declared private here}}
|
2016-02-25 05:54:45 +08:00
|
|
|
};
|
2016-12-08 03:27:16 +08:00
|
|
|
__global__ void friend_of_g(G &arg) { int x = arg.x; }
|
|
|
|
// expected-error@-1 {{__global__ function 'friend_of_g' cannot overload __host__ function 'friend_of_g'}}
|
|
|
|
// expected-error@-2 {{'x' is a private member of 'G'}}
|
|
|
|
void friend_of_g(G &arg) { int x = arg.x; }
|
2016-03-24 06:42:30 +08:00
|
|
|
|
|
|
|
// HD functions are sometimes allowed to call H or D functions -- this
|
|
|
|
// is an artifact of the source-to-source splitting performed by nvcc
|
|
|
|
// that we need to mimic. During device mode compilation in nvcc, host
|
|
|
|
// functions aren't present at all, so don't participate in
|
|
|
|
// overloading. But in clang, H and D functions are present in both
|
|
|
|
// compilation modes. Clang normally uses the target attribute as a
|
|
|
|
// tiebreaker between overloads with otherwise identical priority, but
|
|
|
|
// in order to match nvcc's behavior, we sometimes need to wholly
|
|
|
|
// discard overloads that would not be present during compilation
|
|
|
|
// under nvcc.
|
|
|
|
|
|
|
|
template <typename T> TemplateReturnTy template_vs_function(T arg) {
|
|
|
|
return TemplateReturnTy();
|
|
|
|
}
|
|
|
|
__device__ DeviceReturnTy template_vs_function(float arg) {
|
|
|
|
return DeviceReturnTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Here we expect to call the templated function during host compilation, even
|
|
|
|
// if -fcuda-disable-target-call-checks is passed, and even though C++ overload
|
|
|
|
// rules prefer the non-templated function.
|
|
|
|
__host__ __device__ void test_host_device_calls_template(void) {
|
|
|
|
#ifdef __CUDA_ARCH__
|
|
|
|
typedef DeviceReturnTy ExpectedReturnTy;
|
|
|
|
#else
|
|
|
|
typedef TemplateReturnTy ExpectedReturnTy;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ExpectedReturnTy ret1 = template_vs_function(1.0f);
|
|
|
|
ExpectedReturnTy ret2 = template_vs_function(2.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calls from __host__ and __device__ functions should always call the
|
|
|
|
// overloaded function that matches their mode.
|
|
|
|
__host__ void test_host_calls_template_fn() {
|
|
|
|
TemplateReturnTy ret1 = template_vs_function(1.0f);
|
|
|
|
TemplateReturnTy ret2 = template_vs_function(2.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
__device__ void test_device_calls_template_fn() {
|
|
|
|
DeviceReturnTy ret1 = template_vs_function(1.0f);
|
|
|
|
DeviceReturnTy ret2 = template_vs_function(2.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we have a mix of HD and H-only or D-only candidates in the overload set,
|
|
|
|
// normal C++ overload resolution rules apply first.
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
template <typename T> TemplateReturnTy template_vs_hd_function(T arg)
|
|
|
|
#ifdef __CUDA_ARCH__
|
|
|
|
//expected-note@-2 {{declared here}}
|
|
|
|
#endif
|
|
|
|
{
|
2016-03-24 06:42:30 +08:00
|
|
|
return TemplateReturnTy();
|
|
|
|
}
|
|
|
|
__host__ __device__ HostDeviceReturnTy template_vs_hd_function(float arg) {
|
|
|
|
return HostDeviceReturnTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
__host__ __device__ void test_host_device_calls_hd_template() {
|
|
|
|
HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
|
2016-03-30 00:24:16 +08:00
|
|
|
TemplateReturnTy ret2 = template_vs_hd_function(1);
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
#ifdef __CUDA_ARCH__
|
|
|
|
// expected-error@-2 {{reference to __host__ function 'template_vs_hd_function<int>' in __host__ __device__ function}}
|
|
|
|
#endif
|
2016-03-24 06:42:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
__host__ void test_host_calls_hd_template() {
|
|
|
|
HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
|
|
|
|
TemplateReturnTy ret2 = template_vs_hd_function(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
__device__ void test_device_calls_hd_template() {
|
|
|
|
HostDeviceReturnTy ret1 = template_vs_hd_function(1.0f);
|
|
|
|
// Host-only function template is not callable with strict call checks,
|
|
|
|
// so for device side HD function will be the only choice.
|
|
|
|
HostDeviceReturnTy ret2 = template_vs_hd_function(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that overloads still work the same way on both host and
|
|
|
|
// device side when the overload set contains only functions from one
|
|
|
|
// side of compilation.
|
|
|
|
__device__ DeviceReturnTy device_only_function(int arg) { return DeviceReturnTy(); }
|
|
|
|
__device__ DeviceReturnTy2 device_only_function(float arg) { return DeviceReturnTy2(); }
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
#ifndef __CUDA_ARCH__
|
|
|
|
// expected-note@-3 {{'device_only_function' declared here}}
|
|
|
|
// expected-note@-3 {{'device_only_function' declared here}}
|
|
|
|
#endif
|
2016-03-24 06:42:30 +08:00
|
|
|
__host__ HostReturnTy host_only_function(int arg) { return HostReturnTy(); }
|
|
|
|
__host__ HostReturnTy2 host_only_function(float arg) { return HostReturnTy2(); }
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
#ifdef __CUDA_ARCH__
|
|
|
|
// expected-note@-3 {{'host_only_function' declared here}}
|
|
|
|
// expected-note@-3 {{'host_only_function' declared here}}
|
|
|
|
#endif
|
2016-03-24 06:42:30 +08:00
|
|
|
|
2016-03-30 00:24:16 +08:00
|
|
|
__host__ __device__ void test_host_device_single_side_overloading() {
|
2016-03-24 06:42:30 +08:00
|
|
|
DeviceReturnTy ret1 = device_only_function(1);
|
|
|
|
DeviceReturnTy2 ret2 = device_only_function(1.0f);
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
#ifndef __CUDA_ARCH__
|
|
|
|
// expected-error@-3 {{reference to __device__ function 'device_only_function' in __host__ __device__ function}}
|
|
|
|
// expected-error@-3 {{reference to __device__ function 'device_only_function' in __host__ __device__ function}}
|
|
|
|
#endif
|
2016-03-24 06:42:30 +08:00
|
|
|
HostReturnTy ret3 = host_only_function(1);
|
|
|
|
HostReturnTy2 ret4 = host_only_function(1.0f);
|
[CUDA] Emit deferred diagnostics during Sema rather than during codegen.
Summary:
Emitting deferred diagnostics during codegen was a hack. It did work,
but usability was poor, both for us as compiler devs and for users. We
don't codegen if there are any sema errors, so for users this meant that
they wouldn't see deferred errors if there were any non-deferred errors.
For devs, this meant that we had to carefully split up our tests so that
when we tested deferred errors, we didn't emit any non-deferred errors.
This change moves checking for deferred errors into Sema. See the big
comment in SemaCUDA.cpp for an overview of the idea.
This checking adds overhead to compilation, because we have to maintain
a partial call graph. As a result, this change makes deferred errors a
CUDA-only concept (whereas before they were a general concept). If
anyone else wants to use this framework for something other than CUDA,
we can generalize at that time.
This patch makes the minimal set of test changes -- after this lands,
I'll go back through and do a cleanup of the tests that we no longer
have to split up.
Reviewers: rnk
Subscribers: cfe-commits, rsmith, tra
Differential Revision: https://reviews.llvm.org/D25541
llvm-svn: 284158
2016-10-14 04:52:12 +08:00
|
|
|
#ifdef __CUDA_ARCH__
|
|
|
|
// expected-error@-3 {{reference to __host__ function 'host_only_function' in __host__ __device__ function}}
|
|
|
|
// expected-error@-3 {{reference to __host__ function 'host_only_function' in __host__ __device__ function}}
|
|
|
|
#endif
|
2016-03-24 06:42:30 +08:00
|
|
|
}
|
2016-09-14 06:16:30 +08:00
|
|
|
|
|
|
|
// Verify that we allow overloading function templates.
|
|
|
|
template <typename T> __host__ T template_overload(const T &a) { return a; };
|
|
|
|
template <typename T> __device__ T template_overload(const T &a) { return a; };
|
|
|
|
|
|
|
|
__host__ void test_host_template_overload() {
|
|
|
|
template_overload(1); // OK. Attribute-based overloading picks __host__ variant.
|
|
|
|
}
|
|
|
|
__device__ void test_device_template_overload() {
|
|
|
|
template_overload(1); // OK. Attribute-based overloading picks __device__ variant.
|
|
|
|
}
|
2019-09-20 05:26:18 +08:00
|
|
|
|
|
|
|
// Two classes with `operator-` defined. One of them is device only.
|
|
|
|
struct C1;
|
|
|
|
struct C2;
|
|
|
|
__device__
|
|
|
|
int operator-(const C1 &x, const C1 &y);
|
|
|
|
int operator-(const C2 &x, const C2 &y);
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
__host__ __device__ int constexpr_overload(const T &x, const T &y) {
|
|
|
|
return x - y;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify that function overloading doesn't prune candidate wrongly.
|
|
|
|
int test_constexpr_overload(C2 &x, C2 &y) {
|
|
|
|
return constexpr_overload(x, y);
|
|
|
|
}
|