xref: /aosp_15_r20/external/clang/test/SemaCUDA/host-device-constexpr.cu (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs %s
2*67e74705SXin Li // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -isystem %S/Inputs %s -fcuda-is-device
3*67e74705SXin Li 
4*67e74705SXin Li #include "Inputs/cuda.h"
5*67e74705SXin Li 
6*67e74705SXin Li // Declares one function and pulls it into namespace ns:
7*67e74705SXin Li //
8*67e74705SXin Li //   __device__ int OverloadMe();
9*67e74705SXin Li //   namespace ns { using ::OverloadMe; }
10*67e74705SXin Li //
11*67e74705SXin Li // Clang cares that this is done in a system header.
12*67e74705SXin Li #include <overload.h>
13*67e74705SXin Li 
14*67e74705SXin Li // Opaque type used to determine which overload we're invoking.
15*67e74705SXin Li struct HostReturnTy {};
16*67e74705SXin Li 
17*67e74705SXin Li // These shouldn't become host+device because they already have attributes.
HostOnly()18*67e74705SXin Li __host__ constexpr int HostOnly() { return 0; }
19*67e74705SXin Li // expected-note@-1 0+ {{not viable}}
DeviceOnly()20*67e74705SXin Li __device__ constexpr int DeviceOnly() { return 0; }
21*67e74705SXin Li // expected-note@-1 0+ {{not viable}}
22*67e74705SXin Li 
HostDevice()23*67e74705SXin Li constexpr int HostDevice() { return 0; }
24*67e74705SXin Li 
25*67e74705SXin Li // This should be a host-only function, because there's a previous __device__
26*67e74705SXin Li // overload in <overload.h>.
OverloadMe()27*67e74705SXin Li constexpr HostReturnTy OverloadMe() { return HostReturnTy(); }
28*67e74705SXin Li 
29*67e74705SXin Li namespace ns {
30*67e74705SXin Li // The "using" statement in overload.h should prevent OverloadMe from being
31*67e74705SXin Li // implicitly host+device.
OverloadMe()32*67e74705SXin Li constexpr HostReturnTy OverloadMe() { return HostReturnTy(); }
33*67e74705SXin Li }  // namespace ns
34*67e74705SXin Li 
35*67e74705SXin Li // This is an error, because NonSysHdrOverload was not defined in a system
36*67e74705SXin Li // header.
NonSysHdrOverload()37*67e74705SXin Li __device__ int NonSysHdrOverload() { return 0; }
38*67e74705SXin Li // expected-note@-1 {{conflicting __device__ function declared here}}
NonSysHdrOverload()39*67e74705SXin Li constexpr int NonSysHdrOverload() { return 0; }
40*67e74705SXin Li // expected-error@-1 {{constexpr function 'NonSysHdrOverload' without __host__ or __device__ attributes}}
41*67e74705SXin Li 
42*67e74705SXin Li // Variadic device functions are not allowed, so this is just treated as
43*67e74705SXin Li // host-only.
44*67e74705SXin Li constexpr void Variadic(const char*, ...);
45*67e74705SXin Li // expected-note@-1 {{call to __host__ function from __device__ function}}
46*67e74705SXin Li 
HostFn()47*67e74705SXin Li __host__ void HostFn() {
48*67e74705SXin Li   HostOnly();
49*67e74705SXin Li   DeviceOnly(); // expected-error {{no matching function}}
50*67e74705SXin Li   HostReturnTy x = OverloadMe();
51*67e74705SXin Li   HostReturnTy y = ns::OverloadMe();
52*67e74705SXin Li   Variadic("abc", 42);
53*67e74705SXin Li }
54*67e74705SXin Li 
DeviceFn()55*67e74705SXin Li __device__ void DeviceFn() {
56*67e74705SXin Li   HostOnly(); // expected-error {{no matching function}}
57*67e74705SXin Li   DeviceOnly();
58*67e74705SXin Li   int x = OverloadMe();
59*67e74705SXin Li   int y = ns::OverloadMe();
60*67e74705SXin Li   Variadic("abc", 42); // expected-error {{no matching function}}
61*67e74705SXin Li }
62*67e74705SXin Li 
HostDeviceFn()63*67e74705SXin Li __host__ __device__ void HostDeviceFn() {
64*67e74705SXin Li #ifdef __CUDA_ARCH__
65*67e74705SXin Li   int y = OverloadMe();
66*67e74705SXin Li #else
67*67e74705SXin Li   constexpr HostReturnTy y = OverloadMe();
68*67e74705SXin Li #endif
69*67e74705SXin Li }
70