1 // RUN: %clang_cc1 -verify -triple x86_64-unknown-linux -fopenmp -fopenmp-version=51 -std=c++11 -o - %s
2 // RUN: %clang_cc1 -verify -triple x86_64-unknown-linux -fopenmp -fopenmp-version=51 -std=c++11 \
3 // RUN:  -DNO_INTEROP_T_DEF -o - %s
4 // RUN: %clang_cc1 -verify -triple x86_64-unknown-linux -fopenmp -fopenmp-version=50 -std=c++11 -o - %s
5 // RUN: %clang_cc1 -verify -triple x86_64-unknown-linux -fopenmp -fopenmp-version=51 -DC -x c -o - %s
6 
7 #ifdef NO_INTEROP_T_DEF
8 void foo_v1(float *, void *);
9 // expected-error@+1 {{'omp_interop_t' must be defined when 'append_args' clause is used; include <omp.h>}}
10 #pragma omp declare variant(foo_v1) append_args(interop(target)) \
11   match(construct={dispatch})
12 void foo_v1(float *);
13 #else
14 typedef void *omp_interop_t;
15 
16 int Other;
17 
18 #if _OPENMP >= 202011  // At least OpenMP 5.1
19 #ifdef __cplusplus
20 class A {
21 public:
22   void memberfoo_v0(float *A, float *B, int *I);
23   void memberfoo_v1(float *A, float *B, int *I, omp_interop_t IOp);
24 
25   // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (A::*)(float *, float *, int *)' is incompatible with type 'void (A::*)(float *, float *, int *, omp_interop_t)' with appended arguments}}
26   #pragma omp declare variant(memberfoo_v0) match(construct={dispatch}) \
27                         append_args(interop(target))
28 
29   // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (A::*)(float *, float *, int *, omp_interop_t)' is incompatible with type 'void (A::*)(float *, float *, int *, omp_interop_t, omp_interop_t)' with appended arguments}}
30   #pragma omp declare variant(memberfoo_v1) match(construct={dispatch}) \
31                         append_args(interop(target),interop(target))
32   void memberbar(float *A, float *B, int *I) { return; }
33 
34   static void smemberfoo_v0(float *A, float *B, int *I);
35   static void smemberfoo_v1(float *A, float *B, int *I, omp_interop_t IOp);
36 
37   // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (float *, float *, int *)' is incompatible with type 'void (float *, float *, int *)' with appended arguments}}
38   #pragma omp declare variant(smemberfoo_v0) match(construct={dispatch}) \
39                         append_args(interop(target))
40 
41   // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (float *, float *, int *, omp_interop_t)' (aka 'void (float *, float *, int *, void *)') is incompatible with type 'void (float *, float *, int *)' with appended arguments}}
42   #pragma omp declare variant(smemberfoo_v1) match(construct={dispatch}) \
43                         append_args(interop(target),interop(target))
44   static void smemberbar(float *A, float *B, int *I) { return; }
45 
46   virtual void vmemberfoo_v0(float *A, float *B, int *I);
47   virtual void vmemberfoo_v1(float *A, float *B, int *I, omp_interop_t IOp);
48 
49   // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (A::*)(float *, float *, int *)' is incompatible with type 'void (A::*)(float *, float *, int *, omp_interop_t)' with appended arguments}}
50   #pragma omp declare variant(vmemberfoo_v0) match(construct={dispatch}) \
51     append_args(interop(target))
52 
53   #pragma omp declare variant(vmemberfoo_v1) match(construct={dispatch}) \
54     append_args(interop(target))
55 
56   // expected-error@+1 {{'#pragma omp declare variant' does not support virtual functions}}
57   virtual void vmemberbar(float *A, float *B, int *I) { return; }
58 
59   virtual void pvmemberfoo_v0(float *A, float *B, int *I) = 0;
60   virtual void pvmemberfoo_v1(float *A, float *B, int *I, omp_interop_t IOp) = 0;
61 
62   // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (A::*)(float *, float *, int *)' is incompatible with type 'void (A::*)(float *, float *, int *, omp_interop_t)' with appended arguments}}
63   #pragma omp declare variant(pvmemberfoo_v0) match(construct={dispatch}) \
64     append_args(interop(target))
65 
66   #pragma omp declare variant(pvmemberfoo_v1) match(construct={dispatch}) \
67     append_args(interop(target))
68 
69   // expected-error@+1 {{'#pragma omp declare variant' does not support virtual functions}}
70   virtual void pvmemberbar(float *A, float *B, int *I) = 0;
71 };
72 
73 template <typename T> void templatefoo_v0(const T& t);
74 template <typename T> void templatefoo_v1(const T& t, omp_interop_t I);
75 template <typename T> void templatebar(const T& t) {}
76 
77 // expected-error@+1 {{variant in '#pragma omp declare variant' with type '<overloaded function type>' is incompatible with type 'void (const int &)' with appended arguments}}
78 #pragma omp declare variant(templatefoo_v0<int>) match(construct={dispatch}) \
79                         append_args(interop(target))
80 
81 // expected-error@+1 {{variant in '#pragma omp declare variant' with type '<overloaded function type>' is incompatible with type 'void (const int &)' with appended arguments}}
82 #pragma omp declare variant(templatefoo_v1<int>) match(construct={dispatch}) \
83                         append_args(interop(target),interop(target))
84 void templatebar(const int &t) {}
85 #endif // __cplusplus
86 #endif // _OPENMP >= 202011
87 
88 void foo_v1(float *AAA, float *BBB, int *I) { return; }
89 void foo_v2(float *AAA, float *BBB, int *I) { return; }
90 void foo_v3(float *AAA, float *BBB, int *I) { return; }
91 void foo_v4(float *AAA, float *BBB, int *I, omp_interop_t IOp) { return; }
92 
93 #if _OPENMP >= 202011 // At least OpenMP 5.1
94 void vararg_foo(const char *fmt, omp_interop_t it, ...);
95 // expected-error@+3 {{'append_args' is not allowed with varargs functions}}
96 #pragma omp declare variant(vararg_foo) match(construct={dispatch}) \
97                                         append_args(interop(target))
98 void vararg_bar(const char *fmt, ...) { return; }
99 
100 // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (const char *, omp_interop_t, ...)' (aka 'void (const char *, void *, ...)') is incompatible with type 'void (const char *)' with appended arguments}}
101 #pragma omp declare variant(vararg_foo) match(construct={dispatch}) \
102                                         append_args(interop(target))
103 void vararg_bar2(const char *fmt) { return; }
104 
105 // expected-error@+3 {{'adjust_arg' argument 'AAA' used in multiple clauses}}
106 #pragma omp declare variant(foo_v1)                          \
107    match(construct={dispatch}, device={arch(arm)})           \
108    adjust_args(need_device_ptr:AAA,BBB) adjust_args(need_device_ptr:AAA)
109 
110 // expected-error@+3 {{'adjust_arg' argument 'AAA' used in multiple clauses}}
111 #pragma omp declare variant(foo_v1)                          \
112    match(construct={dispatch}, device={arch(ppc)}),          \
113    adjust_args(need_device_ptr:AAA) adjust_args(nothing:AAA)
114 
115 // expected-error@+2 {{use of undeclared identifier 'J'}}
116 #pragma omp declare variant(foo_v1)                          \
117    adjust_args(nothing:J)                                    \
118    match(construct={dispatch}, device={arch(x86,x86_64)})
119 
120 // expected-error@+2 {{expected reference to one of the parameters of function 'foo'}}
121 #pragma omp declare variant(foo_v3)                          \
122    adjust_args(nothing:Other)                                \
123    match(construct={dispatch}, device={arch(x86,x86_64)})
124 
125 // expected-error@+2 {{'adjust_args' clause requires 'dispatch' context selector}}
126 #pragma omp declare variant(foo_v3)                          \
127    adjust_args(nothing:BBB) match(construct={target}, device={arch(arm)})
128 
129 // expected-error@+2 {{'adjust_args' clause requires 'dispatch' context selector}}
130 #pragma omp declare variant(foo_v3)                          \
131    adjust_args(nothing:BBB) match(device={arch(ppc)})
132 
133 // expected-error@+1 {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
134 #pragma omp declare variant(foo_v1)
135 
136 // expected-error@+1 {{expected 'match', 'adjust_args', or 'append_args' clause on 'omp declare variant' directive}}
137 #pragma omp declare variant(foo_v1) other
138 
139 // expected-error@+2 {{unexpected operation specified in 'append_args' clause, expected 'interop'}}
140 #pragma omp declare variant(foo_v1) match(construct={dispatch}) \
141                                     append_args(foobar(target))
142 
143 // expected-error@+2 {{directive '#pragma omp declare variant' cannot contain more than one 'append_args' clause}}
144 #pragma omp declare variant(foo_v1) match(construct={dispatch}) \
145                                     append_args(interop(target)) \
146                                     append_args(interop(targetsync))
147 
148 // expected-error@+2 {{'append_args' clause requires 'dispatch' context selector}}
149 #pragma omp declare variant(foo_v4)                          \
150                     append_args(interop(target)) match(construct={target})
151 
152 // expected-error@+2 {{'append_args' clause requires 'dispatch' context selector}}
153 #pragma omp declare variant(foo_v4)                          \
154                     match(construct={target}) append_args(interop(target))
155 
156 // expected-warning@+2 {{interop type 'target' cannot be specified more than once}}
157 #pragma omp declare variant(foo_v4) match(construct={dispatch}) \
158                                     append_args(interop(target,target))
159 
160 // expected-warning@+2 {{interop type 'targetsync' cannot be specified more than once}}
161 #pragma omp declare variant(foo_v4) match(construct={dispatch}) \
162                                     append_args(interop(targetsync,targetsync))
163 
164 // expected-error@+2 {{expected interop type: 'target' and/or 'targetsync'}}
165 #pragma omp declare variant(foo_v4) match(construct={dispatch}) \
166                                     append_args(interop())
167 
168 // expected-error@+2 {{expected interop type: 'target' and/or 'targetsync'}}
169 #pragma omp declare variant(foo_v4) match(construct={dispatch}) \
170                                     append_args(interop(somethingelse))
171 
172 // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (float *, float *, int *)' is incompatible with type 'void (float *, float *, int *)' with appended arguments}}
173 #pragma omp declare variant(foo_v1) match(construct={dispatch}) \
174                                     append_args(interop(target))
175 
176 // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (float *, float *, int *)' is incompatible with type 'void (float *, float *, int *)' with appended arguments}}
177 #pragma omp declare variant(foo_v1) match(construct={dispatch}) \
178                                     append_args(interop(target),interop(targetsync))
179 
180 // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (float *, float *, int *, omp_interop_t)' (aka 'void (float *, float *, int *, void *)') is incompatible with type 'void (float *, float *, int *)' with appended arguments}}
181 #pragma omp declare variant(foo_v4) match(construct={dispatch}) \
182                                     append_args(interop(target),interop(targetsync))
183 
184 // expected-error@+1 {{variant in '#pragma omp declare variant' with type 'void (float *, float *, int *, omp_interop_t)' (aka 'void (float *, float *, int *, void *)') is incompatible with type 'void (float *, float *, int *)'}}
185 #pragma omp declare variant(foo_v4) match(construct={dispatch})
186 
187 #endif // _OPENMP >= 202011
188 #if _OPENMP < 202011  // OpenMP 5.0 or lower
189 // expected-error@+2 {{expected 'match' clause on 'omp declare variant' directive}}
190 #pragma omp declare variant(foo_v1)                            \
191    adjust_args(need_device_ptr:AAA) match(device={arch(arm)})
192 // expected-error@+2 {{expected 'match' clause on 'omp declare variant' directive}}
193 #pragma omp declare variant(foo_v1)                            \
194    append_args(interop(target)) match(device={arch(arm)})
195 #endif // _OPENMP < 202011
196 
197 void foo(float *AAA, float *BBB, int *I) { return; }
198 
199 #endif // NO_INTEROP_T_DEF
200 
201 #ifdef C
202 void c_variant(omp_interop_t);
203 // expected-error@+3 {{function with '#pragma omp declare variant' must have a prototype when 'append_args' is used}}
204 #pragma omp declare variant(foo_v1)                            \
205    append_args(interop(target)) match(construct={dispatch})
206 void c_base() {}
207 #endif
208