blob: 2cb1059a57b35d3c2ea510e7b70700a47658020c [file] [log] [blame]
Valentin Clement9aa3dca2020-07-15 00:43:401//===-- lib/Semantics/check-acc-structure.cpp -----------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
Valentin Clement9aa3dca2020-07-15 00:43:408#include "check-acc-structure.h"
9#include "flang/Parser/parse-tree.h"
10#include "flang/Semantics/tools.h"
11
12#define CHECK_SIMPLE_CLAUSE(X, Y) \
13 void AccStructureChecker::Enter(const parser::AccClause::X &) { \
14 CheckAllowed(llvm::acc::Clause::Y); \
15 }
16
17#define CHECK_REQ_SCALAR_INT_CONSTANT_CLAUSE(X, Y) \
18 void AccStructureChecker::Enter(const parser::AccClause::X &c) { \
19 CheckAllowed(llvm::acc::Clause::Y); \
20 RequiresConstantPositiveParameter(llvm::acc::Clause::Y, c.v); \
21 }
22
23namespace Fortran::semantics {
24
25static constexpr inline AccClauseSet
Valentin Clementd5532432020-12-08 19:36:2426 computeConstructOnlyAllowedAfterDeviceTypeClauses{
Valentin Clement9aa3dca2020-07-15 00:43:4027 llvm::acc::Clause::ACCC_async, llvm::acc::Clause::ACCC_wait,
28 llvm::acc::Clause::ACCC_num_gangs, llvm::acc::Clause::ACCC_num_workers,
29 llvm::acc::Clause::ACCC_vector_length};
30
Valentin Clement9aa3dca2020-07-15 00:43:4031static constexpr inline AccClauseSet loopOnlyAllowedAfterDeviceTypeClauses{
32 llvm::acc::Clause::ACCC_auto, llvm::acc::Clause::ACCC_collapse,
33 llvm::acc::Clause::ACCC_independent, llvm::acc::Clause::ACCC_gang,
34 llvm::acc::Clause::ACCC_seq, llvm::acc::Clause::ACCC_tile,
35 llvm::acc::Clause::ACCC_vector, llvm::acc::Clause::ACCC_worker};
36
37static constexpr inline AccClauseSet updateOnlyAllowedAfterDeviceTypeClauses{
38 llvm::acc::Clause::ACCC_async, llvm::acc::Clause::ACCC_wait};
39
40static constexpr inline AccClauseSet routineOnlyAllowedAfterDeviceTypeClauses{
41 llvm::acc::Clause::ACCC_bind, llvm::acc::Clause::ACCC_gang,
42 llvm::acc::Clause::ACCC_vector, llvm::acc::Clause::ACCC_worker};
43
Valentin Clement75ba29a2020-10-29 13:53:1044bool AccStructureChecker::CheckAllowedModifier(llvm::acc::Clause clause) {
45 if (GetContext().directive == llvm::acc::ACCD_enter_data ||
46 GetContext().directive == llvm::acc::ACCD_exit_data) {
47 context_.Say(GetContext().clauseSource,
48 "Modifier is not allowed for the %s clause "
49 "on the %s directive"_err_en_US,
50 parser::ToUpperCaseLetters(getClauseName(clause).str()),
51 ContextDirectiveAsFortran());
52 return true;
53 }
54 return false;
55}
56
Valentin Clementb53115b2020-12-08 20:14:2457bool AccStructureChecker::IsComputeConstruct(
58 llvm::acc::Directive directive) const {
59 return directive == llvm::acc::ACCD_parallel ||
60 directive == llvm::acc::ACCD_parallel_loop ||
61 directive == llvm::acc::ACCD_serial ||
62 directive == llvm::acc::ACCD_serial_loop ||
63 directive == llvm::acc::ACCD_kernels ||
64 directive == llvm::acc::ACCD_kernels_loop;
65}
66
67bool AccStructureChecker::IsInsideComputeConstruct() const {
Diana Picus45cd4052021-06-11 09:07:2368 if (dirContext_.size() <= 1) {
Valentin Clementb53115b2020-12-08 20:14:2469 return false;
Diana Picus45cd4052021-06-11 09:07:2370 }
Valentin Clementb53115b2020-12-08 20:14:2471
72 // Check all nested context skipping the first one.
73 for (std::size_t i = dirContext_.size() - 1; i > 0; --i) {
Diana Picus45cd4052021-06-11 09:07:2374 if (IsComputeConstruct(dirContext_[i - 1].directive)) {
Valentin Clementb53115b2020-12-08 20:14:2475 return true;
Diana Picus45cd4052021-06-11 09:07:2376 }
Valentin Clementb53115b2020-12-08 20:14:2477 }
78 return false;
79}
80
81void AccStructureChecker::CheckNotInComputeConstruct() {
Diana Picus45cd4052021-06-11 09:07:2382 if (IsInsideComputeConstruct()) {
Valentin Clementb53115b2020-12-08 20:14:2483 context_.Say(GetContext().directiveSource,
84 "Directive %s may not be called within a compute region"_err_en_US,
85 ContextDirectiveAsFortran());
Diana Picus45cd4052021-06-11 09:07:2386 }
Valentin Clementb53115b2020-12-08 20:14:2487}
88
Valentin Clement9aa3dca2020-07-15 00:43:4089void AccStructureChecker::Enter(const parser::AccClause &x) {
90 SetContextClause(x);
91}
92
93void AccStructureChecker::Leave(const parser::AccClauseList &) {}
94
95void AccStructureChecker::Enter(const parser::OpenACCBlockConstruct &x) {
96 const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)};
97 const auto &endBlockDir{std::get<parser::AccEndBlockDirective>(x.t)};
98 const auto &beginAccBlockDir{
99 std::get<parser::AccBlockDirective>(beginBlockDir.t)};
100
101 CheckMatching(beginAccBlockDir, endBlockDir.v);
102 PushContextAndClauseSets(beginAccBlockDir.source, beginAccBlockDir.v);
103}
104
105void AccStructureChecker::Leave(const parser::OpenACCBlockConstruct &x) {
106 const auto &beginBlockDir{std::get<parser::AccBeginBlockDirective>(x.t)};
107 const auto &blockDir{std::get<parser::AccBlockDirective>(beginBlockDir.t)};
108 const parser::Block &block{std::get<parser::Block>(x.t)};
109 switch (blockDir.v) {
110 case llvm::acc::Directive::ACCD_kernels:
111 case llvm::acc::Directive::ACCD_parallel:
Valentin Clementd5532432020-12-08 19:36:24112 case llvm::acc::Directive::ACCD_serial:
113 // Restriction - line 1004-1005
Valentin Clement9aa3dca2020-07-15 00:43:40114 CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
Valentin Clementd5532432020-12-08 19:36:24115 computeConstructOnlyAllowedAfterDeviceTypeClauses);
116 // Restriction - line 1001
Valentin Clement9aa3dca2020-07-15 00:43:40117 CheckNoBranching(block, GetContext().directive, blockDir.source);
118 break;
Valentin Clement9aa3dca2020-07-15 00:43:40119 case llvm::acc::Directive::ACCD_data:
Valentin Clementd5532432020-12-08 19:36:24120 // Restriction - line 1249-1250
Valentin Clement9aa3dca2020-07-15 00:43:40121 CheckRequireAtLeastOneOf();
122 break;
123 case llvm::acc::Directive::ACCD_host_data:
Valentin Clementd5532432020-12-08 19:36:24124 // Restriction - line 1746
Valentin Clement9aa3dca2020-07-15 00:43:40125 CheckRequireAtLeastOneOf();
126 break;
127 default:
128 break;
129 }
Valentin Clement40626182020-08-05 18:20:26130 dirContext_.pop_back();
Valentin Clement9aa3dca2020-07-15 00:43:40131}
132
Valentin Clement9aa3dca2020-07-15 00:43:40133void AccStructureChecker::Enter(
134 const parser::OpenACCStandaloneDeclarativeConstruct &x) {
135 const auto &declarativeDir{std::get<parser::AccDeclarativeDirective>(x.t)};
136 PushContextAndClauseSets(declarativeDir.source, declarativeDir.v);
137}
138
139void AccStructureChecker::Leave(
Valentin Clementb73736a2021-01-07 14:25:00140 const parser::OpenACCStandaloneDeclarativeConstruct &x) {
Valentin Clementd5532432020-12-08 19:36:24141 // Restriction - line 2409
Valentin Clement9aa3dca2020-07-15 00:43:40142 CheckAtLeastOneClause();
Valentin Clementb73736a2021-01-07 14:25:00143
144 // Restriction - line 2417-2418 - In a Fortran module declaration section,
145 // only create, copyin, device_resident, and link clauses are allowed.
146 const auto &declarativeDir{std::get<parser::AccDeclarativeDirective>(x.t)};
147 const auto &scope{context_.FindScope(declarativeDir.source)};
148 const Scope &containingScope{GetProgramUnitContaining(scope)};
149 if (containingScope.kind() == Scope::Kind::Module) {
150 for (auto cl : GetContext().actualClauses) {
151 if (cl != llvm::acc::Clause::ACCC_create &&
152 cl != llvm::acc::Clause::ACCC_copyin &&
153 cl != llvm::acc::Clause::ACCC_device_resident &&
Diana Picus45cd4052021-06-11 09:07:23154 cl != llvm::acc::Clause::ACCC_link) {
Valentin Clementb73736a2021-01-07 14:25:00155 context_.Say(GetContext().directiveSource,
156 "%s clause is not allowed on the %s directive in module "
157 "declaration "
158 "section"_err_en_US,
159 parser::ToUpperCaseLetters(
160 llvm::acc::getOpenACCClauseName(cl).str()),
161 ContextDirectiveAsFortran());
Diana Picus45cd4052021-06-11 09:07:23162 }
Valentin Clementb73736a2021-01-07 14:25:00163 }
164 }
Valentin Clement40626182020-08-05 18:20:26165 dirContext_.pop_back();
Valentin Clement9aa3dca2020-07-15 00:43:40166}
167
168void AccStructureChecker::Enter(const parser::OpenACCCombinedConstruct &x) {
Valentin Clement05169af2020-08-13 18:04:43169 const auto &beginCombinedDir{
170 std::get<parser::AccBeginCombinedDirective>(x.t)};
Valentin Clement9aa3dca2020-07-15 00:43:40171 const auto &combinedDir{
Valentin Clement05169af2020-08-13 18:04:43172 std::get<parser::AccCombinedDirective>(beginCombinedDir.t)};
173
174 // check matching, End directive is optional
175 if (const auto &endCombinedDir{
176 std::get<std::optional<parser::AccEndCombinedDirective>>(x.t)}) {
177 CheckMatching<parser::AccCombinedDirective>(combinedDir, endCombinedDir->v);
178 }
179
Valentin Clement9aa3dca2020-07-15 00:43:40180 PushContextAndClauseSets(combinedDir.source, combinedDir.v);
181}
182
183void AccStructureChecker::Leave(const parser::OpenACCCombinedConstruct &x) {
184 const auto &beginBlockDir{std::get<parser::AccBeginCombinedDirective>(x.t)};
185 const auto &combinedDir{
186 std::get<parser::AccCombinedDirective>(beginBlockDir.t)};
187 switch (combinedDir.v) {
188 case llvm::acc::Directive::ACCD_kernels_loop:
189 case llvm::acc::Directive::ACCD_parallel_loop:
Valentin Clement9aa3dca2020-07-15 00:43:40190 case llvm::acc::Directive::ACCD_serial_loop:
Valentin Clementd5532432020-12-08 19:36:24191 // Restriction - line 1004-1005
Valentin Clement9aa3dca2020-07-15 00:43:40192 CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
Valentin Clementd5532432020-12-08 19:36:24193 computeConstructOnlyAllowedAfterDeviceTypeClauses);
Valentin Clement9aa3dca2020-07-15 00:43:40194 break;
195 default:
196 break;
197 }
Valentin Clement40626182020-08-05 18:20:26198 dirContext_.pop_back();
Valentin Clement9aa3dca2020-07-15 00:43:40199}
200
201void AccStructureChecker::Enter(const parser::OpenACCLoopConstruct &x) {
202 const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)};
203 const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)};
204 PushContextAndClauseSets(loopDir.source, loopDir.v);
205}
206
207void AccStructureChecker::Leave(const parser::OpenACCLoopConstruct &x) {
208 const auto &beginDir{std::get<parser::AccBeginLoopDirective>(x.t)};
209 const auto &loopDir{std::get<parser::AccLoopDirective>(beginDir.t)};
210 if (loopDir.v == llvm::acc::Directive::ACCD_loop) {
Valentin Clementd5532432020-12-08 19:36:24211 // Restriction - line 1818-1819
Valentin Clement9aa3dca2020-07-15 00:43:40212 CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
213 loopOnlyAllowedAfterDeviceTypeClauses);
Valentin Clementd5532432020-12-08 19:36:24214 // Restriction - line 1834
Valentin Clement9aa3dca2020-07-15 00:43:40215 CheckNotAllowedIfClause(llvm::acc::Clause::ACCC_seq,
216 {llvm::acc::Clause::ACCC_gang, llvm::acc::Clause::ACCC_vector,
217 llvm::acc::Clause::ACCC_worker});
218 }
Valentin Clement40626182020-08-05 18:20:26219 dirContext_.pop_back();
Valentin Clement9aa3dca2020-07-15 00:43:40220}
221
222void AccStructureChecker::Enter(const parser::OpenACCStandaloneConstruct &x) {
223 const auto &standaloneDir{std::get<parser::AccStandaloneDirective>(x.t)};
224 PushContextAndClauseSets(standaloneDir.source, standaloneDir.v);
225}
226
227void AccStructureChecker::Leave(const parser::OpenACCStandaloneConstruct &x) {
228 const auto &standaloneDir{std::get<parser::AccStandaloneDirective>(x.t)};
229 switch (standaloneDir.v) {
230 case llvm::acc::Directive::ACCD_enter_data:
231 case llvm::acc::Directive::ACCD_exit_data:
Valentin Clementd5532432020-12-08 19:36:24232 // Restriction - line 1310-1311 (ENTER DATA)
233 // Restriction - line 1312-1313 (EXIT DATA)
Valentin Clement9aa3dca2020-07-15 00:43:40234 CheckRequireAtLeastOneOf();
235 break;
Valentin Clementb53115b2020-12-08 20:14:24236 case llvm::acc::Directive::ACCD_set:
237 // Restriction - line 2610
238 CheckRequireAtLeastOneOf();
239 // Restriction - line 2602
240 CheckNotInComputeConstruct();
241 break;
Valentin Clement9aa3dca2020-07-15 00:43:40242 case llvm::acc::Directive::ACCD_update:
Valentin Clement1dd24e62020-12-08 15:36:34243 // Restriction - line 2636
244 CheckRequireAtLeastOneOf();
Valentin Clementd5532432020-12-08 19:36:24245 // Restriction - line 2669
Valentin Clement9aa3dca2020-07-15 00:43:40246 CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
247 updateOnlyAllowedAfterDeviceTypeClauses);
248 break;
Valentin Clementb53115b2020-12-08 20:14:24249 case llvm::acc::Directive::ACCD_init:
250 case llvm::acc::Directive::ACCD_shutdown:
251 // Restriction - line 2525 (INIT)
252 // Restriction - line 2561 (SHUTDOWN)
253 CheckNotInComputeConstruct();
254 break;
Valentin Clement9aa3dca2020-07-15 00:43:40255 default:
256 break;
257 }
Valentin Clement40626182020-08-05 18:20:26258 dirContext_.pop_back();
Valentin Clement9aa3dca2020-07-15 00:43:40259}
260
261void AccStructureChecker::Enter(const parser::OpenACCRoutineConstruct &x) {
262 PushContextAndClauseSets(x.source, llvm::acc::Directive::ACCD_routine);
Valentin Clement71699a92020-12-17 16:32:52263 const auto &optName{std::get<std::optional<parser::Name>>(x.t)};
264 if (!optName) {
265 const auto &verbatim{std::get<parser::Verbatim>(x.t)};
266 const auto &scope{context_.FindScope(verbatim.source)};
267 const Scope &containingScope{GetProgramUnitContaining(scope)};
268 if (containingScope.kind() == Scope::Kind::Module) {
269 context_.Say(GetContext().directiveSource,
270 "ROUTINE directive without name must appear within the specification "
271 "part of a subroutine or function definition, or within an interface "
272 "body for a subroutine or function in an interface block"_err_en_US);
273 }
274 }
Valentin Clement9aa3dca2020-07-15 00:43:40275}
276void AccStructureChecker::Leave(const parser::OpenACCRoutineConstruct &) {
Valentin Clementd5532432020-12-08 19:36:24277 // Restriction - line 2790
Valentin Clement9aa3dca2020-07-15 00:43:40278 CheckRequireAtLeastOneOf();
Valentin Clementd5532432020-12-08 19:36:24279 // Restriction - line 2788-2789
Valentin Clement9aa3dca2020-07-15 00:43:40280 CheckOnlyAllowedAfter(llvm::acc::Clause::ACCC_device_type,
281 routineOnlyAllowedAfterDeviceTypeClauses);
Valentin Clement40626182020-08-05 18:20:26282 dirContext_.pop_back();
Valentin Clement9aa3dca2020-07-15 00:43:40283}
284
Valentin Clement676ff752020-10-23 14:31:33285void AccStructureChecker::Enter(const parser::OpenACCWaitConstruct &x) {
286 const auto &verbatim{std::get<parser::Verbatim>(x.t)};
287 PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_wait);
288}
289void AccStructureChecker::Leave(const parser::OpenACCWaitConstruct &x) {
290 dirContext_.pop_back();
291}
292
293void AccStructureChecker::Enter(const parser::OpenACCAtomicConstruct &x) {
294 PushContextAndClauseSets(x.source, llvm::acc::Directive::ACCD_atomic);
295}
296void AccStructureChecker::Leave(const parser::OpenACCAtomicConstruct &x) {
297 dirContext_.pop_back();
298}
299
Valentin Clemente73d8c72020-11-25 15:28:02300void AccStructureChecker::Enter(const parser::OpenACCCacheConstruct &x) {
301 const auto &verbatim = std::get<parser::Verbatim>(x.t);
302 PushContextAndClauseSets(verbatim.source, llvm::acc::Directive::ACCD_cache);
303 SetContextDirectiveSource(verbatim.source);
304}
305void AccStructureChecker::Leave(const parser::OpenACCCacheConstruct &x) {
306 dirContext_.pop_back();
307}
308
Valentin Clement9aa3dca2020-07-15 00:43:40309// Clause checkers
310CHECK_REQ_SCALAR_INT_CONSTANT_CLAUSE(Collapse, ACCC_collapse)
311
312CHECK_SIMPLE_CLAUSE(Auto, ACCC_auto)
313CHECK_SIMPLE_CLAUSE(Async, ACCC_async)
314CHECK_SIMPLE_CLAUSE(Attach, ACCC_attach)
315CHECK_SIMPLE_CLAUSE(Bind, ACCC_bind)
316CHECK_SIMPLE_CLAUSE(Capture, ACCC_capture)
317CHECK_SIMPLE_CLAUSE(Copy, ACCC_copy)
318CHECK_SIMPLE_CLAUSE(Default, ACCC_default)
319CHECK_SIMPLE_CLAUSE(DefaultAsync, ACCC_default_async)
320CHECK_SIMPLE_CLAUSE(Delete, ACCC_delete)
321CHECK_SIMPLE_CLAUSE(Detach, ACCC_detach)
322CHECK_SIMPLE_CLAUSE(Device, ACCC_device)
323CHECK_SIMPLE_CLAUSE(DeviceNum, ACCC_device_num)
Valentin Clement16c1d252020-08-11 14:43:56324CHECK_SIMPLE_CLAUSE(Deviceptr, ACCC_deviceptr)
Valentin Clement9aa3dca2020-07-15 00:43:40325CHECK_SIMPLE_CLAUSE(DeviceResident, ACCC_device_resident)
326CHECK_SIMPLE_CLAUSE(DeviceType, ACCC_device_type)
327CHECK_SIMPLE_CLAUSE(Finalize, ACCC_finalize)
Valentin Clement16c1d252020-08-11 14:43:56328CHECK_SIMPLE_CLAUSE(Firstprivate, ACCC_firstprivate)
Valentin Clement9aa3dca2020-07-15 00:43:40329CHECK_SIMPLE_CLAUSE(Gang, ACCC_gang)
330CHECK_SIMPLE_CLAUSE(Host, ACCC_host)
331CHECK_SIMPLE_CLAUSE(If, ACCC_if)
332CHECK_SIMPLE_CLAUSE(IfPresent, ACCC_if_present)
333CHECK_SIMPLE_CLAUSE(Independent, ACCC_independent)
334CHECK_SIMPLE_CLAUSE(Link, ACCC_link)
335CHECK_SIMPLE_CLAUSE(NoCreate, ACCC_no_create)
Valentin Clement16c1d252020-08-11 14:43:56336CHECK_SIMPLE_CLAUSE(Nohost, ACCC_nohost)
Valentin Clement9aa3dca2020-07-15 00:43:40337CHECK_SIMPLE_CLAUSE(NumGangs, ACCC_num_gangs)
338CHECK_SIMPLE_CLAUSE(NumWorkers, ACCC_num_workers)
339CHECK_SIMPLE_CLAUSE(Present, ACCC_present)
340CHECK_SIMPLE_CLAUSE(Private, ACCC_private)
341CHECK_SIMPLE_CLAUSE(Read, ACCC_read)
342CHECK_SIMPLE_CLAUSE(Reduction, ACCC_reduction)
Valentin Clement9aa3dca2020-07-15 00:43:40343CHECK_SIMPLE_CLAUSE(Seq, ACCC_seq)
344CHECK_SIMPLE_CLAUSE(Tile, ACCC_tile)
345CHECK_SIMPLE_CLAUSE(UseDevice, ACCC_use_device)
346CHECK_SIMPLE_CLAUSE(Vector, ACCC_vector)
347CHECK_SIMPLE_CLAUSE(VectorLength, ACCC_vector_length)
348CHECK_SIMPLE_CLAUSE(Wait, ACCC_wait)
349CHECK_SIMPLE_CLAUSE(Worker, ACCC_worker)
350CHECK_SIMPLE_CLAUSE(Write, ACCC_write)
Valentin Clement3f46c202021-02-01 18:33:07351CHECK_SIMPLE_CLAUSE(Unknown, ACCC_unknown)
Valentin Clement9aa3dca2020-07-15 00:43:40352
353void AccStructureChecker::Enter(const parser::AccClause::Create &c) {
354 CheckAllowed(llvm::acc::Clause::ACCC_create);
355 const auto &modifierClause{c.v};
356 if (const auto &modifier{
357 std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) {
358 if (modifier->v != parser::AccDataModifier::Modifier::Zero) {
359 context_.Say(GetContext().clauseSource,
360 "Only the ZERO modifier is allowed for the %s clause "
361 "on the %s directive"_err_en_US,
362 parser::ToUpperCaseLetters(
363 llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_create)
364 .str()),
365 ContextDirectiveAsFortran());
366 }
367 }
368}
369
370void AccStructureChecker::Enter(const parser::AccClause::Copyin &c) {
371 CheckAllowed(llvm::acc::Clause::ACCC_copyin);
372 const auto &modifierClause{c.v};
373 if (const auto &modifier{
374 std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) {
Diana Picus45cd4052021-06-11 09:07:23375 if (CheckAllowedModifier(llvm::acc::Clause::ACCC_copyin)) {
Valentin Clement75ba29a2020-10-29 13:53:10376 return;
Diana Picus45cd4052021-06-11 09:07:23377 }
Valentin Clement9aa3dca2020-07-15 00:43:40378 if (modifier->v != parser::AccDataModifier::Modifier::ReadOnly) {
379 context_.Say(GetContext().clauseSource,
380 "Only the READONLY modifier is allowed for the %s clause "
381 "on the %s directive"_err_en_US,
382 parser::ToUpperCaseLetters(
383 llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_copyin)
384 .str()),
385 ContextDirectiveAsFortran());
386 }
387 }
388}
389
390void AccStructureChecker::Enter(const parser::AccClause::Copyout &c) {
391 CheckAllowed(llvm::acc::Clause::ACCC_copyout);
392 const auto &modifierClause{c.v};
393 if (const auto &modifier{
394 std::get<std::optional<parser::AccDataModifier>>(modifierClause.t)}) {
Diana Picus45cd4052021-06-11 09:07:23395 if (CheckAllowedModifier(llvm::acc::Clause::ACCC_copyout)) {
Valentin Clement75ba29a2020-10-29 13:53:10396 return;
Diana Picus45cd4052021-06-11 09:07:23397 }
Valentin Clement9aa3dca2020-07-15 00:43:40398 if (modifier->v != parser::AccDataModifier::Modifier::Zero) {
399 context_.Say(GetContext().clauseSource,
400 "Only the ZERO modifier is allowed for the %s clause "
401 "on the %s directive"_err_en_US,
402 parser::ToUpperCaseLetters(
403 llvm::acc::getOpenACCClauseName(llvm::acc::Clause::ACCC_copyout)
404 .str()),
405 ContextDirectiveAsFortran());
406 }
407 }
408}
409
Valentin Clement1dd24e62020-12-08 15:36:34410void AccStructureChecker::Enter(const parser::AccClause::Self &x) {
411 CheckAllowed(llvm::acc::Clause::ACCC_self);
412 const parser::AccSelfClause &accSelfClause = x.v;
413 if (GetContext().directive == llvm::acc::Directive::ACCD_update &&
414 std::holds_alternative<std::optional<parser::ScalarLogicalExpr>>(
415 accSelfClause.u)) {
416 context_.Say(GetContext().clauseSource,
417 "SELF clause on the %s directive must have a var-list"_err_en_US,
418 ContextDirectiveAsFortran());
419 } else if (GetContext().directive != llvm::acc::Directive::ACCD_update &&
420 std::holds_alternative<parser::AccObjectList>(accSelfClause.u)) {
421 const auto &accObjectList =
422 std::get<parser::AccObjectList>(accSelfClause.u);
423 if (accObjectList.v.size() != 1) {
424 context_.Say(GetContext().clauseSource,
425 "SELF clause on the %s directive only accepts optional scalar logical"
426 " expression"_err_en_US,
427 ContextDirectiveAsFortran());
428 }
429 }
430}
431
Valentin Clement40626182020-08-05 18:20:26432llvm::StringRef AccStructureChecker::getClauseName(llvm::acc::Clause clause) {
433 return llvm::acc::getOpenACCClauseName(clause);
Valentin Clement9aa3dca2020-07-15 00:43:40434}
435
Valentin Clement40626182020-08-05 18:20:26436llvm::StringRef AccStructureChecker::getDirectiveName(
437 llvm::acc::Directive directive) {
438 return llvm::acc::getOpenACCDirectiveName(directive);
Valentin Clement9aa3dca2020-07-15 00:43:40439}
440
441} // namespace Fortran::semantics