xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaOpenACCClause.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===--- SemaOpenACCClause.cpp - Semantic Analysis for OpenACC clause -----===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric /// \file
9*700637cbSDimitry Andric /// This file implements semantic analysis for OpenACC clauses.
10*700637cbSDimitry Andric ///
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "clang/AST/DeclCXX.h"
14*700637cbSDimitry Andric #include "clang/AST/ExprCXX.h"
15*700637cbSDimitry Andric #include "clang/AST/OpenACCClause.h"
16*700637cbSDimitry Andric #include "clang/Basic/DiagnosticSema.h"
17*700637cbSDimitry Andric #include "clang/Basic/OpenACCKinds.h"
18*700637cbSDimitry Andric #include "clang/Sema/SemaOpenACC.h"
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric using namespace clang;
21*700637cbSDimitry Andric 
22*700637cbSDimitry Andric namespace {
checkValidAfterDeviceType(SemaOpenACC & S,const OpenACCDeviceTypeClause & DeviceTypeClause,const SemaOpenACC::OpenACCParsedClause & NewClause)23*700637cbSDimitry Andric bool checkValidAfterDeviceType(
24*700637cbSDimitry Andric     SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause,
25*700637cbSDimitry Andric     const SemaOpenACC::OpenACCParsedClause &NewClause) {
26*700637cbSDimitry Andric   // OpenACC3.3: Section 2.4: Clauses that precede any device_type clause are
27*700637cbSDimitry Andric   // default clauses.  Clauses that follow a device_type clause up to the end of
28*700637cbSDimitry Andric   // the directive or up to the next device_type clause are device-specific
29*700637cbSDimitry Andric   // clauses for the device types specified in the device_type argument.
30*700637cbSDimitry Andric   //
31*700637cbSDimitry Andric   // The above implies that despite what the individual text says, these are
32*700637cbSDimitry Andric   // valid.
33*700637cbSDimitry Andric   if (NewClause.getClauseKind() == OpenACCClauseKind::DType ||
34*700637cbSDimitry Andric       NewClause.getClauseKind() == OpenACCClauseKind::DeviceType)
35*700637cbSDimitry Andric     return false;
36*700637cbSDimitry Andric 
37*700637cbSDimitry Andric   // Implement check from OpenACC3.3: section 2.5.4:
38*700637cbSDimitry Andric   // Only the async, wait, num_gangs, num_workers, and vector_length clauses may
39*700637cbSDimitry Andric   // follow a device_type clause.
40*700637cbSDimitry Andric   if (isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind())) {
41*700637cbSDimitry Andric     switch (NewClause.getClauseKind()) {
42*700637cbSDimitry Andric     case OpenACCClauseKind::Async:
43*700637cbSDimitry Andric     case OpenACCClauseKind::Wait:
44*700637cbSDimitry Andric     case OpenACCClauseKind::NumGangs:
45*700637cbSDimitry Andric     case OpenACCClauseKind::NumWorkers:
46*700637cbSDimitry Andric     case OpenACCClauseKind::VectorLength:
47*700637cbSDimitry Andric       return false;
48*700637cbSDimitry Andric     default:
49*700637cbSDimitry Andric       break;
50*700637cbSDimitry Andric     }
51*700637cbSDimitry Andric   } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
52*700637cbSDimitry Andric     // Implement check from OpenACC3.3: section 2.9:
53*700637cbSDimitry Andric     // Only the collapse, gang, worker, vector, seq, independent, auto, and tile
54*700637cbSDimitry Andric     // clauses may follow a device_type clause.
55*700637cbSDimitry Andric     switch (NewClause.getClauseKind()) {
56*700637cbSDimitry Andric     case OpenACCClauseKind::Collapse:
57*700637cbSDimitry Andric     case OpenACCClauseKind::Gang:
58*700637cbSDimitry Andric     case OpenACCClauseKind::Worker:
59*700637cbSDimitry Andric     case OpenACCClauseKind::Vector:
60*700637cbSDimitry Andric     case OpenACCClauseKind::Seq:
61*700637cbSDimitry Andric     case OpenACCClauseKind::Independent:
62*700637cbSDimitry Andric     case OpenACCClauseKind::Auto:
63*700637cbSDimitry Andric     case OpenACCClauseKind::Tile:
64*700637cbSDimitry Andric       return false;
65*700637cbSDimitry Andric     default:
66*700637cbSDimitry Andric       break;
67*700637cbSDimitry Andric     }
68*700637cbSDimitry Andric   } else if (isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind())) {
69*700637cbSDimitry Andric     // This seems like it should be the union of 2.9 and 2.5.4 from above.
70*700637cbSDimitry Andric     switch (NewClause.getClauseKind()) {
71*700637cbSDimitry Andric     case OpenACCClauseKind::Async:
72*700637cbSDimitry Andric     case OpenACCClauseKind::Wait:
73*700637cbSDimitry Andric     case OpenACCClauseKind::NumGangs:
74*700637cbSDimitry Andric     case OpenACCClauseKind::NumWorkers:
75*700637cbSDimitry Andric     case OpenACCClauseKind::VectorLength:
76*700637cbSDimitry Andric     case OpenACCClauseKind::Collapse:
77*700637cbSDimitry Andric     case OpenACCClauseKind::Gang:
78*700637cbSDimitry Andric     case OpenACCClauseKind::Worker:
79*700637cbSDimitry Andric     case OpenACCClauseKind::Vector:
80*700637cbSDimitry Andric     case OpenACCClauseKind::Seq:
81*700637cbSDimitry Andric     case OpenACCClauseKind::Independent:
82*700637cbSDimitry Andric     case OpenACCClauseKind::Auto:
83*700637cbSDimitry Andric     case OpenACCClauseKind::Tile:
84*700637cbSDimitry Andric       return false;
85*700637cbSDimitry Andric     default:
86*700637cbSDimitry Andric       break;
87*700637cbSDimitry Andric     }
88*700637cbSDimitry Andric   } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Data) {
89*700637cbSDimitry Andric     // OpenACC3.3 section 2.6.5: Only the async and wait clauses may follow a
90*700637cbSDimitry Andric     // device_type clause.
91*700637cbSDimitry Andric     switch (NewClause.getClauseKind()) {
92*700637cbSDimitry Andric     case OpenACCClauseKind::Async:
93*700637cbSDimitry Andric     case OpenACCClauseKind::Wait:
94*700637cbSDimitry Andric       return false;
95*700637cbSDimitry Andric     default:
96*700637cbSDimitry Andric       break;
97*700637cbSDimitry Andric     }
98*700637cbSDimitry Andric   } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Set ||
99*700637cbSDimitry Andric              NewClause.getDirectiveKind() == OpenACCDirectiveKind::Init ||
100*700637cbSDimitry Andric              NewClause.getDirectiveKind() == OpenACCDirectiveKind::Shutdown) {
101*700637cbSDimitry Andric     // There are no restrictions on 'set', 'init', or 'shutdown'.
102*700637cbSDimitry Andric     return false;
103*700637cbSDimitry Andric   } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Update) {
104*700637cbSDimitry Andric     // OpenACC3.3 section 2.14.4: Only the async and wait clauses may follow a
105*700637cbSDimitry Andric     // device_type clause.
106*700637cbSDimitry Andric     switch (NewClause.getClauseKind()) {
107*700637cbSDimitry Andric     case OpenACCClauseKind::Async:
108*700637cbSDimitry Andric     case OpenACCClauseKind::Wait:
109*700637cbSDimitry Andric       return false;
110*700637cbSDimitry Andric     default:
111*700637cbSDimitry Andric       break;
112*700637cbSDimitry Andric     }
113*700637cbSDimitry Andric   } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Routine) {
114*700637cbSDimitry Andric     // OpenACC 3.3 section 2.15: Only the 'gang', 'worker', 'vector', 'seq', and
115*700637cbSDimitry Andric     // 'bind' clauses may follow a device_type clause.
116*700637cbSDimitry Andric     switch (NewClause.getClauseKind()) {
117*700637cbSDimitry Andric     case OpenACCClauseKind::Gang:
118*700637cbSDimitry Andric     case OpenACCClauseKind::Worker:
119*700637cbSDimitry Andric     case OpenACCClauseKind::Vector:
120*700637cbSDimitry Andric     case OpenACCClauseKind::Seq:
121*700637cbSDimitry Andric     case OpenACCClauseKind::Bind:
122*700637cbSDimitry Andric       return false;
123*700637cbSDimitry Andric     default:
124*700637cbSDimitry Andric       break;
125*700637cbSDimitry Andric     }
126*700637cbSDimitry Andric   }
127*700637cbSDimitry Andric   S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type)
128*700637cbSDimitry Andric       << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind()
129*700637cbSDimitry Andric       << NewClause.getDirectiveKind();
130*700637cbSDimitry Andric   S.Diag(DeviceTypeClause.getBeginLoc(),
131*700637cbSDimitry Andric          diag::note_acc_active_applies_clause_here)
132*700637cbSDimitry Andric       << diag::ACCDeviceTypeApp::Active << DeviceTypeClause.getClauseKind();
133*700637cbSDimitry Andric   return true;
134*700637cbSDimitry Andric }
135*700637cbSDimitry Andric 
136*700637cbSDimitry Andric // GCC looks through linkage specs, but not the other transparent declaration
137*700637cbSDimitry Andric // contexts for 'declare' restrictions, so this helper function helps get us
138*700637cbSDimitry Andric // through that.
removeLinkageSpecDC(const DeclContext * DC)139*700637cbSDimitry Andric const DeclContext *removeLinkageSpecDC(const DeclContext *DC) {
140*700637cbSDimitry Andric   while (isa<LinkageSpecDecl>(DC))
141*700637cbSDimitry Andric     DC = DC->getParent();
142*700637cbSDimitry Andric 
143*700637cbSDimitry Andric   return DC;
144*700637cbSDimitry Andric }
145*700637cbSDimitry Andric 
146*700637cbSDimitry Andric class SemaOpenACCClauseVisitor {
147*700637cbSDimitry Andric   SemaOpenACC &SemaRef;
148*700637cbSDimitry Andric   ASTContext &Ctx;
149*700637cbSDimitry Andric   ArrayRef<const OpenACCClause *> ExistingClauses;
150*700637cbSDimitry Andric 
151*700637cbSDimitry Andric   // OpenACC 3.3 2.9:
152*700637cbSDimitry Andric   //  A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
153*700637cbSDimitry Andric   //  appears.
154*700637cbSDimitry Andric   bool
DiagGangWorkerVectorSeqConflict(SemaOpenACC::OpenACCParsedClause & Clause)155*700637cbSDimitry Andric   DiagGangWorkerVectorSeqConflict(SemaOpenACC::OpenACCParsedClause &Clause) {
156*700637cbSDimitry Andric     if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop &&
157*700637cbSDimitry Andric         !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind()))
158*700637cbSDimitry Andric       return false;
159*700637cbSDimitry Andric     assert(Clause.getClauseKind() == OpenACCClauseKind::Gang ||
160*700637cbSDimitry Andric            Clause.getClauseKind() == OpenACCClauseKind::Worker ||
161*700637cbSDimitry Andric            Clause.getClauseKind() == OpenACCClauseKind::Vector);
162*700637cbSDimitry Andric     const auto *Itr =
163*700637cbSDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
164*700637cbSDimitry Andric 
165*700637cbSDimitry Andric     if (Itr != ExistingClauses.end()) {
166*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
167*700637cbSDimitry Andric           << Clause.getClauseKind() << (*Itr)->getClauseKind()
168*700637cbSDimitry Andric           << Clause.getDirectiveKind();
169*700637cbSDimitry Andric       SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
170*700637cbSDimitry Andric           << (*Itr)->getClauseKind();
171*700637cbSDimitry Andric 
172*700637cbSDimitry Andric       return true;
173*700637cbSDimitry Andric     }
174*700637cbSDimitry Andric     return false;
175*700637cbSDimitry Andric   }
176*700637cbSDimitry Andric 
177*700637cbSDimitry Andric   OpenACCModifierKind
CheckModifierList(SemaOpenACC::OpenACCParsedClause & Clause,OpenACCModifierKind Mods)178*700637cbSDimitry Andric   CheckModifierList(SemaOpenACC::OpenACCParsedClause &Clause,
179*700637cbSDimitry Andric                     OpenACCModifierKind Mods) {
180*700637cbSDimitry Andric     auto CheckSingle = [=](OpenACCModifierKind CurMods,
181*700637cbSDimitry Andric                            OpenACCModifierKind ValidKinds,
182*700637cbSDimitry Andric                            OpenACCModifierKind Bit) {
183*700637cbSDimitry Andric       if (!isOpenACCModifierBitSet(CurMods, Bit) ||
184*700637cbSDimitry Andric           isOpenACCModifierBitSet(ValidKinds, Bit))
185*700637cbSDimitry Andric         return CurMods;
186*700637cbSDimitry Andric 
187*700637cbSDimitry Andric       SemaRef.Diag(Clause.getLParenLoc(), diag::err_acc_invalid_modifier)
188*700637cbSDimitry Andric           << Bit << Clause.getClauseKind();
189*700637cbSDimitry Andric 
190*700637cbSDimitry Andric       return CurMods ^ Bit;
191*700637cbSDimitry Andric     };
192*700637cbSDimitry Andric     auto Check = [&](OpenACCModifierKind ValidKinds) {
193*700637cbSDimitry Andric       if ((Mods | ValidKinds) == ValidKinds)
194*700637cbSDimitry Andric         return Mods;
195*700637cbSDimitry Andric 
196*700637cbSDimitry Andric       Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Always);
197*700637cbSDimitry Andric       Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::AlwaysIn);
198*700637cbSDimitry Andric       Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::AlwaysOut);
199*700637cbSDimitry Andric       Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Readonly);
200*700637cbSDimitry Andric       Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Zero);
201*700637cbSDimitry Andric       Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Capture);
202*700637cbSDimitry Andric       return Mods;
203*700637cbSDimitry Andric     };
204*700637cbSDimitry Andric 
205*700637cbSDimitry Andric     // The 'capture' modifier is only valid on copyin, copyout, and create on
206*700637cbSDimitry Andric     // structured data or compute constructs (which also includes combined).
207*700637cbSDimitry Andric     bool IsStructuredDataOrCompute =
208*700637cbSDimitry Andric         Clause.getDirectiveKind() == OpenACCDirectiveKind::Data ||
209*700637cbSDimitry Andric         isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) ||
210*700637cbSDimitry Andric         isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind());
211*700637cbSDimitry Andric 
212*700637cbSDimitry Andric     switch (Clause.getClauseKind()) {
213*700637cbSDimitry Andric     default:
214*700637cbSDimitry Andric       llvm_unreachable("Only for copy, copyin, copyout, create");
215*700637cbSDimitry Andric     case OpenACCClauseKind::Copy:
216*700637cbSDimitry Andric     case OpenACCClauseKind::PCopy:
217*700637cbSDimitry Andric     case OpenACCClauseKind::PresentOrCopy:
218*700637cbSDimitry Andric       // COPY: Capture always
219*700637cbSDimitry Andric       return Check(OpenACCModifierKind::Always | OpenACCModifierKind::AlwaysIn |
220*700637cbSDimitry Andric                    OpenACCModifierKind::AlwaysOut |
221*700637cbSDimitry Andric                    OpenACCModifierKind::Capture);
222*700637cbSDimitry Andric     case OpenACCClauseKind::CopyIn:
223*700637cbSDimitry Andric     case OpenACCClauseKind::PCopyIn:
224*700637cbSDimitry Andric     case OpenACCClauseKind::PresentOrCopyIn:
225*700637cbSDimitry Andric       // COPYIN: Capture only struct.data & compute
226*700637cbSDimitry Andric       return Check(OpenACCModifierKind::Always | OpenACCModifierKind::AlwaysIn |
227*700637cbSDimitry Andric                    OpenACCModifierKind::Readonly |
228*700637cbSDimitry Andric                    (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture
229*700637cbSDimitry Andric                                               : OpenACCModifierKind::Invalid));
230*700637cbSDimitry Andric     case OpenACCClauseKind::CopyOut:
231*700637cbSDimitry Andric     case OpenACCClauseKind::PCopyOut:
232*700637cbSDimitry Andric     case OpenACCClauseKind::PresentOrCopyOut:
233*700637cbSDimitry Andric       // COPYOUT: Capture only struct.data & compute
234*700637cbSDimitry Andric       return Check(OpenACCModifierKind::Always |
235*700637cbSDimitry Andric                    OpenACCModifierKind::AlwaysOut | OpenACCModifierKind::Zero |
236*700637cbSDimitry Andric                    (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture
237*700637cbSDimitry Andric                                               : OpenACCModifierKind::Invalid));
238*700637cbSDimitry Andric     case OpenACCClauseKind::Create:
239*700637cbSDimitry Andric     case OpenACCClauseKind::PCreate:
240*700637cbSDimitry Andric     case OpenACCClauseKind::PresentOrCreate:
241*700637cbSDimitry Andric       // CREATE: Capture only struct.data & compute
242*700637cbSDimitry Andric       return Check(OpenACCModifierKind::Zero |
243*700637cbSDimitry Andric                    (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture
244*700637cbSDimitry Andric                                               : OpenACCModifierKind::Invalid));
245*700637cbSDimitry Andric     }
246*700637cbSDimitry Andric     llvm_unreachable("didn't return from switch above?");
247*700637cbSDimitry Andric   }
248*700637cbSDimitry Andric 
249*700637cbSDimitry Andric   // Helper for the 'routine' checks during 'new' clause addition. Precondition
250*700637cbSDimitry Andric   // is that we already know the new clause is one of the prohbiited ones.
251*700637cbSDimitry Andric   template <typename Pred>
252*700637cbSDimitry Andric   bool
CheckValidRoutineNewClauseHelper(Pred HasPredicate,SemaOpenACC::OpenACCParsedClause & Clause)253*700637cbSDimitry Andric   CheckValidRoutineNewClauseHelper(Pred HasPredicate,
254*700637cbSDimitry Andric                                    SemaOpenACC::OpenACCParsedClause &Clause) {
255*700637cbSDimitry Andric     if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Routine)
256*700637cbSDimitry Andric       return false;
257*700637cbSDimitry Andric 
258*700637cbSDimitry Andric     auto *FirstDeviceType =
259*700637cbSDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
260*700637cbSDimitry Andric 
261*700637cbSDimitry Andric     if (FirstDeviceType == ExistingClauses.end()) {
262*700637cbSDimitry Andric       // If there isn't a device type yet, ANY duplicate is wrong.
263*700637cbSDimitry Andric 
264*700637cbSDimitry Andric       auto *ExistingProhibitedClause =
265*700637cbSDimitry Andric           llvm::find_if(ExistingClauses, HasPredicate);
266*700637cbSDimitry Andric 
267*700637cbSDimitry Andric       if (ExistingProhibitedClause == ExistingClauses.end())
268*700637cbSDimitry Andric         return false;
269*700637cbSDimitry Andric 
270*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
271*700637cbSDimitry Andric           << Clause.getClauseKind()
272*700637cbSDimitry Andric           << (*ExistingProhibitedClause)->getClauseKind()
273*700637cbSDimitry Andric           << Clause.getDirectiveKind();
274*700637cbSDimitry Andric       SemaRef.Diag((*ExistingProhibitedClause)->getBeginLoc(),
275*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
276*700637cbSDimitry Andric           << (*ExistingProhibitedClause)->getClauseKind();
277*700637cbSDimitry Andric       return true;
278*700637cbSDimitry Andric     }
279*700637cbSDimitry Andric 
280*700637cbSDimitry Andric     // At this point we know that this is 'after' a device type. So this is an
281*700637cbSDimitry Andric     // error if: 1- there is one BEFORE the 'device_type' 2- there is one
282*700637cbSDimitry Andric     // between this and the previous 'device_type'.
283*700637cbSDimitry Andric 
284*700637cbSDimitry Andric     auto *BeforeDeviceType =
285*700637cbSDimitry Andric         std::find_if(ExistingClauses.begin(), FirstDeviceType, HasPredicate);
286*700637cbSDimitry Andric     // If there is one before the device_type (and we know we are after a
287*700637cbSDimitry Andric     // device_type), than this is ill-formed.
288*700637cbSDimitry Andric     if (BeforeDeviceType != FirstDeviceType) {
289*700637cbSDimitry Andric       SemaRef.Diag(
290*700637cbSDimitry Andric           Clause.getBeginLoc(),
291*700637cbSDimitry Andric           diag::err_acc_clause_routine_cannot_combine_before_device_type)
292*700637cbSDimitry Andric           << Clause.getClauseKind() << (*BeforeDeviceType)->getClauseKind();
293*700637cbSDimitry Andric       SemaRef.Diag((*BeforeDeviceType)->getBeginLoc(),
294*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
295*700637cbSDimitry Andric           << (*BeforeDeviceType)->getClauseKind();
296*700637cbSDimitry Andric       SemaRef.Diag((*FirstDeviceType)->getBeginLoc(),
297*700637cbSDimitry Andric                    diag::note_acc_active_applies_clause_here)
298*700637cbSDimitry Andric           << diag::ACCDeviceTypeApp::Active
299*700637cbSDimitry Andric           << (*FirstDeviceType)->getClauseKind();
300*700637cbSDimitry Andric       return true;
301*700637cbSDimitry Andric     }
302*700637cbSDimitry Andric 
303*700637cbSDimitry Andric     auto LastDeviceTypeItr =
304*700637cbSDimitry Andric         std::find_if(ExistingClauses.rbegin(), ExistingClauses.rend(),
305*700637cbSDimitry Andric                      llvm::IsaPred<OpenACCDeviceTypeClause>);
306*700637cbSDimitry Andric 
307*700637cbSDimitry Andric     // We already know there is one in the list, so it is nonsensical to not
308*700637cbSDimitry Andric     // have one.
309*700637cbSDimitry Andric     assert(LastDeviceTypeItr != ExistingClauses.rend());
310*700637cbSDimitry Andric 
311*700637cbSDimitry Andric     // Get the device-type from-the-front (not reverse) iterator from the
312*700637cbSDimitry Andric     // reverse iterator.
313*700637cbSDimitry Andric     auto *LastDeviceType = LastDeviceTypeItr.base() - 1;
314*700637cbSDimitry Andric 
315*700637cbSDimitry Andric     auto *ExistingProhibitedSinceLastDevice =
316*700637cbSDimitry Andric         std::find_if(LastDeviceType, ExistingClauses.end(), HasPredicate);
317*700637cbSDimitry Andric 
318*700637cbSDimitry Andric     // No prohibited ones since the last device-type.
319*700637cbSDimitry Andric     if (ExistingProhibitedSinceLastDevice == ExistingClauses.end())
320*700637cbSDimitry Andric       return false;
321*700637cbSDimitry Andric 
322*700637cbSDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(),
323*700637cbSDimitry Andric                  diag::err_acc_clause_routine_cannot_combine_same_device_type)
324*700637cbSDimitry Andric         << Clause.getClauseKind()
325*700637cbSDimitry Andric         << (*ExistingProhibitedSinceLastDevice)->getClauseKind();
326*700637cbSDimitry Andric     SemaRef.Diag((*ExistingProhibitedSinceLastDevice)->getBeginLoc(),
327*700637cbSDimitry Andric                  diag::note_acc_previous_clause_here)
328*700637cbSDimitry Andric         << (*ExistingProhibitedSinceLastDevice)->getClauseKind();
329*700637cbSDimitry Andric     SemaRef.Diag((*LastDeviceType)->getBeginLoc(),
330*700637cbSDimitry Andric                  diag::note_acc_active_applies_clause_here)
331*700637cbSDimitry Andric         << diag::ACCDeviceTypeApp::Active << (*LastDeviceType)->getClauseKind();
332*700637cbSDimitry Andric     return true;
333*700637cbSDimitry Andric   }
334*700637cbSDimitry Andric 
335*700637cbSDimitry Andric   // Routine has a pretty complicated set of rules for how device_type and the
336*700637cbSDimitry Andric   // gang, worker, vector, and seq clauses work.  So diagnose some of it here.
CheckValidRoutineGangWorkerVectorSeqNewClause(SemaOpenACC::OpenACCParsedClause & Clause)337*700637cbSDimitry Andric   bool CheckValidRoutineGangWorkerVectorSeqNewClause(
338*700637cbSDimitry Andric       SemaOpenACC::OpenACCParsedClause &Clause) {
339*700637cbSDimitry Andric 
340*700637cbSDimitry Andric     if (Clause.getClauseKind() != OpenACCClauseKind::Gang &&
341*700637cbSDimitry Andric         Clause.getClauseKind() != OpenACCClauseKind::Vector &&
342*700637cbSDimitry Andric         Clause.getClauseKind() != OpenACCClauseKind::Worker &&
343*700637cbSDimitry Andric         Clause.getClauseKind() != OpenACCClauseKind::Seq)
344*700637cbSDimitry Andric       return false;
345*700637cbSDimitry Andric     auto ProhibitedPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
346*700637cbSDimitry Andric                                         OpenACCVectorClause, OpenACCSeqClause>;
347*700637cbSDimitry Andric 
348*700637cbSDimitry Andric     return CheckValidRoutineNewClauseHelper(ProhibitedPred, Clause);
349*700637cbSDimitry Andric   }
350*700637cbSDimitry Andric 
351*700637cbSDimitry Andric   // Bind should have similar rules on a routine as gang/worker/vector/seq,
352*700637cbSDimitry Andric   // except there is no 'must have 1' rule, so we can get all the checking done
353*700637cbSDimitry Andric   // here.
354*700637cbSDimitry Andric   bool
CheckValidRoutineBindNewClause(SemaOpenACC::OpenACCParsedClause & Clause)355*700637cbSDimitry Andric   CheckValidRoutineBindNewClause(SemaOpenACC::OpenACCParsedClause &Clause) {
356*700637cbSDimitry Andric 
357*700637cbSDimitry Andric     if (Clause.getClauseKind() != OpenACCClauseKind::Bind)
358*700637cbSDimitry Andric       return false;
359*700637cbSDimitry Andric 
360*700637cbSDimitry Andric     auto HasBindPred = llvm::IsaPred<OpenACCBindClause>;
361*700637cbSDimitry Andric     return CheckValidRoutineNewClauseHelper(HasBindPred, Clause);
362*700637cbSDimitry Andric   }
363*700637cbSDimitry Andric 
364*700637cbSDimitry Andric   // For 'tile' and 'collapse', only allow 1 per 'device_type'.
365*700637cbSDimitry Andric   // Also applies to num_worker, num_gangs, vector_length, and async.
366*700637cbSDimitry Andric   // This does introspection into the actual device-types to prevent duplicates
367*700637cbSDimitry Andric   // across device types as well.
368*700637cbSDimitry Andric   template <typename TheClauseTy>
DisallowSinceLastDeviceType(SemaOpenACC::OpenACCParsedClause & Clause)369*700637cbSDimitry Andric   bool DisallowSinceLastDeviceType(SemaOpenACC::OpenACCParsedClause &Clause) {
370*700637cbSDimitry Andric     auto LastDeviceTypeItr =
371*700637cbSDimitry Andric         std::find_if(ExistingClauses.rbegin(), ExistingClauses.rend(),
372*700637cbSDimitry Andric                      llvm::IsaPred<OpenACCDeviceTypeClause>);
373*700637cbSDimitry Andric 
374*700637cbSDimitry Andric     auto LastSinceDevTy =
375*700637cbSDimitry Andric         std::find_if(ExistingClauses.rbegin(), LastDeviceTypeItr,
376*700637cbSDimitry Andric                      llvm::IsaPred<TheClauseTy>);
377*700637cbSDimitry Andric 
378*700637cbSDimitry Andric     // In this case there is a duplicate since the last device_type/lack of a
379*700637cbSDimitry Andric     // device_type.  Diagnose these as duplicates.
380*700637cbSDimitry Andric     if (LastSinceDevTy != LastDeviceTypeItr) {
381*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(),
382*700637cbSDimitry Andric                    diag::err_acc_clause_since_last_device_type)
383*700637cbSDimitry Andric           << Clause.getClauseKind() << Clause.getDirectiveKind()
384*700637cbSDimitry Andric           << (LastDeviceTypeItr != ExistingClauses.rend());
385*700637cbSDimitry Andric 
386*700637cbSDimitry Andric       SemaRef.Diag((*LastSinceDevTy)->getBeginLoc(),
387*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
388*700637cbSDimitry Andric           << (*LastSinceDevTy)->getClauseKind();
389*700637cbSDimitry Andric 
390*700637cbSDimitry Andric       // Mention the last device_type as well.
391*700637cbSDimitry Andric       if (LastDeviceTypeItr != ExistingClauses.rend())
392*700637cbSDimitry Andric         SemaRef.Diag((*LastDeviceTypeItr)->getBeginLoc(),
393*700637cbSDimitry Andric                      diag::note_acc_active_applies_clause_here)
394*700637cbSDimitry Andric             << diag::ACCDeviceTypeApp::Active
395*700637cbSDimitry Andric             << (*LastDeviceTypeItr)->getClauseKind();
396*700637cbSDimitry Andric       return true;
397*700637cbSDimitry Andric     }
398*700637cbSDimitry Andric 
399*700637cbSDimitry Andric     // If this isn't in a device_type, and we didn't diagnose that there are
400*700637cbSDimitry Andric     // dupes above, just give up, no sense in searching for previous device_type
401*700637cbSDimitry Andric     // regions as they don't exist.
402*700637cbSDimitry Andric     if (LastDeviceTypeItr == ExistingClauses.rend())
403*700637cbSDimitry Andric       return false;
404*700637cbSDimitry Andric 
405*700637cbSDimitry Andric     // The device-type that is active for us, so we can compare to the previous
406*700637cbSDimitry Andric     // ones.
407*700637cbSDimitry Andric     const auto &ActiveDeviceTypeClause =
408*700637cbSDimitry Andric         cast<OpenACCDeviceTypeClause>(**LastDeviceTypeItr);
409*700637cbSDimitry Andric 
410*700637cbSDimitry Andric     auto PrevDeviceTypeItr = LastDeviceTypeItr;
411*700637cbSDimitry Andric     auto CurDevTypeItr = LastDeviceTypeItr;
412*700637cbSDimitry Andric 
413*700637cbSDimitry Andric     while ((CurDevTypeItr = std::find_if(
414*700637cbSDimitry Andric                 std::next(PrevDeviceTypeItr), ExistingClauses.rend(),
415*700637cbSDimitry Andric                 llvm::IsaPred<OpenACCDeviceTypeClause>)) !=
416*700637cbSDimitry Andric            ExistingClauses.rend()) {
417*700637cbSDimitry Andric       // At this point, we know that we have a region between two device_types,
418*700637cbSDimitry Andric       // as specified by CurDevTypeItr and PrevDeviceTypeItr.
419*700637cbSDimitry Andric 
420*700637cbSDimitry Andric       auto CurClauseKindItr = std::find_if(PrevDeviceTypeItr, CurDevTypeItr,
421*700637cbSDimitry Andric                                            llvm::IsaPred<TheClauseTy>);
422*700637cbSDimitry Andric 
423*700637cbSDimitry Andric       // There are no clauses of the current kind between these device_types, so
424*700637cbSDimitry Andric       // continue.
425*700637cbSDimitry Andric       if (CurClauseKindItr == CurDevTypeItr) {
426*700637cbSDimitry Andric         PrevDeviceTypeItr = CurDevTypeItr;
427*700637cbSDimitry Andric         continue;
428*700637cbSDimitry Andric       }
429*700637cbSDimitry Andric 
430*700637cbSDimitry Andric       // At this point, we know that this device_type region has a collapse.  So
431*700637cbSDimitry Andric       // diagnose if the two device_types have any overlap in their
432*700637cbSDimitry Andric       // architectures.
433*700637cbSDimitry Andric       const auto &CurDeviceTypeClause =
434*700637cbSDimitry Andric           cast<OpenACCDeviceTypeClause>(**CurDevTypeItr);
435*700637cbSDimitry Andric 
436*700637cbSDimitry Andric       for (const DeviceTypeArgument &arg :
437*700637cbSDimitry Andric            ActiveDeviceTypeClause.getArchitectures()) {
438*700637cbSDimitry Andric         for (const DeviceTypeArgument &prevArg :
439*700637cbSDimitry Andric              CurDeviceTypeClause.getArchitectures()) {
440*700637cbSDimitry Andric 
441*700637cbSDimitry Andric           // This should catch duplicates * regions, duplicate same-text (thanks
442*700637cbSDimitry Andric           // to identifier equiv.) and case insensitive dupes.
443*700637cbSDimitry Andric           if (arg.getIdentifierInfo() == prevArg.getIdentifierInfo() ||
444*700637cbSDimitry Andric               (arg.getIdentifierInfo() && prevArg.getIdentifierInfo() &&
445*700637cbSDimitry Andric                StringRef{arg.getIdentifierInfo()->getName()}.equals_insensitive(
446*700637cbSDimitry Andric                    prevArg.getIdentifierInfo()->getName()))) {
447*700637cbSDimitry Andric             SemaRef.Diag(Clause.getBeginLoc(),
448*700637cbSDimitry Andric                          diag::err_acc_clause_conflicts_prev_dev_type)
449*700637cbSDimitry Andric                 << Clause.getClauseKind()
450*700637cbSDimitry Andric                 << (arg.getIdentifierInfo() ? arg.getIdentifierInfo()->getName()
451*700637cbSDimitry Andric                                             : "*");
452*700637cbSDimitry Andric             // mention the active device type.
453*700637cbSDimitry Andric             SemaRef.Diag(ActiveDeviceTypeClause.getBeginLoc(),
454*700637cbSDimitry Andric                          diag::note_acc_active_applies_clause_here)
455*700637cbSDimitry Andric                 << diag::ACCDeviceTypeApp::Active
456*700637cbSDimitry Andric                 << ActiveDeviceTypeClause.getClauseKind();
457*700637cbSDimitry Andric             // mention the previous clause.
458*700637cbSDimitry Andric             SemaRef.Diag((*CurClauseKindItr)->getBeginLoc(),
459*700637cbSDimitry Andric                          diag::note_acc_previous_clause_here)
460*700637cbSDimitry Andric                 << (*CurClauseKindItr)->getClauseKind();
461*700637cbSDimitry Andric             // mention the previous device type.
462*700637cbSDimitry Andric             SemaRef.Diag(CurDeviceTypeClause.getBeginLoc(),
463*700637cbSDimitry Andric                          diag::note_acc_active_applies_clause_here)
464*700637cbSDimitry Andric                 << diag::ACCDeviceTypeApp::Applies
465*700637cbSDimitry Andric                 << CurDeviceTypeClause.getClauseKind();
466*700637cbSDimitry Andric             return true;
467*700637cbSDimitry Andric           }
468*700637cbSDimitry Andric         }
469*700637cbSDimitry Andric       }
470*700637cbSDimitry Andric 
471*700637cbSDimitry Andric       PrevDeviceTypeItr = CurDevTypeItr;
472*700637cbSDimitry Andric     }
473*700637cbSDimitry Andric     return false;
474*700637cbSDimitry Andric   }
475*700637cbSDimitry Andric 
476*700637cbSDimitry Andric public:
SemaOpenACCClauseVisitor(SemaOpenACC & S,ArrayRef<const OpenACCClause * > ExistingClauses)477*700637cbSDimitry Andric   SemaOpenACCClauseVisitor(SemaOpenACC &S,
478*700637cbSDimitry Andric                            ArrayRef<const OpenACCClause *> ExistingClauses)
479*700637cbSDimitry Andric       : SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {}
480*700637cbSDimitry Andric 
Visit(SemaOpenACC::OpenACCParsedClause & Clause)481*700637cbSDimitry Andric   OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
482*700637cbSDimitry Andric 
483*700637cbSDimitry Andric     if (SemaRef.DiagnoseAllowedOnceClauses(
484*700637cbSDimitry Andric             Clause.getDirectiveKind(), Clause.getClauseKind(),
485*700637cbSDimitry Andric             Clause.getBeginLoc(), ExistingClauses) ||
486*700637cbSDimitry Andric         SemaRef.DiagnoseExclusiveClauses(Clause.getDirectiveKind(),
487*700637cbSDimitry Andric                                          Clause.getClauseKind(),
488*700637cbSDimitry Andric                                          Clause.getBeginLoc(), ExistingClauses))
489*700637cbSDimitry Andric       return nullptr;
490*700637cbSDimitry Andric     if (CheckValidRoutineGangWorkerVectorSeqNewClause(Clause) ||
491*700637cbSDimitry Andric         CheckValidRoutineBindNewClause(Clause))
492*700637cbSDimitry Andric       return nullptr;
493*700637cbSDimitry Andric 
494*700637cbSDimitry Andric     switch (Clause.getClauseKind()) {
495*700637cbSDimitry Andric     case OpenACCClauseKind::Shortloop:
496*700637cbSDimitry Andric       llvm_unreachable("Shortloop shouldn't be generated in clang");
497*700637cbSDimitry Andric     case OpenACCClauseKind::Invalid:
498*700637cbSDimitry Andric       return nullptr;
499*700637cbSDimitry Andric #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
500*700637cbSDimitry Andric   case OpenACCClauseKind::CLAUSE_NAME:                                         \
501*700637cbSDimitry Andric     return Visit##CLAUSE_NAME##Clause(Clause);
502*700637cbSDimitry Andric #define CLAUSE_ALIAS(ALIAS, CLAUSE_NAME, DEPRECATED)                           \
503*700637cbSDimitry Andric   case OpenACCClauseKind::ALIAS:                                               \
504*700637cbSDimitry Andric   if (DEPRECATED)                                                              \
505*700637cbSDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)   \
506*700637cbSDimitry Andric         << Clause.getClauseKind() << OpenACCClauseKind::CLAUSE_NAME;           \
507*700637cbSDimitry Andric   return Visit##CLAUSE_NAME##Clause(Clause);
508*700637cbSDimitry Andric #include "clang/Basic/OpenACCClauses.def"
509*700637cbSDimitry Andric     }
510*700637cbSDimitry Andric     llvm_unreachable("Invalid clause kind");
511*700637cbSDimitry Andric   }
512*700637cbSDimitry Andric 
513*700637cbSDimitry Andric #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
514*700637cbSDimitry Andric   OpenACCClause *Visit##CLAUSE_NAME##Clause(                                   \
515*700637cbSDimitry Andric       SemaOpenACC::OpenACCParsedClause &Clause);
516*700637cbSDimitry Andric #include "clang/Basic/OpenACCClauses.def"
517*700637cbSDimitry Andric };
518*700637cbSDimitry Andric 
VisitDefaultClause(SemaOpenACC::OpenACCParsedClause & Clause)519*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause(
520*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
521*700637cbSDimitry Andric   // Don't add an invalid clause to the AST.
522*700637cbSDimitry Andric   if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
523*700637cbSDimitry Andric     return nullptr;
524*700637cbSDimitry Andric 
525*700637cbSDimitry Andric   return OpenACCDefaultClause::Create(
526*700637cbSDimitry Andric       Ctx, Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
527*700637cbSDimitry Andric       Clause.getLParenLoc(), Clause.getEndLoc());
528*700637cbSDimitry Andric }
529*700637cbSDimitry Andric 
VisitTileClause(SemaOpenACC::OpenACCParsedClause & Clause)530*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause(
531*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
532*700637cbSDimitry Andric 
533*700637cbSDimitry Andric   if (DisallowSinceLastDeviceType<OpenACCTileClause>(Clause))
534*700637cbSDimitry Andric     return nullptr;
535*700637cbSDimitry Andric 
536*700637cbSDimitry Andric   llvm::SmallVector<Expr *> NewSizeExprs;
537*700637cbSDimitry Andric 
538*700637cbSDimitry Andric   // Make sure these are all positive constant expressions or *.
539*700637cbSDimitry Andric   for (Expr *E : Clause.getIntExprs()) {
540*700637cbSDimitry Andric     ExprResult Res = SemaRef.CheckTileSizeExpr(E);
541*700637cbSDimitry Andric 
542*700637cbSDimitry Andric     if (!Res.isUsable())
543*700637cbSDimitry Andric       return nullptr;
544*700637cbSDimitry Andric 
545*700637cbSDimitry Andric     NewSizeExprs.push_back(Res.get());
546*700637cbSDimitry Andric   }
547*700637cbSDimitry Andric 
548*700637cbSDimitry Andric   return OpenACCTileClause::Create(Ctx, Clause.getBeginLoc(),
549*700637cbSDimitry Andric                                    Clause.getLParenLoc(), NewSizeExprs,
550*700637cbSDimitry Andric                                    Clause.getEndLoc());
551*700637cbSDimitry Andric }
552*700637cbSDimitry Andric 
VisitIfClause(SemaOpenACC::OpenACCParsedClause & Clause)553*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
554*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
555*700637cbSDimitry Andric 
556*700637cbSDimitry Andric   // The parser has ensured that we have a proper condition expr, so there
557*700637cbSDimitry Andric   // isn't really much to do here.
558*700637cbSDimitry Andric 
559*700637cbSDimitry Andric   // If the 'if' clause is true, it makes the 'self' clause have no effect,
560*700637cbSDimitry Andric   // diagnose that here.  This only applies on compute/combined constructs.
561*700637cbSDimitry Andric   if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Update) {
562*700637cbSDimitry Andric     const auto *Itr =
563*700637cbSDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);
564*700637cbSDimitry Andric     if (Itr != ExistingClauses.end()) {
565*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
566*700637cbSDimitry Andric       SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
567*700637cbSDimitry Andric           << (*Itr)->getClauseKind();
568*700637cbSDimitry Andric     }
569*700637cbSDimitry Andric   }
570*700637cbSDimitry Andric 
571*700637cbSDimitry Andric   return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(),
572*700637cbSDimitry Andric                                  Clause.getLParenLoc(),
573*700637cbSDimitry Andric                                  Clause.getConditionExpr(), Clause.getEndLoc());
574*700637cbSDimitry Andric }
575*700637cbSDimitry Andric 
VisitSelfClause(SemaOpenACC::OpenACCParsedClause & Clause)576*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
577*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
578*700637cbSDimitry Andric 
579*700637cbSDimitry Andric   // If the 'if' clause is true, it makes the 'self' clause have no effect,
580*700637cbSDimitry Andric   // diagnose that here.  This only applies on compute/combined constructs.
581*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Update)
582*700637cbSDimitry Andric     return OpenACCSelfClause::Create(Ctx, Clause.getBeginLoc(),
583*700637cbSDimitry Andric                                      Clause.getLParenLoc(), Clause.getVarList(),
584*700637cbSDimitry Andric                                      Clause.getEndLoc());
585*700637cbSDimitry Andric 
586*700637cbSDimitry Andric   const auto *Itr =
587*700637cbSDimitry Andric       llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>);
588*700637cbSDimitry Andric   if (Itr != ExistingClauses.end()) {
589*700637cbSDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
590*700637cbSDimitry Andric     SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
591*700637cbSDimitry Andric         << (*Itr)->getClauseKind();
592*700637cbSDimitry Andric   }
593*700637cbSDimitry Andric   return OpenACCSelfClause::Create(
594*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
595*700637cbSDimitry Andric       Clause.getConditionExpr(), Clause.getEndLoc());
596*700637cbSDimitry Andric }
597*700637cbSDimitry Andric 
VisitNumGangsClause(SemaOpenACC::OpenACCParsedClause & Clause)598*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(
599*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
600*700637cbSDimitry Andric 
601*700637cbSDimitry Andric   if (DisallowSinceLastDeviceType<OpenACCNumGangsClause>(Clause))
602*700637cbSDimitry Andric     return nullptr;
603*700637cbSDimitry Andric 
604*700637cbSDimitry Andric   // num_gangs requires at least 1 int expr in all forms.  Diagnose here, but
605*700637cbSDimitry Andric   // allow us to continue, an empty clause might be useful for future
606*700637cbSDimitry Andric   // diagnostics.
607*700637cbSDimitry Andric   if (Clause.getIntExprs().empty())
608*700637cbSDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
609*700637cbSDimitry Andric         << /*NoArgs=*/0;
610*700637cbSDimitry Andric 
611*700637cbSDimitry Andric   unsigned MaxArgs =
612*700637cbSDimitry Andric       (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
613*700637cbSDimitry Andric        Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)
614*700637cbSDimitry Andric           ? 3
615*700637cbSDimitry Andric           : 1;
616*700637cbSDimitry Andric   // The max number of args differs between parallel and other constructs.
617*700637cbSDimitry Andric   // Again, allow us to continue for the purposes of future diagnostics.
618*700637cbSDimitry Andric   if (Clause.getIntExprs().size() > MaxArgs)
619*700637cbSDimitry Andric     SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
620*700637cbSDimitry Andric         << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs
621*700637cbSDimitry Andric         << Clause.getIntExprs().size();
622*700637cbSDimitry Andric 
623*700637cbSDimitry Andric   // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
624*700637cbSDimitry Andric   // directive that has a gang clause and is within a compute construct that has
625*700637cbSDimitry Andric   // a num_gangs clause with more than one explicit argument.
626*700637cbSDimitry Andric   if (Clause.getIntExprs().size() > 1 &&
627*700637cbSDimitry Andric       isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) {
628*700637cbSDimitry Andric     auto *GangClauseItr =
629*700637cbSDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
630*700637cbSDimitry Andric     auto *ReductionClauseItr =
631*700637cbSDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
632*700637cbSDimitry Andric 
633*700637cbSDimitry Andric     if (GangClauseItr != ExistingClauses.end() &&
634*700637cbSDimitry Andric         ReductionClauseItr != ExistingClauses.end()) {
635*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(),
636*700637cbSDimitry Andric                    diag::err_acc_gang_reduction_numgangs_conflict)
637*700637cbSDimitry Andric           << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang
638*700637cbSDimitry Andric           << Clause.getDirectiveKind() << /*is on combined directive=*/1;
639*700637cbSDimitry Andric       SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),
640*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
641*700637cbSDimitry Andric           << (*ReductionClauseItr)->getClauseKind();
642*700637cbSDimitry Andric       SemaRef.Diag((*GangClauseItr)->getBeginLoc(),
643*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
644*700637cbSDimitry Andric           << (*GangClauseItr)->getClauseKind();
645*700637cbSDimitry Andric       return nullptr;
646*700637cbSDimitry Andric     }
647*700637cbSDimitry Andric   }
648*700637cbSDimitry Andric 
649*700637cbSDimitry Andric   // OpenACC 3.3 Section 2.5.4:
650*700637cbSDimitry Andric   // A reduction clause may not appear on a parallel construct with a
651*700637cbSDimitry Andric   // num_gangs clause that has more than one argument.
652*700637cbSDimitry Andric   if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
653*700637cbSDimitry Andric        Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) &&
654*700637cbSDimitry Andric       Clause.getIntExprs().size() > 1) {
655*700637cbSDimitry Andric     auto *Parallel =
656*700637cbSDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
657*700637cbSDimitry Andric 
658*700637cbSDimitry Andric     if (Parallel != ExistingClauses.end()) {
659*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(),
660*700637cbSDimitry Andric                    diag::err_acc_reduction_num_gangs_conflict)
661*700637cbSDimitry Andric           << /*>1 arg in first loc=*/1 << Clause.getClauseKind()
662*700637cbSDimitry Andric           << Clause.getDirectiveKind() << OpenACCClauseKind::Reduction;
663*700637cbSDimitry Andric       SemaRef.Diag((*Parallel)->getBeginLoc(),
664*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
665*700637cbSDimitry Andric           << (*Parallel)->getClauseKind();
666*700637cbSDimitry Andric       return nullptr;
667*700637cbSDimitry Andric     }
668*700637cbSDimitry Andric   }
669*700637cbSDimitry Andric 
670*700637cbSDimitry Andric   // OpenACC 3.3 Section 2.9.2:
671*700637cbSDimitry Andric   // An argument with no keyword or with the 'num' keyword is allowed only when
672*700637cbSDimitry Andric   // the 'num_gangs' does not appear on the 'kernel' construct.
673*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
674*700637cbSDimitry Andric     auto GangClauses = llvm::make_filter_range(
675*700637cbSDimitry Andric         ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
676*700637cbSDimitry Andric 
677*700637cbSDimitry Andric     for (auto *GC : GangClauses) {
678*700637cbSDimitry Andric       if (cast<OpenACCGangClause>(GC)->hasExprOfKind(OpenACCGangKind::Num)) {
679*700637cbSDimitry Andric         SemaRef.Diag(Clause.getBeginLoc(),
680*700637cbSDimitry Andric                      diag::err_acc_num_arg_conflict_reverse)
681*700637cbSDimitry Andric             << OpenACCClauseKind::NumGangs << OpenACCClauseKind::Gang
682*700637cbSDimitry Andric             << /*Num argument*/ 1;
683*700637cbSDimitry Andric         SemaRef.Diag(GC->getBeginLoc(), diag::note_acc_previous_clause_here)
684*700637cbSDimitry Andric             << GC->getClauseKind();
685*700637cbSDimitry Andric         return nullptr;
686*700637cbSDimitry Andric       }
687*700637cbSDimitry Andric     }
688*700637cbSDimitry Andric   }
689*700637cbSDimitry Andric 
690*700637cbSDimitry Andric   return OpenACCNumGangsClause::Create(
691*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs(),
692*700637cbSDimitry Andric       Clause.getEndLoc());
693*700637cbSDimitry Andric }
694*700637cbSDimitry Andric 
VisitNumWorkersClause(SemaOpenACC::OpenACCParsedClause & Clause)695*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(
696*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
697*700637cbSDimitry Andric 
698*700637cbSDimitry Andric   if (DisallowSinceLastDeviceType<OpenACCNumWorkersClause>(Clause))
699*700637cbSDimitry Andric     return nullptr;
700*700637cbSDimitry Andric 
701*700637cbSDimitry Andric   // OpenACC 3.3 Section 2.9.2:
702*700637cbSDimitry Andric   // An argument is allowed only when the 'num_workers' does not appear on the
703*700637cbSDimitry Andric   // kernels construct.
704*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
705*700637cbSDimitry Andric     auto WorkerClauses = llvm::make_filter_range(
706*700637cbSDimitry Andric         ExistingClauses, llvm::IsaPred<OpenACCWorkerClause>);
707*700637cbSDimitry Andric 
708*700637cbSDimitry Andric     for (auto *WC : WorkerClauses) {
709*700637cbSDimitry Andric       if (cast<OpenACCWorkerClause>(WC)->hasIntExpr()) {
710*700637cbSDimitry Andric         SemaRef.Diag(Clause.getBeginLoc(),
711*700637cbSDimitry Andric                      diag::err_acc_num_arg_conflict_reverse)
712*700637cbSDimitry Andric             << OpenACCClauseKind::NumWorkers << OpenACCClauseKind::Worker
713*700637cbSDimitry Andric             << /*num argument*/ 0;
714*700637cbSDimitry Andric         SemaRef.Diag(WC->getBeginLoc(), diag::note_acc_previous_clause_here)
715*700637cbSDimitry Andric             << WC->getClauseKind();
716*700637cbSDimitry Andric         return nullptr;
717*700637cbSDimitry Andric       }
718*700637cbSDimitry Andric     }
719*700637cbSDimitry Andric   }
720*700637cbSDimitry Andric 
721*700637cbSDimitry Andric   assert(Clause.getIntExprs().size() == 1 &&
722*700637cbSDimitry Andric          "Invalid number of expressions for NumWorkers");
723*700637cbSDimitry Andric   return OpenACCNumWorkersClause::Create(
724*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
725*700637cbSDimitry Andric       Clause.getEndLoc());
726*700637cbSDimitry Andric }
727*700637cbSDimitry Andric 
VisitVectorLengthClause(SemaOpenACC::OpenACCParsedClause & Clause)728*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause(
729*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
730*700637cbSDimitry Andric 
731*700637cbSDimitry Andric   if (DisallowSinceLastDeviceType<OpenACCVectorLengthClause>(Clause))
732*700637cbSDimitry Andric     return nullptr;
733*700637cbSDimitry Andric 
734*700637cbSDimitry Andric   // OpenACC 3.3 Section 2.9.4:
735*700637cbSDimitry Andric   // An argument is allowed only when the 'vector_length' does not appear on the
736*700637cbSDimitry Andric   // 'kernels' construct.
737*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
738*700637cbSDimitry Andric     auto VectorClauses = llvm::make_filter_range(
739*700637cbSDimitry Andric         ExistingClauses, llvm::IsaPred<OpenACCVectorClause>);
740*700637cbSDimitry Andric 
741*700637cbSDimitry Andric     for (auto *VC : VectorClauses) {
742*700637cbSDimitry Andric       if (cast<OpenACCVectorClause>(VC)->hasIntExpr()) {
743*700637cbSDimitry Andric         SemaRef.Diag(Clause.getBeginLoc(),
744*700637cbSDimitry Andric                      diag::err_acc_num_arg_conflict_reverse)
745*700637cbSDimitry Andric             << OpenACCClauseKind::VectorLength << OpenACCClauseKind::Vector
746*700637cbSDimitry Andric             << /*num argument*/ 0;
747*700637cbSDimitry Andric         SemaRef.Diag(VC->getBeginLoc(), diag::note_acc_previous_clause_here)
748*700637cbSDimitry Andric             << VC->getClauseKind();
749*700637cbSDimitry Andric         return nullptr;
750*700637cbSDimitry Andric       }
751*700637cbSDimitry Andric     }
752*700637cbSDimitry Andric   }
753*700637cbSDimitry Andric 
754*700637cbSDimitry Andric   assert(Clause.getIntExprs().size() == 1 &&
755*700637cbSDimitry Andric          "Invalid number of expressions for NumWorkers");
756*700637cbSDimitry Andric   return OpenACCVectorLengthClause::Create(
757*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
758*700637cbSDimitry Andric       Clause.getEndLoc());
759*700637cbSDimitry Andric }
760*700637cbSDimitry Andric 
VisitAsyncClause(SemaOpenACC::OpenACCParsedClause & Clause)761*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(
762*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
763*700637cbSDimitry Andric   if (DisallowSinceLastDeviceType<OpenACCAsyncClause>(Clause))
764*700637cbSDimitry Andric     return nullptr;
765*700637cbSDimitry Andric 
766*700637cbSDimitry Andric   assert(Clause.getNumIntExprs() < 2 &&
767*700637cbSDimitry Andric          "Invalid number of expressions for Async");
768*700637cbSDimitry Andric   return OpenACCAsyncClause::Create(
769*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
770*700637cbSDimitry Andric       Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr,
771*700637cbSDimitry Andric       Clause.getEndLoc());
772*700637cbSDimitry Andric }
773*700637cbSDimitry Andric 
VisitDeviceNumClause(SemaOpenACC::OpenACCParsedClause & Clause)774*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause(
775*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
776*700637cbSDimitry Andric   assert(Clause.getNumIntExprs() == 1 &&
777*700637cbSDimitry Andric          "Invalid number of expressions for device_num");
778*700637cbSDimitry Andric   return OpenACCDeviceNumClause::Create(
779*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
780*700637cbSDimitry Andric       Clause.getEndLoc());
781*700637cbSDimitry Andric }
782*700637cbSDimitry Andric 
VisitDefaultAsyncClause(SemaOpenACC::OpenACCParsedClause & Clause)783*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultAsyncClause(
784*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
785*700637cbSDimitry Andric   assert(Clause.getNumIntExprs() == 1 &&
786*700637cbSDimitry Andric          "Invalid number of expressions for default_async");
787*700637cbSDimitry Andric   return OpenACCDefaultAsyncClause::Create(
788*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
789*700637cbSDimitry Andric       Clause.getEndLoc());
790*700637cbSDimitry Andric }
791*700637cbSDimitry Andric 
VisitPrivateClause(SemaOpenACC::OpenACCParsedClause & Clause)792*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
793*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
794*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
795*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
796*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
797*700637cbSDimitry Andric 
798*700637cbSDimitry Andric   return OpenACCPrivateClause::Create(Ctx, Clause.getBeginLoc(),
799*700637cbSDimitry Andric                                       Clause.getLParenLoc(),
800*700637cbSDimitry Andric                                       Clause.getVarList(), Clause.getEndLoc());
801*700637cbSDimitry Andric }
802*700637cbSDimitry Andric 
VisitFirstPrivateClause(SemaOpenACC::OpenACCParsedClause & Clause)803*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
804*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
805*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
806*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
807*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
808*700637cbSDimitry Andric 
809*700637cbSDimitry Andric   return OpenACCFirstPrivateClause::Create(
810*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
811*700637cbSDimitry Andric       Clause.getEndLoc());
812*700637cbSDimitry Andric }
813*700637cbSDimitry Andric 
VisitNoCreateClause(SemaOpenACC::OpenACCParsedClause & Clause)814*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitNoCreateClause(
815*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
816*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
817*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
818*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
819*700637cbSDimitry Andric 
820*700637cbSDimitry Andric   return OpenACCNoCreateClause::Create(Ctx, Clause.getBeginLoc(),
821*700637cbSDimitry Andric                                        Clause.getLParenLoc(),
822*700637cbSDimitry Andric                                        Clause.getVarList(), Clause.getEndLoc());
823*700637cbSDimitry Andric }
824*700637cbSDimitry Andric 
VisitPresentClause(SemaOpenACC::OpenACCParsedClause & Clause)825*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitPresentClause(
826*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
827*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
828*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
829*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
830*700637cbSDimitry Andric 
831*700637cbSDimitry Andric   // 'declare' has some restrictions that need to be enforced separately, so
832*700637cbSDimitry Andric   // check it here.
833*700637cbSDimitry Andric   if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))
834*700637cbSDimitry Andric     return nullptr;
835*700637cbSDimitry Andric 
836*700637cbSDimitry Andric   return OpenACCPresentClause::Create(Ctx, Clause.getBeginLoc(),
837*700637cbSDimitry Andric                                       Clause.getLParenLoc(),
838*700637cbSDimitry Andric                                       Clause.getVarList(), Clause.getEndLoc());
839*700637cbSDimitry Andric }
840*700637cbSDimitry Andric 
VisitHostClause(SemaOpenACC::OpenACCParsedClause & Clause)841*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitHostClause(
842*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
843*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
844*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
845*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
846*700637cbSDimitry Andric 
847*700637cbSDimitry Andric   return OpenACCHostClause::Create(Ctx, Clause.getBeginLoc(),
848*700637cbSDimitry Andric                                    Clause.getLParenLoc(), Clause.getVarList(),
849*700637cbSDimitry Andric                                    Clause.getEndLoc());
850*700637cbSDimitry Andric }
851*700637cbSDimitry Andric 
VisitDeviceClause(SemaOpenACC::OpenACCParsedClause & Clause)852*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceClause(
853*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
854*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
855*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
856*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
857*700637cbSDimitry Andric 
858*700637cbSDimitry Andric   return OpenACCDeviceClause::Create(Ctx, Clause.getBeginLoc(),
859*700637cbSDimitry Andric                                      Clause.getLParenLoc(), Clause.getVarList(),
860*700637cbSDimitry Andric                                      Clause.getEndLoc());
861*700637cbSDimitry Andric }
862*700637cbSDimitry Andric 
VisitCopyClause(SemaOpenACC::OpenACCParsedClause & Clause)863*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyClause(
864*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
865*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
866*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
867*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
868*700637cbSDimitry Andric 
869*700637cbSDimitry Andric   OpenACCModifierKind NewMods =
870*700637cbSDimitry Andric       CheckModifierList(Clause, Clause.getModifierList());
871*700637cbSDimitry Andric 
872*700637cbSDimitry Andric   // 'declare' has some restrictions that need to be enforced separately, so
873*700637cbSDimitry Andric   // check it here.
874*700637cbSDimitry Andric   if (SemaRef.CheckDeclareClause(Clause, NewMods))
875*700637cbSDimitry Andric     return nullptr;
876*700637cbSDimitry Andric 
877*700637cbSDimitry Andric   return OpenACCCopyClause::Create(
878*700637cbSDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
879*700637cbSDimitry Andric       Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());
880*700637cbSDimitry Andric }
881*700637cbSDimitry Andric 
VisitLinkClause(SemaOpenACC::OpenACCParsedClause & Clause)882*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitLinkClause(
883*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
884*700637cbSDimitry Andric   // 'declare' has some restrictions that need to be enforced separately, so
885*700637cbSDimitry Andric   // check it here.
886*700637cbSDimitry Andric   if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))
887*700637cbSDimitry Andric     return nullptr;
888*700637cbSDimitry Andric 
889*700637cbSDimitry Andric   Clause.setVarListDetails(SemaRef.CheckLinkClauseVarList(Clause.getVarList()),
890*700637cbSDimitry Andric                            OpenACCModifierKind::Invalid);
891*700637cbSDimitry Andric 
892*700637cbSDimitry Andric   return OpenACCLinkClause::Create(Ctx, Clause.getBeginLoc(),
893*700637cbSDimitry Andric                                    Clause.getLParenLoc(), Clause.getVarList(),
894*700637cbSDimitry Andric                                    Clause.getEndLoc());
895*700637cbSDimitry Andric }
896*700637cbSDimitry Andric 
VisitDeviceResidentClause(SemaOpenACC::OpenACCParsedClause & Clause)897*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceResidentClause(
898*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
899*700637cbSDimitry Andric   // 'declare' has some restrictions that need to be enforced separately, so
900*700637cbSDimitry Andric   // check it here.
901*700637cbSDimitry Andric   if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))
902*700637cbSDimitry Andric     return nullptr;
903*700637cbSDimitry Andric 
904*700637cbSDimitry Andric   return OpenACCDeviceResidentClause::Create(
905*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
906*700637cbSDimitry Andric       Clause.getEndLoc());
907*700637cbSDimitry Andric }
908*700637cbSDimitry Andric 
VisitCopyInClause(SemaOpenACC::OpenACCParsedClause & Clause)909*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyInClause(
910*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
911*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
912*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
913*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
914*700637cbSDimitry Andric 
915*700637cbSDimitry Andric   OpenACCModifierKind NewMods =
916*700637cbSDimitry Andric       CheckModifierList(Clause, Clause.getModifierList());
917*700637cbSDimitry Andric 
918*700637cbSDimitry Andric   // 'declare' has some restrictions that need to be enforced separately, so
919*700637cbSDimitry Andric   // check it here.
920*700637cbSDimitry Andric   if (SemaRef.CheckDeclareClause(Clause, NewMods))
921*700637cbSDimitry Andric     return nullptr;
922*700637cbSDimitry Andric 
923*700637cbSDimitry Andric   return OpenACCCopyInClause::Create(
924*700637cbSDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
925*700637cbSDimitry Andric       Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());
926*700637cbSDimitry Andric }
927*700637cbSDimitry Andric 
VisitCopyOutClause(SemaOpenACC::OpenACCParsedClause & Clause)928*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyOutClause(
929*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
930*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
931*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
932*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
933*700637cbSDimitry Andric 
934*700637cbSDimitry Andric   OpenACCModifierKind NewMods =
935*700637cbSDimitry Andric       CheckModifierList(Clause, Clause.getModifierList());
936*700637cbSDimitry Andric 
937*700637cbSDimitry Andric   // 'declare' has some restrictions that need to be enforced separately, so
938*700637cbSDimitry Andric   // check it here.
939*700637cbSDimitry Andric   if (SemaRef.CheckDeclareClause(Clause, NewMods))
940*700637cbSDimitry Andric     return nullptr;
941*700637cbSDimitry Andric 
942*700637cbSDimitry Andric   return OpenACCCopyOutClause::Create(
943*700637cbSDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
944*700637cbSDimitry Andric       Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());
945*700637cbSDimitry Andric }
946*700637cbSDimitry Andric 
VisitCreateClause(SemaOpenACC::OpenACCParsedClause & Clause)947*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCreateClause(
948*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
949*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
950*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
951*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
952*700637cbSDimitry Andric 
953*700637cbSDimitry Andric   OpenACCModifierKind NewMods =
954*700637cbSDimitry Andric       CheckModifierList(Clause, Clause.getModifierList());
955*700637cbSDimitry Andric 
956*700637cbSDimitry Andric   // 'declare' has some restrictions that need to be enforced separately, so
957*700637cbSDimitry Andric   // check it here.
958*700637cbSDimitry Andric   if (SemaRef.CheckDeclareClause(Clause, NewMods))
959*700637cbSDimitry Andric     return nullptr;
960*700637cbSDimitry Andric 
961*700637cbSDimitry Andric   return OpenACCCreateClause::Create(
962*700637cbSDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
963*700637cbSDimitry Andric       Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());
964*700637cbSDimitry Andric }
965*700637cbSDimitry Andric 
VisitAttachClause(SemaOpenACC::OpenACCParsedClause & Clause)966*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitAttachClause(
967*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
968*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, but we
969*700637cbSDimitry Andric   // still have to make sure it is a pointer type.
970*700637cbSDimitry Andric   llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
971*700637cbSDimitry Andric   llvm::erase_if(VarList, [&](Expr *E) {
972*700637cbSDimitry Andric     return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Attach, E);
973*700637cbSDimitry Andric   });
974*700637cbSDimitry Andric   Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);
975*700637cbSDimitry Andric   return OpenACCAttachClause::Create(Ctx, Clause.getBeginLoc(),
976*700637cbSDimitry Andric                                      Clause.getLParenLoc(), Clause.getVarList(),
977*700637cbSDimitry Andric                                      Clause.getEndLoc());
978*700637cbSDimitry Andric }
979*700637cbSDimitry Andric 
VisitDetachClause(SemaOpenACC::OpenACCParsedClause & Clause)980*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDetachClause(
981*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
982*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, but we
983*700637cbSDimitry Andric   // still have to make sure it is a pointer type.
984*700637cbSDimitry Andric   llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
985*700637cbSDimitry Andric   llvm::erase_if(VarList, [&](Expr *E) {
986*700637cbSDimitry Andric     return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Detach, E);
987*700637cbSDimitry Andric   });
988*700637cbSDimitry Andric   Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);
989*700637cbSDimitry Andric   return OpenACCDetachClause::Create(Ctx, Clause.getBeginLoc(),
990*700637cbSDimitry Andric                                      Clause.getLParenLoc(), Clause.getVarList(),
991*700637cbSDimitry Andric                                      Clause.getEndLoc());
992*700637cbSDimitry Andric }
993*700637cbSDimitry Andric 
VisitDeleteClause(SemaOpenACC::OpenACCParsedClause & Clause)994*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDeleteClause(
995*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
996*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, so there
997*700637cbSDimitry Andric   // really isn't anything to do here. GCC does some duplicate-finding, though
998*700637cbSDimitry Andric   // it isn't apparent in the standard where this is justified.
999*700637cbSDimitry Andric   return OpenACCDeleteClause::Create(Ctx, Clause.getBeginLoc(),
1000*700637cbSDimitry Andric                                      Clause.getLParenLoc(), Clause.getVarList(),
1001*700637cbSDimitry Andric                                      Clause.getEndLoc());
1002*700637cbSDimitry Andric }
1003*700637cbSDimitry Andric 
VisitUseDeviceClause(SemaOpenACC::OpenACCParsedClause & Clause)1004*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitUseDeviceClause(
1005*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1006*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable or array, so nothing
1007*700637cbSDimitry Andric   // left to do here.
1008*700637cbSDimitry Andric   return OpenACCUseDeviceClause::Create(
1009*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
1010*700637cbSDimitry Andric       Clause.getEndLoc());
1011*700637cbSDimitry Andric }
1012*700637cbSDimitry Andric 
VisitDevicePtrClause(SemaOpenACC::OpenACCParsedClause & Clause)1013*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause(
1014*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1015*700637cbSDimitry Andric   // ActOnVar ensured that everything is a valid variable reference, but we
1016*700637cbSDimitry Andric   // still have to make sure it is a pointer type.
1017*700637cbSDimitry Andric   llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
1018*700637cbSDimitry Andric   llvm::erase_if(VarList, [&](Expr *E) {
1019*700637cbSDimitry Andric     return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::DevicePtr, E);
1020*700637cbSDimitry Andric   });
1021*700637cbSDimitry Andric   Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);
1022*700637cbSDimitry Andric 
1023*700637cbSDimitry Andric   // 'declare' has some restrictions that need to be enforced separately, so
1024*700637cbSDimitry Andric   // check it here.
1025*700637cbSDimitry Andric   if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))
1026*700637cbSDimitry Andric     return nullptr;
1027*700637cbSDimitry Andric 
1028*700637cbSDimitry Andric   return OpenACCDevicePtrClause::Create(
1029*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
1030*700637cbSDimitry Andric       Clause.getEndLoc());
1031*700637cbSDimitry Andric }
1032*700637cbSDimitry Andric 
VisitWaitClause(SemaOpenACC::OpenACCParsedClause & Clause)1033*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause(
1034*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1035*700637cbSDimitry Andric   return OpenACCWaitClause::Create(
1036*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getDevNumExpr(),
1037*700637cbSDimitry Andric       Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc());
1038*700637cbSDimitry Andric }
1039*700637cbSDimitry Andric 
VisitDeviceTypeClause(SemaOpenACC::OpenACCParsedClause & Clause)1040*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
1041*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1042*700637cbSDimitry Andric 
1043*700637cbSDimitry Andric   // Based on discussions, having more than 1 'architecture' on a 'set' is
1044*700637cbSDimitry Andric   // nonsensical, so we're going to fix the standard to reflect this.  Implement
1045*700637cbSDimitry Andric   // the limitation, since the Dialect requires this.
1046*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set &&
1047*700637cbSDimitry Andric       Clause.getDeviceTypeArchitectures().size() > 1) {
1048*700637cbSDimitry Andric     SemaRef.Diag(Clause.getDeviceTypeArchitectures()[1].getLoc(),
1049*700637cbSDimitry Andric                  diag::err_acc_device_type_multiple_archs);
1050*700637cbSDimitry Andric     return nullptr;
1051*700637cbSDimitry Andric   }
1052*700637cbSDimitry Andric 
1053*700637cbSDimitry Andric   // The list of valid device_type values. Flang also has these hardcoded in
1054*700637cbSDimitry Andric   // openacc_parsers.cpp, as there does not seem to be a reliable backend
1055*700637cbSDimitry Andric   // source. The list below is sourced from Flang, though NVC++ supports only
1056*700637cbSDimitry Andric   // 'nvidia', 'host', 'multicore', and 'default'.
1057*700637cbSDimitry Andric   const std::array<llvm::StringLiteral, 6> ValidValues{
1058*700637cbSDimitry Andric       "default", "nvidia", "acc_device_nvidia", "radeon", "host", "multicore"};
1059*700637cbSDimitry Andric   // As an optimization, we have a manually maintained list of valid values
1060*700637cbSDimitry Andric   // below, rather than trying to calculate from above. These should be kept in
1061*700637cbSDimitry Andric   // sync if/when the above list ever changes.
1062*700637cbSDimitry Andric   std::string ValidValuesString =
1063*700637cbSDimitry Andric       "'default', 'nvidia', 'acc_device_nvidia', 'radeon', 'host', 'multicore'";
1064*700637cbSDimitry Andric 
1065*700637cbSDimitry Andric   llvm::SmallVector<DeviceTypeArgument> Architectures{
1066*700637cbSDimitry Andric       Clause.getDeviceTypeArchitectures()};
1067*700637cbSDimitry Andric 
1068*700637cbSDimitry Andric   // The parser has ensured that we either have a single entry of just '*'
1069*700637cbSDimitry Andric   // (represented by a nullptr IdentifierInfo), or a list.
1070*700637cbSDimitry Andric 
1071*700637cbSDimitry Andric   bool Diagnosed = false;
1072*700637cbSDimitry Andric   auto FilterPred = [&](const DeviceTypeArgument &Arch) {
1073*700637cbSDimitry Andric     // The '*' case.
1074*700637cbSDimitry Andric     if (!Arch.getIdentifierInfo())
1075*700637cbSDimitry Andric       return false;
1076*700637cbSDimitry Andric     return llvm::find_if(ValidValues, [&](StringRef RHS) {
1077*700637cbSDimitry Andric              return Arch.getIdentifierInfo()->getName().equals_insensitive(RHS);
1078*700637cbSDimitry Andric            }) == ValidValues.end();
1079*700637cbSDimitry Andric   };
1080*700637cbSDimitry Andric 
1081*700637cbSDimitry Andric   auto Diagnose = [&](const DeviceTypeArgument &Arch) {
1082*700637cbSDimitry Andric     Diagnosed = SemaRef.Diag(Arch.getLoc(), diag::err_acc_invalid_default_type)
1083*700637cbSDimitry Andric                 << Arch.getIdentifierInfo() << Clause.getClauseKind()
1084*700637cbSDimitry Andric                 << ValidValuesString;
1085*700637cbSDimitry Andric   };
1086*700637cbSDimitry Andric 
1087*700637cbSDimitry Andric   // There aren't stable enumertor versions of 'for-each-then-erase', so do it
1088*700637cbSDimitry Andric   // here.  We DO keep track of whether we diagnosed something to make sure we
1089*700637cbSDimitry Andric   // don't do the 'erase_if' in the event that the first list didn't find
1090*700637cbSDimitry Andric   // anything.
1091*700637cbSDimitry Andric   llvm::for_each(llvm::make_filter_range(Architectures, FilterPred), Diagnose);
1092*700637cbSDimitry Andric   if (Diagnosed)
1093*700637cbSDimitry Andric     llvm::erase_if(Architectures, FilterPred);
1094*700637cbSDimitry Andric 
1095*700637cbSDimitry Andric   return OpenACCDeviceTypeClause::Create(
1096*700637cbSDimitry Andric       Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
1097*700637cbSDimitry Andric       Architectures, Clause.getEndLoc());
1098*700637cbSDimitry Andric }
1099*700637cbSDimitry Andric 
VisitAutoClause(SemaOpenACC::OpenACCParsedClause & Clause)1100*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
1101*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1102*700637cbSDimitry Andric 
1103*700637cbSDimitry Andric   return OpenACCAutoClause::Create(Ctx, Clause.getBeginLoc(),
1104*700637cbSDimitry Andric                                    Clause.getEndLoc());
1105*700637cbSDimitry Andric }
1106*700637cbSDimitry Andric 
VisitNoHostClause(SemaOpenACC::OpenACCParsedClause & Clause)1107*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitNoHostClause(
1108*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1109*700637cbSDimitry Andric   return OpenACCNoHostClause::Create(Ctx, Clause.getBeginLoc(),
1110*700637cbSDimitry Andric                                      Clause.getEndLoc());
1111*700637cbSDimitry Andric }
1112*700637cbSDimitry Andric 
VisitIndependentClause(SemaOpenACC::OpenACCParsedClause & Clause)1113*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
1114*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1115*700637cbSDimitry Andric 
1116*700637cbSDimitry Andric   return OpenACCIndependentClause::Create(Ctx, Clause.getBeginLoc(),
1117*700637cbSDimitry Andric                                           Clause.getEndLoc());
1118*700637cbSDimitry Andric }
1119*700637cbSDimitry Andric 
CheckGangStaticExpr(SemaOpenACC & S,Expr * E)1120*700637cbSDimitry Andric ExprResult CheckGangStaticExpr(SemaOpenACC &S, Expr *E) {
1121*700637cbSDimitry Andric   if (isa<OpenACCAsteriskSizeExpr>(E))
1122*700637cbSDimitry Andric     return E;
1123*700637cbSDimitry Andric   return S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang,
1124*700637cbSDimitry Andric                         E->getBeginLoc(), E);
1125*700637cbSDimitry Andric }
1126*700637cbSDimitry Andric 
IsOrphanLoop(OpenACCDirectiveKind DK,OpenACCDirectiveKind AssocKind)1127*700637cbSDimitry Andric bool IsOrphanLoop(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {
1128*700637cbSDimitry Andric   return DK == OpenACCDirectiveKind::Loop &&
1129*700637cbSDimitry Andric          AssocKind == OpenACCDirectiveKind::Invalid;
1130*700637cbSDimitry Andric }
1131*700637cbSDimitry Andric 
HasAssocKind(OpenACCDirectiveKind DK,OpenACCDirectiveKind AssocKind)1132*700637cbSDimitry Andric bool HasAssocKind(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {
1133*700637cbSDimitry Andric   return DK == OpenACCDirectiveKind::Loop &&
1134*700637cbSDimitry Andric          AssocKind != OpenACCDirectiveKind::Invalid;
1135*700637cbSDimitry Andric }
1136*700637cbSDimitry Andric 
DiagIntArgInvalid(SemaOpenACC & S,Expr * E,OpenACCGangKind GK,OpenACCClauseKind CK,OpenACCDirectiveKind DK,OpenACCDirectiveKind AssocKind)1137*700637cbSDimitry Andric ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, OpenACCGangKind GK,
1138*700637cbSDimitry Andric                              OpenACCClauseKind CK, OpenACCDirectiveKind DK,
1139*700637cbSDimitry Andric                              OpenACCDirectiveKind AssocKind) {
1140*700637cbSDimitry Andric   S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)
1141*700637cbSDimitry Andric       << GK << CK << IsOrphanLoop(DK, AssocKind) << DK
1142*700637cbSDimitry Andric       << HasAssocKind(DK, AssocKind) << AssocKind;
1143*700637cbSDimitry Andric   return ExprError();
1144*700637cbSDimitry Andric }
DiagIntArgInvalid(SemaOpenACC & S,Expr * E,StringRef TagKind,OpenACCClauseKind CK,OpenACCDirectiveKind DK,OpenACCDirectiveKind AssocKind)1145*700637cbSDimitry Andric ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, StringRef TagKind,
1146*700637cbSDimitry Andric                              OpenACCClauseKind CK, OpenACCDirectiveKind DK,
1147*700637cbSDimitry Andric                              OpenACCDirectiveKind AssocKind) {
1148*700637cbSDimitry Andric   S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)
1149*700637cbSDimitry Andric       << TagKind << CK << IsOrphanLoop(DK, AssocKind) << DK
1150*700637cbSDimitry Andric       << HasAssocKind(DK, AssocKind) << AssocKind;
1151*700637cbSDimitry Andric   return ExprError();
1152*700637cbSDimitry Andric }
1153*700637cbSDimitry Andric 
CheckGangDimExpr(SemaOpenACC & S,Expr * E)1154*700637cbSDimitry Andric ExprResult CheckGangDimExpr(SemaOpenACC &S, Expr *E) {
1155*700637cbSDimitry Andric   // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
1156*700637cbSDimitry Andric   // construct, or an orphaned loop construct, the gang clause behaves as
1157*700637cbSDimitry Andric   // follows. ... The dim argument must be a constant positive integer value
1158*700637cbSDimitry Andric   // 1, 2, or 3.
1159*700637cbSDimitry Andric   // -also-
1160*700637cbSDimitry Andric   // OpenACC 3.3 2.15: The 'dim' argument must be a constant positive integer
1161*700637cbSDimitry Andric   // with value 1, 2, or 3.
1162*700637cbSDimitry Andric   if (!E)
1163*700637cbSDimitry Andric     return ExprError();
1164*700637cbSDimitry Andric   ExprResult Res = S.ActOnIntExpr(OpenACCDirectiveKind::Invalid,
1165*700637cbSDimitry Andric                                   OpenACCClauseKind::Gang, E->getBeginLoc(), E);
1166*700637cbSDimitry Andric 
1167*700637cbSDimitry Andric   if (!Res.isUsable())
1168*700637cbSDimitry Andric     return Res;
1169*700637cbSDimitry Andric 
1170*700637cbSDimitry Andric   if (Res.get()->isInstantiationDependent())
1171*700637cbSDimitry Andric     return Res;
1172*700637cbSDimitry Andric 
1173*700637cbSDimitry Andric   std::optional<llvm::APSInt> ICE =
1174*700637cbSDimitry Andric       Res.get()->getIntegerConstantExpr(S.getASTContext());
1175*700637cbSDimitry Andric 
1176*700637cbSDimitry Andric   if (!ICE || *ICE <= 0 || ICE > 3) {
1177*700637cbSDimitry Andric     S.Diag(Res.get()->getBeginLoc(), diag::err_acc_gang_dim_value)
1178*700637cbSDimitry Andric         << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
1179*700637cbSDimitry Andric     return ExprError();
1180*700637cbSDimitry Andric   }
1181*700637cbSDimitry Andric 
1182*700637cbSDimitry Andric   return ExprResult{
1183*700637cbSDimitry Andric       ConstantExpr::Create(S.getASTContext(), Res.get(), APValue{*ICE})};
1184*700637cbSDimitry Andric }
1185*700637cbSDimitry Andric 
CheckGangParallelExpr(SemaOpenACC & S,OpenACCDirectiveKind DK,OpenACCDirectiveKind AssocKind,OpenACCGangKind GK,Expr * E)1186*700637cbSDimitry Andric ExprResult CheckGangParallelExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1187*700637cbSDimitry Andric                                  OpenACCDirectiveKind AssocKind,
1188*700637cbSDimitry Andric                                  OpenACCGangKind GK, Expr *E) {
1189*700637cbSDimitry Andric   switch (GK) {
1190*700637cbSDimitry Andric   case OpenACCGangKind::Static:
1191*700637cbSDimitry Andric     return CheckGangStaticExpr(S, E);
1192*700637cbSDimitry Andric   case OpenACCGangKind::Num:
1193*700637cbSDimitry Andric     // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
1194*700637cbSDimitry Andric     // construct, or an orphaned loop construct, the gang clause behaves as
1195*700637cbSDimitry Andric     // follows. ... The num argument is not allowed.
1196*700637cbSDimitry Andric     return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1197*700637cbSDimitry Andric   case OpenACCGangKind::Dim:
1198*700637cbSDimitry Andric     return CheckGangDimExpr(S, E);
1199*700637cbSDimitry Andric   }
1200*700637cbSDimitry Andric   llvm_unreachable("Unknown gang kind in gang parallel check");
1201*700637cbSDimitry Andric }
1202*700637cbSDimitry Andric 
CheckGangKernelsExpr(SemaOpenACC & S,ArrayRef<const OpenACCClause * > ExistingClauses,OpenACCDirectiveKind DK,OpenACCDirectiveKind AssocKind,OpenACCGangKind GK,Expr * E)1203*700637cbSDimitry Andric ExprResult CheckGangKernelsExpr(SemaOpenACC &S,
1204*700637cbSDimitry Andric                                 ArrayRef<const OpenACCClause *> ExistingClauses,
1205*700637cbSDimitry Andric                                 OpenACCDirectiveKind DK,
1206*700637cbSDimitry Andric                                 OpenACCDirectiveKind AssocKind,
1207*700637cbSDimitry Andric                                 OpenACCGangKind GK, Expr *E) {
1208*700637cbSDimitry Andric   switch (GK) {
1209*700637cbSDimitry Andric   // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1210*700637cbSDimitry Andric   // construct, the gang clause behaves as follows. ... The dim argument is
1211*700637cbSDimitry Andric   // not allowed.
1212*700637cbSDimitry Andric   case OpenACCGangKind::Dim:
1213*700637cbSDimitry Andric     return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1214*700637cbSDimitry Andric   case OpenACCGangKind::Num: {
1215*700637cbSDimitry Andric     // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1216*700637cbSDimitry Andric     // construct, the gang clause behaves as follows. ... An argument with no
1217*700637cbSDimitry Andric     // keyword or with num keyword is only allowed when num_gangs does not
1218*700637cbSDimitry Andric     // appear on the kernels construct. ... The region of a loop with the gang
1219*700637cbSDimitry Andric     // clause may not contain another loop with a gang clause unless within a
1220*700637cbSDimitry Andric     // nested compute region.
1221*700637cbSDimitry Andric 
1222*700637cbSDimitry Andric     // If this is a 'combined' construct, search the list of existing clauses.
1223*700637cbSDimitry Andric     // Else we need to search the containing 'kernel'.
1224*700637cbSDimitry Andric     auto Collection = isOpenACCCombinedDirectiveKind(DK)
1225*700637cbSDimitry Andric                           ? ExistingClauses
1226*700637cbSDimitry Andric                           : S.getActiveComputeConstructInfo().Clauses;
1227*700637cbSDimitry Andric 
1228*700637cbSDimitry Andric     const auto *Itr =
1229*700637cbSDimitry Andric         llvm::find_if(Collection, llvm::IsaPred<OpenACCNumGangsClause>);
1230*700637cbSDimitry Andric 
1231*700637cbSDimitry Andric     if (Itr != Collection.end()) {
1232*700637cbSDimitry Andric       S.Diag(E->getBeginLoc(), diag::err_acc_num_arg_conflict)
1233*700637cbSDimitry Andric           << "num" << OpenACCClauseKind::Gang << DK
1234*700637cbSDimitry Andric           << HasAssocKind(DK, AssocKind) << AssocKind
1235*700637cbSDimitry Andric           << OpenACCClauseKind::NumGangs;
1236*700637cbSDimitry Andric 
1237*700637cbSDimitry Andric       S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1238*700637cbSDimitry Andric           << (*Itr)->getClauseKind();
1239*700637cbSDimitry Andric       return ExprError();
1240*700637cbSDimitry Andric     }
1241*700637cbSDimitry Andric     return ExprResult{E};
1242*700637cbSDimitry Andric   }
1243*700637cbSDimitry Andric   case OpenACCGangKind::Static:
1244*700637cbSDimitry Andric     return CheckGangStaticExpr(S, E);
1245*700637cbSDimitry Andric   }
1246*700637cbSDimitry Andric   llvm_unreachable("Unknown gang kind in gang kernels check");
1247*700637cbSDimitry Andric }
1248*700637cbSDimitry Andric 
CheckGangSerialExpr(SemaOpenACC & S,OpenACCDirectiveKind DK,OpenACCDirectiveKind AssocKind,OpenACCGangKind GK,Expr * E)1249*700637cbSDimitry Andric ExprResult CheckGangSerialExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1250*700637cbSDimitry Andric                                OpenACCDirectiveKind AssocKind,
1251*700637cbSDimitry Andric                                OpenACCGangKind GK, Expr *E) {
1252*700637cbSDimitry Andric   switch (GK) {
1253*700637cbSDimitry Andric   // 'dim' and 'num' don't really make sense on serial, and GCC rejects them
1254*700637cbSDimitry Andric   // too, so we disallow them too.
1255*700637cbSDimitry Andric   case OpenACCGangKind::Dim:
1256*700637cbSDimitry Andric   case OpenACCGangKind::Num:
1257*700637cbSDimitry Andric     return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1258*700637cbSDimitry Andric   case OpenACCGangKind::Static:
1259*700637cbSDimitry Andric     return CheckGangStaticExpr(S, E);
1260*700637cbSDimitry Andric   }
1261*700637cbSDimitry Andric   llvm_unreachable("Unknown gang kind in gang serial check");
1262*700637cbSDimitry Andric }
1263*700637cbSDimitry Andric 
CheckGangRoutineExpr(SemaOpenACC & S,OpenACCDirectiveKind DK,OpenACCDirectiveKind AssocKind,OpenACCGangKind GK,Expr * E)1264*700637cbSDimitry Andric ExprResult CheckGangRoutineExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1265*700637cbSDimitry Andric                                 OpenACCDirectiveKind AssocKind,
1266*700637cbSDimitry Andric                                 OpenACCGangKind GK, Expr *E) {
1267*700637cbSDimitry Andric   switch (GK) {
1268*700637cbSDimitry Andric     // Only 'dim' is allowed on a routine, so diallow num and static.
1269*700637cbSDimitry Andric   case OpenACCGangKind::Num:
1270*700637cbSDimitry Andric   case OpenACCGangKind::Static:
1271*700637cbSDimitry Andric     return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1272*700637cbSDimitry Andric   case OpenACCGangKind::Dim:
1273*700637cbSDimitry Andric     return CheckGangDimExpr(S, E);
1274*700637cbSDimitry Andric   }
1275*700637cbSDimitry Andric   llvm_unreachable("Unknown gang kind in gang serial check");
1276*700637cbSDimitry Andric }
1277*700637cbSDimitry Andric 
VisitVectorClause(SemaOpenACC::OpenACCParsedClause & Clause)1278*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(
1279*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1280*700637cbSDimitry Andric   if (DiagGangWorkerVectorSeqConflict(Clause))
1281*700637cbSDimitry Andric     return nullptr;
1282*700637cbSDimitry Andric 
1283*700637cbSDimitry Andric   Expr *IntExpr =
1284*700637cbSDimitry Andric       Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1285*700637cbSDimitry Andric   if (IntExpr) {
1286*700637cbSDimitry Andric     switch (Clause.getDirectiveKind()) {
1287*700637cbSDimitry Andric     default:
1288*700637cbSDimitry Andric       llvm_unreachable("Invalid directive kind for this clause");
1289*700637cbSDimitry Andric     case OpenACCDirectiveKind::Loop:
1290*700637cbSDimitry Andric       switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1291*700637cbSDimitry Andric       case OpenACCDirectiveKind::Invalid:
1292*700637cbSDimitry Andric       case OpenACCDirectiveKind::Parallel:
1293*700637cbSDimitry Andric       case OpenACCDirectiveKind::ParallelLoop:
1294*700637cbSDimitry Andric         // No restriction on when 'parallel' can contain an argument.
1295*700637cbSDimitry Andric         break;
1296*700637cbSDimitry Andric       case OpenACCDirectiveKind::Serial:
1297*700637cbSDimitry Andric       case OpenACCDirectiveKind::SerialLoop:
1298*700637cbSDimitry Andric         // GCC disallows this, and there is no real good reason for us to permit
1299*700637cbSDimitry Andric         // it, so disallow until we come up with a use case that makes sense.
1300*700637cbSDimitry Andric         DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector,
1301*700637cbSDimitry Andric                           Clause.getDirectiveKind(),
1302*700637cbSDimitry Andric                           SemaRef.getActiveComputeConstructInfo().Kind);
1303*700637cbSDimitry Andric         IntExpr = nullptr;
1304*700637cbSDimitry Andric         break;
1305*700637cbSDimitry Andric       case OpenACCDirectiveKind::Kernels:
1306*700637cbSDimitry Andric       case OpenACCDirectiveKind::KernelsLoop: {
1307*700637cbSDimitry Andric         const auto *Itr =
1308*700637cbSDimitry Andric             llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
1309*700637cbSDimitry Andric                           llvm::IsaPred<OpenACCVectorLengthClause>);
1310*700637cbSDimitry Andric         if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1311*700637cbSDimitry Andric           SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1312*700637cbSDimitry Andric               << "length" << OpenACCClauseKind::Vector
1313*700637cbSDimitry Andric               << Clause.getDirectiveKind()
1314*700637cbSDimitry Andric               << HasAssocKind(Clause.getDirectiveKind(),
1315*700637cbSDimitry Andric                               SemaRef.getActiveComputeConstructInfo().Kind)
1316*700637cbSDimitry Andric               << SemaRef.getActiveComputeConstructInfo().Kind
1317*700637cbSDimitry Andric               << OpenACCClauseKind::VectorLength;
1318*700637cbSDimitry Andric           SemaRef.Diag((*Itr)->getBeginLoc(),
1319*700637cbSDimitry Andric                        diag::note_acc_previous_clause_here)
1320*700637cbSDimitry Andric               << (*Itr)->getClauseKind();
1321*700637cbSDimitry Andric 
1322*700637cbSDimitry Andric           IntExpr = nullptr;
1323*700637cbSDimitry Andric         }
1324*700637cbSDimitry Andric         break;
1325*700637cbSDimitry Andric       }
1326*700637cbSDimitry Andric       default:
1327*700637cbSDimitry Andric         llvm_unreachable("Non compute construct in active compute construct");
1328*700637cbSDimitry Andric       }
1329*700637cbSDimitry Andric       break;
1330*700637cbSDimitry Andric     case OpenACCDirectiveKind::KernelsLoop: {
1331*700637cbSDimitry Andric       const auto *Itr = llvm::find_if(ExistingClauses,
1332*700637cbSDimitry Andric                                       llvm::IsaPred<OpenACCVectorLengthClause>);
1333*700637cbSDimitry Andric       if (Itr != ExistingClauses.end()) {
1334*700637cbSDimitry Andric         SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1335*700637cbSDimitry Andric             << "length" << OpenACCClauseKind::Vector
1336*700637cbSDimitry Andric             << Clause.getDirectiveKind()
1337*700637cbSDimitry Andric             << HasAssocKind(Clause.getDirectiveKind(),
1338*700637cbSDimitry Andric                             SemaRef.getActiveComputeConstructInfo().Kind)
1339*700637cbSDimitry Andric             << SemaRef.getActiveComputeConstructInfo().Kind
1340*700637cbSDimitry Andric             << OpenACCClauseKind::VectorLength;
1341*700637cbSDimitry Andric         SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1342*700637cbSDimitry Andric             << (*Itr)->getClauseKind();
1343*700637cbSDimitry Andric 
1344*700637cbSDimitry Andric         IntExpr = nullptr;
1345*700637cbSDimitry Andric       }
1346*700637cbSDimitry Andric       break;
1347*700637cbSDimitry Andric     }
1348*700637cbSDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
1349*700637cbSDimitry Andric     case OpenACCDirectiveKind::Routine:
1350*700637cbSDimitry Andric       DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector,
1351*700637cbSDimitry Andric                         Clause.getDirectiveKind(),
1352*700637cbSDimitry Andric                         SemaRef.getActiveComputeConstructInfo().Kind);
1353*700637cbSDimitry Andric       IntExpr = nullptr;
1354*700637cbSDimitry Andric       break;
1355*700637cbSDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
1356*700637cbSDimitry Andric       break;
1357*700637cbSDimitry Andric     case OpenACCDirectiveKind::Invalid:
1358*700637cbSDimitry Andric       // This can happen when the directive was not recognized, but we continued
1359*700637cbSDimitry Andric       // anyway.  Since there is a lot of stuff that can happen (including
1360*700637cbSDimitry Andric       // 'allow anything' in the parallel loop case), just skip all checking and
1361*700637cbSDimitry Andric       // continue.
1362*700637cbSDimitry Andric       break;
1363*700637cbSDimitry Andric     }
1364*700637cbSDimitry Andric   }
1365*700637cbSDimitry Andric 
1366*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1367*700637cbSDimitry Andric     // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1368*700637cbSDimitry Andric     // contain a loop with a gang, worker, or vector clause unless within a
1369*700637cbSDimitry Andric     // nested compute region.
1370*700637cbSDimitry Andric     if (SemaRef.LoopVectorClauseLoc.isValid()) {
1371*700637cbSDimitry Andric       // This handles the 'inner loop' diagnostic, but we cannot set that we're
1372*700637cbSDimitry Andric       // on one of these until we get to the end of the construct.
1373*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1374*700637cbSDimitry Andric           << OpenACCClauseKind::Vector << OpenACCClauseKind::Vector
1375*700637cbSDimitry Andric           << /*skip kernels construct info*/ 0;
1376*700637cbSDimitry Andric       SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1377*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
1378*700637cbSDimitry Andric           << "vector";
1379*700637cbSDimitry Andric       return nullptr;
1380*700637cbSDimitry Andric     }
1381*700637cbSDimitry Andric   }
1382*700637cbSDimitry Andric 
1383*700637cbSDimitry Andric   return OpenACCVectorClause::Create(Ctx, Clause.getBeginLoc(),
1384*700637cbSDimitry Andric                                      Clause.getLParenLoc(), IntExpr,
1385*700637cbSDimitry Andric                                      Clause.getEndLoc());
1386*700637cbSDimitry Andric }
1387*700637cbSDimitry Andric 
VisitWorkerClause(SemaOpenACC::OpenACCParsedClause & Clause)1388*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
1389*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1390*700637cbSDimitry Andric   if (DiagGangWorkerVectorSeqConflict(Clause))
1391*700637cbSDimitry Andric     return nullptr;
1392*700637cbSDimitry Andric 
1393*700637cbSDimitry Andric   Expr *IntExpr =
1394*700637cbSDimitry Andric       Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1395*700637cbSDimitry Andric 
1396*700637cbSDimitry Andric   if (IntExpr) {
1397*700637cbSDimitry Andric     switch (Clause.getDirectiveKind()) {
1398*700637cbSDimitry Andric     default:
1399*700637cbSDimitry Andric       llvm_unreachable("Invalid directive kind for this clause");
1400*700637cbSDimitry Andric     case OpenACCDirectiveKind::Invalid:
1401*700637cbSDimitry Andric       // This can happen in cases where the directive was not recognized but we
1402*700637cbSDimitry Andric       // continued anyway.  Kernels allows kind of any integer argument, so we
1403*700637cbSDimitry Andric       // can assume it is that (rather than marking the argument invalid like
1404*700637cbSDimitry Andric       // with parallel/serial/routine), and just continue as if nothing
1405*700637cbSDimitry Andric       // happened.  We'll skip the 'kernels' checking vs num-workers, since this
1406*700637cbSDimitry Andric       // MIGHT be something else.
1407*700637cbSDimitry Andric       break;
1408*700637cbSDimitry Andric     case OpenACCDirectiveKind::Loop:
1409*700637cbSDimitry Andric       switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1410*700637cbSDimitry Andric       case OpenACCDirectiveKind::Invalid:
1411*700637cbSDimitry Andric       case OpenACCDirectiveKind::ParallelLoop:
1412*700637cbSDimitry Andric       case OpenACCDirectiveKind::SerialLoop:
1413*700637cbSDimitry Andric       case OpenACCDirectiveKind::Parallel:
1414*700637cbSDimitry Andric       case OpenACCDirectiveKind::Serial:
1415*700637cbSDimitry Andric         DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num,
1416*700637cbSDimitry Andric                           OpenACCClauseKind::Worker, Clause.getDirectiveKind(),
1417*700637cbSDimitry Andric                           SemaRef.getActiveComputeConstructInfo().Kind);
1418*700637cbSDimitry Andric         IntExpr = nullptr;
1419*700637cbSDimitry Andric         break;
1420*700637cbSDimitry Andric       case OpenACCDirectiveKind::KernelsLoop:
1421*700637cbSDimitry Andric       case OpenACCDirectiveKind::Kernels: {
1422*700637cbSDimitry Andric         const auto *Itr =
1423*700637cbSDimitry Andric             llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
1424*700637cbSDimitry Andric                           llvm::IsaPred<OpenACCNumWorkersClause>);
1425*700637cbSDimitry Andric         if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1426*700637cbSDimitry Andric           SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1427*700637cbSDimitry Andric               << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()
1428*700637cbSDimitry Andric               << HasAssocKind(Clause.getDirectiveKind(),
1429*700637cbSDimitry Andric                               SemaRef.getActiveComputeConstructInfo().Kind)
1430*700637cbSDimitry Andric               << SemaRef.getActiveComputeConstructInfo().Kind
1431*700637cbSDimitry Andric               << OpenACCClauseKind::NumWorkers;
1432*700637cbSDimitry Andric           SemaRef.Diag((*Itr)->getBeginLoc(),
1433*700637cbSDimitry Andric                        diag::note_acc_previous_clause_here)
1434*700637cbSDimitry Andric               << (*Itr)->getClauseKind();
1435*700637cbSDimitry Andric 
1436*700637cbSDimitry Andric           IntExpr = nullptr;
1437*700637cbSDimitry Andric         }
1438*700637cbSDimitry Andric         break;
1439*700637cbSDimitry Andric       }
1440*700637cbSDimitry Andric       default:
1441*700637cbSDimitry Andric         llvm_unreachable("Non compute construct in active compute construct");
1442*700637cbSDimitry Andric       }
1443*700637cbSDimitry Andric       break;
1444*700637cbSDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
1445*700637cbSDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
1446*700637cbSDimitry Andric     case OpenACCDirectiveKind::Routine:
1447*700637cbSDimitry Andric       DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num,
1448*700637cbSDimitry Andric                         OpenACCClauseKind::Worker, Clause.getDirectiveKind(),
1449*700637cbSDimitry Andric                         SemaRef.getActiveComputeConstructInfo().Kind);
1450*700637cbSDimitry Andric       IntExpr = nullptr;
1451*700637cbSDimitry Andric       break;
1452*700637cbSDimitry Andric     case OpenACCDirectiveKind::KernelsLoop: {
1453*700637cbSDimitry Andric       const auto *Itr = llvm::find_if(ExistingClauses,
1454*700637cbSDimitry Andric                                       llvm::IsaPred<OpenACCNumWorkersClause>);
1455*700637cbSDimitry Andric       if (Itr != ExistingClauses.end()) {
1456*700637cbSDimitry Andric         SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1457*700637cbSDimitry Andric             << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()
1458*700637cbSDimitry Andric             << HasAssocKind(Clause.getDirectiveKind(),
1459*700637cbSDimitry Andric                             SemaRef.getActiveComputeConstructInfo().Kind)
1460*700637cbSDimitry Andric             << SemaRef.getActiveComputeConstructInfo().Kind
1461*700637cbSDimitry Andric             << OpenACCClauseKind::NumWorkers;
1462*700637cbSDimitry Andric         SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1463*700637cbSDimitry Andric             << (*Itr)->getClauseKind();
1464*700637cbSDimitry Andric 
1465*700637cbSDimitry Andric         IntExpr = nullptr;
1466*700637cbSDimitry Andric       }
1467*700637cbSDimitry Andric     }
1468*700637cbSDimitry Andric     }
1469*700637cbSDimitry Andric   }
1470*700637cbSDimitry Andric 
1471*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1472*700637cbSDimitry Andric     // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1473*700637cbSDimitry Andric     // contain a loop with a gang or worker clause unless within a nested
1474*700637cbSDimitry Andric     // compute region.
1475*700637cbSDimitry Andric     if (SemaRef.LoopWorkerClauseLoc.isValid()) {
1476*700637cbSDimitry Andric       // This handles the 'inner loop' diagnostic, but we cannot set that we're
1477*700637cbSDimitry Andric       // on one of these until we get to the end of the construct.
1478*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1479*700637cbSDimitry Andric           << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker
1480*700637cbSDimitry Andric           << /*skip kernels construct info*/ 0;
1481*700637cbSDimitry Andric       SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1482*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
1483*700637cbSDimitry Andric           << "worker";
1484*700637cbSDimitry Andric       return nullptr;
1485*700637cbSDimitry Andric     }
1486*700637cbSDimitry Andric 
1487*700637cbSDimitry Andric     // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1488*700637cbSDimitry Andric     // contain a loop with a gang, worker, or vector clause unless within a
1489*700637cbSDimitry Andric     // nested compute region.
1490*700637cbSDimitry Andric     if (SemaRef.LoopVectorClauseLoc.isValid()) {
1491*700637cbSDimitry Andric       // This handles the 'inner loop' diagnostic, but we cannot set that we're
1492*700637cbSDimitry Andric       // on one of these until we get to the end of the construct.
1493*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1494*700637cbSDimitry Andric           << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector
1495*700637cbSDimitry Andric           << /*skip kernels construct info*/ 0;
1496*700637cbSDimitry Andric       SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1497*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
1498*700637cbSDimitry Andric           << "vector";
1499*700637cbSDimitry Andric       return nullptr;
1500*700637cbSDimitry Andric     }
1501*700637cbSDimitry Andric   }
1502*700637cbSDimitry Andric 
1503*700637cbSDimitry Andric   return OpenACCWorkerClause::Create(Ctx, Clause.getBeginLoc(),
1504*700637cbSDimitry Andric                                      Clause.getLParenLoc(), IntExpr,
1505*700637cbSDimitry Andric                                      Clause.getEndLoc());
1506*700637cbSDimitry Andric }
1507*700637cbSDimitry Andric 
VisitGangClause(SemaOpenACC::OpenACCParsedClause & Clause)1508*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
1509*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1510*700637cbSDimitry Andric 
1511*700637cbSDimitry Andric   if (DiagGangWorkerVectorSeqConflict(Clause))
1512*700637cbSDimitry Andric     return nullptr;
1513*700637cbSDimitry Andric 
1514*700637cbSDimitry Andric   // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
1515*700637cbSDimitry Andric   // directive that has a gang clause and is within a compute construct that has
1516*700637cbSDimitry Andric   // a num_gangs clause with more than one explicit argument.
1517*700637cbSDimitry Andric   if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
1518*700637cbSDimitry Andric        SemaRef.getActiveComputeConstructInfo().Kind !=
1519*700637cbSDimitry Andric            OpenACCDirectiveKind::Invalid) ||
1520*700637cbSDimitry Andric       isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) {
1521*700637cbSDimitry Andric     // num_gangs clause on the active compute construct.
1522*700637cbSDimitry Andric     auto ActiveComputeConstructContainer =
1523*700637cbSDimitry Andric         isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())
1524*700637cbSDimitry Andric             ? ExistingClauses
1525*700637cbSDimitry Andric             : SemaRef.getActiveComputeConstructInfo().Clauses;
1526*700637cbSDimitry Andric     auto *NumGangsClauseItr = llvm::find_if(
1527*700637cbSDimitry Andric         ActiveComputeConstructContainer, llvm::IsaPred<OpenACCNumGangsClause>);
1528*700637cbSDimitry Andric 
1529*700637cbSDimitry Andric     if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&
1530*700637cbSDimitry Andric         cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >
1531*700637cbSDimitry Andric             1) {
1532*700637cbSDimitry Andric       auto *ReductionClauseItr =
1533*700637cbSDimitry Andric           llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
1534*700637cbSDimitry Andric 
1535*700637cbSDimitry Andric       if (ReductionClauseItr != ExistingClauses.end()) {
1536*700637cbSDimitry Andric         SemaRef.Diag(Clause.getBeginLoc(),
1537*700637cbSDimitry Andric                      diag::err_acc_gang_reduction_numgangs_conflict)
1538*700637cbSDimitry Andric             << OpenACCClauseKind::Gang << OpenACCClauseKind::Reduction
1539*700637cbSDimitry Andric             << Clause.getDirectiveKind()
1540*700637cbSDimitry Andric             << isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind());
1541*700637cbSDimitry Andric         SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),
1542*700637cbSDimitry Andric                      diag::note_acc_previous_clause_here)
1543*700637cbSDimitry Andric             << (*ReductionClauseItr)->getClauseKind();
1544*700637cbSDimitry Andric         SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
1545*700637cbSDimitry Andric                      diag::note_acc_previous_clause_here)
1546*700637cbSDimitry Andric             << (*NumGangsClauseItr)->getClauseKind();
1547*700637cbSDimitry Andric         return nullptr;
1548*700637cbSDimitry Andric       }
1549*700637cbSDimitry Andric     }
1550*700637cbSDimitry Andric   }
1551*700637cbSDimitry Andric 
1552*700637cbSDimitry Andric   llvm::SmallVector<OpenACCGangKind> GangKinds;
1553*700637cbSDimitry Andric   llvm::SmallVector<Expr *> IntExprs;
1554*700637cbSDimitry Andric 
1555*700637cbSDimitry Andric   // Store the existing locations, so we can do duplicate checking.  Index is
1556*700637cbSDimitry Andric   // the int-value of the OpenACCGangKind enum.
1557*700637cbSDimitry Andric   SourceLocation ExistingElemLoc[3];
1558*700637cbSDimitry Andric 
1559*700637cbSDimitry Andric   for (unsigned I = 0; I < Clause.getIntExprs().size(); ++I) {
1560*700637cbSDimitry Andric     OpenACCGangKind GK = Clause.getGangKinds()[I];
1561*700637cbSDimitry Andric     ExprResult ER =
1562*700637cbSDimitry Andric         SemaRef.CheckGangExpr(ExistingClauses, Clause.getDirectiveKind(), GK,
1563*700637cbSDimitry Andric                               Clause.getIntExprs()[I]);
1564*700637cbSDimitry Andric 
1565*700637cbSDimitry Andric     if (!ER.isUsable())
1566*700637cbSDimitry Andric       continue;
1567*700637cbSDimitry Andric 
1568*700637cbSDimitry Andric     // OpenACC 3.3 2.9: 'gang-arg-list' may have at most one num, one dim, and
1569*700637cbSDimitry Andric     // one static argument.
1570*700637cbSDimitry Andric     if (ExistingElemLoc[static_cast<unsigned>(GK)].isValid()) {
1571*700637cbSDimitry Andric       SemaRef.Diag(ER.get()->getBeginLoc(), diag::err_acc_gang_multiple_elt)
1572*700637cbSDimitry Andric           << static_cast<unsigned>(GK);
1573*700637cbSDimitry Andric       SemaRef.Diag(ExistingElemLoc[static_cast<unsigned>(GK)],
1574*700637cbSDimitry Andric                    diag::note_acc_previous_expr_here);
1575*700637cbSDimitry Andric       continue;
1576*700637cbSDimitry Andric     }
1577*700637cbSDimitry Andric 
1578*700637cbSDimitry Andric     ExistingElemLoc[static_cast<unsigned>(GK)] = ER.get()->getBeginLoc();
1579*700637cbSDimitry Andric     GangKinds.push_back(GK);
1580*700637cbSDimitry Andric     IntExprs.push_back(ER.get());
1581*700637cbSDimitry Andric   }
1582*700637cbSDimitry Andric 
1583*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1584*700637cbSDimitry Andric     // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1585*700637cbSDimitry Andric     // construct, the gang clause behaves as follows. ... The region of a loop
1586*700637cbSDimitry Andric     // with a gang clause may not contain another loop with a gang clause unless
1587*700637cbSDimitry Andric     // within a nested compute region.
1588*700637cbSDimitry Andric     if (SemaRef.LoopGangClauseOnKernel.Loc.isValid()) {
1589*700637cbSDimitry Andric       // This handles the 'inner loop' diagnostic, but we cannot set that we're
1590*700637cbSDimitry Andric       // on one of these until we get to the end of the construct.
1591*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1592*700637cbSDimitry Andric           << OpenACCClauseKind::Gang << OpenACCClauseKind::Gang
1593*700637cbSDimitry Andric           << /*kernels construct info*/ 1
1594*700637cbSDimitry Andric           << SemaRef.LoopGangClauseOnKernel.DirKind;
1595*700637cbSDimitry Andric       SemaRef.Diag(SemaRef.LoopGangClauseOnKernel.Loc,
1596*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
1597*700637cbSDimitry Andric           << "gang";
1598*700637cbSDimitry Andric       return nullptr;
1599*700637cbSDimitry Andric     }
1600*700637cbSDimitry Andric 
1601*700637cbSDimitry Andric     // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1602*700637cbSDimitry Andric     // contain a loop with a gang or worker clause unless within a nested
1603*700637cbSDimitry Andric     // compute region.
1604*700637cbSDimitry Andric     if (SemaRef.LoopWorkerClauseLoc.isValid()) {
1605*700637cbSDimitry Andric       // This handles the 'inner loop' diagnostic, but we cannot set that we're
1606*700637cbSDimitry Andric       // on one of these until we get to the end of the construct.
1607*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1608*700637cbSDimitry Andric           << OpenACCClauseKind::Gang << OpenACCClauseKind::Worker
1609*700637cbSDimitry Andric           << /*!kernels construct info*/ 0;
1610*700637cbSDimitry Andric       SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1611*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
1612*700637cbSDimitry Andric           << "worker";
1613*700637cbSDimitry Andric       return nullptr;
1614*700637cbSDimitry Andric     }
1615*700637cbSDimitry Andric 
1616*700637cbSDimitry Andric     // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1617*700637cbSDimitry Andric     // contain a loop with a gang, worker, or vector clause unless within a
1618*700637cbSDimitry Andric     // nested compute region.
1619*700637cbSDimitry Andric     if (SemaRef.LoopVectorClauseLoc.isValid()) {
1620*700637cbSDimitry Andric       // This handles the 'inner loop' diagnostic, but we cannot set that we're
1621*700637cbSDimitry Andric       // on one of these until we get to the end of the construct.
1622*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1623*700637cbSDimitry Andric           << OpenACCClauseKind::Gang << OpenACCClauseKind::Vector
1624*700637cbSDimitry Andric           << /*!kernels construct info*/ 0;
1625*700637cbSDimitry Andric       SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1626*700637cbSDimitry Andric                    diag::note_acc_previous_clause_here)
1627*700637cbSDimitry Andric           << "vector";
1628*700637cbSDimitry Andric       return nullptr;
1629*700637cbSDimitry Andric     }
1630*700637cbSDimitry Andric   }
1631*700637cbSDimitry Andric 
1632*700637cbSDimitry Andric   return SemaRef.CheckGangClause(Clause.getDirectiveKind(), ExistingClauses,
1633*700637cbSDimitry Andric                                  Clause.getBeginLoc(), Clause.getLParenLoc(),
1634*700637cbSDimitry Andric                                  GangKinds, IntExprs, Clause.getEndLoc());
1635*700637cbSDimitry Andric }
1636*700637cbSDimitry Andric 
VisitFinalizeClause(SemaOpenACC::OpenACCParsedClause & Clause)1637*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitFinalizeClause(
1638*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1639*700637cbSDimitry Andric   // There isn't anything to do here, this is only valid on one construct, and
1640*700637cbSDimitry Andric   // has no associated rules.
1641*700637cbSDimitry Andric   return OpenACCFinalizeClause::Create(Ctx, Clause.getBeginLoc(),
1642*700637cbSDimitry Andric                                        Clause.getEndLoc());
1643*700637cbSDimitry Andric }
1644*700637cbSDimitry Andric 
VisitIfPresentClause(SemaOpenACC::OpenACCParsedClause & Clause)1645*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitIfPresentClause(
1646*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1647*700637cbSDimitry Andric   // There isn't anything to do here, this is only valid on one construct, and
1648*700637cbSDimitry Andric   // has no associated rules.
1649*700637cbSDimitry Andric   return OpenACCIfPresentClause::Create(Ctx, Clause.getBeginLoc(),
1650*700637cbSDimitry Andric                                         Clause.getEndLoc());
1651*700637cbSDimitry Andric }
1652*700637cbSDimitry Andric 
VisitSeqClause(SemaOpenACC::OpenACCParsedClause & Clause)1653*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
1654*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1655*700637cbSDimitry Andric   // OpenACC 3.3 2.9:
1656*700637cbSDimitry Andric   //  A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
1657*700637cbSDimitry Andric   //  appears.
1658*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop ||
1659*700637cbSDimitry Andric       isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) {
1660*700637cbSDimitry Andric     const auto *Itr = llvm::find_if(
1661*700637cbSDimitry Andric         ExistingClauses, llvm::IsaPred<OpenACCGangClause, OpenACCVectorClause,
1662*700637cbSDimitry Andric                                        OpenACCWorkerClause>);
1663*700637cbSDimitry Andric     if (Itr != ExistingClauses.end()) {
1664*700637cbSDimitry Andric       SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
1665*700637cbSDimitry Andric           << Clause.getClauseKind() << (*Itr)->getClauseKind()
1666*700637cbSDimitry Andric           << Clause.getDirectiveKind();
1667*700637cbSDimitry Andric       SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1668*700637cbSDimitry Andric           << (*Itr)->getClauseKind();
1669*700637cbSDimitry Andric       return nullptr;
1670*700637cbSDimitry Andric     }
1671*700637cbSDimitry Andric   }
1672*700637cbSDimitry Andric 
1673*700637cbSDimitry Andric   return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(),
1674*700637cbSDimitry Andric                                   Clause.getEndLoc());
1675*700637cbSDimitry Andric }
1676*700637cbSDimitry Andric 
VisitReductionClause(SemaOpenACC::OpenACCParsedClause & Clause)1677*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
1678*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1679*700637cbSDimitry Andric   // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
1680*700637cbSDimitry Andric   // directive that has a gang clause and is within a compute construct that has
1681*700637cbSDimitry Andric   // a num_gangs clause with more than one explicit argument.
1682*700637cbSDimitry Andric   if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
1683*700637cbSDimitry Andric        SemaRef.getActiveComputeConstructInfo().Kind !=
1684*700637cbSDimitry Andric            OpenACCDirectiveKind::Invalid) ||
1685*700637cbSDimitry Andric       isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) {
1686*700637cbSDimitry Andric     // num_gangs clause on the active compute construct.
1687*700637cbSDimitry Andric     auto ActiveComputeConstructContainer =
1688*700637cbSDimitry Andric         isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())
1689*700637cbSDimitry Andric             ? ExistingClauses
1690*700637cbSDimitry Andric             : SemaRef.getActiveComputeConstructInfo().Clauses;
1691*700637cbSDimitry Andric     auto *NumGangsClauseItr = llvm::find_if(
1692*700637cbSDimitry Andric         ActiveComputeConstructContainer, llvm::IsaPred<OpenACCNumGangsClause>);
1693*700637cbSDimitry Andric 
1694*700637cbSDimitry Andric     if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&
1695*700637cbSDimitry Andric         cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >
1696*700637cbSDimitry Andric             1) {
1697*700637cbSDimitry Andric       auto *GangClauseItr =
1698*700637cbSDimitry Andric           llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
1699*700637cbSDimitry Andric 
1700*700637cbSDimitry Andric       if (GangClauseItr != ExistingClauses.end()) {
1701*700637cbSDimitry Andric         SemaRef.Diag(Clause.getBeginLoc(),
1702*700637cbSDimitry Andric                      diag::err_acc_gang_reduction_numgangs_conflict)
1703*700637cbSDimitry Andric             << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang
1704*700637cbSDimitry Andric             << Clause.getDirectiveKind()
1705*700637cbSDimitry Andric             << isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind());
1706*700637cbSDimitry Andric         SemaRef.Diag((*GangClauseItr)->getBeginLoc(),
1707*700637cbSDimitry Andric                      diag::note_acc_previous_clause_here)
1708*700637cbSDimitry Andric             << (*GangClauseItr)->getClauseKind();
1709*700637cbSDimitry Andric         SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
1710*700637cbSDimitry Andric                      diag::note_acc_previous_clause_here)
1711*700637cbSDimitry Andric             << (*NumGangsClauseItr)->getClauseKind();
1712*700637cbSDimitry Andric         return nullptr;
1713*700637cbSDimitry Andric       }
1714*700637cbSDimitry Andric     }
1715*700637cbSDimitry Andric   }
1716*700637cbSDimitry Andric 
1717*700637cbSDimitry Andric   // OpenACC3.3 Section 2.9.11: If a variable is involved in a reduction that
1718*700637cbSDimitry Andric   // spans multiple nested loops where two or more of those loops have
1719*700637cbSDimitry Andric   // associated loop directives, a reduction clause containing that variable
1720*700637cbSDimitry Andric   // must appear on each of those loop directives.
1721*700637cbSDimitry Andric   //
1722*700637cbSDimitry Andric   // This can't really be implemented in the CFE, as this requires a level of
1723*700637cbSDimitry Andric   // rechability/useage analysis that we're not really wanting to get into.
1724*700637cbSDimitry Andric   // Additionally, I'm alerted that this restriction is one that the middle-end
1725*700637cbSDimitry Andric   // can just 'figure out' as an extension and isn't really necessary.
1726*700637cbSDimitry Andric   //
1727*700637cbSDimitry Andric   // OpenACC3.3 Section 2.9.11: Every 'var' in a reduction clause appearing on
1728*700637cbSDimitry Andric   // an orphaned loop construct must be private.
1729*700637cbSDimitry Andric   //
1730*700637cbSDimitry Andric   // This again is something we cannot really diagnose, as it requires we see
1731*700637cbSDimitry Andric   // all the uses/scopes of all variables referenced.  The middle end/MLIR might
1732*700637cbSDimitry Andric   // be able to diagnose this.
1733*700637cbSDimitry Andric 
1734*700637cbSDimitry Andric   // OpenACC 3.3 Section 2.5.4:
1735*700637cbSDimitry Andric   // A reduction clause may not appear on a parallel construct with a
1736*700637cbSDimitry Andric   // num_gangs clause that has more than one argument.
1737*700637cbSDimitry Andric   if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
1738*700637cbSDimitry Andric       Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) {
1739*700637cbSDimitry Andric     auto NumGangsClauses = llvm::make_filter_range(
1740*700637cbSDimitry Andric         ExistingClauses, llvm::IsaPred<OpenACCNumGangsClause>);
1741*700637cbSDimitry Andric 
1742*700637cbSDimitry Andric     for (auto *NGC : NumGangsClauses) {
1743*700637cbSDimitry Andric       unsigned NumExprs =
1744*700637cbSDimitry Andric           cast<OpenACCNumGangsClause>(NGC)->getIntExprs().size();
1745*700637cbSDimitry Andric 
1746*700637cbSDimitry Andric       if (NumExprs > 1) {
1747*700637cbSDimitry Andric         SemaRef.Diag(Clause.getBeginLoc(),
1748*700637cbSDimitry Andric                      diag::err_acc_reduction_num_gangs_conflict)
1749*700637cbSDimitry Andric             << /*>1 arg in first loc=*/0 << Clause.getClauseKind()
1750*700637cbSDimitry Andric             << Clause.getDirectiveKind() << OpenACCClauseKind::NumGangs;
1751*700637cbSDimitry Andric         SemaRef.Diag(NGC->getBeginLoc(), diag::note_acc_previous_clause_here)
1752*700637cbSDimitry Andric             << NGC->getClauseKind();
1753*700637cbSDimitry Andric         return nullptr;
1754*700637cbSDimitry Andric       }
1755*700637cbSDimitry Andric     }
1756*700637cbSDimitry Andric   }
1757*700637cbSDimitry Andric 
1758*700637cbSDimitry Andric   SmallVector<Expr *> ValidVars;
1759*700637cbSDimitry Andric 
1760*700637cbSDimitry Andric   for (Expr *Var : Clause.getVarList()) {
1761*700637cbSDimitry Andric     ExprResult Res = SemaRef.CheckReductionVar(Clause.getDirectiveKind(),
1762*700637cbSDimitry Andric                                                Clause.getReductionOp(), Var);
1763*700637cbSDimitry Andric 
1764*700637cbSDimitry Andric     if (Res.isUsable())
1765*700637cbSDimitry Andric       ValidVars.push_back(Res.get());
1766*700637cbSDimitry Andric   }
1767*700637cbSDimitry Andric 
1768*700637cbSDimitry Andric   return SemaRef.CheckReductionClause(
1769*700637cbSDimitry Andric       ExistingClauses, Clause.getDirectiveKind(), Clause.getBeginLoc(),
1770*700637cbSDimitry Andric       Clause.getLParenLoc(), Clause.getReductionOp(), ValidVars,
1771*700637cbSDimitry Andric       Clause.getEndLoc());
1772*700637cbSDimitry Andric }
1773*700637cbSDimitry Andric 
VisitCollapseClause(SemaOpenACC::OpenACCParsedClause & Clause)1774*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
1775*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1776*700637cbSDimitry Andric 
1777*700637cbSDimitry Andric   if (DisallowSinceLastDeviceType<OpenACCCollapseClause>(Clause))
1778*700637cbSDimitry Andric     return nullptr;
1779*700637cbSDimitry Andric 
1780*700637cbSDimitry Andric   ExprResult LoopCount = SemaRef.CheckCollapseLoopCount(Clause.getLoopCount());
1781*700637cbSDimitry Andric 
1782*700637cbSDimitry Andric   if (!LoopCount.isUsable())
1783*700637cbSDimitry Andric     return nullptr;
1784*700637cbSDimitry Andric 
1785*700637cbSDimitry Andric   return OpenACCCollapseClause::Create(Ctx, Clause.getBeginLoc(),
1786*700637cbSDimitry Andric                                        Clause.getLParenLoc(), Clause.isForce(),
1787*700637cbSDimitry Andric                                        LoopCount.get(), Clause.getEndLoc());
1788*700637cbSDimitry Andric }
1789*700637cbSDimitry Andric 
VisitBindClause(SemaOpenACC::OpenACCParsedClause & Clause)1790*700637cbSDimitry Andric OpenACCClause *SemaOpenACCClauseVisitor::VisitBindClause(
1791*700637cbSDimitry Andric     SemaOpenACC::OpenACCParsedClause &Clause) {
1792*700637cbSDimitry Andric 
1793*700637cbSDimitry Andric   if (std::holds_alternative<StringLiteral *>(Clause.getBindDetails()))
1794*700637cbSDimitry Andric     return OpenACCBindClause::Create(
1795*700637cbSDimitry Andric         Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
1796*700637cbSDimitry Andric         std::get<StringLiteral *>(Clause.getBindDetails()), Clause.getEndLoc());
1797*700637cbSDimitry Andric   return OpenACCBindClause::Create(
1798*700637cbSDimitry Andric       Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
1799*700637cbSDimitry Andric       std::get<IdentifierInfo *>(Clause.getBindDetails()), Clause.getEndLoc());
1800*700637cbSDimitry Andric }
1801*700637cbSDimitry Andric 
1802*700637cbSDimitry Andric // Return true if the two vars refer to the same variable, for the purposes of
1803*700637cbSDimitry Andric // equality checking.
areVarsEqual(Expr * VarExpr1,Expr * VarExpr2)1804*700637cbSDimitry Andric bool areVarsEqual(Expr *VarExpr1, Expr *VarExpr2) {
1805*700637cbSDimitry Andric   if (VarExpr1->isInstantiationDependent() ||
1806*700637cbSDimitry Andric       VarExpr2->isInstantiationDependent())
1807*700637cbSDimitry Andric     return false;
1808*700637cbSDimitry Andric 
1809*700637cbSDimitry Andric   VarExpr1 = VarExpr1->IgnoreParenCasts();
1810*700637cbSDimitry Andric   VarExpr2 = VarExpr2->IgnoreParenCasts();
1811*700637cbSDimitry Andric 
1812*700637cbSDimitry Andric   // Legal expressions can be: Scalar variable reference, sub-array, array
1813*700637cbSDimitry Andric   // element, or composite variable member.
1814*700637cbSDimitry Andric 
1815*700637cbSDimitry Andric   // Sub-array.
1816*700637cbSDimitry Andric   if (isa<ArraySectionExpr>(VarExpr1)) {
1817*700637cbSDimitry Andric     auto *Expr2AS = dyn_cast<ArraySectionExpr>(VarExpr2);
1818*700637cbSDimitry Andric     if (!Expr2AS)
1819*700637cbSDimitry Andric       return false;
1820*700637cbSDimitry Andric 
1821*700637cbSDimitry Andric     auto *Expr1AS = cast<ArraySectionExpr>(VarExpr1);
1822*700637cbSDimitry Andric 
1823*700637cbSDimitry Andric     if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))
1824*700637cbSDimitry Andric       return false;
1825*700637cbSDimitry Andric     // We could possibly check to see if the ranges aren't overlapping, but it
1826*700637cbSDimitry Andric     // isn't clear that the rules allow this.
1827*700637cbSDimitry Andric     return true;
1828*700637cbSDimitry Andric   }
1829*700637cbSDimitry Andric 
1830*700637cbSDimitry Andric   // Array-element.
1831*700637cbSDimitry Andric   if (isa<ArraySubscriptExpr>(VarExpr1)) {
1832*700637cbSDimitry Andric     auto *Expr2AS = dyn_cast<ArraySubscriptExpr>(VarExpr2);
1833*700637cbSDimitry Andric     if (!Expr2AS)
1834*700637cbSDimitry Andric       return false;
1835*700637cbSDimitry Andric 
1836*700637cbSDimitry Andric     auto *Expr1AS = cast<ArraySubscriptExpr>(VarExpr1);
1837*700637cbSDimitry Andric 
1838*700637cbSDimitry Andric     if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))
1839*700637cbSDimitry Andric       return false;
1840*700637cbSDimitry Andric 
1841*700637cbSDimitry Andric     // We could possibly check to see if the elements referenced aren't the
1842*700637cbSDimitry Andric     // same, but it isn't clear by reading of the standard that this is allowed
1843*700637cbSDimitry Andric     // (and that the 'var' refered to isn't the array).
1844*700637cbSDimitry Andric     return true;
1845*700637cbSDimitry Andric   }
1846*700637cbSDimitry Andric 
1847*700637cbSDimitry Andric   // Scalar variable reference, or composite variable.
1848*700637cbSDimitry Andric   if (isa<DeclRefExpr>(VarExpr1)) {
1849*700637cbSDimitry Andric     auto *Expr2DRE = dyn_cast<DeclRefExpr>(VarExpr2);
1850*700637cbSDimitry Andric     if (!Expr2DRE)
1851*700637cbSDimitry Andric       return false;
1852*700637cbSDimitry Andric 
1853*700637cbSDimitry Andric     auto *Expr1DRE = cast<DeclRefExpr>(VarExpr1);
1854*700637cbSDimitry Andric 
1855*700637cbSDimitry Andric     return Expr1DRE->getDecl()->getMostRecentDecl() ==
1856*700637cbSDimitry Andric            Expr2DRE->getDecl()->getMostRecentDecl();
1857*700637cbSDimitry Andric   }
1858*700637cbSDimitry Andric 
1859*700637cbSDimitry Andric   llvm_unreachable("Unknown variable type encountered");
1860*700637cbSDimitry Andric }
1861*700637cbSDimitry Andric } // namespace
1862*700637cbSDimitry Andric 
1863*700637cbSDimitry Andric OpenACCClause *
ActOnClause(ArrayRef<const OpenACCClause * > ExistingClauses,OpenACCParsedClause & Clause)1864*700637cbSDimitry Andric SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
1865*700637cbSDimitry Andric                          OpenACCParsedClause &Clause) {
1866*700637cbSDimitry Andric   if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)
1867*700637cbSDimitry Andric     return nullptr;
1868*700637cbSDimitry Andric 
1869*700637cbSDimitry Andric   if (DiagnoseAllowedClauses(Clause.getDirectiveKind(), Clause.getClauseKind(),
1870*700637cbSDimitry Andric                              Clause.getBeginLoc()))
1871*700637cbSDimitry Andric     return nullptr;
1872*700637cbSDimitry Andric   //// Diagnose that we don't support this clause on this directive.
1873*700637cbSDimitry Andric   // if (!doesClauseApplyToDirective(Clause.getDirectiveKind(),
1874*700637cbSDimitry Andric   //                                 Clause.getClauseKind())) {
1875*700637cbSDimitry Andric   //   Diag(Clause.getBeginLoc(), diag::err_acc_clause_appertainment)
1876*700637cbSDimitry Andric   //       << Clause.getDirectiveKind() << Clause.getClauseKind();
1877*700637cbSDimitry Andric   //   return nullptr;
1878*700637cbSDimitry Andric   // }
1879*700637cbSDimitry Andric 
1880*700637cbSDimitry Andric   if (const auto *DevTypeClause = llvm::find_if(
1881*700637cbSDimitry Andric           ExistingClauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
1882*700637cbSDimitry Andric       DevTypeClause != ExistingClauses.end()) {
1883*700637cbSDimitry Andric     if (checkValidAfterDeviceType(
1884*700637cbSDimitry Andric             *this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))
1885*700637cbSDimitry Andric       return nullptr;
1886*700637cbSDimitry Andric   }
1887*700637cbSDimitry Andric 
1888*700637cbSDimitry Andric   SemaOpenACCClauseVisitor Visitor{*this, ExistingClauses};
1889*700637cbSDimitry Andric   OpenACCClause *Result = Visitor.Visit(Clause);
1890*700637cbSDimitry Andric   assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) &&
1891*700637cbSDimitry Andric          "Created wrong clause?");
1892*700637cbSDimitry Andric 
1893*700637cbSDimitry Andric   return Result;
1894*700637cbSDimitry Andric }
1895*700637cbSDimitry Andric 
1896*700637cbSDimitry Andric /// OpenACC 3.3 section 2.5.15:
1897*700637cbSDimitry Andric /// At a mininmum, the supported data types include ... the numerical data types
1898*700637cbSDimitry Andric /// in C, C++, and Fortran.
1899*700637cbSDimitry Andric ///
1900*700637cbSDimitry Andric /// If the reduction var is a composite variable, each
1901*700637cbSDimitry Andric /// member of the composite variable must be a supported datatype for the
1902*700637cbSDimitry Andric /// reduction operation.
CheckReductionVar(OpenACCDirectiveKind DirectiveKind,OpenACCReductionOperator ReductionOp,Expr * VarExpr)1903*700637cbSDimitry Andric ExprResult SemaOpenACC::CheckReductionVar(OpenACCDirectiveKind DirectiveKind,
1904*700637cbSDimitry Andric                                           OpenACCReductionOperator ReductionOp,
1905*700637cbSDimitry Andric                                           Expr *VarExpr) {
1906*700637cbSDimitry Andric   VarExpr = VarExpr->IgnoreParenCasts();
1907*700637cbSDimitry Andric 
1908*700637cbSDimitry Andric   auto TypeIsValid = [](QualType Ty) {
1909*700637cbSDimitry Andric     return Ty->isDependentType() || Ty->isScalarType();
1910*700637cbSDimitry Andric   };
1911*700637cbSDimitry Andric 
1912*700637cbSDimitry Andric   if (isa<ArraySectionExpr>(VarExpr)) {
1913*700637cbSDimitry Andric     Expr *ASExpr = VarExpr;
1914*700637cbSDimitry Andric     QualType BaseTy = ArraySectionExpr::getBaseOriginalType(ASExpr);
1915*700637cbSDimitry Andric     QualType EltTy = getASTContext().getBaseElementType(BaseTy);
1916*700637cbSDimitry Andric 
1917*700637cbSDimitry Andric     if (!TypeIsValid(EltTy)) {
1918*700637cbSDimitry Andric       Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
1919*700637cbSDimitry Andric           << EltTy << /*Sub array base type*/ 1;
1920*700637cbSDimitry Andric       return ExprError();
1921*700637cbSDimitry Andric     }
1922*700637cbSDimitry Andric   } else if (auto *RD = VarExpr->getType()->getAsRecordDecl()) {
1923*700637cbSDimitry Andric     if (!RD->isStruct() && !RD->isClass()) {
1924*700637cbSDimitry Andric       Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1925*700637cbSDimitry Andric           << /*not class or struct*/ 0 << VarExpr->getType();
1926*700637cbSDimitry Andric       return ExprError();
1927*700637cbSDimitry Andric     }
1928*700637cbSDimitry Andric 
1929*700637cbSDimitry Andric     if (!RD->isCompleteDefinition()) {
1930*700637cbSDimitry Andric       Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1931*700637cbSDimitry Andric           << /*incomplete*/ 1 << VarExpr->getType();
1932*700637cbSDimitry Andric       return ExprError();
1933*700637cbSDimitry Andric     }
1934*700637cbSDimitry Andric     if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
1935*700637cbSDimitry Andric         CXXRD && !CXXRD->isAggregate()) {
1936*700637cbSDimitry Andric       Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1937*700637cbSDimitry Andric           << /*aggregate*/ 2 << VarExpr->getType();
1938*700637cbSDimitry Andric       return ExprError();
1939*700637cbSDimitry Andric     }
1940*700637cbSDimitry Andric 
1941*700637cbSDimitry Andric     for (FieldDecl *FD : RD->fields()) {
1942*700637cbSDimitry Andric       if (!TypeIsValid(FD->getType())) {
1943*700637cbSDimitry Andric         Diag(VarExpr->getExprLoc(),
1944*700637cbSDimitry Andric              diag::err_acc_reduction_composite_member_type);
1945*700637cbSDimitry Andric         Diag(FD->getLocation(), diag::note_acc_reduction_composite_member_loc);
1946*700637cbSDimitry Andric         return ExprError();
1947*700637cbSDimitry Andric       }
1948*700637cbSDimitry Andric     }
1949*700637cbSDimitry Andric   } else if (!TypeIsValid(VarExpr->getType())) {
1950*700637cbSDimitry Andric     Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
1951*700637cbSDimitry Andric         << VarExpr->getType() << /*Sub array base type*/ 0;
1952*700637cbSDimitry Andric     return ExprError();
1953*700637cbSDimitry Andric   }
1954*700637cbSDimitry Andric 
1955*700637cbSDimitry Andric   // OpenACC3.3: 2.9.11: Reduction clauses on nested constructs for the same
1956*700637cbSDimitry Andric   // reduction 'var' must have the same reduction operator.
1957*700637cbSDimitry Andric   if (!VarExpr->isInstantiationDependent()) {
1958*700637cbSDimitry Andric 
1959*700637cbSDimitry Andric     for (const OpenACCReductionClause *RClause : ActiveReductionClauses) {
1960*700637cbSDimitry Andric       if (RClause->getReductionOp() == ReductionOp)
1961*700637cbSDimitry Andric         break;
1962*700637cbSDimitry Andric 
1963*700637cbSDimitry Andric       for (Expr *OldVarExpr : RClause->getVarList()) {
1964*700637cbSDimitry Andric         if (OldVarExpr->isInstantiationDependent())
1965*700637cbSDimitry Andric           continue;
1966*700637cbSDimitry Andric 
1967*700637cbSDimitry Andric         if (areVarsEqual(VarExpr, OldVarExpr)) {
1968*700637cbSDimitry Andric           Diag(VarExpr->getExprLoc(), diag::err_reduction_op_mismatch)
1969*700637cbSDimitry Andric               << ReductionOp << RClause->getReductionOp();
1970*700637cbSDimitry Andric           Diag(OldVarExpr->getExprLoc(), diag::note_acc_previous_clause_here)
1971*700637cbSDimitry Andric               << RClause->getClauseKind();
1972*700637cbSDimitry Andric           return ExprError();
1973*700637cbSDimitry Andric         }
1974*700637cbSDimitry Andric       }
1975*700637cbSDimitry Andric     }
1976*700637cbSDimitry Andric   }
1977*700637cbSDimitry Andric 
1978*700637cbSDimitry Andric   return VarExpr;
1979*700637cbSDimitry Andric }
1980*700637cbSDimitry Andric 
CheckTileSizeExpr(Expr * SizeExpr)1981*700637cbSDimitry Andric ExprResult SemaOpenACC::CheckTileSizeExpr(Expr *SizeExpr) {
1982*700637cbSDimitry Andric   if (!SizeExpr)
1983*700637cbSDimitry Andric     return ExprError();
1984*700637cbSDimitry Andric 
1985*700637cbSDimitry Andric   assert((SizeExpr->isInstantiationDependent() ||
1986*700637cbSDimitry Andric           SizeExpr->getType()->isIntegerType()) &&
1987*700637cbSDimitry Andric          "size argument non integer?");
1988*700637cbSDimitry Andric 
1989*700637cbSDimitry Andric   // If dependent, or an asterisk, the expression is fine.
1990*700637cbSDimitry Andric   if (SizeExpr->isInstantiationDependent() ||
1991*700637cbSDimitry Andric       isa<OpenACCAsteriskSizeExpr>(SizeExpr))
1992*700637cbSDimitry Andric     return ExprResult{SizeExpr};
1993*700637cbSDimitry Andric 
1994*700637cbSDimitry Andric   std::optional<llvm::APSInt> ICE =
1995*700637cbSDimitry Andric       SizeExpr->getIntegerConstantExpr(getASTContext());
1996*700637cbSDimitry Andric 
1997*700637cbSDimitry Andric   // OpenACC 3.3 2.9.8
1998*700637cbSDimitry Andric   // where each tile size is a constant positive integer expression or asterisk.
1999*700637cbSDimitry Andric   if (!ICE || *ICE <= 0) {
2000*700637cbSDimitry Andric     Diag(SizeExpr->getBeginLoc(), diag::err_acc_size_expr_value)
2001*700637cbSDimitry Andric         << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
2002*700637cbSDimitry Andric     return ExprError();
2003*700637cbSDimitry Andric   }
2004*700637cbSDimitry Andric 
2005*700637cbSDimitry Andric   return ExprResult{
2006*700637cbSDimitry Andric       ConstantExpr::Create(getASTContext(), SizeExpr, APValue{*ICE})};
2007*700637cbSDimitry Andric }
2008*700637cbSDimitry Andric 
CheckCollapseLoopCount(Expr * LoopCount)2009*700637cbSDimitry Andric ExprResult SemaOpenACC::CheckCollapseLoopCount(Expr *LoopCount) {
2010*700637cbSDimitry Andric   if (!LoopCount)
2011*700637cbSDimitry Andric     return ExprError();
2012*700637cbSDimitry Andric 
2013*700637cbSDimitry Andric   assert((LoopCount->isInstantiationDependent() ||
2014*700637cbSDimitry Andric           LoopCount->getType()->isIntegerType()) &&
2015*700637cbSDimitry Andric          "Loop argument non integer?");
2016*700637cbSDimitry Andric 
2017*700637cbSDimitry Andric   // If this is dependent, there really isn't anything we can check.
2018*700637cbSDimitry Andric   if (LoopCount->isInstantiationDependent())
2019*700637cbSDimitry Andric     return ExprResult{LoopCount};
2020*700637cbSDimitry Andric 
2021*700637cbSDimitry Andric   std::optional<llvm::APSInt> ICE =
2022*700637cbSDimitry Andric       LoopCount->getIntegerConstantExpr(getASTContext());
2023*700637cbSDimitry Andric 
2024*700637cbSDimitry Andric   // OpenACC 3.3: 2.9.1
2025*700637cbSDimitry Andric   // The argument to the collapse clause must be a constant positive integer
2026*700637cbSDimitry Andric   // expression.
2027*700637cbSDimitry Andric   if (!ICE || *ICE <= 0) {
2028*700637cbSDimitry Andric     Diag(LoopCount->getBeginLoc(), diag::err_acc_collapse_loop_count)
2029*700637cbSDimitry Andric         << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
2030*700637cbSDimitry Andric     return ExprError();
2031*700637cbSDimitry Andric   }
2032*700637cbSDimitry Andric 
2033*700637cbSDimitry Andric   return ExprResult{
2034*700637cbSDimitry Andric       ConstantExpr::Create(getASTContext(), LoopCount, APValue{*ICE})};
2035*700637cbSDimitry Andric }
2036*700637cbSDimitry Andric 
2037*700637cbSDimitry Andric ExprResult
CheckGangExpr(ArrayRef<const OpenACCClause * > ExistingClauses,OpenACCDirectiveKind DK,OpenACCGangKind GK,Expr * E)2038*700637cbSDimitry Andric SemaOpenACC::CheckGangExpr(ArrayRef<const OpenACCClause *> ExistingClauses,
2039*700637cbSDimitry Andric                            OpenACCDirectiveKind DK, OpenACCGangKind GK,
2040*700637cbSDimitry Andric                            Expr *E) {
2041*700637cbSDimitry Andric   // There are two cases for the enforcement here: the 'current' directive is a
2042*700637cbSDimitry Andric   // 'loop', where we need to check the active compute construct kind, or the
2043*700637cbSDimitry Andric   // current directive is a 'combined' construct, where we have to check the
2044*700637cbSDimitry Andric   // current one.
2045*700637cbSDimitry Andric   switch (DK) {
2046*700637cbSDimitry Andric   case OpenACCDirectiveKind::ParallelLoop:
2047*700637cbSDimitry Andric     return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2048*700637cbSDimitry Andric                                  E);
2049*700637cbSDimitry Andric   case OpenACCDirectiveKind::SerialLoop:
2050*700637cbSDimitry Andric     return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2051*700637cbSDimitry Andric                                E);
2052*700637cbSDimitry Andric   case OpenACCDirectiveKind::KernelsLoop:
2053*700637cbSDimitry Andric     return CheckGangKernelsExpr(*this, ExistingClauses, DK,
2054*700637cbSDimitry Andric                                 ActiveComputeConstructInfo.Kind, GK, E);
2055*700637cbSDimitry Andric   case OpenACCDirectiveKind::Routine:
2056*700637cbSDimitry Andric     return CheckGangRoutineExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2057*700637cbSDimitry Andric                                 E);
2058*700637cbSDimitry Andric   case OpenACCDirectiveKind::Loop:
2059*700637cbSDimitry Andric     switch (ActiveComputeConstructInfo.Kind) {
2060*700637cbSDimitry Andric     case OpenACCDirectiveKind::Invalid:
2061*700637cbSDimitry Andric     case OpenACCDirectiveKind::Parallel:
2062*700637cbSDimitry Andric     case OpenACCDirectiveKind::ParallelLoop:
2063*700637cbSDimitry Andric       return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind,
2064*700637cbSDimitry Andric                                    GK, E);
2065*700637cbSDimitry Andric     case OpenACCDirectiveKind::SerialLoop:
2066*700637cbSDimitry Andric     case OpenACCDirectiveKind::Serial:
2067*700637cbSDimitry Andric       return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2068*700637cbSDimitry Andric                                  E);
2069*700637cbSDimitry Andric     case OpenACCDirectiveKind::KernelsLoop:
2070*700637cbSDimitry Andric     case OpenACCDirectiveKind::Kernels:
2071*700637cbSDimitry Andric       return CheckGangKernelsExpr(*this, ExistingClauses, DK,
2072*700637cbSDimitry Andric                                   ActiveComputeConstructInfo.Kind, GK, E);
2073*700637cbSDimitry Andric     default:
2074*700637cbSDimitry Andric       llvm_unreachable("Non compute construct in active compute construct?");
2075*700637cbSDimitry Andric     }
2076*700637cbSDimitry Andric   case OpenACCDirectiveKind::Invalid:
2077*700637cbSDimitry Andric     // This can happen in cases where the the directive was not recognized but
2078*700637cbSDimitry Andric     // we continued anyway. Since the validity checking is all-over the place
2079*700637cbSDimitry Andric     // (it can be a star/integer, or a constant expr depending on the tag), we
2080*700637cbSDimitry Andric     // just give up and return an ExprError here.
2081*700637cbSDimitry Andric     return ExprError();
2082*700637cbSDimitry Andric   default:
2083*700637cbSDimitry Andric     llvm_unreachable("Invalid directive kind for a Gang clause");
2084*700637cbSDimitry Andric   }
2085*700637cbSDimitry Andric   llvm_unreachable("Compute construct directive not handled?");
2086*700637cbSDimitry Andric }
2087*700637cbSDimitry Andric 
2088*700637cbSDimitry Andric OpenACCClause *
CheckGangClause(OpenACCDirectiveKind DirKind,ArrayRef<const OpenACCClause * > ExistingClauses,SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<OpenACCGangKind> GangKinds,ArrayRef<Expr * > IntExprs,SourceLocation EndLoc)2089*700637cbSDimitry Andric SemaOpenACC::CheckGangClause(OpenACCDirectiveKind DirKind,
2090*700637cbSDimitry Andric                              ArrayRef<const OpenACCClause *> ExistingClauses,
2091*700637cbSDimitry Andric                              SourceLocation BeginLoc, SourceLocation LParenLoc,
2092*700637cbSDimitry Andric                              ArrayRef<OpenACCGangKind> GangKinds,
2093*700637cbSDimitry Andric                              ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) {
2094*700637cbSDimitry Andric   // Reduction isn't possible on 'routine' so we don't bother checking it here.
2095*700637cbSDimitry Andric   if (DirKind != OpenACCDirectiveKind::Routine) {
2096*700637cbSDimitry Andric     // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
2097*700637cbSDimitry Andric     // that has a gang clause with a dim: argument whose value is greater
2098*700637cbSDimitry Andric     // than 1.
2099*700637cbSDimitry Andric     const auto *ReductionItr =
2100*700637cbSDimitry Andric         llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
2101*700637cbSDimitry Andric 
2102*700637cbSDimitry Andric     if (ReductionItr != ExistingClauses.end()) {
2103*700637cbSDimitry Andric       const auto GangZip = llvm::zip_equal(GangKinds, IntExprs);
2104*700637cbSDimitry Andric       const auto GangItr = llvm::find_if(GangZip, [](const auto &Tuple) {
2105*700637cbSDimitry Andric         return std::get<0>(Tuple) == OpenACCGangKind::Dim;
2106*700637cbSDimitry Andric       });
2107*700637cbSDimitry Andric 
2108*700637cbSDimitry Andric       if (GangItr != GangZip.end()) {
2109*700637cbSDimitry Andric         const Expr *DimExpr = std::get<1>(*GangItr);
2110*700637cbSDimitry Andric 
2111*700637cbSDimitry Andric         assert((DimExpr->isInstantiationDependent() ||
2112*700637cbSDimitry Andric                 isa<ConstantExpr>(DimExpr)) &&
2113*700637cbSDimitry Andric                "Improperly formed gang argument");
2114*700637cbSDimitry Andric         if (const auto *DimVal = dyn_cast<ConstantExpr>(DimExpr);
2115*700637cbSDimitry Andric             DimVal && DimVal->getResultAsAPSInt() > 1) {
2116*700637cbSDimitry Andric           Diag(DimVal->getBeginLoc(), diag::err_acc_gang_reduction_conflict)
2117*700637cbSDimitry Andric               << /*gang/reduction=*/0 << DirKind;
2118*700637cbSDimitry Andric           Diag((*ReductionItr)->getBeginLoc(),
2119*700637cbSDimitry Andric                diag::note_acc_previous_clause_here)
2120*700637cbSDimitry Andric               << (*ReductionItr)->getClauseKind();
2121*700637cbSDimitry Andric           return nullptr;
2122*700637cbSDimitry Andric         }
2123*700637cbSDimitry Andric       }
2124*700637cbSDimitry Andric     }
2125*700637cbSDimitry Andric   }
2126*700637cbSDimitry Andric 
2127*700637cbSDimitry Andric   return OpenACCGangClause::Create(getASTContext(), BeginLoc, LParenLoc,
2128*700637cbSDimitry Andric                                    GangKinds, IntExprs, EndLoc);
2129*700637cbSDimitry Andric }
2130*700637cbSDimitry Andric 
CheckReductionClause(ArrayRef<const OpenACCClause * > ExistingClauses,OpenACCDirectiveKind DirectiveKind,SourceLocation BeginLoc,SourceLocation LParenLoc,OpenACCReductionOperator ReductionOp,ArrayRef<Expr * > Vars,SourceLocation EndLoc)2131*700637cbSDimitry Andric OpenACCClause *SemaOpenACC::CheckReductionClause(
2132*700637cbSDimitry Andric     ArrayRef<const OpenACCClause *> ExistingClauses,
2133*700637cbSDimitry Andric     OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc,
2134*700637cbSDimitry Andric     SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp,
2135*700637cbSDimitry Andric     ArrayRef<Expr *> Vars, SourceLocation EndLoc) {
2136*700637cbSDimitry Andric   if (DirectiveKind == OpenACCDirectiveKind::Loop ||
2137*700637cbSDimitry Andric       isOpenACCCombinedDirectiveKind(DirectiveKind)) {
2138*700637cbSDimitry Andric     // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
2139*700637cbSDimitry Andric     // that has a gang clause with a dim: argument whose value is greater
2140*700637cbSDimitry Andric     // than 1.
2141*700637cbSDimitry Andric     const auto GangClauses = llvm::make_filter_range(
2142*700637cbSDimitry Andric         ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
2143*700637cbSDimitry Andric 
2144*700637cbSDimitry Andric     for (auto *GC : GangClauses) {
2145*700637cbSDimitry Andric       const auto *GangClause = cast<OpenACCGangClause>(GC);
2146*700637cbSDimitry Andric       for (unsigned I = 0; I < GangClause->getNumExprs(); ++I) {
2147*700637cbSDimitry Andric         std::pair<OpenACCGangKind, const Expr *> EPair = GangClause->getExpr(I);
2148*700637cbSDimitry Andric         if (EPair.first != OpenACCGangKind::Dim)
2149*700637cbSDimitry Andric           continue;
2150*700637cbSDimitry Andric 
2151*700637cbSDimitry Andric         if (const auto *DimVal = dyn_cast<ConstantExpr>(EPair.second);
2152*700637cbSDimitry Andric             DimVal && DimVal->getResultAsAPSInt() > 1) {
2153*700637cbSDimitry Andric           Diag(BeginLoc, diag::err_acc_gang_reduction_conflict)
2154*700637cbSDimitry Andric               << /*reduction/gang=*/1 << DirectiveKind;
2155*700637cbSDimitry Andric           Diag(GangClause->getBeginLoc(), diag::note_acc_previous_clause_here)
2156*700637cbSDimitry Andric               << GangClause->getClauseKind();
2157*700637cbSDimitry Andric           return nullptr;
2158*700637cbSDimitry Andric         }
2159*700637cbSDimitry Andric       }
2160*700637cbSDimitry Andric     }
2161*700637cbSDimitry Andric   }
2162*700637cbSDimitry Andric 
2163*700637cbSDimitry Andric   auto *Ret = OpenACCReductionClause::Create(
2164*700637cbSDimitry Andric       getASTContext(), BeginLoc, LParenLoc, ReductionOp, Vars, EndLoc);
2165*700637cbSDimitry Andric   return Ret;
2166*700637cbSDimitry Andric }
2167*700637cbSDimitry Andric 
2168*700637cbSDimitry Andric llvm::SmallVector<Expr *>
CheckLinkClauseVarList(ArrayRef<Expr * > VarExprs)2169*700637cbSDimitry Andric SemaOpenACC::CheckLinkClauseVarList(ArrayRef<Expr *> VarExprs) {
2170*700637cbSDimitry Andric   const DeclContext *DC = removeLinkageSpecDC(getCurContext());
2171*700637cbSDimitry Andric 
2172*700637cbSDimitry Andric   // Link has no special restrictions on its var list unless it is not at NS/TU
2173*700637cbSDimitry Andric   // scope.
2174*700637cbSDimitry Andric   if (isa<NamespaceDecl, TranslationUnitDecl>(DC))
2175*700637cbSDimitry Andric     return llvm::SmallVector<Expr *>(VarExprs);
2176*700637cbSDimitry Andric 
2177*700637cbSDimitry Andric   llvm::SmallVector<Expr *> NewVarList;
2178*700637cbSDimitry Andric 
2179*700637cbSDimitry Andric   for (Expr *VarExpr : VarExprs) {
2180*700637cbSDimitry Andric     if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(VarExpr)) {
2181*700637cbSDimitry Andric       NewVarList.push_back(VarExpr);
2182*700637cbSDimitry Andric       continue;
2183*700637cbSDimitry Andric     }
2184*700637cbSDimitry Andric 
2185*700637cbSDimitry Andric     // Field decls can't be global, nor extern, and declare can't refer to
2186*700637cbSDimitry Andric     // non-static fields in class-scope, so this always fails the scope check.
2187*700637cbSDimitry Andric     // BUT for now we add this so it gets diagnosed by the general 'declare'
2188*700637cbSDimitry Andric     // rules.
2189*700637cbSDimitry Andric     if (isa<MemberExpr>(VarExpr)) {
2190*700637cbSDimitry Andric       NewVarList.push_back(VarExpr);
2191*700637cbSDimitry Andric       continue;
2192*700637cbSDimitry Andric     }
2193*700637cbSDimitry Andric 
2194*700637cbSDimitry Andric     const auto *DRE = cast<DeclRefExpr>(VarExpr);
2195*700637cbSDimitry Andric     const VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl());
2196*700637cbSDimitry Andric 
2197*700637cbSDimitry Andric     if (!Var || !Var->hasExternalStorage())
2198*700637cbSDimitry Andric       Diag(VarExpr->getBeginLoc(), diag::err_acc_link_not_extern);
2199*700637cbSDimitry Andric     else
2200*700637cbSDimitry Andric       NewVarList.push_back(VarExpr);
2201*700637cbSDimitry Andric   }
2202*700637cbSDimitry Andric 
2203*700637cbSDimitry Andric   return NewVarList;
2204*700637cbSDimitry Andric }
CheckDeclareClause(SemaOpenACC::OpenACCParsedClause & Clause,OpenACCModifierKind Mods)2205*700637cbSDimitry Andric bool SemaOpenACC::CheckDeclareClause(SemaOpenACC::OpenACCParsedClause &Clause,
2206*700637cbSDimitry Andric                                      OpenACCModifierKind Mods) {
2207*700637cbSDimitry Andric 
2208*700637cbSDimitry Andric   if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Declare)
2209*700637cbSDimitry Andric     return false;
2210*700637cbSDimitry Andric 
2211*700637cbSDimitry Andric   const DeclContext *DC = removeLinkageSpecDC(getCurContext());
2212*700637cbSDimitry Andric 
2213*700637cbSDimitry Andric   // Whether this is 'create', 'copyin', 'deviceptr', 'device_resident', or
2214*700637cbSDimitry Andric   // 'link', which have 2 special rules.
2215*700637cbSDimitry Andric   bool IsSpecialClause =
2216*700637cbSDimitry Andric       Clause.getClauseKind() == OpenACCClauseKind::Create ||
2217*700637cbSDimitry Andric       Clause.getClauseKind() == OpenACCClauseKind::CopyIn ||
2218*700637cbSDimitry Andric       Clause.getClauseKind() == OpenACCClauseKind::DevicePtr ||
2219*700637cbSDimitry Andric       Clause.getClauseKind() == OpenACCClauseKind::DeviceResident ||
2220*700637cbSDimitry Andric       Clause.getClauseKind() == OpenACCClauseKind::Link;
2221*700637cbSDimitry Andric 
2222*700637cbSDimitry Andric   // OpenACC 3.3 2.13:
2223*700637cbSDimitry Andric   // In C or C++ global or namespace scope, only 'create',
2224*700637cbSDimitry Andric   // 'copyin', 'deviceptr', 'device_resident', or 'link' clauses are
2225*700637cbSDimitry Andric   // allowed.
2226*700637cbSDimitry Andric   if (!IsSpecialClause && isa<NamespaceDecl, TranslationUnitDecl>(DC)) {
2227*700637cbSDimitry Andric     return Diag(Clause.getBeginLoc(), diag::err_acc_declare_clause_at_global)
2228*700637cbSDimitry Andric            << Clause.getClauseKind();
2229*700637cbSDimitry Andric   }
2230*700637cbSDimitry Andric 
2231*700637cbSDimitry Andric   llvm::SmallVector<Expr *> FilteredVarList;
2232*700637cbSDimitry Andric   const DeclaratorDecl *CurDecl = nullptr;
2233*700637cbSDimitry Andric   for (Expr *VarExpr : Clause.getVarList()) {
2234*700637cbSDimitry Andric     if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(VarExpr)) {
2235*700637cbSDimitry Andric       // There isn't really anything we can do here, so we add them anyway and
2236*700637cbSDimitry Andric       // we can check them again when we instantiate this.
2237*700637cbSDimitry Andric     } else if (const auto *MemExpr = dyn_cast<MemberExpr>(VarExpr)) {
2238*700637cbSDimitry Andric       FieldDecl *FD =
2239*700637cbSDimitry Andric           cast<FieldDecl>(MemExpr->getMemberDecl()->getCanonicalDecl());
2240*700637cbSDimitry Andric       CurDecl = FD;
2241*700637cbSDimitry Andric 
2242*700637cbSDimitry Andric       if (removeLinkageSpecDC(
2243*700637cbSDimitry Andric               FD->getLexicalDeclContext()->getPrimaryContext()) != DC) {
2244*700637cbSDimitry Andric         Diag(MemExpr->getBeginLoc(), diag::err_acc_declare_same_scope)
2245*700637cbSDimitry Andric             << Clause.getClauseKind();
2246*700637cbSDimitry Andric         continue;
2247*700637cbSDimitry Andric       }
2248*700637cbSDimitry Andric     } else {
2249*700637cbSDimitry Andric       const auto *DRE = cast<DeclRefExpr>(VarExpr);
2250*700637cbSDimitry Andric       if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
2251*700637cbSDimitry Andric         CurDecl = Var->getCanonicalDecl();
2252*700637cbSDimitry Andric 
2253*700637cbSDimitry Andric         // OpenACC3.3 2.13:
2254*700637cbSDimitry Andric         // A 'declare' directive must be in the same scope as the declaration of
2255*700637cbSDimitry Andric         // any var that appears in the clauses of the directive or any scope
2256*700637cbSDimitry Andric         // within a C/C++ function.
2257*700637cbSDimitry Andric         // We can't really check 'scope' here, so we check declaration context,
2258*700637cbSDimitry Andric         // which is a reasonable approximation, but misses scopes inside of
2259*700637cbSDimitry Andric         // functions.
2260*700637cbSDimitry Andric         if (removeLinkageSpecDC(
2261*700637cbSDimitry Andric                 Var->getLexicalDeclContext()->getPrimaryContext()) != DC) {
2262*700637cbSDimitry Andric           Diag(VarExpr->getBeginLoc(), diag::err_acc_declare_same_scope)
2263*700637cbSDimitry Andric               << Clause.getClauseKind();
2264*700637cbSDimitry Andric           continue;
2265*700637cbSDimitry Andric         }
2266*700637cbSDimitry Andric         // OpenACC3.3 2.13:
2267*700637cbSDimitry Andric         // C and C++ extern variables may only appear in 'create',
2268*700637cbSDimitry Andric         // 'copyin', 'deviceptr', 'device_resident', or 'link' clauses on a
2269*700637cbSDimitry Andric         // 'declare' directive.
2270*700637cbSDimitry Andric         if (!IsSpecialClause && Var->hasExternalStorage()) {
2271*700637cbSDimitry Andric           Diag(VarExpr->getBeginLoc(), diag::err_acc_declare_extern)
2272*700637cbSDimitry Andric               << Clause.getClauseKind();
2273*700637cbSDimitry Andric           continue;
2274*700637cbSDimitry Andric         }
2275*700637cbSDimitry Andric       }
2276*700637cbSDimitry Andric 
2277*700637cbSDimitry Andric       // OpenACC3.3 2.13:
2278*700637cbSDimitry Andric       // A var may appear at most once in all the clauses of declare
2279*700637cbSDimitry Andric       // directives for a function, subroutine, program, or module.
2280*700637cbSDimitry Andric 
2281*700637cbSDimitry Andric       if (CurDecl) {
2282*700637cbSDimitry Andric         auto [Itr, Inserted] = DeclareVarReferences.try_emplace(CurDecl);
2283*700637cbSDimitry Andric         if (!Inserted) {
2284*700637cbSDimitry Andric           Diag(VarExpr->getBeginLoc(), diag::err_acc_multiple_references)
2285*700637cbSDimitry Andric               << Clause.getClauseKind();
2286*700637cbSDimitry Andric           Diag(Itr->second, diag::note_acc_previous_reference);
2287*700637cbSDimitry Andric           continue;
2288*700637cbSDimitry Andric         } else {
2289*700637cbSDimitry Andric           Itr->second = VarExpr->getBeginLoc();
2290*700637cbSDimitry Andric         }
2291*700637cbSDimitry Andric       }
2292*700637cbSDimitry Andric     }
2293*700637cbSDimitry Andric     FilteredVarList.push_back(VarExpr);
2294*700637cbSDimitry Andric   }
2295*700637cbSDimitry Andric 
2296*700637cbSDimitry Andric   Clause.setVarListDetails(FilteredVarList, Mods);
2297*700637cbSDimitry Andric   return false;
2298*700637cbSDimitry Andric }
2299