1 | // RUN: %libomptarget-compile-generic -fopenmp-version=51 |
2 | // RUN: %libomptarget-run-generic 2>&1 \ |
3 | // RUN: | %fcheck-generic |
4 | |
5 | extern "C" int printf(const char *, ...); |
6 | template <typename T> class A { |
7 | protected: |
8 | T X; |
9 | T Y; |
10 | |
11 | public: |
12 | A(T x, T y) : X{x}, Y{y} {}; |
13 | }; |
14 | |
15 | template <typename T> class B : public A<T> { |
16 | using A<T>::X; |
17 | using A<T>::Y; |
18 | |
19 | public: |
20 | T res; |
21 | |
22 | B(T x, T y) : A<T>(x, y), res{0} {}; |
23 | |
24 | void run(void) { |
25 | #pragma omp target map(res) |
26 | { res = X + Y; } |
27 | } |
28 | }; |
29 | |
30 | class X { |
31 | protected: |
32 | int A; |
33 | |
34 | public: |
35 | X(int a) : A{a} {}; |
36 | }; |
37 | class Y : public X { |
38 | using X::A; |
39 | |
40 | protected: |
41 | int B; |
42 | |
43 | public: |
44 | Y(int a, int b) : X(a), B{b} {}; |
45 | }; |
46 | class Z : public Y { |
47 | using X::A; |
48 | using Y::B; |
49 | |
50 | public: |
51 | int res; |
52 | Z(int a, int b) : Y(a, b), res{0} {}; |
53 | void run(void) { |
54 | #pragma omp target map(res) |
55 | { res = A + B; } |
56 | } |
57 | }; |
58 | struct descriptor { |
59 | int A; |
60 | int C; |
61 | }; |
62 | |
63 | class BASE {}; |
64 | |
65 | class C : public BASE { |
66 | public: |
67 | void bar(descriptor &d) { |
68 | auto Asize = 4; |
69 | auto Csize = 4; |
70 | |
71 | #pragma omp target data map(from : d.C) |
72 | { |
73 | #pragma omp target teams firstprivate(Csize) |
74 | d.C = 1; |
75 | } |
76 | #pragma omp target map(from : d.A) |
77 | d.A = 3; |
78 | } |
79 | }; |
80 | |
81 | int main(int argc, char *argv[]) { |
82 | B<int> b(2, 3); |
83 | b.run(); |
84 | // CHECK: 5 |
85 | printf("b.res = %d \n" , b.res); |
86 | Z c(2, 3); |
87 | c.run(); |
88 | // CHECK: 5 |
89 | printf("c.res = %d \n" , c.res); |
90 | |
91 | descriptor d; |
92 | C z; |
93 | z.bar(d); |
94 | // CHECK 1 |
95 | printf("%d\n" , d.C); |
96 | // CHECK 3 |
97 | printf("%d\n" , d.A); |
98 | } |
99 | |