xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaOpenACC.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===--- SemaOpenACC.cpp - Semantic Analysis for OpenACC constructs -------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric /// \file
9*0fca6ea1SDimitry Andric /// This file implements semantic analysis for OpenACC constructs and
10*0fca6ea1SDimitry Andric /// clauses.
11*0fca6ea1SDimitry Andric ///
12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
13*0fca6ea1SDimitry Andric 
14*0fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenACC.h"
15*0fca6ea1SDimitry Andric #include "clang/AST/StmtOpenACC.h"
16*0fca6ea1SDimitry Andric #include "clang/Basic/DiagnosticSema.h"
17*0fca6ea1SDimitry Andric #include "clang/Basic/OpenACCKinds.h"
18*0fca6ea1SDimitry Andric #include "clang/Sema/Sema.h"
19*0fca6ea1SDimitry Andric #include "llvm/ADT/StringExtras.h"
20*0fca6ea1SDimitry Andric #include "llvm/Support/Casting.h"
21*0fca6ea1SDimitry Andric 
22*0fca6ea1SDimitry Andric using namespace clang;
23*0fca6ea1SDimitry Andric 
24*0fca6ea1SDimitry Andric namespace {
25*0fca6ea1SDimitry Andric bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,
26*0fca6ea1SDimitry Andric                                     SourceLocation StartLoc, bool IsStmt) {
27*0fca6ea1SDimitry Andric   switch (K) {
28*0fca6ea1SDimitry Andric   default:
29*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Invalid:
30*0fca6ea1SDimitry Andric     // Nothing to do here, both invalid and unimplemented don't really need to
31*0fca6ea1SDimitry Andric     // do anything.
32*0fca6ea1SDimitry Andric     break;
33*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Parallel:
34*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Serial:
35*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Kernels:
36*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Loop:
37*0fca6ea1SDimitry Andric     if (!IsStmt)
38*0fca6ea1SDimitry Andric       return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
39*0fca6ea1SDimitry Andric     break;
40*0fca6ea1SDimitry Andric   }
41*0fca6ea1SDimitry Andric   return false;
42*0fca6ea1SDimitry Andric }
43*0fca6ea1SDimitry Andric 
44*0fca6ea1SDimitry Andric bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
45*0fca6ea1SDimitry Andric                                 OpenACCClauseKind ClauseKind) {
46*0fca6ea1SDimitry Andric   switch (ClauseKind) {
47*0fca6ea1SDimitry Andric     // FIXME: For each clause as we implement them, we can add the
48*0fca6ea1SDimitry Andric     // 'legalization' list here.
49*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Default:
50*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
51*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
52*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
53*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
54*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
55*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
56*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
57*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
58*0fca6ea1SDimitry Andric       return true;
59*0fca6ea1SDimitry Andric     default:
60*0fca6ea1SDimitry Andric       return false;
61*0fca6ea1SDimitry Andric     }
62*0fca6ea1SDimitry Andric   case OpenACCClauseKind::If:
63*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
64*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
65*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
66*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
67*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
68*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::EnterData:
69*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ExitData:
70*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::HostData:
71*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Init:
72*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Shutdown:
73*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Set:
74*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Update:
75*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Wait:
76*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
77*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
78*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
79*0fca6ea1SDimitry Andric       return true;
80*0fca6ea1SDimitry Andric     default:
81*0fca6ea1SDimitry Andric       return false;
82*0fca6ea1SDimitry Andric     }
83*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Self:
84*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
85*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
86*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
87*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
88*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Update:
89*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
90*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
91*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
92*0fca6ea1SDimitry Andric       return true;
93*0fca6ea1SDimitry Andric     default:
94*0fca6ea1SDimitry Andric       return false;
95*0fca6ea1SDimitry Andric     }
96*0fca6ea1SDimitry Andric   case OpenACCClauseKind::NumGangs:
97*0fca6ea1SDimitry Andric   case OpenACCClauseKind::NumWorkers:
98*0fca6ea1SDimitry Andric   case OpenACCClauseKind::VectorLength:
99*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
100*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
101*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
102*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
103*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
104*0fca6ea1SDimitry Andric       return true;
105*0fca6ea1SDimitry Andric     default:
106*0fca6ea1SDimitry Andric       return false;
107*0fca6ea1SDimitry Andric     }
108*0fca6ea1SDimitry Andric   case OpenACCClauseKind::FirstPrivate:
109*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
110*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
111*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
112*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
113*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
114*0fca6ea1SDimitry Andric       return true;
115*0fca6ea1SDimitry Andric     default:
116*0fca6ea1SDimitry Andric       return false;
117*0fca6ea1SDimitry Andric     }
118*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Private:
119*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
120*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
121*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
122*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Loop:
123*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
124*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
125*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
126*0fca6ea1SDimitry Andric       return true;
127*0fca6ea1SDimitry Andric     default:
128*0fca6ea1SDimitry Andric       return false;
129*0fca6ea1SDimitry Andric     }
130*0fca6ea1SDimitry Andric   case OpenACCClauseKind::NoCreate:
131*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
132*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
133*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
134*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
135*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
136*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
137*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
138*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
139*0fca6ea1SDimitry Andric       return true;
140*0fca6ea1SDimitry Andric     default:
141*0fca6ea1SDimitry Andric       return false;
142*0fca6ea1SDimitry Andric     }
143*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Present:
144*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
145*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
146*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
147*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
148*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
149*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Declare:
150*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
151*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
152*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
153*0fca6ea1SDimitry Andric       return true;
154*0fca6ea1SDimitry Andric     default:
155*0fca6ea1SDimitry Andric       return false;
156*0fca6ea1SDimitry Andric     }
157*0fca6ea1SDimitry Andric 
158*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Copy:
159*0fca6ea1SDimitry Andric   case OpenACCClauseKind::PCopy:
160*0fca6ea1SDimitry Andric   case OpenACCClauseKind::PresentOrCopy:
161*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
162*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
163*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
164*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
165*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
166*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Declare:
167*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
168*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
169*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
170*0fca6ea1SDimitry Andric       return true;
171*0fca6ea1SDimitry Andric     default:
172*0fca6ea1SDimitry Andric       return false;
173*0fca6ea1SDimitry Andric     }
174*0fca6ea1SDimitry Andric   case OpenACCClauseKind::CopyIn:
175*0fca6ea1SDimitry Andric   case OpenACCClauseKind::PCopyIn:
176*0fca6ea1SDimitry Andric   case OpenACCClauseKind::PresentOrCopyIn:
177*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
178*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
179*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
180*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
181*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
182*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::EnterData:
183*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Declare:
184*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
185*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
186*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
187*0fca6ea1SDimitry Andric       return true;
188*0fca6ea1SDimitry Andric     default:
189*0fca6ea1SDimitry Andric       return false;
190*0fca6ea1SDimitry Andric     }
191*0fca6ea1SDimitry Andric   case OpenACCClauseKind::CopyOut:
192*0fca6ea1SDimitry Andric   case OpenACCClauseKind::PCopyOut:
193*0fca6ea1SDimitry Andric   case OpenACCClauseKind::PresentOrCopyOut:
194*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
195*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
196*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
197*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
198*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
199*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ExitData:
200*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Declare:
201*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
202*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
203*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
204*0fca6ea1SDimitry Andric       return true;
205*0fca6ea1SDimitry Andric     default:
206*0fca6ea1SDimitry Andric       return false;
207*0fca6ea1SDimitry Andric     }
208*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Create:
209*0fca6ea1SDimitry Andric   case OpenACCClauseKind::PCreate:
210*0fca6ea1SDimitry Andric   case OpenACCClauseKind::PresentOrCreate:
211*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
212*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
213*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
214*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
215*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
216*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::EnterData:
217*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
218*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
219*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
220*0fca6ea1SDimitry Andric       return true;
221*0fca6ea1SDimitry Andric     default:
222*0fca6ea1SDimitry Andric       return false;
223*0fca6ea1SDimitry Andric     }
224*0fca6ea1SDimitry Andric 
225*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Attach:
226*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
227*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
228*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
229*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
230*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
231*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::EnterData:
232*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
233*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
234*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
235*0fca6ea1SDimitry Andric       return true;
236*0fca6ea1SDimitry Andric     default:
237*0fca6ea1SDimitry Andric       return false;
238*0fca6ea1SDimitry Andric     }
239*0fca6ea1SDimitry Andric   case OpenACCClauseKind::DevicePtr:
240*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
241*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
242*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
243*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
244*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
245*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Declare:
246*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
247*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
248*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
249*0fca6ea1SDimitry Andric       return true;
250*0fca6ea1SDimitry Andric     default:
251*0fca6ea1SDimitry Andric       return false;
252*0fca6ea1SDimitry Andric     }
253*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Async:
254*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
255*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
256*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
257*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
258*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
259*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::EnterData:
260*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ExitData:
261*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Set:
262*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Update:
263*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Wait:
264*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
265*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
266*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
267*0fca6ea1SDimitry Andric       return true;
268*0fca6ea1SDimitry Andric     default:
269*0fca6ea1SDimitry Andric       return false;
270*0fca6ea1SDimitry Andric     }
271*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Wait:
272*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
273*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
274*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
275*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
276*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
277*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::EnterData:
278*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ExitData:
279*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Update:
280*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
281*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
282*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
283*0fca6ea1SDimitry Andric       return true;
284*0fca6ea1SDimitry Andric     default:
285*0fca6ea1SDimitry Andric       return false;
286*0fca6ea1SDimitry Andric     }
287*0fca6ea1SDimitry Andric 
288*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Seq:
289*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
290*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Loop:
291*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Routine:
292*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
293*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
294*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
295*0fca6ea1SDimitry Andric       return true;
296*0fca6ea1SDimitry Andric     default:
297*0fca6ea1SDimitry Andric       return false;
298*0fca6ea1SDimitry Andric     }
299*0fca6ea1SDimitry Andric 
300*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Independent:
301*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Auto:
302*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
303*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Loop:
304*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
305*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
306*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
307*0fca6ea1SDimitry Andric       return true;
308*0fca6ea1SDimitry Andric     default:
309*0fca6ea1SDimitry Andric       return false;
310*0fca6ea1SDimitry Andric     }
311*0fca6ea1SDimitry Andric 
312*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Reduction:
313*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
314*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
315*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
316*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Loop:
317*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
318*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
319*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
320*0fca6ea1SDimitry Andric       return true;
321*0fca6ea1SDimitry Andric     default:
322*0fca6ea1SDimitry Andric       return false;
323*0fca6ea1SDimitry Andric     }
324*0fca6ea1SDimitry Andric 
325*0fca6ea1SDimitry Andric   case OpenACCClauseKind::DeviceType:
326*0fca6ea1SDimitry Andric   case OpenACCClauseKind::DType:
327*0fca6ea1SDimitry Andric     switch (DirectiveKind) {
328*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Parallel:
329*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Serial:
330*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Kernels:
331*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Data:
332*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Init:
333*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Shutdown:
334*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Set:
335*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Update:
336*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Loop:
337*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::Routine:
338*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
339*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
340*0fca6ea1SDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
341*0fca6ea1SDimitry Andric       return true;
342*0fca6ea1SDimitry Andric     default:
343*0fca6ea1SDimitry Andric       return false;
344*0fca6ea1SDimitry Andric     }
345*0fca6ea1SDimitry Andric 
346*0fca6ea1SDimitry Andric   default:
347*0fca6ea1SDimitry Andric     // Do nothing so we can go to the 'unimplemented' diagnostic instead.
348*0fca6ea1SDimitry Andric     return true;
349*0fca6ea1SDimitry Andric   }
350*0fca6ea1SDimitry Andric   llvm_unreachable("Invalid clause kind");
351*0fca6ea1SDimitry Andric }
352*0fca6ea1SDimitry Andric 
353*0fca6ea1SDimitry Andric bool checkAlreadyHasClauseOfKind(
354*0fca6ea1SDimitry Andric     SemaOpenACC &S, ArrayRef<const OpenACCClause *> ExistingClauses,
355*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
356*0fca6ea1SDimitry Andric   const auto *Itr = llvm::find_if(ExistingClauses, [&](const OpenACCClause *C) {
357*0fca6ea1SDimitry Andric     return C->getClauseKind() == Clause.getClauseKind();
358*0fca6ea1SDimitry Andric   });
359*0fca6ea1SDimitry Andric   if (Itr != ExistingClauses.end()) {
360*0fca6ea1SDimitry Andric     S.Diag(Clause.getBeginLoc(), diag::err_acc_duplicate_clause_disallowed)
361*0fca6ea1SDimitry Andric         << Clause.getDirectiveKind() << Clause.getClauseKind();
362*0fca6ea1SDimitry Andric     S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
363*0fca6ea1SDimitry Andric     return true;
364*0fca6ea1SDimitry Andric   }
365*0fca6ea1SDimitry Andric   return false;
366*0fca6ea1SDimitry Andric }
367*0fca6ea1SDimitry Andric 
368*0fca6ea1SDimitry Andric bool checkValidAfterDeviceType(
369*0fca6ea1SDimitry Andric     SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause,
370*0fca6ea1SDimitry Andric     const SemaOpenACC::OpenACCParsedClause &NewClause) {
371*0fca6ea1SDimitry Andric   // This is only a requirement on compute and loop constructs so far, so this
372*0fca6ea1SDimitry Andric   // is fine otherwise.
373*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind()) &&
374*0fca6ea1SDimitry Andric       NewClause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
375*0fca6ea1SDimitry Andric     return false;
376*0fca6ea1SDimitry Andric 
377*0fca6ea1SDimitry Andric   // OpenACC3.3: Section 2.4: Clauses that precede any device_type clause are
378*0fca6ea1SDimitry Andric   // default clauses.  Clauses that follow a device_type clause up to the end of
379*0fca6ea1SDimitry Andric   // the directive or up to the next device_type clause are device-specific
380*0fca6ea1SDimitry Andric   // clauses for the device types specified in the device_type argument.
381*0fca6ea1SDimitry Andric   //
382*0fca6ea1SDimitry Andric   // The above implies that despite what the individual text says, these are
383*0fca6ea1SDimitry Andric   // valid.
384*0fca6ea1SDimitry Andric   if (NewClause.getClauseKind() == OpenACCClauseKind::DType ||
385*0fca6ea1SDimitry Andric       NewClause.getClauseKind() == OpenACCClauseKind::DeviceType)
386*0fca6ea1SDimitry Andric     return false;
387*0fca6ea1SDimitry Andric 
388*0fca6ea1SDimitry Andric   // Implement check from OpenACC3.3: section 2.5.4:
389*0fca6ea1SDimitry Andric   // Only the async, wait, num_gangs, num_workers, and vector_length clauses may
390*0fca6ea1SDimitry Andric   // follow a device_type clause.
391*0fca6ea1SDimitry Andric   if (isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind())) {
392*0fca6ea1SDimitry Andric     switch (NewClause.getClauseKind()) {
393*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Async:
394*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Wait:
395*0fca6ea1SDimitry Andric     case OpenACCClauseKind::NumGangs:
396*0fca6ea1SDimitry Andric     case OpenACCClauseKind::NumWorkers:
397*0fca6ea1SDimitry Andric     case OpenACCClauseKind::VectorLength:
398*0fca6ea1SDimitry Andric       return false;
399*0fca6ea1SDimitry Andric     default:
400*0fca6ea1SDimitry Andric       break;
401*0fca6ea1SDimitry Andric     }
402*0fca6ea1SDimitry Andric   } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
403*0fca6ea1SDimitry Andric     // Implement check from OpenACC3.3: section 2.9:
404*0fca6ea1SDimitry Andric     // Only the collapse, gang, worker, vector, seq, independent, auto, and tile
405*0fca6ea1SDimitry Andric     // clauses may follow a device_type clause.
406*0fca6ea1SDimitry Andric     switch (NewClause.getClauseKind()) {
407*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Collapse:
408*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Gang:
409*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Worker:
410*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Vector:
411*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Seq:
412*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Independent:
413*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Auto:
414*0fca6ea1SDimitry Andric     case OpenACCClauseKind::Tile:
415*0fca6ea1SDimitry Andric       return false;
416*0fca6ea1SDimitry Andric     default:
417*0fca6ea1SDimitry Andric       break;
418*0fca6ea1SDimitry Andric     }
419*0fca6ea1SDimitry Andric   }
420*0fca6ea1SDimitry Andric   S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type)
421*0fca6ea1SDimitry Andric       << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind()
422*0fca6ea1SDimitry Andric       << isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind())
423*0fca6ea1SDimitry Andric       << NewClause.getDirectiveKind();
424*0fca6ea1SDimitry Andric   S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here);
425*0fca6ea1SDimitry Andric   return true;
426*0fca6ea1SDimitry Andric }
427*0fca6ea1SDimitry Andric 
428*0fca6ea1SDimitry Andric class SemaOpenACCClauseVisitor {
429*0fca6ea1SDimitry Andric   SemaOpenACC &SemaRef;
430*0fca6ea1SDimitry Andric   ASTContext &Ctx;
431*0fca6ea1SDimitry Andric   ArrayRef<const OpenACCClause *> ExistingClauses;
432*0fca6ea1SDimitry Andric   bool NotImplemented = false;
433*0fca6ea1SDimitry Andric 
434*0fca6ea1SDimitry Andric   OpenACCClause *isNotImplemented() {
435*0fca6ea1SDimitry Andric     NotImplemented = true;
436*0fca6ea1SDimitry Andric     return nullptr;
437*0fca6ea1SDimitry Andric   }
438*0fca6ea1SDimitry Andric 
439*0fca6ea1SDimitry Andric public:
440*0fca6ea1SDimitry Andric   SemaOpenACCClauseVisitor(SemaOpenACC &S,
441*0fca6ea1SDimitry Andric                            ArrayRef<const OpenACCClause *> ExistingClauses)
442*0fca6ea1SDimitry Andric       : SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {}
443*0fca6ea1SDimitry Andric   // Once we've implemented everything, we shouldn't need this infrastructure.
444*0fca6ea1SDimitry Andric   // But in the meantime, we use this to help decide whether the clause was
445*0fca6ea1SDimitry Andric   // handled for this directive.
446*0fca6ea1SDimitry Andric   bool diagNotImplemented() { return NotImplemented; }
447*0fca6ea1SDimitry Andric 
448*0fca6ea1SDimitry Andric   OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
449*0fca6ea1SDimitry Andric     switch (Clause.getClauseKind()) {
450*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Gang:
451*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Worker:
452*0fca6ea1SDimitry Andric   case OpenACCClauseKind::Vector: {
453*0fca6ea1SDimitry Andric     // TODO OpenACC: These are only implemented enough for the 'seq' diagnostic,
454*0fca6ea1SDimitry Andric     // otherwise treats itself as unimplemented.  When we implement these, we
455*0fca6ea1SDimitry Andric     // can remove them from here.
456*0fca6ea1SDimitry Andric 
457*0fca6ea1SDimitry Andric     // OpenACC 3.3 2.9:
458*0fca6ea1SDimitry Andric     // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
459*0fca6ea1SDimitry Andric     // appears.
460*0fca6ea1SDimitry Andric     const auto *Itr =
461*0fca6ea1SDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
462*0fca6ea1SDimitry Andric 
463*0fca6ea1SDimitry Andric     if (Itr != ExistingClauses.end()) {
464*0fca6ea1SDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
465*0fca6ea1SDimitry Andric           << Clause.getClauseKind() << (*Itr)->getClauseKind();
466*0fca6ea1SDimitry Andric       SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
467*0fca6ea1SDimitry Andric     }
468*0fca6ea1SDimitry Andric     return isNotImplemented();
469*0fca6ea1SDimitry Andric   }
470*0fca6ea1SDimitry Andric 
471*0fca6ea1SDimitry Andric #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
472*0fca6ea1SDimitry Andric   case OpenACCClauseKind::CLAUSE_NAME:                                         \
473*0fca6ea1SDimitry Andric     return Visit##CLAUSE_NAME##Clause(Clause);
474*0fca6ea1SDimitry Andric #define CLAUSE_ALIAS(ALIAS, CLAUSE_NAME, DEPRECATED)                           \
475*0fca6ea1SDimitry Andric   case OpenACCClauseKind::ALIAS:                                               \
476*0fca6ea1SDimitry Andric   if (DEPRECATED)                                                              \
477*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)   \
478*0fca6ea1SDimitry Andric         << Clause.getClauseKind() << OpenACCClauseKind::CLAUSE_NAME;           \
479*0fca6ea1SDimitry Andric   return Visit##CLAUSE_NAME##Clause(Clause);
480*0fca6ea1SDimitry Andric #include "clang/Basic/OpenACCClauses.def"
481*0fca6ea1SDimitry Andric     default:
482*0fca6ea1SDimitry Andric       return isNotImplemented();
483*0fca6ea1SDimitry Andric     }
484*0fca6ea1SDimitry Andric     llvm_unreachable("Invalid clause kind");
485*0fca6ea1SDimitry Andric   }
486*0fca6ea1SDimitry Andric 
487*0fca6ea1SDimitry Andric #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
488*0fca6ea1SDimitry Andric   OpenACCClause *Visit##CLAUSE_NAME##Clause(                                   \
489*0fca6ea1SDimitry Andric       SemaOpenACC::OpenACCParsedClause &Clause);
490*0fca6ea1SDimitry Andric #include "clang/Basic/OpenACCClauses.def"
491*0fca6ea1SDimitry Andric };
492*0fca6ea1SDimitry Andric 
493*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause(
494*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
495*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
496*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
497*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
498*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
499*0fca6ea1SDimitry Andric     return isNotImplemented();
500*0fca6ea1SDimitry Andric 
501*0fca6ea1SDimitry Andric   // Don't add an invalid clause to the AST.
502*0fca6ea1SDimitry Andric   if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
503*0fca6ea1SDimitry Andric     return nullptr;
504*0fca6ea1SDimitry Andric 
505*0fca6ea1SDimitry Andric   // OpenACC 3.3, Section 2.5.4:
506*0fca6ea1SDimitry Andric   // At most one 'default' clause may appear, and it must have a value of
507*0fca6ea1SDimitry Andric   // either 'none' or 'present'.
508*0fca6ea1SDimitry Andric   // Second half of the sentence is diagnosed during parsing.
509*0fca6ea1SDimitry Andric   if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
510*0fca6ea1SDimitry Andric     return nullptr;
511*0fca6ea1SDimitry Andric 
512*0fca6ea1SDimitry Andric   return OpenACCDefaultClause::Create(
513*0fca6ea1SDimitry Andric       Ctx, Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
514*0fca6ea1SDimitry Andric       Clause.getLParenLoc(), Clause.getEndLoc());
515*0fca6ea1SDimitry Andric }
516*0fca6ea1SDimitry Andric 
517*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
518*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
519*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
520*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
521*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
522*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
523*0fca6ea1SDimitry Andric     return isNotImplemented();
524*0fca6ea1SDimitry Andric 
525*0fca6ea1SDimitry Andric   // There is no prose in the standard that says duplicates aren't allowed,
526*0fca6ea1SDimitry Andric   // but this diagnostic is present in other compilers, as well as makes
527*0fca6ea1SDimitry Andric   // sense.
528*0fca6ea1SDimitry Andric   if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
529*0fca6ea1SDimitry Andric     return nullptr;
530*0fca6ea1SDimitry Andric 
531*0fca6ea1SDimitry Andric   // The parser has ensured that we have a proper condition expr, so there
532*0fca6ea1SDimitry Andric   // isn't really much to do here.
533*0fca6ea1SDimitry Andric 
534*0fca6ea1SDimitry Andric   // If the 'if' clause is true, it makes the 'self' clause have no effect,
535*0fca6ea1SDimitry Andric   // diagnose that here.
536*0fca6ea1SDimitry Andric   // TODO OpenACC: When we add these two to other constructs, we might not
537*0fca6ea1SDimitry Andric   // want to warn on this (for example, 'update').
538*0fca6ea1SDimitry Andric   const auto *Itr =
539*0fca6ea1SDimitry Andric       llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);
540*0fca6ea1SDimitry Andric   if (Itr != ExistingClauses.end()) {
541*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
542*0fca6ea1SDimitry Andric     SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
543*0fca6ea1SDimitry Andric   }
544*0fca6ea1SDimitry Andric 
545*0fca6ea1SDimitry Andric   return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(),
546*0fca6ea1SDimitry Andric                                  Clause.getLParenLoc(),
547*0fca6ea1SDimitry Andric                                  Clause.getConditionExpr(), Clause.getEndLoc());
548*0fca6ea1SDimitry Andric }
549*0fca6ea1SDimitry Andric 
550*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
551*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
552*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
553*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
554*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
555*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
556*0fca6ea1SDimitry Andric     return isNotImplemented();
557*0fca6ea1SDimitry Andric 
558*0fca6ea1SDimitry Andric   // TODO OpenACC: When we implement this for 'update', this takes a
559*0fca6ea1SDimitry Andric   // 'var-list' instead of a condition expression, so semantics/handling has
560*0fca6ea1SDimitry Andric   // to happen differently here.
561*0fca6ea1SDimitry Andric 
562*0fca6ea1SDimitry Andric   // There is no prose in the standard that says duplicates aren't allowed,
563*0fca6ea1SDimitry Andric   // but this diagnostic is present in other compilers, as well as makes
564*0fca6ea1SDimitry Andric   // sense.
565*0fca6ea1SDimitry Andric   if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
566*0fca6ea1SDimitry Andric     return nullptr;
567*0fca6ea1SDimitry Andric 
568*0fca6ea1SDimitry Andric   // If the 'if' clause is true, it makes the 'self' clause have no effect,
569*0fca6ea1SDimitry Andric   // diagnose that here.
570*0fca6ea1SDimitry Andric   // TODO OpenACC: When we add these two to other constructs, we might not
571*0fca6ea1SDimitry Andric   // want to warn on this (for example, 'update').
572*0fca6ea1SDimitry Andric   const auto *Itr =
573*0fca6ea1SDimitry Andric       llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>);
574*0fca6ea1SDimitry Andric   if (Itr != ExistingClauses.end()) {
575*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
576*0fca6ea1SDimitry Andric     SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
577*0fca6ea1SDimitry Andric   }
578*0fca6ea1SDimitry Andric   return OpenACCSelfClause::Create(
579*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
580*0fca6ea1SDimitry Andric       Clause.getConditionExpr(), Clause.getEndLoc());
581*0fca6ea1SDimitry Andric }
582*0fca6ea1SDimitry Andric 
583*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(
584*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
585*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
586*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
587*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
588*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
589*0fca6ea1SDimitry Andric     return isNotImplemented();
590*0fca6ea1SDimitry Andric 
591*0fca6ea1SDimitry Andric   // There is no prose in the standard that says duplicates aren't allowed,
592*0fca6ea1SDimitry Andric   // but this diagnostic is present in other compilers, as well as makes
593*0fca6ea1SDimitry Andric   // sense.
594*0fca6ea1SDimitry Andric   if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
595*0fca6ea1SDimitry Andric     return nullptr;
596*0fca6ea1SDimitry Andric 
597*0fca6ea1SDimitry Andric   // num_gangs requires at least 1 int expr in all forms.  Diagnose here, but
598*0fca6ea1SDimitry Andric   // allow us to continue, an empty clause might be useful for future
599*0fca6ea1SDimitry Andric   // diagnostics.
600*0fca6ea1SDimitry Andric   if (Clause.getIntExprs().empty())
601*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
602*0fca6ea1SDimitry Andric         << /*NoArgs=*/0;
603*0fca6ea1SDimitry Andric 
604*0fca6ea1SDimitry Andric   unsigned MaxArgs =
605*0fca6ea1SDimitry Andric       (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
606*0fca6ea1SDimitry Andric        Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)
607*0fca6ea1SDimitry Andric           ? 3
608*0fca6ea1SDimitry Andric           : 1;
609*0fca6ea1SDimitry Andric   // The max number of args differs between parallel and other constructs.
610*0fca6ea1SDimitry Andric   // Again, allow us to continue for the purposes of future diagnostics.
611*0fca6ea1SDimitry Andric   if (Clause.getIntExprs().size() > MaxArgs)
612*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
613*0fca6ea1SDimitry Andric         << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs
614*0fca6ea1SDimitry Andric         << Clause.getIntExprs().size();
615*0fca6ea1SDimitry Andric 
616*0fca6ea1SDimitry Andric   // OpenACC 3.3 Section 2.5.4:
617*0fca6ea1SDimitry Andric   // A reduction clause may not appear on a parallel construct with a
618*0fca6ea1SDimitry Andric   // num_gangs clause that has more than one argument.
619*0fca6ea1SDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel &&
620*0fca6ea1SDimitry Andric       Clause.getIntExprs().size() > 1) {
621*0fca6ea1SDimitry Andric     auto *Parallel =
622*0fca6ea1SDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
623*0fca6ea1SDimitry Andric 
624*0fca6ea1SDimitry Andric     if (Parallel != ExistingClauses.end()) {
625*0fca6ea1SDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(),
626*0fca6ea1SDimitry Andric                    diag::err_acc_reduction_num_gangs_conflict)
627*0fca6ea1SDimitry Andric           << Clause.getIntExprs().size();
628*0fca6ea1SDimitry Andric       SemaRef.Diag((*Parallel)->getBeginLoc(),
629*0fca6ea1SDimitry Andric                    diag::note_acc_previous_clause_here);
630*0fca6ea1SDimitry Andric       return nullptr;
631*0fca6ea1SDimitry Andric     }
632*0fca6ea1SDimitry Andric   }
633*0fca6ea1SDimitry Andric   return OpenACCNumGangsClause::Create(
634*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs(),
635*0fca6ea1SDimitry Andric       Clause.getEndLoc());
636*0fca6ea1SDimitry Andric }
637*0fca6ea1SDimitry Andric 
638*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(
639*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
640*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
641*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
642*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
643*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
644*0fca6ea1SDimitry Andric     return isNotImplemented();
645*0fca6ea1SDimitry Andric 
646*0fca6ea1SDimitry Andric   // There is no prose in the standard that says duplicates aren't allowed,
647*0fca6ea1SDimitry Andric   // but this diagnostic is present in other compilers, as well as makes
648*0fca6ea1SDimitry Andric   // sense.
649*0fca6ea1SDimitry Andric   if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
650*0fca6ea1SDimitry Andric     return nullptr;
651*0fca6ea1SDimitry Andric 
652*0fca6ea1SDimitry Andric   assert(Clause.getIntExprs().size() == 1 &&
653*0fca6ea1SDimitry Andric          "Invalid number of expressions for NumWorkers");
654*0fca6ea1SDimitry Andric   return OpenACCNumWorkersClause::Create(
655*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
656*0fca6ea1SDimitry Andric       Clause.getEndLoc());
657*0fca6ea1SDimitry Andric }
658*0fca6ea1SDimitry Andric 
659*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause(
660*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
661*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
662*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
663*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
664*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
665*0fca6ea1SDimitry Andric     return isNotImplemented();
666*0fca6ea1SDimitry Andric 
667*0fca6ea1SDimitry Andric   // There is no prose in the standard that says duplicates aren't allowed,
668*0fca6ea1SDimitry Andric   // but this diagnostic is present in other compilers, as well as makes
669*0fca6ea1SDimitry Andric   // sense.
670*0fca6ea1SDimitry Andric   if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
671*0fca6ea1SDimitry Andric     return nullptr;
672*0fca6ea1SDimitry Andric 
673*0fca6ea1SDimitry Andric   assert(Clause.getIntExprs().size() == 1 &&
674*0fca6ea1SDimitry Andric          "Invalid number of expressions for NumWorkers");
675*0fca6ea1SDimitry Andric   return OpenACCVectorLengthClause::Create(
676*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
677*0fca6ea1SDimitry Andric       Clause.getEndLoc());
678*0fca6ea1SDimitry Andric }
679*0fca6ea1SDimitry Andric 
680*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(
681*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
682*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
683*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
684*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
685*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
686*0fca6ea1SDimitry Andric     return isNotImplemented();
687*0fca6ea1SDimitry Andric 
688*0fca6ea1SDimitry Andric   // There is no prose in the standard that says duplicates aren't allowed,
689*0fca6ea1SDimitry Andric   // but this diagnostic is present in other compilers, as well as makes
690*0fca6ea1SDimitry Andric   // sense.
691*0fca6ea1SDimitry Andric   if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
692*0fca6ea1SDimitry Andric     return nullptr;
693*0fca6ea1SDimitry Andric 
694*0fca6ea1SDimitry Andric   assert(Clause.getNumIntExprs() < 2 &&
695*0fca6ea1SDimitry Andric          "Invalid number of expressions for Async");
696*0fca6ea1SDimitry Andric   return OpenACCAsyncClause::Create(
697*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
698*0fca6ea1SDimitry Andric       Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr,
699*0fca6ea1SDimitry Andric       Clause.getEndLoc());
700*0fca6ea1SDimitry Andric }
701*0fca6ea1SDimitry Andric 
702*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
703*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
704*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' and 'loop'
705*0fca6ea1SDimitry Andric   // constructs, and 'compute'/'loop' constructs are the only construct that
706*0fca6ea1SDimitry Andric   // can do anything with this yet, so skip/treat as unimplemented in this
707*0fca6ea1SDimitry Andric   // case.
708*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) &&
709*0fca6ea1SDimitry Andric       Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
710*0fca6ea1SDimitry Andric     return isNotImplemented();
711*0fca6ea1SDimitry Andric 
712*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
713*0fca6ea1SDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
714*0fca6ea1SDimitry Andric   // it isn't apparent in the standard where this is justified.
715*0fca6ea1SDimitry Andric 
716*0fca6ea1SDimitry Andric   return OpenACCPrivateClause::Create(Ctx, Clause.getBeginLoc(),
717*0fca6ea1SDimitry Andric                                       Clause.getLParenLoc(),
718*0fca6ea1SDimitry Andric                                       Clause.getVarList(), Clause.getEndLoc());
719*0fca6ea1SDimitry Andric }
720*0fca6ea1SDimitry Andric 
721*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
722*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
723*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
724*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
725*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
726*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
727*0fca6ea1SDimitry Andric     return isNotImplemented();
728*0fca6ea1SDimitry Andric 
729*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
730*0fca6ea1SDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
731*0fca6ea1SDimitry Andric   // it isn't apparent in the standard where this is justified.
732*0fca6ea1SDimitry Andric 
733*0fca6ea1SDimitry Andric   return OpenACCFirstPrivateClause::Create(
734*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
735*0fca6ea1SDimitry Andric       Clause.getEndLoc());
736*0fca6ea1SDimitry Andric }
737*0fca6ea1SDimitry Andric 
738*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitNoCreateClause(
739*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
740*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
741*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
742*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
743*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
744*0fca6ea1SDimitry Andric     return isNotImplemented();
745*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
746*0fca6ea1SDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
747*0fca6ea1SDimitry Andric   // it isn't apparent in the standard where this is justified.
748*0fca6ea1SDimitry Andric 
749*0fca6ea1SDimitry Andric   return OpenACCNoCreateClause::Create(Ctx, Clause.getBeginLoc(),
750*0fca6ea1SDimitry Andric                                        Clause.getLParenLoc(),
751*0fca6ea1SDimitry Andric                                        Clause.getVarList(), Clause.getEndLoc());
752*0fca6ea1SDimitry Andric }
753*0fca6ea1SDimitry Andric 
754*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitPresentClause(
755*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
756*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
757*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
758*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
759*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
760*0fca6ea1SDimitry Andric     return isNotImplemented();
761*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
762*0fca6ea1SDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
763*0fca6ea1SDimitry Andric   // it isn't apparent in the standard where this is justified.
764*0fca6ea1SDimitry Andric 
765*0fca6ea1SDimitry Andric   return OpenACCPresentClause::Create(Ctx, Clause.getBeginLoc(),
766*0fca6ea1SDimitry Andric                                       Clause.getLParenLoc(),
767*0fca6ea1SDimitry Andric                                       Clause.getVarList(), Clause.getEndLoc());
768*0fca6ea1SDimitry Andric }
769*0fca6ea1SDimitry Andric 
770*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyClause(
771*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
772*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
773*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
774*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
775*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
776*0fca6ea1SDimitry Andric     return isNotImplemented();
777*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
778*0fca6ea1SDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
779*0fca6ea1SDimitry Andric   // it isn't apparent in the standard where this is justified.
780*0fca6ea1SDimitry Andric 
781*0fca6ea1SDimitry Andric   return OpenACCCopyClause::Create(
782*0fca6ea1SDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
783*0fca6ea1SDimitry Andric       Clause.getVarList(), Clause.getEndLoc());
784*0fca6ea1SDimitry Andric }
785*0fca6ea1SDimitry Andric 
786*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyInClause(
787*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
788*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
789*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
790*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
791*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
792*0fca6ea1SDimitry Andric     return isNotImplemented();
793*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
794*0fca6ea1SDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
795*0fca6ea1SDimitry Andric   // it isn't apparent in the standard where this is justified.
796*0fca6ea1SDimitry Andric 
797*0fca6ea1SDimitry Andric   return OpenACCCopyInClause::Create(
798*0fca6ea1SDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
799*0fca6ea1SDimitry Andric       Clause.isReadOnly(), Clause.getVarList(), Clause.getEndLoc());
800*0fca6ea1SDimitry Andric }
801*0fca6ea1SDimitry Andric 
802*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyOutClause(
803*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
804*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
805*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
806*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
807*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
808*0fca6ea1SDimitry Andric     return isNotImplemented();
809*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
810*0fca6ea1SDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
811*0fca6ea1SDimitry Andric   // it isn't apparent in the standard where this is justified.
812*0fca6ea1SDimitry Andric 
813*0fca6ea1SDimitry Andric   return OpenACCCopyOutClause::Create(
814*0fca6ea1SDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
815*0fca6ea1SDimitry Andric       Clause.isZero(), Clause.getVarList(), Clause.getEndLoc());
816*0fca6ea1SDimitry Andric }
817*0fca6ea1SDimitry Andric 
818*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCreateClause(
819*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
820*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
821*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
822*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
823*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
824*0fca6ea1SDimitry Andric     return isNotImplemented();
825*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
826*0fca6ea1SDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
827*0fca6ea1SDimitry Andric   // it isn't apparent in the standard where this is justified.
828*0fca6ea1SDimitry Andric 
829*0fca6ea1SDimitry Andric   return OpenACCCreateClause::Create(
830*0fca6ea1SDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
831*0fca6ea1SDimitry Andric       Clause.isZero(), Clause.getVarList(), Clause.getEndLoc());
832*0fca6ea1SDimitry Andric }
833*0fca6ea1SDimitry Andric 
834*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitAttachClause(
835*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
836*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
837*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
838*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
839*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
840*0fca6ea1SDimitry Andric     return isNotImplemented();
841*0fca6ea1SDimitry Andric 
842*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, but we
843*0fca6ea1SDimitry Andric   // still have to make sure it is a pointer type.
844*0fca6ea1SDimitry Andric   llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
845*0fca6ea1SDimitry Andric   llvm::erase_if(VarList, [&](Expr *E) {
846*0fca6ea1SDimitry Andric     return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Attach, E);
847*0fca6ea1SDimitry Andric   });
848*0fca6ea1SDimitry Andric   Clause.setVarListDetails(VarList,
849*0fca6ea1SDimitry Andric                            /*IsReadOnly=*/false, /*IsZero=*/false);
850*0fca6ea1SDimitry Andric   return OpenACCAttachClause::Create(Ctx, Clause.getBeginLoc(),
851*0fca6ea1SDimitry Andric                                      Clause.getLParenLoc(), Clause.getVarList(),
852*0fca6ea1SDimitry Andric                                      Clause.getEndLoc());
853*0fca6ea1SDimitry Andric }
854*0fca6ea1SDimitry Andric 
855*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause(
856*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
857*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
858*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
859*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
860*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
861*0fca6ea1SDimitry Andric     return isNotImplemented();
862*0fca6ea1SDimitry Andric 
863*0fca6ea1SDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, but we
864*0fca6ea1SDimitry Andric   // still have to make sure it is a pointer type.
865*0fca6ea1SDimitry Andric   llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
866*0fca6ea1SDimitry Andric   llvm::erase_if(VarList, [&](Expr *E) {
867*0fca6ea1SDimitry Andric     return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::DevicePtr, E);
868*0fca6ea1SDimitry Andric   });
869*0fca6ea1SDimitry Andric   Clause.setVarListDetails(VarList,
870*0fca6ea1SDimitry Andric                            /*IsReadOnly=*/false, /*IsZero=*/false);
871*0fca6ea1SDimitry Andric 
872*0fca6ea1SDimitry Andric   return OpenACCDevicePtrClause::Create(
873*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
874*0fca6ea1SDimitry Andric       Clause.getEndLoc());
875*0fca6ea1SDimitry Andric }
876*0fca6ea1SDimitry Andric 
877*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause(
878*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
879*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
880*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
881*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
882*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
883*0fca6ea1SDimitry Andric     return isNotImplemented();
884*0fca6ea1SDimitry Andric 
885*0fca6ea1SDimitry Andric   return OpenACCWaitClause::Create(
886*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getDevNumExpr(),
887*0fca6ea1SDimitry Andric       Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc());
888*0fca6ea1SDimitry Andric }
889*0fca6ea1SDimitry Andric 
890*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
891*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
892*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' and 'loop'
893*0fca6ea1SDimitry Andric   // constructs, and 'compute'/'loop' constructs are the only construct that
894*0fca6ea1SDimitry Andric   // can do anything with this yet, so skip/treat as unimplemented in this
895*0fca6ea1SDimitry Andric   // case.
896*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) &&
897*0fca6ea1SDimitry Andric       Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
898*0fca6ea1SDimitry Andric     return isNotImplemented();
899*0fca6ea1SDimitry Andric 
900*0fca6ea1SDimitry Andric   // TODO OpenACC: Once we get enough of the CodeGen implemented that we have
901*0fca6ea1SDimitry Andric   // a source for the list of valid architectures, we need to warn on unknown
902*0fca6ea1SDimitry Andric   // identifiers here.
903*0fca6ea1SDimitry Andric 
904*0fca6ea1SDimitry Andric   return OpenACCDeviceTypeClause::Create(
905*0fca6ea1SDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
906*0fca6ea1SDimitry Andric       Clause.getDeviceTypeArchitectures(), Clause.getEndLoc());
907*0fca6ea1SDimitry Andric }
908*0fca6ea1SDimitry Andric 
909*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
910*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
911*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'loop' constructs, and it is
912*0fca6ea1SDimitry Andric   // the only construct that can do anything with this, so skip/treat as
913*0fca6ea1SDimitry Andric   // unimplemented for the combined constructs.
914*0fca6ea1SDimitry Andric   if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
915*0fca6ea1SDimitry Andric     return isNotImplemented();
916*0fca6ea1SDimitry Andric 
917*0fca6ea1SDimitry Andric   // OpenACC 3.3 2.9:
918*0fca6ea1SDimitry Andric   // Only one of the seq, independent, and auto clauses may appear.
919*0fca6ea1SDimitry Andric   const auto *Itr =
920*0fca6ea1SDimitry Andric       llvm::find_if(ExistingClauses,
921*0fca6ea1SDimitry Andric                     llvm::IsaPred<OpenACCIndependentClause, OpenACCSeqClause>);
922*0fca6ea1SDimitry Andric   if (Itr != ExistingClauses.end()) {
923*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
924*0fca6ea1SDimitry Andric         << Clause.getClauseKind() << Clause.getDirectiveKind();
925*0fca6ea1SDimitry Andric     SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
926*0fca6ea1SDimitry Andric     return nullptr;
927*0fca6ea1SDimitry Andric   }
928*0fca6ea1SDimitry Andric 
929*0fca6ea1SDimitry Andric   return OpenACCAutoClause::Create(Ctx, Clause.getBeginLoc(),
930*0fca6ea1SDimitry Andric                                    Clause.getEndLoc());
931*0fca6ea1SDimitry Andric }
932*0fca6ea1SDimitry Andric 
933*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
934*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
935*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'loop' constructs, and it is
936*0fca6ea1SDimitry Andric   // the only construct that can do anything with this, so skip/treat as
937*0fca6ea1SDimitry Andric   // unimplemented for the combined constructs.
938*0fca6ea1SDimitry Andric   if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
939*0fca6ea1SDimitry Andric     return isNotImplemented();
940*0fca6ea1SDimitry Andric 
941*0fca6ea1SDimitry Andric   // OpenACC 3.3 2.9:
942*0fca6ea1SDimitry Andric   // Only one of the seq, independent, and auto clauses may appear.
943*0fca6ea1SDimitry Andric   const auto *Itr = llvm::find_if(
944*0fca6ea1SDimitry Andric       ExistingClauses, llvm::IsaPred<OpenACCAutoClause, OpenACCSeqClause>);
945*0fca6ea1SDimitry Andric   if (Itr != ExistingClauses.end()) {
946*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
947*0fca6ea1SDimitry Andric         << Clause.getClauseKind() << Clause.getDirectiveKind();
948*0fca6ea1SDimitry Andric     SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
949*0fca6ea1SDimitry Andric     return nullptr;
950*0fca6ea1SDimitry Andric   }
951*0fca6ea1SDimitry Andric 
952*0fca6ea1SDimitry Andric   return OpenACCIndependentClause::Create(Ctx, Clause.getBeginLoc(),
953*0fca6ea1SDimitry Andric                                           Clause.getEndLoc());
954*0fca6ea1SDimitry Andric }
955*0fca6ea1SDimitry Andric 
956*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
957*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
958*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'loop' constructs, and it is
959*0fca6ea1SDimitry Andric   // the only construct that can do anything with this, so skip/treat as
960*0fca6ea1SDimitry Andric   // unimplemented for the combined constructs.
961*0fca6ea1SDimitry Andric   if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
962*0fca6ea1SDimitry Andric     return isNotImplemented();
963*0fca6ea1SDimitry Andric 
964*0fca6ea1SDimitry Andric   // OpenACC 3.3 2.9:
965*0fca6ea1SDimitry Andric   // Only one of the seq, independent, and auto clauses may appear.
966*0fca6ea1SDimitry Andric   const auto *Itr =
967*0fca6ea1SDimitry Andric       llvm::find_if(ExistingClauses,
968*0fca6ea1SDimitry Andric                     llvm::IsaPred<OpenACCAutoClause, OpenACCIndependentClause>);
969*0fca6ea1SDimitry Andric   if (Itr != ExistingClauses.end()) {
970*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
971*0fca6ea1SDimitry Andric         << Clause.getClauseKind() << Clause.getDirectiveKind();
972*0fca6ea1SDimitry Andric     SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
973*0fca6ea1SDimitry Andric     return nullptr;
974*0fca6ea1SDimitry Andric   }
975*0fca6ea1SDimitry Andric 
976*0fca6ea1SDimitry Andric   // OpenACC 3.3 2.9:
977*0fca6ea1SDimitry Andric   // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
978*0fca6ea1SDimitry Andric   // appears.
979*0fca6ea1SDimitry Andric   Itr = llvm::find_if(ExistingClauses,
980*0fca6ea1SDimitry Andric                       llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
981*0fca6ea1SDimitry Andric                                     OpenACCVectorClause>);
982*0fca6ea1SDimitry Andric 
983*0fca6ea1SDimitry Andric   if (Itr != ExistingClauses.end()) {
984*0fca6ea1SDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
985*0fca6ea1SDimitry Andric         << Clause.getClauseKind() << (*Itr)->getClauseKind();
986*0fca6ea1SDimitry Andric     SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
987*0fca6ea1SDimitry Andric     return nullptr;
988*0fca6ea1SDimitry Andric   }
989*0fca6ea1SDimitry Andric 
990*0fca6ea1SDimitry Andric   // TODO OpenACC: 2.9 ~ line 2010 specifies that the associated loop has some
991*0fca6ea1SDimitry Andric   // restrictions when there is a 'seq' clause in place. We probably need to
992*0fca6ea1SDimitry Andric   // implement that.
993*0fca6ea1SDimitry Andric   return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(),
994*0fca6ea1SDimitry Andric                                   Clause.getEndLoc());
995*0fca6ea1SDimitry Andric }
996*0fca6ea1SDimitry Andric 
997*0fca6ea1SDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
998*0fca6ea1SDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
999*0fca6ea1SDimitry Andric   // Restrictions only properly implemented on 'compute' constructs, and
1000*0fca6ea1SDimitry Andric   // 'compute' constructs are the only construct that can do anything with
1001*0fca6ea1SDimitry Andric   // this yet, so skip/treat as unimplemented in this case.
1002*0fca6ea1SDimitry Andric   if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
1003*0fca6ea1SDimitry Andric     return isNotImplemented();
1004*0fca6ea1SDimitry Andric 
1005*0fca6ea1SDimitry Andric   // OpenACC 3.3 Section 2.5.4:
1006*0fca6ea1SDimitry Andric   // A reduction clause may not appear on a parallel construct with a
1007*0fca6ea1SDimitry Andric   // num_gangs clause that has more than one argument.
1008*0fca6ea1SDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel) {
1009*0fca6ea1SDimitry Andric     auto NumGangsClauses = llvm::make_filter_range(
1010*0fca6ea1SDimitry Andric         ExistingClauses, llvm::IsaPred<OpenACCNumGangsClause>);
1011*0fca6ea1SDimitry Andric 
1012*0fca6ea1SDimitry Andric     for (auto *NGC : NumGangsClauses) {
1013*0fca6ea1SDimitry Andric       unsigned NumExprs =
1014*0fca6ea1SDimitry Andric           cast<OpenACCNumGangsClause>(NGC)->getIntExprs().size();
1015*0fca6ea1SDimitry Andric 
1016*0fca6ea1SDimitry Andric       if (NumExprs > 1) {
1017*0fca6ea1SDimitry Andric         SemaRef.Diag(Clause.getBeginLoc(),
1018*0fca6ea1SDimitry Andric                      diag::err_acc_reduction_num_gangs_conflict)
1019*0fca6ea1SDimitry Andric             << NumExprs;
1020*0fca6ea1SDimitry Andric         SemaRef.Diag(NGC->getBeginLoc(), diag::note_acc_previous_clause_here);
1021*0fca6ea1SDimitry Andric         return nullptr;
1022*0fca6ea1SDimitry Andric       }
1023*0fca6ea1SDimitry Andric     }
1024*0fca6ea1SDimitry Andric   }
1025*0fca6ea1SDimitry Andric 
1026*0fca6ea1SDimitry Andric   SmallVector<Expr *> ValidVars;
1027*0fca6ea1SDimitry Andric 
1028*0fca6ea1SDimitry Andric   for (Expr *Var : Clause.getVarList()) {
1029*0fca6ea1SDimitry Andric     ExprResult Res = SemaRef.CheckReductionVar(Var);
1030*0fca6ea1SDimitry Andric 
1031*0fca6ea1SDimitry Andric     if (Res.isUsable())
1032*0fca6ea1SDimitry Andric       ValidVars.push_back(Res.get());
1033*0fca6ea1SDimitry Andric   }
1034*0fca6ea1SDimitry Andric 
1035*0fca6ea1SDimitry Andric   return OpenACCReductionClause::Create(
1036*0fca6ea1SDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getReductionOp(),
1037*0fca6ea1SDimitry Andric       ValidVars, Clause.getEndLoc());
1038*0fca6ea1SDimitry Andric }
1039*0fca6ea1SDimitry Andric 
1040*0fca6ea1SDimitry Andric } // namespace
1041*0fca6ea1SDimitry Andric 
1042*0fca6ea1SDimitry Andric SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
1043*0fca6ea1SDimitry Andric 
1044*0fca6ea1SDimitry Andric SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(SemaOpenACC &S,
1045*0fca6ea1SDimitry Andric                                                     OpenACCDirectiveKind DK)
1046*0fca6ea1SDimitry Andric     : SemaRef(S), WasInsideComputeConstruct(S.InsideComputeConstruct),
1047*0fca6ea1SDimitry Andric       DirKind(DK) {
1048*0fca6ea1SDimitry Andric   // Compute constructs end up taking their 'loop'.
1049*0fca6ea1SDimitry Andric   if (DirKind == OpenACCDirectiveKind::Parallel ||
1050*0fca6ea1SDimitry Andric       DirKind == OpenACCDirectiveKind::Serial ||
1051*0fca6ea1SDimitry Andric       DirKind == OpenACCDirectiveKind::Kernels) {
1052*0fca6ea1SDimitry Andric     SemaRef.InsideComputeConstruct = true;
1053*0fca6ea1SDimitry Andric     SemaRef.ParentlessLoopConstructs.swap(ParentlessLoopConstructs);
1054*0fca6ea1SDimitry Andric   }
1055*0fca6ea1SDimitry Andric }
1056*0fca6ea1SDimitry Andric 
1057*0fca6ea1SDimitry Andric SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
1058*0fca6ea1SDimitry Andric   SemaRef.InsideComputeConstruct = WasInsideComputeConstruct;
1059*0fca6ea1SDimitry Andric   if (DirKind == OpenACCDirectiveKind::Parallel ||
1060*0fca6ea1SDimitry Andric       DirKind == OpenACCDirectiveKind::Serial ||
1061*0fca6ea1SDimitry Andric       DirKind == OpenACCDirectiveKind::Kernels) {
1062*0fca6ea1SDimitry Andric     assert(SemaRef.ParentlessLoopConstructs.empty() &&
1063*0fca6ea1SDimitry Andric            "Didn't consume loop construct list?");
1064*0fca6ea1SDimitry Andric     SemaRef.ParentlessLoopConstructs.swap(ParentlessLoopConstructs);
1065*0fca6ea1SDimitry Andric   }
1066*0fca6ea1SDimitry Andric }
1067*0fca6ea1SDimitry Andric 
1068*0fca6ea1SDimitry Andric OpenACCClause *
1069*0fca6ea1SDimitry Andric SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
1070*0fca6ea1SDimitry Andric                          OpenACCParsedClause &Clause) {
1071*0fca6ea1SDimitry Andric   if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)
1072*0fca6ea1SDimitry Andric     return nullptr;
1073*0fca6ea1SDimitry Andric 
1074*0fca6ea1SDimitry Andric   // Diagnose that we don't support this clause on this directive.
1075*0fca6ea1SDimitry Andric   if (!doesClauseApplyToDirective(Clause.getDirectiveKind(),
1076*0fca6ea1SDimitry Andric                                   Clause.getClauseKind())) {
1077*0fca6ea1SDimitry Andric     Diag(Clause.getBeginLoc(), diag::err_acc_clause_appertainment)
1078*0fca6ea1SDimitry Andric         << Clause.getDirectiveKind() << Clause.getClauseKind();
1079*0fca6ea1SDimitry Andric     return nullptr;
1080*0fca6ea1SDimitry Andric   }
1081*0fca6ea1SDimitry Andric 
1082*0fca6ea1SDimitry Andric   if (const auto *DevTypeClause =
1083*0fca6ea1SDimitry Andric           llvm::find_if(ExistingClauses,
1084*0fca6ea1SDimitry Andric                         [&](const OpenACCClause *C) {
1085*0fca6ea1SDimitry Andric                           return isa<OpenACCDeviceTypeClause>(C);
1086*0fca6ea1SDimitry Andric                         });
1087*0fca6ea1SDimitry Andric       DevTypeClause != ExistingClauses.end()) {
1088*0fca6ea1SDimitry Andric     if (checkValidAfterDeviceType(
1089*0fca6ea1SDimitry Andric             *this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))
1090*0fca6ea1SDimitry Andric       return nullptr;
1091*0fca6ea1SDimitry Andric   }
1092*0fca6ea1SDimitry Andric 
1093*0fca6ea1SDimitry Andric   SemaOpenACCClauseVisitor Visitor{*this, ExistingClauses};
1094*0fca6ea1SDimitry Andric   OpenACCClause *Result = Visitor.Visit(Clause);
1095*0fca6ea1SDimitry Andric   assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) &&
1096*0fca6ea1SDimitry Andric          "Created wrong clause?");
1097*0fca6ea1SDimitry Andric 
1098*0fca6ea1SDimitry Andric   if (Visitor.diagNotImplemented())
1099*0fca6ea1SDimitry Andric     Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
1100*0fca6ea1SDimitry Andric         << Clause.getClauseKind();
1101*0fca6ea1SDimitry Andric 
1102*0fca6ea1SDimitry Andric   return Result;
1103*0fca6ea1SDimitry Andric 
1104*0fca6ea1SDimitry Andric   //  switch (Clause.getClauseKind()) {
1105*0fca6ea1SDimitry Andric   //  case OpenACCClauseKind::PresentOrCopy:
1106*0fca6ea1SDimitry Andric   //  case OpenACCClauseKind::PCopy:
1107*0fca6ea1SDimitry Andric   //    Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)
1108*0fca6ea1SDimitry Andric   //        << Clause.getClauseKind() << OpenACCClauseKind::Copy;
1109*0fca6ea1SDimitry Andric   //    LLVM_FALLTHROUGH;
1110*0fca6ea1SDimitry Andric   //  case OpenACCClauseKind::PresentOrCreate:
1111*0fca6ea1SDimitry Andric   //  case OpenACCClauseKind::PCreate:
1112*0fca6ea1SDimitry Andric   //    Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)
1113*0fca6ea1SDimitry Andric   //        << Clause.getClauseKind() << OpenACCClauseKind::Create;
1114*0fca6ea1SDimitry Andric   //    LLVM_FALLTHROUGH;
1115*0fca6ea1SDimitry Andric   //
1116*0fca6ea1SDimitry Andric   //
1117*0fca6ea1SDimitry Andric   //
1118*0fca6ea1SDimitry Andric   //
1119*0fca6ea1SDimitry Andric   //  case OpenACCClauseKind::DType:
1120*0fca6ea1SDimitry Andric   //
1121*0fca6ea1SDimitry Andric   //
1122*0fca6ea1SDimitry Andric   //
1123*0fca6ea1SDimitry Andric   //
1124*0fca6ea1SDimitry Andric   //
1125*0fca6ea1SDimitry Andric   //
1126*0fca6ea1SDimitry Andric   //
1127*0fca6ea1SDimitry Andric   //
1128*0fca6ea1SDimitry Andric   //  case OpenACCClauseKind::Gang:
1129*0fca6ea1SDimitry Andric   //  case OpenACCClauseKind::Worker:
1130*0fca6ea1SDimitry Andric   //  case OpenACCClauseKind::Vector: {
1131*0fca6ea1SDimitry Andric   //    // OpenACC 3.3 2.9:
1132*0fca6ea1SDimitry Andric   //    // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq'
1133*0fca6ea1SDimitry Andric   //    clause
1134*0fca6ea1SDimitry Andric   //    // appears.
1135*0fca6ea1SDimitry Andric   //    const auto *Itr =
1136*0fca6ea1SDimitry Andric   //        llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
1137*0fca6ea1SDimitry Andric   //
1138*0fca6ea1SDimitry Andric   //    if (Itr != ExistingClauses.end()) {
1139*0fca6ea1SDimitry Andric   //      Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
1140*0fca6ea1SDimitry Andric   //          << Clause.getClauseKind() << (*Itr)->getClauseKind();
1141*0fca6ea1SDimitry Andric   //      Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
1142*0fca6ea1SDimitry Andric   //    }
1143*0fca6ea1SDimitry Andric   //    // Not yet implemented, so immediately drop to the 'not yet implemented'
1144*0fca6ea1SDimitry Andric   //    // diagnostic.
1145*0fca6ea1SDimitry Andric   //    break;
1146*0fca6ea1SDimitry Andric   //  }
1147*0fca6ea1SDimitry Andric   //  */
1148*0fca6ea1SDimitry Andric 
1149*0fca6ea1SDimitry Andric }
1150*0fca6ea1SDimitry Andric 
1151*0fca6ea1SDimitry Andric /// OpenACC 3.3 section 2.5.15:
1152*0fca6ea1SDimitry Andric /// At a mininmum, the supported data types include ... the numerical data types
1153*0fca6ea1SDimitry Andric /// in C, C++, and Fortran.
1154*0fca6ea1SDimitry Andric ///
1155*0fca6ea1SDimitry Andric /// If the reduction var is a composite variable, each
1156*0fca6ea1SDimitry Andric /// member of the composite variable must be a supported datatype for the
1157*0fca6ea1SDimitry Andric /// reduction operation.
1158*0fca6ea1SDimitry Andric ExprResult SemaOpenACC::CheckReductionVar(Expr *VarExpr) {
1159*0fca6ea1SDimitry Andric   VarExpr = VarExpr->IgnoreParenCasts();
1160*0fca6ea1SDimitry Andric 
1161*0fca6ea1SDimitry Andric   auto TypeIsValid = [](QualType Ty) {
1162*0fca6ea1SDimitry Andric     return Ty->isDependentType() || Ty->isScalarType();
1163*0fca6ea1SDimitry Andric   };
1164*0fca6ea1SDimitry Andric 
1165*0fca6ea1SDimitry Andric   if (isa<ArraySectionExpr>(VarExpr)) {
1166*0fca6ea1SDimitry Andric     Expr *ASExpr = VarExpr;
1167*0fca6ea1SDimitry Andric     QualType BaseTy = ArraySectionExpr::getBaseOriginalType(ASExpr);
1168*0fca6ea1SDimitry Andric     QualType EltTy = getASTContext().getBaseElementType(BaseTy);
1169*0fca6ea1SDimitry Andric 
1170*0fca6ea1SDimitry Andric     if (!TypeIsValid(EltTy)) {
1171*0fca6ea1SDimitry Andric       Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
1172*0fca6ea1SDimitry Andric           << EltTy << /*Sub array base type*/ 1;
1173*0fca6ea1SDimitry Andric       return ExprError();
1174*0fca6ea1SDimitry Andric     }
1175*0fca6ea1SDimitry Andric   } else if (auto *RD = VarExpr->getType()->getAsRecordDecl()) {
1176*0fca6ea1SDimitry Andric     if (!RD->isStruct() && !RD->isClass()) {
1177*0fca6ea1SDimitry Andric       Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1178*0fca6ea1SDimitry Andric           << /*not class or struct*/ 0 << VarExpr->getType();
1179*0fca6ea1SDimitry Andric       return ExprError();
1180*0fca6ea1SDimitry Andric     }
1181*0fca6ea1SDimitry Andric 
1182*0fca6ea1SDimitry Andric     if (!RD->isCompleteDefinition()) {
1183*0fca6ea1SDimitry Andric       Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1184*0fca6ea1SDimitry Andric           << /*incomplete*/ 1 << VarExpr->getType();
1185*0fca6ea1SDimitry Andric       return ExprError();
1186*0fca6ea1SDimitry Andric     }
1187*0fca6ea1SDimitry Andric     if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
1188*0fca6ea1SDimitry Andric         CXXRD && !CXXRD->isAggregate()) {
1189*0fca6ea1SDimitry Andric       Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1190*0fca6ea1SDimitry Andric           << /*aggregate*/ 2 << VarExpr->getType();
1191*0fca6ea1SDimitry Andric       return ExprError();
1192*0fca6ea1SDimitry Andric     }
1193*0fca6ea1SDimitry Andric 
1194*0fca6ea1SDimitry Andric     for (FieldDecl *FD : RD->fields()) {
1195*0fca6ea1SDimitry Andric       if (!TypeIsValid(FD->getType())) {
1196*0fca6ea1SDimitry Andric         Diag(VarExpr->getExprLoc(),
1197*0fca6ea1SDimitry Andric              diag::err_acc_reduction_composite_member_type);
1198*0fca6ea1SDimitry Andric         Diag(FD->getLocation(), diag::note_acc_reduction_composite_member_loc);
1199*0fca6ea1SDimitry Andric         return ExprError();
1200*0fca6ea1SDimitry Andric       }
1201*0fca6ea1SDimitry Andric     }
1202*0fca6ea1SDimitry Andric   } else if (!TypeIsValid(VarExpr->getType())) {
1203*0fca6ea1SDimitry Andric     Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
1204*0fca6ea1SDimitry Andric         << VarExpr->getType() << /*Sub array base type*/ 0;
1205*0fca6ea1SDimitry Andric     return ExprError();
1206*0fca6ea1SDimitry Andric   }
1207*0fca6ea1SDimitry Andric 
1208*0fca6ea1SDimitry Andric   return VarExpr;
1209*0fca6ea1SDimitry Andric }
1210*0fca6ea1SDimitry Andric 
1211*0fca6ea1SDimitry Andric void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
1212*0fca6ea1SDimitry Andric                                  SourceLocation DirLoc) {
1213*0fca6ea1SDimitry Andric   switch (K) {
1214*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Invalid:
1215*0fca6ea1SDimitry Andric     // Nothing to do here, an invalid kind has nothing we can check here.  We
1216*0fca6ea1SDimitry Andric     // want to continue parsing clauses as far as we can, so we will just
1217*0fca6ea1SDimitry Andric     // ensure that we can still work and don't check any construct-specific
1218*0fca6ea1SDimitry Andric     // rules anywhere.
1219*0fca6ea1SDimitry Andric     break;
1220*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Parallel:
1221*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Serial:
1222*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Kernels:
1223*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Loop:
1224*0fca6ea1SDimitry Andric     // Nothing to do here, there is no real legalization that needs to happen
1225*0fca6ea1SDimitry Andric     // here as these constructs do not take any arguments.
1226*0fca6ea1SDimitry Andric     break;
1227*0fca6ea1SDimitry Andric   default:
1228*0fca6ea1SDimitry Andric     Diag(DirLoc, diag::warn_acc_construct_unimplemented) << K;
1229*0fca6ea1SDimitry Andric     break;
1230*0fca6ea1SDimitry Andric   }
1231*0fca6ea1SDimitry Andric }
1232*0fca6ea1SDimitry Andric 
1233*0fca6ea1SDimitry Andric ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind DK,
1234*0fca6ea1SDimitry Andric                                      OpenACCClauseKind CK, SourceLocation Loc,
1235*0fca6ea1SDimitry Andric                                      Expr *IntExpr) {
1236*0fca6ea1SDimitry Andric 
1237*0fca6ea1SDimitry Andric   assert(((DK != OpenACCDirectiveKind::Invalid &&
1238*0fca6ea1SDimitry Andric            CK == OpenACCClauseKind::Invalid) ||
1239*0fca6ea1SDimitry Andric           (DK == OpenACCDirectiveKind::Invalid &&
1240*0fca6ea1SDimitry Andric            CK != OpenACCClauseKind::Invalid) ||
1241*0fca6ea1SDimitry Andric           (DK == OpenACCDirectiveKind::Invalid &&
1242*0fca6ea1SDimitry Andric            CK == OpenACCClauseKind::Invalid)) &&
1243*0fca6ea1SDimitry Andric          "Only one of directive or clause kind should be provided");
1244*0fca6ea1SDimitry Andric 
1245*0fca6ea1SDimitry Andric   class IntExprConverter : public Sema::ICEConvertDiagnoser {
1246*0fca6ea1SDimitry Andric     OpenACCDirectiveKind DirectiveKind;
1247*0fca6ea1SDimitry Andric     OpenACCClauseKind ClauseKind;
1248*0fca6ea1SDimitry Andric     Expr *IntExpr;
1249*0fca6ea1SDimitry Andric 
1250*0fca6ea1SDimitry Andric     // gets the index into the diagnostics so we can use this for clauses,
1251*0fca6ea1SDimitry Andric     // directives, and sub array.s
1252*0fca6ea1SDimitry Andric     unsigned getDiagKind() const {
1253*0fca6ea1SDimitry Andric       if (ClauseKind != OpenACCClauseKind::Invalid)
1254*0fca6ea1SDimitry Andric         return 0;
1255*0fca6ea1SDimitry Andric       if (DirectiveKind != OpenACCDirectiveKind::Invalid)
1256*0fca6ea1SDimitry Andric         return 1;
1257*0fca6ea1SDimitry Andric       return 2;
1258*0fca6ea1SDimitry Andric     }
1259*0fca6ea1SDimitry Andric 
1260*0fca6ea1SDimitry Andric   public:
1261*0fca6ea1SDimitry Andric     IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
1262*0fca6ea1SDimitry Andric                      Expr *IntExpr)
1263*0fca6ea1SDimitry Andric         : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false,
1264*0fca6ea1SDimitry Andric                               /*Suppress=*/false,
1265*0fca6ea1SDimitry Andric                               /*SuppressConversion=*/true),
1266*0fca6ea1SDimitry Andric           DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
1267*0fca6ea1SDimitry Andric 
1268*0fca6ea1SDimitry Andric     bool match(QualType T) override {
1269*0fca6ea1SDimitry Andric       // OpenACC spec just calls this 'integer expression' as having an
1270*0fca6ea1SDimitry Andric       // 'integer type', so fall back on C99's 'integer type'.
1271*0fca6ea1SDimitry Andric       return T->isIntegerType();
1272*0fca6ea1SDimitry Andric     }
1273*0fca6ea1SDimitry Andric     SemaBase::SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
1274*0fca6ea1SDimitry Andric                                                    QualType T) override {
1275*0fca6ea1SDimitry Andric       return S.Diag(Loc, diag::err_acc_int_expr_requires_integer)
1276*0fca6ea1SDimitry Andric              << getDiagKind() << ClauseKind << DirectiveKind << T;
1277*0fca6ea1SDimitry Andric     }
1278*0fca6ea1SDimitry Andric 
1279*0fca6ea1SDimitry Andric     SemaBase::SemaDiagnosticBuilder
1280*0fca6ea1SDimitry Andric     diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override {
1281*0fca6ea1SDimitry Andric       return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type)
1282*0fca6ea1SDimitry Andric              << T << IntExpr->getSourceRange();
1283*0fca6ea1SDimitry Andric     }
1284*0fca6ea1SDimitry Andric 
1285*0fca6ea1SDimitry Andric     SemaBase::SemaDiagnosticBuilder
1286*0fca6ea1SDimitry Andric     diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T,
1287*0fca6ea1SDimitry Andric                          QualType ConvTy) override {
1288*0fca6ea1SDimitry Andric       return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion)
1289*0fca6ea1SDimitry Andric              << T << ConvTy;
1290*0fca6ea1SDimitry Andric     }
1291*0fca6ea1SDimitry Andric 
1292*0fca6ea1SDimitry Andric     SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
1293*0fca6ea1SDimitry Andric                                                      CXXConversionDecl *Conv,
1294*0fca6ea1SDimitry Andric                                                      QualType ConvTy) override {
1295*0fca6ea1SDimitry Andric       return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
1296*0fca6ea1SDimitry Andric              << ConvTy->isEnumeralType() << ConvTy;
1297*0fca6ea1SDimitry Andric     }
1298*0fca6ea1SDimitry Andric 
1299*0fca6ea1SDimitry Andric     SemaBase::SemaDiagnosticBuilder
1300*0fca6ea1SDimitry Andric     diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override {
1301*0fca6ea1SDimitry Andric       return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T;
1302*0fca6ea1SDimitry Andric     }
1303*0fca6ea1SDimitry Andric 
1304*0fca6ea1SDimitry Andric     SemaBase::SemaDiagnosticBuilder
1305*0fca6ea1SDimitry Andric     noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
1306*0fca6ea1SDimitry Andric       return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
1307*0fca6ea1SDimitry Andric              << ConvTy->isEnumeralType() << ConvTy;
1308*0fca6ea1SDimitry Andric     }
1309*0fca6ea1SDimitry Andric 
1310*0fca6ea1SDimitry Andric     SemaBase::SemaDiagnosticBuilder
1311*0fca6ea1SDimitry Andric     diagnoseConversion(Sema &S, SourceLocation Loc, QualType T,
1312*0fca6ea1SDimitry Andric                        QualType ConvTy) override {
1313*0fca6ea1SDimitry Andric       llvm_unreachable("conversion functions are permitted");
1314*0fca6ea1SDimitry Andric     }
1315*0fca6ea1SDimitry Andric   } IntExprDiagnoser(DK, CK, IntExpr);
1316*0fca6ea1SDimitry Andric 
1317*0fca6ea1SDimitry Andric   ExprResult IntExprResult = SemaRef.PerformContextualImplicitConversion(
1318*0fca6ea1SDimitry Andric       Loc, IntExpr, IntExprDiagnoser);
1319*0fca6ea1SDimitry Andric   if (IntExprResult.isInvalid())
1320*0fca6ea1SDimitry Andric     return ExprError();
1321*0fca6ea1SDimitry Andric 
1322*0fca6ea1SDimitry Andric   IntExpr = IntExprResult.get();
1323*0fca6ea1SDimitry Andric   if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType())
1324*0fca6ea1SDimitry Andric     return ExprError();
1325*0fca6ea1SDimitry Andric 
1326*0fca6ea1SDimitry Andric   // TODO OpenACC: Do we want to perform usual unary conversions here? When
1327*0fca6ea1SDimitry Andric   // doing codegen we might find that is necessary, but skip it for now.
1328*0fca6ea1SDimitry Andric   return IntExpr;
1329*0fca6ea1SDimitry Andric }
1330*0fca6ea1SDimitry Andric 
1331*0fca6ea1SDimitry Andric bool SemaOpenACC::CheckVarIsPointerType(OpenACCClauseKind ClauseKind,
1332*0fca6ea1SDimitry Andric                                         Expr *VarExpr) {
1333*0fca6ea1SDimitry Andric   // We already know that VarExpr is a proper reference to a variable, so we
1334*0fca6ea1SDimitry Andric   // should be able to just take the type of the expression to get the type of
1335*0fca6ea1SDimitry Andric   // the referenced variable.
1336*0fca6ea1SDimitry Andric 
1337*0fca6ea1SDimitry Andric   // We've already seen an error, don't diagnose anything else.
1338*0fca6ea1SDimitry Andric   if (!VarExpr || VarExpr->containsErrors())
1339*0fca6ea1SDimitry Andric     return false;
1340*0fca6ea1SDimitry Andric 
1341*0fca6ea1SDimitry Andric   if (isa<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()) ||
1342*0fca6ea1SDimitry Andric       VarExpr->hasPlaceholderType(BuiltinType::ArraySection)) {
1343*0fca6ea1SDimitry Andric     Diag(VarExpr->getExprLoc(), diag::err_array_section_use) << /*OpenACC=*/0;
1344*0fca6ea1SDimitry Andric     Diag(VarExpr->getExprLoc(), diag::note_acc_expected_pointer_var);
1345*0fca6ea1SDimitry Andric     return true;
1346*0fca6ea1SDimitry Andric   }
1347*0fca6ea1SDimitry Andric 
1348*0fca6ea1SDimitry Andric   QualType Ty = VarExpr->getType();
1349*0fca6ea1SDimitry Andric   Ty = Ty.getNonReferenceType().getUnqualifiedType();
1350*0fca6ea1SDimitry Andric 
1351*0fca6ea1SDimitry Andric   // Nothing we can do if this is a dependent type.
1352*0fca6ea1SDimitry Andric   if (Ty->isDependentType())
1353*0fca6ea1SDimitry Andric     return false;
1354*0fca6ea1SDimitry Andric 
1355*0fca6ea1SDimitry Andric   if (!Ty->isPointerType())
1356*0fca6ea1SDimitry Andric     return Diag(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)
1357*0fca6ea1SDimitry Andric            << ClauseKind << Ty;
1358*0fca6ea1SDimitry Andric   return false;
1359*0fca6ea1SDimitry Andric }
1360*0fca6ea1SDimitry Andric 
1361*0fca6ea1SDimitry Andric ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKind CK, Expr *VarExpr) {
1362*0fca6ea1SDimitry Andric   Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
1363*0fca6ea1SDimitry Andric 
1364*0fca6ea1SDimitry Andric   // Sub-arrays/subscript-exprs are fine as long as the base is a
1365*0fca6ea1SDimitry Andric   // VarExpr/MemberExpr. So strip all of those off.
1366*0fca6ea1SDimitry Andric   while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
1367*0fca6ea1SDimitry Andric     if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
1368*0fca6ea1SDimitry Andric       CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
1369*0fca6ea1SDimitry Andric     else
1370*0fca6ea1SDimitry Andric       CurVarExpr =
1371*0fca6ea1SDimitry Andric           cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
1372*0fca6ea1SDimitry Andric   }
1373*0fca6ea1SDimitry Andric 
1374*0fca6ea1SDimitry Andric   // References to a VarDecl are fine.
1375*0fca6ea1SDimitry Andric   if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
1376*0fca6ea1SDimitry Andric     if (isa<VarDecl, NonTypeTemplateParmDecl>(
1377*0fca6ea1SDimitry Andric             DRE->getFoundDecl()->getCanonicalDecl()))
1378*0fca6ea1SDimitry Andric       return VarExpr;
1379*0fca6ea1SDimitry Andric   }
1380*0fca6ea1SDimitry Andric 
1381*0fca6ea1SDimitry Andric   // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
1382*0fca6ea1SDimitry Andric   // reduction clause must be a scalar variable name, an aggregate variable
1383*0fca6ea1SDimitry Andric   // name, an array element, or a subarray.
1384*0fca6ea1SDimitry Andric   // A MemberExpr that references a Field is valid.
1385*0fca6ea1SDimitry Andric   if (CK != OpenACCClauseKind::Reduction) {
1386*0fca6ea1SDimitry Andric     if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
1387*0fca6ea1SDimitry Andric       if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl()))
1388*0fca6ea1SDimitry Andric         return VarExpr;
1389*0fca6ea1SDimitry Andric     }
1390*0fca6ea1SDimitry Andric   }
1391*0fca6ea1SDimitry Andric 
1392*0fca6ea1SDimitry Andric   // Referring to 'this' is always OK.
1393*0fca6ea1SDimitry Andric   if (isa<CXXThisExpr>(CurVarExpr))
1394*0fca6ea1SDimitry Andric     return VarExpr;
1395*0fca6ea1SDimitry Andric 
1396*0fca6ea1SDimitry Andric   // Nothing really we can do here, as these are dependent.  So just return they
1397*0fca6ea1SDimitry Andric   // are valid.
1398*0fca6ea1SDimitry Andric   if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
1399*0fca6ea1SDimitry Andric       (CK != OpenACCClauseKind::Reduction &&
1400*0fca6ea1SDimitry Andric        isa<CXXDependentScopeMemberExpr>(CurVarExpr)))
1401*0fca6ea1SDimitry Andric     return VarExpr;
1402*0fca6ea1SDimitry Andric 
1403*0fca6ea1SDimitry Andric   // There isn't really anything we can do in the case of a recovery expr, so
1404*0fca6ea1SDimitry Andric   // skip the diagnostic rather than produce a confusing diagnostic.
1405*0fca6ea1SDimitry Andric   if (isa<RecoveryExpr>(CurVarExpr))
1406*0fca6ea1SDimitry Andric     return ExprError();
1407*0fca6ea1SDimitry Andric 
1408*0fca6ea1SDimitry Andric   Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
1409*0fca6ea1SDimitry Andric       << (CK != OpenACCClauseKind::Reduction);
1410*0fca6ea1SDimitry Andric   return ExprError();
1411*0fca6ea1SDimitry Andric }
1412*0fca6ea1SDimitry Andric 
1413*0fca6ea1SDimitry Andric ExprResult SemaOpenACC::ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
1414*0fca6ea1SDimitry Andric                                               Expr *LowerBound,
1415*0fca6ea1SDimitry Andric                                               SourceLocation ColonLoc,
1416*0fca6ea1SDimitry Andric                                               Expr *Length,
1417*0fca6ea1SDimitry Andric                                               SourceLocation RBLoc) {
1418*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
1419*0fca6ea1SDimitry Andric 
1420*0fca6ea1SDimitry Andric   // Handle placeholders.
1421*0fca6ea1SDimitry Andric   if (Base->hasPlaceholderType() &&
1422*0fca6ea1SDimitry Andric       !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
1423*0fca6ea1SDimitry Andric     ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
1424*0fca6ea1SDimitry Andric     if (Result.isInvalid())
1425*0fca6ea1SDimitry Andric       return ExprError();
1426*0fca6ea1SDimitry Andric     Base = Result.get();
1427*0fca6ea1SDimitry Andric   }
1428*0fca6ea1SDimitry Andric   if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
1429*0fca6ea1SDimitry Andric     ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
1430*0fca6ea1SDimitry Andric     if (Result.isInvalid())
1431*0fca6ea1SDimitry Andric       return ExprError();
1432*0fca6ea1SDimitry Andric     Result = SemaRef.DefaultLvalueConversion(Result.get());
1433*0fca6ea1SDimitry Andric     if (Result.isInvalid())
1434*0fca6ea1SDimitry Andric       return ExprError();
1435*0fca6ea1SDimitry Andric     LowerBound = Result.get();
1436*0fca6ea1SDimitry Andric   }
1437*0fca6ea1SDimitry Andric   if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
1438*0fca6ea1SDimitry Andric     ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
1439*0fca6ea1SDimitry Andric     if (Result.isInvalid())
1440*0fca6ea1SDimitry Andric       return ExprError();
1441*0fca6ea1SDimitry Andric     Result = SemaRef.DefaultLvalueConversion(Result.get());
1442*0fca6ea1SDimitry Andric     if (Result.isInvalid())
1443*0fca6ea1SDimitry Andric       return ExprError();
1444*0fca6ea1SDimitry Andric     Length = Result.get();
1445*0fca6ea1SDimitry Andric   }
1446*0fca6ea1SDimitry Andric 
1447*0fca6ea1SDimitry Andric   // Check the 'base' value, it must be an array or pointer type, and not to/of
1448*0fca6ea1SDimitry Andric   // a function type.
1449*0fca6ea1SDimitry Andric   QualType OriginalBaseTy = ArraySectionExpr::getBaseOriginalType(Base);
1450*0fca6ea1SDimitry Andric   QualType ResultTy;
1451*0fca6ea1SDimitry Andric   if (!Base->isTypeDependent()) {
1452*0fca6ea1SDimitry Andric     if (OriginalBaseTy->isAnyPointerType()) {
1453*0fca6ea1SDimitry Andric       ResultTy = OriginalBaseTy->getPointeeType();
1454*0fca6ea1SDimitry Andric     } else if (OriginalBaseTy->isArrayType()) {
1455*0fca6ea1SDimitry Andric       ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
1456*0fca6ea1SDimitry Andric     } else {
1457*0fca6ea1SDimitry Andric       return ExprError(
1458*0fca6ea1SDimitry Andric           Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
1459*0fca6ea1SDimitry Andric           << Base->getSourceRange());
1460*0fca6ea1SDimitry Andric     }
1461*0fca6ea1SDimitry Andric 
1462*0fca6ea1SDimitry Andric     if (ResultTy->isFunctionType()) {
1463*0fca6ea1SDimitry Andric       Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
1464*0fca6ea1SDimitry Andric           << ResultTy << Base->getSourceRange();
1465*0fca6ea1SDimitry Andric       return ExprError();
1466*0fca6ea1SDimitry Andric     }
1467*0fca6ea1SDimitry Andric 
1468*0fca6ea1SDimitry Andric     if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
1469*0fca6ea1SDimitry Andric                                     diag::err_acc_subarray_incomplete_type,
1470*0fca6ea1SDimitry Andric                                     Base))
1471*0fca6ea1SDimitry Andric       return ExprError();
1472*0fca6ea1SDimitry Andric 
1473*0fca6ea1SDimitry Andric     if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
1474*0fca6ea1SDimitry Andric       ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
1475*0fca6ea1SDimitry Andric       if (Result.isInvalid())
1476*0fca6ea1SDimitry Andric         return ExprError();
1477*0fca6ea1SDimitry Andric       Base = Result.get();
1478*0fca6ea1SDimitry Andric     }
1479*0fca6ea1SDimitry Andric   }
1480*0fca6ea1SDimitry Andric 
1481*0fca6ea1SDimitry Andric   auto GetRecovery = [&](Expr *E, QualType Ty) {
1482*0fca6ea1SDimitry Andric     ExprResult Recovery =
1483*0fca6ea1SDimitry Andric         SemaRef.CreateRecoveryExpr(E->getBeginLoc(), E->getEndLoc(), E, Ty);
1484*0fca6ea1SDimitry Andric     return Recovery.isUsable() ? Recovery.get() : nullptr;
1485*0fca6ea1SDimitry Andric   };
1486*0fca6ea1SDimitry Andric 
1487*0fca6ea1SDimitry Andric   // Ensure both of the expressions are int-exprs.
1488*0fca6ea1SDimitry Andric   if (LowerBound && !LowerBound->isTypeDependent()) {
1489*0fca6ea1SDimitry Andric     ExprResult LBRes =
1490*0fca6ea1SDimitry Andric         ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Invalid,
1491*0fca6ea1SDimitry Andric                      LowerBound->getExprLoc(), LowerBound);
1492*0fca6ea1SDimitry Andric 
1493*0fca6ea1SDimitry Andric     if (LBRes.isUsable())
1494*0fca6ea1SDimitry Andric       LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
1495*0fca6ea1SDimitry Andric     LowerBound =
1496*0fca6ea1SDimitry Andric         LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
1497*0fca6ea1SDimitry Andric   }
1498*0fca6ea1SDimitry Andric 
1499*0fca6ea1SDimitry Andric   if (Length && !Length->isTypeDependent()) {
1500*0fca6ea1SDimitry Andric     ExprResult LenRes =
1501*0fca6ea1SDimitry Andric         ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Invalid,
1502*0fca6ea1SDimitry Andric                      Length->getExprLoc(), Length);
1503*0fca6ea1SDimitry Andric 
1504*0fca6ea1SDimitry Andric     if (LenRes.isUsable())
1505*0fca6ea1SDimitry Andric       LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
1506*0fca6ea1SDimitry Andric     Length =
1507*0fca6ea1SDimitry Andric         LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
1508*0fca6ea1SDimitry Andric   }
1509*0fca6ea1SDimitry Andric 
1510*0fca6ea1SDimitry Andric   // Length is required if the base type is not an array of known bounds.
1511*0fca6ea1SDimitry Andric   if (!Length && (OriginalBaseTy.isNull() ||
1512*0fca6ea1SDimitry Andric                   (!OriginalBaseTy->isDependentType() &&
1513*0fca6ea1SDimitry Andric                    !OriginalBaseTy->isConstantArrayType() &&
1514*0fca6ea1SDimitry Andric                    !OriginalBaseTy->isDependentSizedArrayType()))) {
1515*0fca6ea1SDimitry Andric     bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
1516*0fca6ea1SDimitry Andric     Diag(ColonLoc, diag::err_acc_subarray_no_length) << IsArray;
1517*0fca6ea1SDimitry Andric     // Fill in a dummy 'length' so that when we instantiate this we don't
1518*0fca6ea1SDimitry Andric     // double-diagnose here.
1519*0fca6ea1SDimitry Andric     ExprResult Recovery = SemaRef.CreateRecoveryExpr(
1520*0fca6ea1SDimitry Andric         ColonLoc, SourceLocation(), ArrayRef<Expr *>{std::nullopt},
1521*0fca6ea1SDimitry Andric         Context.IntTy);
1522*0fca6ea1SDimitry Andric     Length = Recovery.isUsable() ? Recovery.get() : nullptr;
1523*0fca6ea1SDimitry Andric   }
1524*0fca6ea1SDimitry Andric 
1525*0fca6ea1SDimitry Andric   // Check the values of each of the arguments, they cannot be negative(we
1526*0fca6ea1SDimitry Andric   // assume), and if the array bound is known, must be within range. As we do
1527*0fca6ea1SDimitry Andric   // so, do our best to continue with evaluation, we can set the
1528*0fca6ea1SDimitry Andric   // value/expression to nullptr/nullopt if they are invalid, and treat them as
1529*0fca6ea1SDimitry Andric   // not present for the rest of evaluation.
1530*0fca6ea1SDimitry Andric 
1531*0fca6ea1SDimitry Andric   // We don't have to check for dependence, because the dependent size is
1532*0fca6ea1SDimitry Andric   // represented as a different AST node.
1533*0fca6ea1SDimitry Andric   std::optional<llvm::APSInt> BaseSize;
1534*0fca6ea1SDimitry Andric   if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
1535*0fca6ea1SDimitry Andric     const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);
1536*0fca6ea1SDimitry Andric     BaseSize = ArrayTy->getSize();
1537*0fca6ea1SDimitry Andric   }
1538*0fca6ea1SDimitry Andric 
1539*0fca6ea1SDimitry Andric   auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
1540*0fca6ea1SDimitry Andric     if (!E || E->isInstantiationDependent())
1541*0fca6ea1SDimitry Andric       return std::nullopt;
1542*0fca6ea1SDimitry Andric 
1543*0fca6ea1SDimitry Andric     Expr::EvalResult Res;
1544*0fca6ea1SDimitry Andric     if (!E->EvaluateAsInt(Res, Context))
1545*0fca6ea1SDimitry Andric       return std::nullopt;
1546*0fca6ea1SDimitry Andric     return Res.Val.getInt();
1547*0fca6ea1SDimitry Andric   };
1548*0fca6ea1SDimitry Andric 
1549*0fca6ea1SDimitry Andric   std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
1550*0fca6ea1SDimitry Andric   std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
1551*0fca6ea1SDimitry Andric 
1552*0fca6ea1SDimitry Andric   // Check lower bound for negative or out of range.
1553*0fca6ea1SDimitry Andric   if (LowerBoundValue.has_value()) {
1554*0fca6ea1SDimitry Andric     if (LowerBoundValue->isNegative()) {
1555*0fca6ea1SDimitry Andric       Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
1556*0fca6ea1SDimitry Andric           << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
1557*0fca6ea1SDimitry Andric       LowerBoundValue.reset();
1558*0fca6ea1SDimitry Andric       LowerBound = GetRecovery(LowerBound, LowerBound->getType());
1559*0fca6ea1SDimitry Andric     } else if (BaseSize.has_value() &&
1560*0fca6ea1SDimitry Andric                llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
1561*0fca6ea1SDimitry Andric       // Lower bound (start index) must be less than the size of the array.
1562*0fca6ea1SDimitry Andric       Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
1563*0fca6ea1SDimitry Andric           << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
1564*0fca6ea1SDimitry Andric           << toString(*BaseSize, /*Radix=*/10);
1565*0fca6ea1SDimitry Andric       LowerBoundValue.reset();
1566*0fca6ea1SDimitry Andric       LowerBound = GetRecovery(LowerBound, LowerBound->getType());
1567*0fca6ea1SDimitry Andric     }
1568*0fca6ea1SDimitry Andric   }
1569*0fca6ea1SDimitry Andric 
1570*0fca6ea1SDimitry Andric   // Check length for negative or out of range.
1571*0fca6ea1SDimitry Andric   if (LengthValue.has_value()) {
1572*0fca6ea1SDimitry Andric     if (LengthValue->isNegative()) {
1573*0fca6ea1SDimitry Andric       Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
1574*0fca6ea1SDimitry Andric           << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
1575*0fca6ea1SDimitry Andric       LengthValue.reset();
1576*0fca6ea1SDimitry Andric       Length = GetRecovery(Length, Length->getType());
1577*0fca6ea1SDimitry Andric     } else if (BaseSize.has_value() &&
1578*0fca6ea1SDimitry Andric                llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
1579*0fca6ea1SDimitry Andric       // Length must be lessthan or EQUAL to the size of the array.
1580*0fca6ea1SDimitry Andric       Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
1581*0fca6ea1SDimitry Andric           << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
1582*0fca6ea1SDimitry Andric           << toString(*BaseSize, /*Radix=*/10);
1583*0fca6ea1SDimitry Andric       LengthValue.reset();
1584*0fca6ea1SDimitry Andric       Length = GetRecovery(Length, Length->getType());
1585*0fca6ea1SDimitry Andric     }
1586*0fca6ea1SDimitry Andric   }
1587*0fca6ea1SDimitry Andric 
1588*0fca6ea1SDimitry Andric   // Adding two APSInts requires matching sign, so extract that here.
1589*0fca6ea1SDimitry Andric   auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
1590*0fca6ea1SDimitry Andric     if (LHS.isSigned() == RHS.isSigned())
1591*0fca6ea1SDimitry Andric       return LHS + RHS;
1592*0fca6ea1SDimitry Andric 
1593*0fca6ea1SDimitry Andric     unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
1594*0fca6ea1SDimitry Andric     return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), /*Signed=*/true);
1595*0fca6ea1SDimitry Andric   };
1596*0fca6ea1SDimitry Andric 
1597*0fca6ea1SDimitry Andric   // If we know all 3 values, we can diagnose that the total value would be out
1598*0fca6ea1SDimitry Andric   // of range.
1599*0fca6ea1SDimitry Andric   if (BaseSize.has_value() && LowerBoundValue.has_value() &&
1600*0fca6ea1SDimitry Andric       LengthValue.has_value() &&
1601*0fca6ea1SDimitry Andric       llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
1602*0fca6ea1SDimitry Andric                                   *BaseSize) > 0) {
1603*0fca6ea1SDimitry Andric     Diag(Base->getExprLoc(),
1604*0fca6ea1SDimitry Andric          diag::err_acc_subarray_base_plus_length_out_of_range)
1605*0fca6ea1SDimitry Andric         << toString(*LowerBoundValue, /*Radix=*/10)
1606*0fca6ea1SDimitry Andric         << toString(*LengthValue, /*Radix=*/10)
1607*0fca6ea1SDimitry Andric         << toString(*BaseSize, /*Radix=*/10);
1608*0fca6ea1SDimitry Andric 
1609*0fca6ea1SDimitry Andric     LowerBoundValue.reset();
1610*0fca6ea1SDimitry Andric     LowerBound = GetRecovery(LowerBound, LowerBound->getType());
1611*0fca6ea1SDimitry Andric     LengthValue.reset();
1612*0fca6ea1SDimitry Andric     Length = GetRecovery(Length, Length->getType());
1613*0fca6ea1SDimitry Andric   }
1614*0fca6ea1SDimitry Andric 
1615*0fca6ea1SDimitry Andric   // If any part of the expression is dependent, return a dependent sub-array.
1616*0fca6ea1SDimitry Andric   QualType ArrayExprTy = Context.ArraySectionTy;
1617*0fca6ea1SDimitry Andric   if (Base->isTypeDependent() ||
1618*0fca6ea1SDimitry Andric       (LowerBound && LowerBound->isInstantiationDependent()) ||
1619*0fca6ea1SDimitry Andric       (Length && Length->isInstantiationDependent()))
1620*0fca6ea1SDimitry Andric     ArrayExprTy = Context.DependentTy;
1621*0fca6ea1SDimitry Andric 
1622*0fca6ea1SDimitry Andric   return new (Context)
1623*0fca6ea1SDimitry Andric       ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
1624*0fca6ea1SDimitry Andric                        OK_Ordinary, ColonLoc, RBLoc);
1625*0fca6ea1SDimitry Andric }
1626*0fca6ea1SDimitry Andric 
1627*0fca6ea1SDimitry Andric bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K,
1628*0fca6ea1SDimitry Andric                                           SourceLocation StartLoc) {
1629*0fca6ea1SDimitry Andric   return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
1630*0fca6ea1SDimitry Andric }
1631*0fca6ea1SDimitry Andric 
1632*0fca6ea1SDimitry Andric StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K,
1633*0fca6ea1SDimitry Andric                                               SourceLocation StartLoc,
1634*0fca6ea1SDimitry Andric                                               SourceLocation DirLoc,
1635*0fca6ea1SDimitry Andric                                               SourceLocation EndLoc,
1636*0fca6ea1SDimitry Andric                                               ArrayRef<OpenACCClause *> Clauses,
1637*0fca6ea1SDimitry Andric                                               StmtResult AssocStmt) {
1638*0fca6ea1SDimitry Andric   switch (K) {
1639*0fca6ea1SDimitry Andric   default:
1640*0fca6ea1SDimitry Andric     return StmtEmpty();
1641*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Invalid:
1642*0fca6ea1SDimitry Andric     return StmtError();
1643*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Parallel:
1644*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Serial:
1645*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Kernels: {
1646*0fca6ea1SDimitry Andric     auto *ComputeConstruct = OpenACCComputeConstruct::Create(
1647*0fca6ea1SDimitry Andric         getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
1648*0fca6ea1SDimitry Andric         AssocStmt.isUsable() ? AssocStmt.get() : nullptr,
1649*0fca6ea1SDimitry Andric         ParentlessLoopConstructs);
1650*0fca6ea1SDimitry Andric 
1651*0fca6ea1SDimitry Andric     ParentlessLoopConstructs.clear();
1652*0fca6ea1SDimitry Andric     return ComputeConstruct;
1653*0fca6ea1SDimitry Andric   }
1654*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Loop: {
1655*0fca6ea1SDimitry Andric     auto *LoopConstruct = OpenACCLoopConstruct::Create(
1656*0fca6ea1SDimitry Andric         getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
1657*0fca6ea1SDimitry Andric         AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1658*0fca6ea1SDimitry Andric 
1659*0fca6ea1SDimitry Andric     // If we are in the scope of a compute construct, add this to the list of
1660*0fca6ea1SDimitry Andric     // loop constructs that need assigning to the next closing compute
1661*0fca6ea1SDimitry Andric     // construct.
1662*0fca6ea1SDimitry Andric     if (InsideComputeConstruct)
1663*0fca6ea1SDimitry Andric       ParentlessLoopConstructs.push_back(LoopConstruct);
1664*0fca6ea1SDimitry Andric 
1665*0fca6ea1SDimitry Andric     return LoopConstruct;
1666*0fca6ea1SDimitry Andric   }
1667*0fca6ea1SDimitry Andric   }
1668*0fca6ea1SDimitry Andric   llvm_unreachable("Unhandled case in directive handling?");
1669*0fca6ea1SDimitry Andric }
1670*0fca6ea1SDimitry Andric 
1671*0fca6ea1SDimitry Andric StmtResult SemaOpenACC::ActOnAssociatedStmt(SourceLocation DirectiveLoc,
1672*0fca6ea1SDimitry Andric                                             OpenACCDirectiveKind K,
1673*0fca6ea1SDimitry Andric                                             StmtResult AssocStmt) {
1674*0fca6ea1SDimitry Andric   switch (K) {
1675*0fca6ea1SDimitry Andric   default:
1676*0fca6ea1SDimitry Andric     llvm_unreachable("Unimplemented associated statement application");
1677*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Parallel:
1678*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Serial:
1679*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Kernels:
1680*0fca6ea1SDimitry Andric     // There really isn't any checking here that could happen. As long as we
1681*0fca6ea1SDimitry Andric     // have a statement to associate, this should be fine.
1682*0fca6ea1SDimitry Andric     // OpenACC 3.3 Section 6:
1683*0fca6ea1SDimitry Andric     // Structured Block: in C or C++, an executable statement, possibly
1684*0fca6ea1SDimitry Andric     // compound, with a single entry at the top and a single exit at the
1685*0fca6ea1SDimitry Andric     // bottom.
1686*0fca6ea1SDimitry Andric     // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
1687*0fca6ea1SDimitry Andric     // an interpretation of it is to allow this and treat the initializer as
1688*0fca6ea1SDimitry Andric     // the 'structured block'.
1689*0fca6ea1SDimitry Andric     return AssocStmt;
1690*0fca6ea1SDimitry Andric   case OpenACCDirectiveKind::Loop:
1691*0fca6ea1SDimitry Andric     if (AssocStmt.isUsable() &&
1692*0fca6ea1SDimitry Andric         !isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
1693*0fca6ea1SDimitry Andric       Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop);
1694*0fca6ea1SDimitry Andric       Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
1695*0fca6ea1SDimitry Andric       return StmtError();
1696*0fca6ea1SDimitry Andric     }
1697*0fca6ea1SDimitry Andric     // TODO OpenACC: 2.9 ~ line 2010 specifies that the associated loop has some
1698*0fca6ea1SDimitry Andric     // restrictions when there is a 'seq' clause in place. We probably need to
1699*0fca6ea1SDimitry Andric     // implement that, including piping in the clauses here.
1700*0fca6ea1SDimitry Andric     return AssocStmt;
1701*0fca6ea1SDimitry Andric   }
1702*0fca6ea1SDimitry Andric   llvm_unreachable("Invalid associated statement application");
1703*0fca6ea1SDimitry Andric }
1704*0fca6ea1SDimitry Andric 
1705*0fca6ea1SDimitry Andric bool SemaOpenACC::ActOnStartDeclDirective(OpenACCDirectiveKind K,
1706*0fca6ea1SDimitry Andric                                           SourceLocation StartLoc) {
1707*0fca6ea1SDimitry Andric   return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
1708*0fca6ea1SDimitry Andric }
1709*0fca6ea1SDimitry Andric 
1710*0fca6ea1SDimitry Andric DeclGroupRef SemaOpenACC::ActOnEndDeclDirective() { return DeclGroupRef{}; }
1711