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