Clang Project

clang_source_code/test/SemaCUDA/call-device-fn-from-host.cu
1// RUN: %clang_cc1 %s --std=c++11 -triple x86_64-unknown-linux -emit-llvm -o - \
2// RUN:   -verify -verify-ignore-unexpected=note
3
4// Note: This test won't work with -fsyntax-only, because some of these errors
5// are emitted during codegen.
6
7#include "Inputs/cuda.h"
8
9__device__ void device_fn() {}
10// expected-note@-1 5 {{'device_fn' declared here}}
11
12struct S {
13  __device__ S() {}
14  // expected-note@-1 2 {{'S' declared here}}
15  __device__ ~S() { device_fn(); }
16  // expected-note@-1 {{'~S' declared here}}
17  int x;
18};
19
20struct T {
21  __host__ __device__ void hd() { device_fn(); }
22  // expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
23
24  // No error; this is (implicitly) inline and is never called, so isn't
25  // codegen'ed.
26  __host__ __device__ void hd2() { device_fn(); }
27
28  __host__ __device__ void hd3();
29
30  __device__ void d() {}
31  // expected-note@-1 {{'d' declared here}}
32};
33
34__host__ __device__ void T::hd3() {
35  device_fn();
36  // expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
37}
38
39template <typename T> __host__ __device__ void hd2() { device_fn(); }
40// expected-error@-1 2 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
41void host_fn() { hd2<int>(); }
42
43__host__ __device__ void hd() { device_fn(); }
44// expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
45
46// No error because this is never instantiated.
47template <typename T> __host__ __device__ void hd3() { device_fn(); }
48
49__host__ __device__ void local_var() {
50  S s;
51  // expected-error@-1 {{reference to __device__ function 'S' in __host__ __device__ function}}
52}
53
54__host__ __device__ void placement_new(char *ptr) {
55  ::new(ptr) S();
56  // expected-error@-1 {{reference to __device__ function 'S' in __host__ __device__ function}}
57}
58
59__host__ __device__ void explicit_destructor(S *s) {
60  s->~S();
61  // expected-error@-1 {{reference to __device__ function '~S' in __host__ __device__ function}}
62}
63
64__host__ __device__ void hd_member_fn() {
65  T t;
66  // Necessary to trigger an error on T::hd.  It's (implicitly) inline, so
67  // isn't codegen'ed until we call it.
68  t.hd();
69}
70
71__host__ __device__ void h_member_fn() {
72  T t;
73  t.d();
74  // expected-error@-1 {{reference to __device__ function 'd' in __host__ __device__ function}}
75}
76
77__host__ __device__ void fn_ptr() {
78  auto* ptr = &device_fn;
79  // expected-error@-1 {{reference to __device__ function 'device_fn' in __host__ __device__ function}}
80}
81
82template <typename T>
83__host__ __device__ void fn_ptr_template() {
84  auto* ptr = &device_fn;  // Not an error because the template isn't instantiated.
85}
86
87// Launching a kernel from a host function does not result in code generation
88// for it, so calling HD function which calls a D function should not trigger
89// errors.
90static __host__ __device__ void hd_func() { device_fn(); }
91__global__ void kernel() { hd_func(); }
92void host_func(void) { kernel<<<1, 1>>>(); }
93
94// Should allow host function call kernel template with device function argument.
95__device__ void f();
96template<void(*F)()> __global__ void t() { F(); }
97__host__ void g() { t<f><<<1,1>>>(); }
98