1//===--- SemaOpenACC.cpp - Semantic Analysis for OpenACC constructs -------===//
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//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenACC constructs, and things
10/// that are not clause specific.
11///
12//===----------------------------------------------------------------------===//
13
14#include "clang/Sema/SemaOpenACC.h"
15#include "clang/AST/DeclOpenACC.h"
16#include "clang/AST/StmtOpenACC.h"
17#include "clang/Basic/DiagnosticSema.h"
18#include "clang/Basic/OpenACCKinds.h"
19#include "clang/Basic/SourceManager.h"
20#include "clang/Sema/Scope.h"
21#include "clang/Sema/Sema.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/Casting.h"
24
25using namespace clang;
26
27namespace {
28bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,
29 SourceLocation StartLoc, bool IsStmt) {
30 switch (K) {
31 default:
32 case OpenACCDirectiveKind::Invalid:
33 // Nothing to do here, both invalid and unimplemented don't really need to
34 // do anything.
35 break;
36 case OpenACCDirectiveKind::Parallel:
37 case OpenACCDirectiveKind::ParallelLoop:
38 case OpenACCDirectiveKind::Serial:
39 case OpenACCDirectiveKind::SerialLoop:
40 case OpenACCDirectiveKind::Kernels:
41 case OpenACCDirectiveKind::KernelsLoop:
42 case OpenACCDirectiveKind::Loop:
43 case OpenACCDirectiveKind::Data:
44 case OpenACCDirectiveKind::EnterData:
45 case OpenACCDirectiveKind::ExitData:
46 case OpenACCDirectiveKind::HostData:
47 case OpenACCDirectiveKind::Wait:
48 case OpenACCDirectiveKind::Update:
49 case OpenACCDirectiveKind::Init:
50 case OpenACCDirectiveKind::Shutdown:
51 case OpenACCDirectiveKind::Cache:
52 case OpenACCDirectiveKind::Atomic:
53 if (!IsStmt)
54 return S.Diag(Loc: StartLoc, DiagID: diag::err_acc_construct_appertainment) << K;
55 break;
56 }
57 return false;
58}
59
60void CollectActiveReductionClauses(
61 llvm::SmallVector<OpenACCReductionClause *> &ActiveClauses,
62 ArrayRef<OpenACCClause *> CurClauses) {
63 for (auto *CurClause : CurClauses) {
64 if (auto *RedClause = dyn_cast<OpenACCReductionClause>(Val: CurClause);
65 RedClause && !RedClause->getVarList().empty())
66 ActiveClauses.push_back(Elt: RedClause);
67 }
68}
69
70// Depth needs to be preserved for all associated statements that aren't
71// supposed to modify the compute/combined/loop construct information.
72bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
73 switch (DK) {
74 case OpenACCDirectiveKind::Parallel:
75 case OpenACCDirectiveKind::ParallelLoop:
76 case OpenACCDirectiveKind::Serial:
77 case OpenACCDirectiveKind::SerialLoop:
78 case OpenACCDirectiveKind::Kernels:
79 case OpenACCDirectiveKind::KernelsLoop:
80 case OpenACCDirectiveKind::Loop:
81 return false;
82 case OpenACCDirectiveKind::Data:
83 case OpenACCDirectiveKind::HostData:
84 case OpenACCDirectiveKind::Atomic:
85 return true;
86 case OpenACCDirectiveKind::Cache:
87 case OpenACCDirectiveKind::Routine:
88 case OpenACCDirectiveKind::Declare:
89 case OpenACCDirectiveKind::EnterData:
90 case OpenACCDirectiveKind::ExitData:
91 case OpenACCDirectiveKind::Wait:
92 case OpenACCDirectiveKind::Init:
93 case OpenACCDirectiveKind::Shutdown:
94 case OpenACCDirectiveKind::Set:
95 case OpenACCDirectiveKind::Update:
96 llvm_unreachable("Doesn't have an associated stmt");
97 case OpenACCDirectiveKind::Invalid:
98 llvm_unreachable("Unhandled directive kind?");
99 }
100 llvm_unreachable("Unhandled directive kind?");
101}
102
103} // namespace
104
105SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
106
107SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
108 SemaOpenACC &S, OpenACCDirectiveKind DK, SourceLocation DirLoc,
109 ArrayRef<const OpenACCClause *> UnInstClauses,
110 ArrayRef<OpenACCClause *> Clauses)
111 : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
112 DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel),
113 OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
114 OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
115 OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo),
116 ActiveReductionClauses(S.ActiveReductionClauses),
117 LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DK: DirKind)) {
118
119 // Compute constructs end up taking their 'loop'.
120 if (DirKind == OpenACCDirectiveKind::Parallel ||
121 DirKind == OpenACCDirectiveKind::Serial ||
122 DirKind == OpenACCDirectiveKind::Kernels) {
123 CollectActiveReductionClauses(ActiveClauses&: S.ActiveReductionClauses, CurClauses: Clauses);
124 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
125 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
126
127 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
128 // construct, the gang clause behaves as follows. ... The region of a loop
129 // with a gang clause may not contain another loop with a gang clause unless
130 // within a nested compute region.
131 //
132 // Implement the 'unless within a nested compute region' part.
133 SemaRef.LoopGangClauseOnKernel = {};
134 SemaRef.LoopWorkerClauseLoc = {};
135 SemaRef.LoopVectorClauseLoc = {};
136 SemaRef.LoopWithoutSeqInfo = {};
137 } else if (DirKind == OpenACCDirectiveKind::ParallelLoop ||
138 DirKind == OpenACCDirectiveKind::SerialLoop ||
139 DirKind == OpenACCDirectiveKind::KernelsLoop) {
140 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
141 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
142
143 CollectActiveReductionClauses(ActiveClauses&: S.ActiveReductionClauses, CurClauses: Clauses);
144 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
145 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
146
147 SemaRef.LoopGangClauseOnKernel = {};
148 SemaRef.LoopWorkerClauseLoc = {};
149 SemaRef.LoopVectorClauseLoc = {};
150
151 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
152 // diagnose the for loops.
153 SemaRef.LoopWithoutSeqInfo = {};
154 if (Clauses.end() ==
155 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCSeqClause>))
156 SemaRef.LoopWithoutSeqInfo = {.Kind: DirKind, .Loc: DirLoc};
157
158 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
159 // construct, the gang clause behaves as follows. ... The region of a loop
160 // with a gang clause may not contain another loop with a gang clause unless
161 // within a nested compute region.
162 //
163 // We don't bother doing this when this is a template instantiation, as
164 // there is no reason to do these checks: the existance of a
165 // gang/kernels/etc cannot be dependent.
166 if (DirKind == OpenACCDirectiveKind::KernelsLoop && UnInstClauses.empty()) {
167 // This handles the 'outer loop' part of this.
168 auto *Itr = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCGangClause>);
169 if (Itr != Clauses.end())
170 SemaRef.LoopGangClauseOnKernel = {.Loc: (*Itr)->getBeginLoc(), .DirKind: DirKind};
171 }
172
173 if (UnInstClauses.empty()) {
174 auto *Itr = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCWorkerClause>);
175 if (Itr != Clauses.end())
176 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
177
178 auto *Itr2 = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCVectorClause>);
179 if (Itr2 != Clauses.end())
180 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
181 }
182 } else if (DirKind == OpenACCDirectiveKind::Loop) {
183 CollectActiveReductionClauses(ActiveClauses&: S.ActiveReductionClauses, CurClauses: Clauses);
184 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
185 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
186
187 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
188 // diagnose the for loops.
189 SemaRef.LoopWithoutSeqInfo = {};
190 if (Clauses.end() ==
191 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCSeqClause>))
192 SemaRef.LoopWithoutSeqInfo = {.Kind: DirKind, .Loc: DirLoc};
193
194 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
195 // construct, the gang clause behaves as follows. ... The region of a loop
196 // with a gang clause may not contain another loop with a gang clause unless
197 // within a nested compute region.
198 //
199 // We don't bother doing this when this is a template instantiation, as
200 // there is no reason to do these checks: the existance of a
201 // gang/kernels/etc cannot be dependent.
202 if (SemaRef.getActiveComputeConstructInfo().Kind ==
203 OpenACCDirectiveKind::Kernels &&
204 UnInstClauses.empty()) {
205 // This handles the 'outer loop' part of this.
206 auto *Itr = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCGangClause>);
207 if (Itr != Clauses.end())
208 SemaRef.LoopGangClauseOnKernel = {.Loc: (*Itr)->getBeginLoc(),
209 .DirKind: OpenACCDirectiveKind::Kernels};
210 }
211
212 if (UnInstClauses.empty()) {
213 auto *Itr = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCWorkerClause>);
214 if (Itr != Clauses.end())
215 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
216
217 auto *Itr2 = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCVectorClause>);
218 if (Itr2 != Clauses.end())
219 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
220 }
221 }
222}
223
224namespace {
225// Given two collapse clauses, and the uninstanted version of the new one,
226// return the 'best' one for the purposes of setting the collapse checking
227// values.
228const OpenACCCollapseClause *
229getBestCollapseCandidate(const OpenACCCollapseClause *Old,
230 const OpenACCCollapseClause *New,
231 const OpenACCCollapseClause *UnInstNew) {
232 // If the loop count is nullptr, it is because instantiation failed, so this
233 // can't be the best one.
234 if (!New->getLoopCount())
235 return Old;
236
237 // If the loop-count had an error, than 'new' isn't a candidate.
238 if (!New->getLoopCount())
239 return Old;
240
241 // Don't consider uninstantiated ones, since we can't really check these.
242 if (New->getLoopCount()->isInstantiationDependent())
243 return Old;
244
245 // If this is an instantiation, and the old version wasn't instantation
246 // dependent, than nothing has changed and we've already done a diagnostic
247 // based on this one, so don't consider it.
248 if (UnInstNew && !UnInstNew->getLoopCount()->isInstantiationDependent())
249 return Old;
250
251 // New is now a valid candidate, so if there isn't an old one at this point,
252 // New is the only valid one.
253 if (!Old)
254 return New;
255
256 // If the 'New' expression has a larger value than 'Old', then it is the new
257 // best candidate.
258 if (cast<ConstantExpr>(Val: Old->getLoopCount())->getResultAsAPSInt() <
259 cast<ConstantExpr>(Val: New->getLoopCount())->getResultAsAPSInt())
260 return New;
261
262 return Old;
263}
264} // namespace
265
266void SemaOpenACC::AssociatedStmtRAII::SetCollapseInfoBeforeAssociatedStmt(
267 ArrayRef<const OpenACCClause *> UnInstClauses,
268 ArrayRef<OpenACCClause *> Clauses) {
269
270 // Reset this checking for loops that aren't covered in a RAII object.
271 SemaRef.LoopInfo.CurLevelHasLoopAlready = false;
272 SemaRef.CollapseInfo.CollapseDepthSatisfied = true;
273 SemaRef.CollapseInfo.CurCollapseCount = 0;
274 SemaRef.TileInfo.TileDepthSatisfied = true;
275
276 // We make sure to take an optional list of uninstantiated clauses, so that
277 // we can check to make sure we don't 'double diagnose' in the event that
278 // the value of 'N' was not dependent in a template. Since we cannot count on
279 // there only being a single collapse clause, we count on the order to make
280 // sure get the matching ones, and we count on TreeTransform not removing
281 // these, even if loop-count instantiation failed. We can check the
282 // non-dependent ones right away, and realize that subsequent instantiation
283 // can only make it more specific.
284
285 auto *UnInstClauseItr =
286 llvm::find_if(Range&: UnInstClauses, P: llvm::IsaPred<OpenACCCollapseClause>);
287 auto *ClauseItr =
288 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCCollapseClause>);
289 const OpenACCCollapseClause *FoundClause = nullptr;
290
291 // Loop through the list of Collapse clauses and find the one that:
292 // 1- Has a non-dependent, non-null loop count (null means error, likely
293 // during instantiation).
294 // 2- If UnInstClauses isn't empty, its corresponding
295 // loop count was dependent.
296 // 3- Has the largest 'loop count' of all.
297 while (ClauseItr != Clauses.end()) {
298 const OpenACCCollapseClause *CurClause =
299 cast<OpenACCCollapseClause>(Val: *ClauseItr);
300 const OpenACCCollapseClause *UnInstCurClause =
301 UnInstClauseItr == UnInstClauses.end()
302 ? nullptr
303 : cast<OpenACCCollapseClause>(Val: *UnInstClauseItr);
304
305 FoundClause =
306 getBestCollapseCandidate(Old: FoundClause, New: CurClause, UnInstNew: UnInstCurClause);
307
308 UnInstClauseItr =
309 UnInstClauseItr == UnInstClauses.end()
310 ? UnInstClauseItr
311 : std::find_if(first: std::next(x: UnInstClauseItr), last: UnInstClauses.end(),
312 pred: llvm::IsaPred<OpenACCCollapseClause>);
313 ClauseItr = std::find_if(first: std::next(x: ClauseItr), last: Clauses.end(),
314 pred: llvm::IsaPred<OpenACCCollapseClause>);
315 }
316
317 if (!FoundClause)
318 return;
319
320 SemaRef.CollapseInfo.ActiveCollapse = FoundClause;
321 SemaRef.CollapseInfo.CollapseDepthSatisfied = false;
322 SemaRef.CollapseInfo.CurCollapseCount =
323 cast<ConstantExpr>(Val: FoundClause->getLoopCount())->getResultAsAPSInt();
324 SemaRef.CollapseInfo.DirectiveKind = DirKind;
325}
326
327void SemaOpenACC::AssociatedStmtRAII::SetTileInfoBeforeAssociatedStmt(
328 ArrayRef<const OpenACCClause *> UnInstClauses,
329 ArrayRef<OpenACCClause *> Clauses) {
330 // We don't diagnose if this is during instantiation, since the only thing we
331 // care about is the number of arguments, which we can figure out without
332 // instantiation, so we don't want to double-diagnose.
333 if (UnInstClauses.size() > 0)
334 return;
335 auto *TileClauseItr =
336 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCTileClause>);
337
338 if (Clauses.end() == TileClauseItr)
339 return;
340
341 OpenACCTileClause *TileClause = cast<OpenACCTileClause>(Val: *TileClauseItr);
342
343 // Multiple tile clauses are allowed, so ensure that we use the one with the
344 // largest 'tile count'.
345 while (Clauses.end() !=
346 (TileClauseItr = std::find_if(first: std::next(x: TileClauseItr), last: Clauses.end(),
347 pred: llvm::IsaPred<OpenACCTileClause>))) {
348 OpenACCTileClause *NewClause = cast<OpenACCTileClause>(Val: *TileClauseItr);
349 if (NewClause->getSizeExprs().size() > TileClause->getSizeExprs().size())
350 TileClause = NewClause;
351 }
352
353 SemaRef.TileInfo.ActiveTile = TileClause;
354 SemaRef.TileInfo.TileDepthSatisfied = false;
355 SemaRef.TileInfo.CurTileCount =
356 static_cast<unsigned>(TileClause->getSizeExprs().size());
357 SemaRef.TileInfo.DirectiveKind = DirKind;
358}
359
360SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
361 if (DirKind == OpenACCDirectiveKind::Parallel ||
362 DirKind == OpenACCDirectiveKind::Serial ||
363 DirKind == OpenACCDirectiveKind::Kernels ||
364 DirKind == OpenACCDirectiveKind::Loop ||
365 DirKind == OpenACCDirectiveKind::ParallelLoop ||
366 DirKind == OpenACCDirectiveKind::SerialLoop ||
367 DirKind == OpenACCDirectiveKind::KernelsLoop) {
368 SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
369 SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;
370 SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
371 SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
372 SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;
373 SemaRef.ActiveReductionClauses.swap(RHS&: ActiveReductionClauses);
374 } else if (DirKind == OpenACCDirectiveKind::Data ||
375 DirKind == OpenACCDirectiveKind::HostData) {
376 // Intentionally doesn't reset the Loop, Compute Construct, or reduction
377 // effects.
378 }
379}
380
381void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
382 SourceLocation DirLoc) {
383 // Start an evaluation context to parse the clause arguments on.
384 SemaRef.PushExpressionEvaluationContext(
385 NewContext: Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
386
387 // There is nothing do do here as all we have at this point is the name of the
388 // construct itself.
389}
390
391ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind DK,
392 OpenACCClauseKind CK, SourceLocation Loc,
393 Expr *IntExpr) {
394
395 assert(((DK != OpenACCDirectiveKind::Invalid &&
396 CK == OpenACCClauseKind::Invalid) ||
397 (DK == OpenACCDirectiveKind::Invalid &&
398 CK != OpenACCClauseKind::Invalid) ||
399 (DK == OpenACCDirectiveKind::Invalid &&
400 CK == OpenACCClauseKind::Invalid)) &&
401 "Only one of directive or clause kind should be provided");
402
403 class IntExprConverter : public Sema::ICEConvertDiagnoser {
404 OpenACCDirectiveKind DirectiveKind;
405 OpenACCClauseKind ClauseKind;
406 Expr *IntExpr;
407
408 // gets the index into the diagnostics so we can use this for clauses,
409 // directives, and sub array.s
410 unsigned getDiagKind() const {
411 if (ClauseKind != OpenACCClauseKind::Invalid)
412 return 0;
413 if (DirectiveKind != OpenACCDirectiveKind::Invalid)
414 return 1;
415 return 2;
416 }
417
418 public:
419 IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
420 Expr *IntExpr)
421 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false,
422 /*Suppress=*/false,
423 /*SuppressConversion=*/true),
424 DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
425
426 bool match(QualType T) override {
427 // OpenACC spec just calls this 'integer expression' as having an
428 // 'integer type', so fall back on C99's 'integer type'.
429 return T->isIntegerType();
430 }
431 SemaBase::SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
432 QualType T) override {
433 return S.Diag(Loc, DiagID: diag::err_acc_int_expr_requires_integer)
434 << getDiagKind() << ClauseKind << DirectiveKind << T;
435 }
436
437 SemaBase::SemaDiagnosticBuilder
438 diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override {
439 return S.Diag(Loc, DiagID: diag::err_acc_int_expr_incomplete_class_type)
440 << T << IntExpr->getSourceRange();
441 }
442
443 SemaBase::SemaDiagnosticBuilder
444 diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T,
445 QualType ConvTy) override {
446 return S.Diag(Loc, DiagID: diag::err_acc_int_expr_explicit_conversion)
447 << T << ConvTy;
448 }
449
450 SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
451 CXXConversionDecl *Conv,
452 QualType ConvTy) override {
453 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_acc_int_expr_conversion)
454 << ConvTy->isEnumeralType() << ConvTy;
455 }
456
457 SemaBase::SemaDiagnosticBuilder
458 diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override {
459 return S.Diag(Loc, DiagID: diag::err_acc_int_expr_multiple_conversions) << T;
460 }
461
462 SemaBase::SemaDiagnosticBuilder
463 noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
464 return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_acc_int_expr_conversion)
465 << ConvTy->isEnumeralType() << ConvTy;
466 }
467
468 SemaBase::SemaDiagnosticBuilder
469 diagnoseConversion(Sema &S, SourceLocation Loc, QualType T,
470 QualType ConvTy) override {
471 llvm_unreachable("conversion functions are permitted");
472 }
473 } IntExprDiagnoser(DK, CK, IntExpr);
474
475 if (!IntExpr)
476 return ExprError();
477
478 ExprResult IntExprResult = SemaRef.PerformContextualImplicitConversion(
479 Loc, FromE: IntExpr, Converter&: IntExprDiagnoser);
480 if (IntExprResult.isInvalid())
481 return ExprError();
482
483 IntExpr = IntExprResult.get();
484 if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType())
485 return ExprError();
486
487 // TODO OpenACC: Do we want to perform usual unary conversions here? When
488 // doing codegen we might find that is necessary, but skip it for now.
489 return IntExpr;
490}
491
492bool SemaOpenACC::CheckVarIsPointerType(OpenACCClauseKind ClauseKind,
493 Expr *VarExpr) {
494 // We already know that VarExpr is a proper reference to a variable, so we
495 // should be able to just take the type of the expression to get the type of
496 // the referenced variable.
497
498 // We've already seen an error, don't diagnose anything else.
499 if (!VarExpr || VarExpr->containsErrors())
500 return false;
501
502 if (isa<ArraySectionExpr>(Val: VarExpr->IgnoreParenImpCasts()) ||
503 VarExpr->hasPlaceholderType(K: BuiltinType::ArraySection)) {
504 Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_array_section_use) << /*OpenACC=*/0;
505 Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::note_acc_expected_pointer_var);
506 return true;
507 }
508
509 QualType Ty = VarExpr->getType();
510 Ty = Ty.getNonReferenceType().getUnqualifiedType();
511
512 // Nothing we can do if this is a dependent type.
513 if (Ty->isDependentType())
514 return false;
515
516 if (!Ty->isPointerType())
517 return Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_var_not_pointer_type)
518 << ClauseKind << Ty;
519 return false;
520}
521
522void SemaOpenACC::ActOnStartParseVar(OpenACCDirectiveKind DK,
523 OpenACCClauseKind CK) {
524 if (DK == OpenACCDirectiveKind::Cache) {
525 CacheInfo.ParsingCacheVarList = true;
526 CacheInfo.IsInvalidCacheRef = false;
527 }
528}
529
530void SemaOpenACC::ActOnInvalidParseVar() {
531 CacheInfo.ParsingCacheVarList = false;
532 CacheInfo.IsInvalidCacheRef = false;
533}
534
535ExprResult SemaOpenACC::ActOnCacheVar(Expr *VarExpr) {
536 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
537 // Clear this here, so we can do the returns based on the invalid cache ref
538 // here. Note all return statements in this function must return ExprError if
539 // IsInvalidCacheRef. However, instead of doing an 'early return' in that
540 // case, we can let the rest of the diagnostics happen, as the invalid decl
541 // ref is a warning.
542 bool WasParsingInvalidCacheRef =
543 CacheInfo.ParsingCacheVarList && CacheInfo.IsInvalidCacheRef;
544 CacheInfo.ParsingCacheVarList = false;
545 CacheInfo.IsInvalidCacheRef = false;
546
547 if (!isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) {
548 Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_not_a_var_ref_cache);
549 return ExprError();
550 }
551
552 // It isn't clear what 'simple array element or simple subarray' means, so we
553 // will just allow arbitrary depth.
554 while (isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) {
555 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(Val: CurVarExpr))
556 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
557 else
558 CurVarExpr =
559 cast<ArraySectionExpr>(Val: CurVarExpr)->getBase()->IgnoreParenImpCasts();
560 }
561
562 // References to a VarDecl are fine.
563 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: CurVarExpr)) {
564 if (isa<VarDecl, NonTypeTemplateParmDecl>(
565 Val: DRE->getFoundDecl()->getCanonicalDecl()))
566 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
567 }
568
569 if (const auto *ME = dyn_cast<MemberExpr>(Val: CurVarExpr)) {
570 if (isa<FieldDecl>(Val: ME->getMemberDecl()->getCanonicalDecl())) {
571 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
572 }
573 }
574
575 // Nothing really we can do here, as these are dependent. So just return they
576 // are valid.
577 if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(Val: CurVarExpr))
578 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
579
580 // There isn't really anything we can do in the case of a recovery expr, so
581 // skip the diagnostic rather than produce a confusing diagnostic.
582 if (isa<RecoveryExpr>(Val: CurVarExpr))
583 return ExprError();
584
585 Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_not_a_var_ref_cache);
586 return ExprError();
587}
588
589void SemaOpenACC::CheckDeclReference(SourceLocation Loc, Expr *E, Decl *D) {
590 if (!getLangOpts().OpenACC || !CacheInfo.ParsingCacheVarList || !D ||
591 D->isInvalidDecl())
592 return;
593 // A 'cache' variable reference MUST be declared before the 'acc.loop' we
594 // generate in codegen, so we have to mark it invalid here in some way. We do
595 // so in a bit of a convoluted way as there is no good way to put this into
596 // the AST, so we store it in SemaOpenACC State. We can check the Scope
597 // during parsing to make sure there is a 'loop' before the decl is
598 // declared(and skip during instantiation).
599 // We only diagnose this as a warning, as this isn't required by the standard
600 // (unless you take a VERY awkward reading of some awkward prose).
601
602 Scope *CurScope = SemaRef.getCurScope();
603
604 // if we are at TU level, we are either doing some EXTRA wacky, or are in a
605 // template instantiation, so just give up.
606 if (CurScope->getDepth() == 0)
607 return;
608
609 while (CurScope) {
610 // If we run into a loop construct scope, than this is 'correct' in that the
611 // declaration is outside of the loop.
612 if (CurScope->isOpenACCLoopConstructScope())
613 return;
614
615 if (CurScope->isDeclScope(D)) {
616 Diag(Loc, DiagID: diag::warn_acc_cache_var_not_outside_loop);
617
618 CacheInfo.IsInvalidCacheRef = true;
619 }
620
621 CurScope = CurScope->getParent();
622 }
623 // If we don't find the decl at all, we assume that it must be outside of the
624 // loop (or we aren't in a loop!) so skip the diagnostic.
625}
626
627ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
628 Expr *VarExpr) {
629 // This has unique enough restrictions that we should split it to a separate
630 // function.
631 if (DK == OpenACCDirectiveKind::Cache)
632 return ActOnCacheVar(VarExpr);
633
634 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
635
636 // 'use_device' doesn't allow array subscript or array sections.
637 // OpenACC3.3 2.8:
638 // A 'var' in a 'use_device' clause must be the name of a variable or array.
639 // OpenACC3.3 2.13:
640 // A 'var' in a 'declare' directive must be a variable or array name.
641 if ((CK == OpenACCClauseKind::UseDevice ||
642 DK == OpenACCDirectiveKind::Declare) &&
643 isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) {
644 Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_not_a_var_ref_use_device_declare)
645 << (DK == OpenACCDirectiveKind::Declare);
646 return ExprError();
647 }
648
649 // Sub-arrays/subscript-exprs are fine as long as the base is a
650 // VarExpr/MemberExpr. So strip all of those off.
651 while (isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) {
652 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(Val: CurVarExpr))
653 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
654 else
655 CurVarExpr =
656 cast<ArraySectionExpr>(Val: CurVarExpr)->getBase()->IgnoreParenImpCasts();
657 }
658
659 // References to a VarDecl are fine.
660 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: CurVarExpr)) {
661 if (isa<VarDecl, NonTypeTemplateParmDecl>(
662 Val: DRE->getFoundDecl()->getCanonicalDecl()))
663 return VarExpr;
664 }
665
666 // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
667 // reduction clause must be a scalar variable name, an aggregate variable
668 // name, an array element, or a subarray.
669 // If CK is a 'use_device', this also isn't valid, as it isn't the name of a
670 // variable or array, if not done as a member expr.
671 // A MemberExpr that references a Field is valid for other clauses.
672 if (const auto *ME = dyn_cast<MemberExpr>(Val: CurVarExpr)) {
673 if (isa<FieldDecl>(Val: ME->getMemberDecl()->getCanonicalDecl())) {
674 if (DK == OpenACCDirectiveKind::Declare ||
675 CK == OpenACCClauseKind::Reduction ||
676 CK == OpenACCClauseKind::UseDevice) {
677
678 // We can allow 'member expr' if the 'this' is implicit in the case of
679 // declare, reduction, and use_device.
680 const auto *This = dyn_cast<CXXThisExpr>(Val: ME->getBase());
681 if (This && This->isImplicit())
682 return VarExpr;
683 } else {
684 return VarExpr;
685 }
686 }
687 }
688
689 // Referring to 'this' is ok for the most part, but for 'use_device'/'declare'
690 // doesn't fall into 'variable or array name'
691 if (CK != OpenACCClauseKind::UseDevice &&
692 DK != OpenACCDirectiveKind::Declare && isa<CXXThisExpr>(Val: CurVarExpr))
693 return VarExpr;
694
695 // Nothing really we can do here, as these are dependent. So just return they
696 // are valid.
697 if (isa<DependentScopeDeclRefExpr>(Val: CurVarExpr) ||
698 (CK != OpenACCClauseKind::Reduction &&
699 isa<CXXDependentScopeMemberExpr>(Val: CurVarExpr)))
700 return VarExpr;
701
702 // There isn't really anything we can do in the case of a recovery expr, so
703 // skip the diagnostic rather than produce a confusing diagnostic.
704 if (isa<RecoveryExpr>(Val: CurVarExpr))
705 return ExprError();
706
707 if (DK == OpenACCDirectiveKind::Declare)
708 Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_not_a_var_ref_use_device_declare)
709 << /*declare*/ 1;
710 else if (CK == OpenACCClauseKind::UseDevice)
711 Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_not_a_var_ref_use_device_declare)
712 << /*use_device*/ 0;
713 else
714 Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_not_a_var_ref)
715 << (CK != OpenACCClauseKind::Reduction);
716 return ExprError();
717}
718
719ExprResult SemaOpenACC::ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
720 Expr *LowerBound,
721 SourceLocation ColonLoc,
722 Expr *Length,
723 SourceLocation RBLoc) {
724 ASTContext &Context = getASTContext();
725
726 // Handle placeholders.
727 if (Base->hasPlaceholderType() &&
728 !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
729 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
730 if (Result.isInvalid())
731 return ExprError();
732 Base = Result.get();
733 }
734 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
735 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound);
736 if (Result.isInvalid())
737 return ExprError();
738 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
739 if (Result.isInvalid())
740 return ExprError();
741 LowerBound = Result.get();
742 }
743 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
744 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length);
745 if (Result.isInvalid())
746 return ExprError();
747 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
748 if (Result.isInvalid())
749 return ExprError();
750 Length = Result.get();
751 }
752
753 // Check the 'base' value, it must be an array or pointer type, and not to/of
754 // a function type.
755 QualType OriginalBaseTy = ArraySectionExpr::getBaseOriginalType(Base);
756 QualType ResultTy;
757 if (!Base->isTypeDependent()) {
758 if (OriginalBaseTy->isAnyPointerType()) {
759 ResultTy = OriginalBaseTy->getPointeeType();
760 } else if (OriginalBaseTy->isArrayType()) {
761 ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
762 } else {
763 return ExprError(
764 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_acc_typecheck_subarray_value)
765 << Base->getSourceRange());
766 }
767
768 if (ResultTy->isFunctionType()) {
769 Diag(Loc: Base->getExprLoc(), DiagID: diag::err_acc_subarray_function_type)
770 << ResultTy << Base->getSourceRange();
771 return ExprError();
772 }
773
774 if (SemaRef.RequireCompleteType(Loc: Base->getExprLoc(), T: ResultTy,
775 DiagID: diag::err_acc_subarray_incomplete_type,
776 Args: Base))
777 return ExprError();
778
779 if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
780 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base);
781 if (Result.isInvalid())
782 return ExprError();
783 Base = Result.get();
784 }
785 }
786
787 auto GetRecovery = [&](Expr *E, QualType Ty) {
788 ExprResult Recovery =
789 SemaRef.CreateRecoveryExpr(Begin: E->getBeginLoc(), End: E->getEndLoc(), SubExprs: E, T: Ty);
790 return Recovery.isUsable() ? Recovery.get() : nullptr;
791 };
792
793 // Ensure both of the expressions are int-exprs.
794 if (LowerBound && !LowerBound->isTypeDependent()) {
795 ExprResult LBRes =
796 ActOnIntExpr(DK: OpenACCDirectiveKind::Invalid, CK: OpenACCClauseKind::Invalid,
797 Loc: LowerBound->getExprLoc(), IntExpr: LowerBound);
798
799 if (LBRes.isUsable())
800 LBRes = SemaRef.DefaultLvalueConversion(E: LBRes.get());
801 LowerBound =
802 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
803 }
804
805 if (Length && !Length->isTypeDependent()) {
806 ExprResult LenRes =
807 ActOnIntExpr(DK: OpenACCDirectiveKind::Invalid, CK: OpenACCClauseKind::Invalid,
808 Loc: Length->getExprLoc(), IntExpr: Length);
809
810 if (LenRes.isUsable())
811 LenRes = SemaRef.DefaultLvalueConversion(E: LenRes.get());
812 Length =
813 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
814 }
815
816 // Length is required if the base type is not an array of known bounds.
817 if (!Length && (OriginalBaseTy.isNull() ||
818 (!OriginalBaseTy->isDependentType() &&
819 !OriginalBaseTy->isConstantArrayType() &&
820 !OriginalBaseTy->isDependentSizedArrayType()))) {
821 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
822 SourceLocation DiagLoc = ColonLoc.isInvalid() ? LBLoc : ColonLoc;
823 Diag(Loc: DiagLoc, DiagID: diag::err_acc_subarray_no_length) << IsArray;
824 // Fill in a dummy 'length' so that when we instantiate this we don't
825 // double-diagnose here.
826 ExprResult Recovery = SemaRef.CreateRecoveryExpr(
827 Begin: DiagLoc, End: SourceLocation(), SubExprs: ArrayRef<Expr *>(), T: Context.IntTy);
828 Length = Recovery.isUsable() ? Recovery.get() : nullptr;
829 }
830
831 // Check the values of each of the arguments, they cannot be negative(we
832 // assume), and if the array bound is known, must be within range. As we do
833 // so, do our best to continue with evaluation, we can set the
834 // value/expression to nullptr/nullopt if they are invalid, and treat them as
835 // not present for the rest of evaluation.
836
837 // We don't have to check for dependence, because the dependent size is
838 // represented as a different AST node.
839 std::optional<llvm::APSInt> BaseSize;
840 if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
841 const auto *ArrayTy = Context.getAsConstantArrayType(T: OriginalBaseTy);
842 BaseSize = ArrayTy->getSize();
843 }
844
845 auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
846 if (!E || E->isInstantiationDependent())
847 return std::nullopt;
848
849 Expr::EvalResult Res;
850 if (!E->EvaluateAsInt(Result&: Res, Ctx: Context))
851 return std::nullopt;
852 return Res.Val.getInt();
853 };
854
855 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
856 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
857
858 // Check lower bound for negative or out of range.
859 if (LowerBoundValue.has_value()) {
860 if (LowerBoundValue->isNegative()) {
861 Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::err_acc_subarray_negative)
862 << /*LowerBound=*/0 << toString(I: *LowerBoundValue, /*Radix=*/10);
863 LowerBoundValue.reset();
864 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
865 } else if (BaseSize.has_value() &&
866 llvm::APSInt::compareValues(I1: *LowerBoundValue, I2: *BaseSize) >= 0) {
867 // Lower bound (start index) must be less than the size of the array.
868 Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::err_acc_subarray_out_of_range)
869 << /*LowerBound=*/0 << toString(I: *LowerBoundValue, /*Radix=*/10)
870 << toString(I: *BaseSize, /*Radix=*/10);
871 LowerBoundValue.reset();
872 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
873 }
874 }
875
876 // Check length for negative or out of range.
877 if (LengthValue.has_value()) {
878 if (LengthValue->isNegative()) {
879 Diag(Loc: Length->getExprLoc(), DiagID: diag::err_acc_subarray_negative)
880 << /*Length=*/1 << toString(I: *LengthValue, /*Radix=*/10);
881 LengthValue.reset();
882 Length = GetRecovery(Length, Length->getType());
883 } else if (BaseSize.has_value() &&
884 llvm::APSInt::compareValues(I1: *LengthValue, I2: *BaseSize) > 0) {
885 // Length must be lessthan or EQUAL to the size of the array.
886 Diag(Loc: Length->getExprLoc(), DiagID: diag::err_acc_subarray_out_of_range)
887 << /*Length=*/1 << toString(I: *LengthValue, /*Radix=*/10)
888 << toString(I: *BaseSize, /*Radix=*/10);
889 LengthValue.reset();
890 Length = GetRecovery(Length, Length->getType());
891 }
892 }
893
894 // Adding two APSInts requires matching sign, so extract that here.
895 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
896 if (LHS.isSigned() == RHS.isSigned())
897 return LHS + RHS;
898
899 unsigned Width = std::max(a: LHS.getBitWidth(), b: RHS.getBitWidth()) + 1;
900 return llvm::APSInt(LHS.sext(width: Width) + RHS.sext(width: Width), /*Signed=*/true);
901 };
902
903 // If we know all 3 values, we can diagnose that the total value would be out
904 // of range.
905 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
906 LengthValue.has_value() &&
907 llvm::APSInt::compareValues(I1: AddAPSInt(*LowerBoundValue, *LengthValue),
908 I2: *BaseSize) > 0) {
909 Diag(Loc: Base->getExprLoc(),
910 DiagID: diag::err_acc_subarray_base_plus_length_out_of_range)
911 << toString(I: *LowerBoundValue, /*Radix=*/10)
912 << toString(I: *LengthValue, /*Radix=*/10)
913 << toString(I: *BaseSize, /*Radix=*/10);
914
915 LowerBoundValue.reset();
916 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
917 LengthValue.reset();
918 Length = GetRecovery(Length, Length->getType());
919 }
920
921 // If any part of the expression is dependent, return a dependent sub-array.
922 QualType ArrayExprTy = Context.ArraySectionTy;
923 if (Base->isTypeDependent() ||
924 (LowerBound && LowerBound->isInstantiationDependent()) ||
925 (Length && Length->isInstantiationDependent()))
926 ArrayExprTy = Context.DependentTy;
927
928 return new (Context)
929 ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
930 OK_Ordinary, ColonLoc, RBLoc);
931}
932
933void SemaOpenACC::ActOnWhileStmt(SourceLocation WhileLoc) {
934 if (!getLangOpts().OpenACC)
935 return;
936
937 if (!LoopInfo.TopLevelLoopSeen)
938 return;
939
940 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
941 Diag(Loc: WhileLoc, DiagID: diag::err_acc_invalid_in_loop)
942 << /*while loop*/ 1 << CollapseInfo.DirectiveKind
943 << OpenACCClauseKind::Collapse;
944 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
945 Diag(Loc: CollapseInfo.ActiveCollapse->getBeginLoc(),
946 DiagID: diag::note_acc_active_clause_here)
947 << OpenACCClauseKind::Collapse;
948
949 // Remove the value so that we don't get cascading errors in the body. The
950 // caller RAII object will restore this.
951 CollapseInfo.CurCollapseCount = std::nullopt;
952 }
953
954 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
955 Diag(Loc: WhileLoc, DiagID: diag::err_acc_invalid_in_loop)
956 << /*while loop*/ 1 << TileInfo.DirectiveKind
957 << OpenACCClauseKind::Tile;
958 assert(TileInfo.ActiveTile && "tile count without object?");
959 Diag(Loc: TileInfo.ActiveTile->getBeginLoc(), DiagID: diag::note_acc_active_clause_here)
960 << OpenACCClauseKind::Tile;
961
962 // Remove the value so that we don't get cascading errors in the body. The
963 // caller RAII object will restore this.
964 TileInfo.CurTileCount = std::nullopt;
965 }
966}
967
968void SemaOpenACC::ActOnDoStmt(SourceLocation DoLoc) {
969 if (!getLangOpts().OpenACC)
970 return;
971
972 if (!LoopInfo.TopLevelLoopSeen)
973 return;
974
975 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
976 Diag(Loc: DoLoc, DiagID: diag::err_acc_invalid_in_loop)
977 << /*do loop*/ 2 << CollapseInfo.DirectiveKind
978 << OpenACCClauseKind::Collapse;
979 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
980 Diag(Loc: CollapseInfo.ActiveCollapse->getBeginLoc(),
981 DiagID: diag::note_acc_active_clause_here)
982 << OpenACCClauseKind::Collapse;
983
984 // Remove the value so that we don't get cascading errors in the body. The
985 // caller RAII object will restore this.
986 CollapseInfo.CurCollapseCount = std::nullopt;
987 }
988
989 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
990 Diag(Loc: DoLoc, DiagID: diag::err_acc_invalid_in_loop)
991 << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
992 assert(TileInfo.ActiveTile && "tile count without object?");
993 Diag(Loc: TileInfo.ActiveTile->getBeginLoc(), DiagID: diag::note_acc_active_clause_here)
994 << OpenACCClauseKind::Tile;
995
996 // Remove the value so that we don't get cascading errors in the body. The
997 // caller RAII object will restore this.
998 TileInfo.CurTileCount = std::nullopt;
999 }
1000}
1001
1002void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
1003 ForStmtBeginChecker &C) {
1004 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
1005
1006 // Enable the while/do-while checking.
1007 LoopInfo.TopLevelLoopSeen = true;
1008
1009 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1010 // Check the format of this loop if it is affected by the collapse.
1011 C.check();
1012
1013 // OpenACC 3.3 2.9.1:
1014 // Each associated loop, except the innermost, must contain exactly one loop
1015 // or loop nest.
1016 // This checks for more than 1 loop at the current level, the
1017 // 'depth'-satisifed checking manages the 'not zero' case.
1018 if (LoopInfo.CurLevelHasLoopAlready) {
1019 Diag(Loc: ForLoc, DiagID: diag::err_acc_clause_multiple_loops)
1020 << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
1021 assert(CollapseInfo.ActiveCollapse && "No collapse object?");
1022 Diag(Loc: CollapseInfo.ActiveCollapse->getBeginLoc(),
1023 DiagID: diag::note_acc_active_clause_here)
1024 << OpenACCClauseKind::Collapse;
1025 } else {
1026 --(*CollapseInfo.CurCollapseCount);
1027
1028 // Once we've hit zero here, we know we have deep enough 'for' loops to
1029 // get to the bottom.
1030 if (*CollapseInfo.CurCollapseCount == 0)
1031 CollapseInfo.CollapseDepthSatisfied = true;
1032 }
1033 }
1034
1035 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1036 // Check the format of this loop if it is affected by the tile.
1037 C.check();
1038
1039 if (LoopInfo.CurLevelHasLoopAlready) {
1040 Diag(Loc: ForLoc, DiagID: diag::err_acc_clause_multiple_loops)
1041 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
1042 assert(TileInfo.ActiveTile && "No tile object?");
1043 Diag(Loc: TileInfo.ActiveTile->getBeginLoc(),
1044 DiagID: diag::note_acc_active_clause_here)
1045 << OpenACCClauseKind::Tile;
1046 } else {
1047 TileInfo.CurTileCount = *TileInfo.CurTileCount - 1;
1048 // Once we've hit zero here, we know we have deep enough 'for' loops to
1049 // get to the bottom.
1050 if (*TileInfo.CurTileCount == 0)
1051 TileInfo.TileDepthSatisfied = true;
1052 }
1053 }
1054
1055 // Set this to 'false' for the body of this loop, so that the next level
1056 // checks independently.
1057 LoopInfo.CurLevelHasLoopAlready = false;
1058}
1059
1060namespace {
1061bool isValidLoopVariableType(QualType LoopVarTy) {
1062 // Just skip if it is dependent, it could be any of the below.
1063 if (LoopVarTy->isDependentType())
1064 return true;
1065
1066 // The loop variable must be of integer,
1067 if (LoopVarTy->isIntegerType())
1068 return true;
1069
1070 // C/C++ pointer,
1071 if (LoopVarTy->isPointerType())
1072 return true;
1073
1074 // or C++ random-access iterator type.
1075 if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
1076 // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
1077 // iterator type!
1078
1079 // We could either do a lot of work to see if this matches
1080 // random-access-iterator, but it seems that just checking that the
1081 // 'iterator_category' typedef is more than sufficient. If programmers are
1082 // willing to lie about this, we can let them.
1083
1084 for (const auto *TD :
1085 llvm::make_filter_range(Range: RD->decls(), Pred: llvm::IsaPred<TypedefNameDecl>)) {
1086 const auto *TDND = cast<TypedefNameDecl>(Val: TD)->getCanonicalDecl();
1087
1088 if (TDND->getName() != "iterator_category")
1089 continue;
1090
1091 // If there is no type for this decl, return false.
1092 if (TDND->getUnderlyingType().isNull())
1093 return false;
1094
1095 const CXXRecordDecl *ItrCategoryDecl =
1096 TDND->getUnderlyingType()->getAsCXXRecordDecl();
1097
1098 // If the category isn't a record decl, it isn't the tag type.
1099 if (!ItrCategoryDecl)
1100 return false;
1101
1102 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
1103 if (RD->getName() != "random_access_iterator_tag")
1104 return false;
1105 // Checks just for std::random_access_iterator_tag.
1106 return RD->getEnclosingNamespaceContext()->isStdNamespace();
1107 };
1108
1109 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
1110 return true;
1111
1112 // We can also support tag-types inherited from the
1113 // random_access_iterator_tag.
1114 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases())
1115 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
1116 return true;
1117
1118 return false;
1119 }
1120 }
1121
1122 return false;
1123}
1124const ValueDecl *getDeclFromExpr(const Expr *E) {
1125 E = E->IgnoreParenImpCasts();
1126 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1127 E = FE->getSubExpr();
1128
1129 E = E->IgnoreParenImpCasts();
1130
1131 if (!E)
1132 return nullptr;
1133 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
1134 return dyn_cast<ValueDecl>(Val: DRE->getDecl());
1135
1136 if (const auto *ME = dyn_cast<MemberExpr>(Val: E))
1137 if (isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
1138 return ME->getMemberDecl();
1139
1140 return nullptr;
1141}
1142} // namespace
1143
1144void SemaOpenACC::ForStmtBeginChecker::checkRangeFor() {
1145 const RangeForInfo &RFI = std::get<RangeForInfo>(v&: Info);
1146 // If this hasn't changed since last instantiated we're done.
1147 if (RFI.Uninstantiated == RFI.CurrentVersion)
1148 return;
1149
1150 const DeclStmt *UninstRangeStmt =
1151 IsInstantiation ? RFI.Uninstantiated->getBeginStmt() : nullptr;
1152 const DeclStmt *RangeStmt = RFI.CurrentVersion->getBeginStmt();
1153
1154 // If this isn't the first time we've checked this loop, suppress any cases
1155 // where we previously diagnosed.
1156 if (UninstRangeStmt) {
1157 const ValueDecl *InitVar =
1158 cast<ValueDecl>(Val: UninstRangeStmt->getSingleDecl());
1159 QualType VarType = InitVar->getType().getNonReferenceType();
1160
1161 if (!isValidLoopVariableType(LoopVarTy: VarType))
1162 return;
1163 }
1164
1165 // In some dependent contexts, the autogenerated range statement doesn't get
1166 // included until instantiation, so skip for now.
1167 if (RangeStmt) {
1168 const ValueDecl *InitVar = cast<ValueDecl>(Val: RangeStmt->getSingleDecl());
1169 QualType VarType = InitVar->getType().getNonReferenceType();
1170
1171 if (!isValidLoopVariableType(LoopVarTy: VarType)) {
1172 SemaRef.Diag(Loc: InitVar->getBeginLoc(), DiagID: diag::err_acc_loop_variable_type)
1173 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1174 SemaRef.Diag(Loc: SemaRef.LoopWithoutSeqInfo.Loc,
1175 DiagID: diag::note_acc_construct_here)
1176 << SemaRef.LoopWithoutSeqInfo.Kind;
1177 return;
1178 }
1179 }
1180}
1181bool SemaOpenACC::ForStmtBeginChecker::checkForInit(const Stmt *InitStmt,
1182 const ValueDecl *&InitVar,
1183 bool Diag) {
1184 // Init statement is required.
1185 if (!InitStmt) {
1186 if (Diag) {
1187 SemaRef.Diag(Loc: ForLoc, DiagID: diag::err_acc_loop_variable)
1188 << SemaRef.LoopWithoutSeqInfo.Kind;
1189 SemaRef.Diag(Loc: SemaRef.LoopWithoutSeqInfo.Loc,
1190 DiagID: diag::note_acc_construct_here)
1191 << SemaRef.LoopWithoutSeqInfo.Kind;
1192 }
1193 return true;
1194 }
1195 auto DiagLoopVar = [this, Diag, InitStmt]() {
1196 if (Diag) {
1197 SemaRef.Diag(Loc: InitStmt->getBeginLoc(), DiagID: diag::err_acc_loop_variable)
1198 << SemaRef.LoopWithoutSeqInfo.Kind;
1199 SemaRef.Diag(Loc: SemaRef.LoopWithoutSeqInfo.Loc,
1200 DiagID: diag::note_acc_construct_here)
1201 << SemaRef.LoopWithoutSeqInfo.Kind;
1202 }
1203 return true;
1204 };
1205
1206 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: InitStmt))
1207 InitStmt = ExprTemp->getSubExpr();
1208 if (const auto *E = dyn_cast<Expr>(Val: InitStmt))
1209 InitStmt = E->IgnoreParenImpCasts();
1210
1211 InitVar = nullptr;
1212 if (const auto *BO = dyn_cast<BinaryOperator>(Val: InitStmt)) {
1213 // Allow assignment operator here.
1214
1215 if (!BO->isAssignmentOp())
1216 return DiagLoopVar();
1217
1218 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
1219 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS))
1220 InitVar = DRE->getDecl();
1221 } else if (const auto *DS = dyn_cast<DeclStmt>(Val: InitStmt)) {
1222 // Allow T t = <whatever>
1223 if (!DS->isSingleDecl())
1224 return DiagLoopVar();
1225 InitVar = dyn_cast<ValueDecl>(Val: DS->getSingleDecl());
1226
1227 // Ensure we have an initializer, unless this is a record/dependent type.
1228 if (InitVar) {
1229 if (!isa<VarDecl>(Val: InitVar))
1230 return DiagLoopVar();
1231
1232 if (!InitVar->getType()->isRecordType() &&
1233 !InitVar->getType()->isDependentType() &&
1234 !cast<VarDecl>(Val: InitVar)->hasInit())
1235 return DiagLoopVar();
1236 }
1237 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: InitStmt)) {
1238 // Allow assignment operator call.
1239 if (CE->getOperator() != OO_Equal)
1240 return DiagLoopVar();
1241
1242 const Expr *LHS = CE->getArg(Arg: 0)->IgnoreParenImpCasts();
1243 if (auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS)) {
1244 InitVar = DRE->getDecl();
1245 } else if (auto *ME = dyn_cast<MemberExpr>(Val: LHS)) {
1246 if (isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
1247 InitVar = ME->getMemberDecl();
1248 }
1249 }
1250
1251 // If after all of that, we haven't found a variable, give up.
1252 if (!InitVar)
1253 return DiagLoopVar();
1254
1255 InitVar = cast<ValueDecl>(Val: InitVar->getCanonicalDecl());
1256 QualType VarType = InitVar->getType().getNonReferenceType();
1257
1258 // Since we have one, all we need to do is ensure it is the right type.
1259 if (!isValidLoopVariableType(LoopVarTy: VarType)) {
1260 if (Diag) {
1261 SemaRef.Diag(Loc: InitVar->getBeginLoc(), DiagID: diag::err_acc_loop_variable_type)
1262 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1263 SemaRef.Diag(Loc: SemaRef.LoopWithoutSeqInfo.Loc,
1264 DiagID: diag::note_acc_construct_here)
1265 << SemaRef.LoopWithoutSeqInfo.Kind;
1266 }
1267 return true;
1268 }
1269
1270 return false;
1271}
1272
1273bool SemaOpenACC::ForStmtBeginChecker::checkForCond(const Stmt *CondStmt,
1274 const ValueDecl *InitVar,
1275 bool Diag) {
1276 // A condition statement is required.
1277 if (!CondStmt) {
1278 if (Diag) {
1279 SemaRef.Diag(Loc: ForLoc, DiagID: diag::err_acc_loop_terminating_condition)
1280 << SemaRef.LoopWithoutSeqInfo.Kind;
1281 SemaRef.Diag(Loc: SemaRef.LoopWithoutSeqInfo.Loc,
1282 DiagID: diag::note_acc_construct_here)
1283 << SemaRef.LoopWithoutSeqInfo.Kind;
1284 }
1285
1286 return true;
1287 }
1288 auto DiagCondVar = [this, Diag, CondStmt] {
1289 if (Diag) {
1290 SemaRef.Diag(Loc: CondStmt->getBeginLoc(),
1291 DiagID: diag::err_acc_loop_terminating_condition)
1292 << SemaRef.LoopWithoutSeqInfo.Kind;
1293 SemaRef.Diag(Loc: SemaRef.LoopWithoutSeqInfo.Loc,
1294 DiagID: diag::note_acc_construct_here)
1295 << SemaRef.LoopWithoutSeqInfo.Kind;
1296 }
1297 return true;
1298 };
1299
1300 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: CondStmt))
1301 CondStmt = ExprTemp->getSubExpr();
1302 if (const auto *E = dyn_cast<Expr>(Val: CondStmt))
1303 CondStmt = E->IgnoreParenImpCasts();
1304
1305 const ValueDecl *CondVar = nullptr;
1306 if (const auto *BO = dyn_cast<BinaryOperator>(Val: CondStmt)) {
1307 switch (BO->getOpcode()) {
1308 default:
1309 return DiagCondVar();
1310 case BO_EQ:
1311 case BO_LT:
1312 case BO_GT:
1313 case BO_NE:
1314 case BO_LE:
1315 case BO_GE:
1316 break;
1317 }
1318
1319 // Assign the condition-var to the LHS. If it either comes back null, or
1320 // the LHS doesn't match the InitVar, assign it to the RHS so that 5 < N is
1321 // allowed.
1322 CondVar = getDeclFromExpr(E: BO->getLHS());
1323 if (!CondVar ||
1324 (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl()))
1325 CondVar = getDeclFromExpr(E: BO->getRHS());
1326
1327 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: CondStmt)) {
1328 // Any of the comparison ops should be ok here, but we don't know how to
1329 // handle spaceship, so disallow for now.
1330 if (!CE->isComparisonOp() || CE->getOperator() == OO_Spaceship)
1331 return DiagCondVar();
1332
1333 // Same logic here: Assign it to the LHS, unless the LHS comes back null or
1334 // not equal to the init var.
1335 CondVar = getDeclFromExpr(E: CE->getArg(Arg: 0));
1336 if (!CondVar ||
1337 (InitVar &&
1338 CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl() &&
1339 CE->getNumArgs() > 1))
1340 CondVar = getDeclFromExpr(E: CE->getArg(Arg: 1));
1341 } else {
1342 return DiagCondVar();
1343 }
1344
1345 if (!CondVar)
1346 return DiagCondVar();
1347
1348 // Don't consider this an error unless the init variable was properly set,
1349 // else check to make sure they are the same variable.
1350 if (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1351 return DiagCondVar();
1352
1353 return false;
1354}
1355
1356namespace {
1357// Helper to check the RHS of an assignment during for's step. We can allow
1358// InitVar = InitVar + N, InitVar = N + InitVar, and Initvar = Initvar - N,
1359// where N is an integer.
1360bool isValidForIncRHSAssign(const ValueDecl *InitVar, const Expr *RHS) {
1361
1362 auto isValid = [](const ValueDecl *InitVar, const Expr *InnerLHS,
1363 const Expr *InnerRHS, bool IsAddition) {
1364 // ONE of the sides has to be an integer type.
1365 if (!InnerLHS->getType()->isIntegerType() &&
1366 !InnerRHS->getType()->isIntegerType())
1367 return false;
1368
1369 // If the init var is already an error, don't bother trying to check for
1370 // it.
1371 if (!InitVar)
1372 return true;
1373
1374 const ValueDecl *LHSDecl = getDeclFromExpr(E: InnerLHS);
1375 const ValueDecl *RHSDecl = getDeclFromExpr(E: InnerRHS);
1376 // If we can't get a declaration, this is probably an error, so give up.
1377 if (!LHSDecl || !RHSDecl)
1378 return true;
1379
1380 // If the LHS is the InitVar, the other must be int, so this is valid.
1381 if (LHSDecl->getCanonicalDecl() ==
1382 InitVar->getCanonicalDecl())
1383 return true;
1384
1385 // Subtraction doesn't allow the RHS to be init var, so this is invalid.
1386 if (!IsAddition)
1387 return false;
1388
1389 return RHSDecl->getCanonicalDecl() ==
1390 InitVar->getCanonicalDecl();
1391 };
1392
1393 if (const auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
1394 BinaryOperatorKind OpC = BO->getOpcode();
1395 if (OpC != BO_Add && OpC != BO_Sub)
1396 return false;
1397 return isValid(InitVar, BO->getLHS(), BO->getRHS(), OpC == BO_Add);
1398 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
1399 OverloadedOperatorKind Op = CE->getOperator();
1400 if (Op != OO_Plus && Op != OO_Minus)
1401 return false;
1402 return isValid(InitVar, CE->getArg(Arg: 0), CE->getArg(Arg: 1), Op == OO_Plus);
1403 }
1404
1405 return false;
1406}
1407} // namespace
1408
1409bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,
1410 const ValueDecl *InitVar,
1411 bool Diag) {
1412 if (!IncStmt) {
1413 if (Diag) {
1414 SemaRef.Diag(Loc: ForLoc, DiagID: diag::err_acc_loop_not_monotonic)
1415 << SemaRef.LoopWithoutSeqInfo.Kind;
1416 SemaRef.Diag(Loc: SemaRef.LoopWithoutSeqInfo.Loc,
1417 DiagID: diag::note_acc_construct_here)
1418 << SemaRef.LoopWithoutSeqInfo.Kind;
1419 }
1420 return true;
1421 }
1422 auto DiagIncVar = [this, Diag, IncStmt] {
1423 if (Diag) {
1424 SemaRef.Diag(Loc: IncStmt->getBeginLoc(), DiagID: diag::err_acc_loop_not_monotonic)
1425 << SemaRef.LoopWithoutSeqInfo.Kind;
1426 SemaRef.Diag(Loc: SemaRef.LoopWithoutSeqInfo.Loc,
1427 DiagID: diag::note_acc_construct_here)
1428 << SemaRef.LoopWithoutSeqInfo.Kind;
1429 }
1430 return true;
1431 };
1432
1433 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: IncStmt))
1434 IncStmt = ExprTemp->getSubExpr();
1435 if (const auto *E = dyn_cast<Expr>(Val: IncStmt))
1436 IncStmt = E->IgnoreParenImpCasts();
1437
1438 const ValueDecl *IncVar = nullptr;
1439 // Here we enforce the monotonically increase/decrease:
1440 if (const auto *UO = dyn_cast<UnaryOperator>(Val: IncStmt)) {
1441 // Allow increment/decrement ops.
1442 if (!UO->isIncrementDecrementOp())
1443 return DiagIncVar();
1444 IncVar = getDeclFromExpr(E: UO->getSubExpr());
1445 } else if (const auto *BO = dyn_cast<BinaryOperator>(Val: IncStmt)) {
1446 switch (BO->getOpcode()) {
1447 default:
1448 return DiagIncVar();
1449 case BO_AddAssign:
1450 case BO_SubAssign:
1451 break;
1452 case BO_Assign:
1453 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1454 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1455 if (!isValidForIncRHSAssign(InitVar, RHS: BO->getRHS()))
1456 return DiagIncVar();
1457 break;
1458 }
1459 IncVar = getDeclFromExpr(E: BO->getLHS());
1460 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: IncStmt)) {
1461 switch (CE->getOperator()) {
1462 default:
1463 return DiagIncVar();
1464 case OO_PlusPlus:
1465 case OO_MinusMinus:
1466 case OO_PlusEqual:
1467 case OO_MinusEqual:
1468 break;
1469 case OO_Equal:
1470 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1471 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1472 if (!isValidForIncRHSAssign(InitVar, RHS: CE->getArg(Arg: 1)))
1473 return DiagIncVar();
1474 break;
1475 }
1476
1477 IncVar = getDeclFromExpr(E: CE->getArg(Arg: 0));
1478 } else {
1479 return DiagIncVar();
1480 }
1481
1482 if (!IncVar)
1483 return DiagIncVar();
1484
1485 // InitVar shouldn't be null unless there was an error, so don't diagnose if
1486 // that is the case. Else we should ensure that it refers to the loop
1487 // value.
1488 if (InitVar && IncVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1489 return DiagIncVar();
1490
1491 return false;
1492}
1493
1494void SemaOpenACC::ForStmtBeginChecker::checkFor() {
1495 const CheckForInfo &CFI = std::get<CheckForInfo>(v&: Info);
1496
1497 if (!IsInstantiation) {
1498 // If this isn't an instantiation, we can just check all of these and
1499 // diagnose.
1500 const ValueDecl *CurInitVar = nullptr;
1501 checkForInit(InitStmt: CFI.Current.Init, InitVar&: CurInitVar, /*Diag=*/true);
1502 checkForCond(CondStmt: CFI.Current.Condition, InitVar: CurInitVar, /*Diag=*/true);
1503 checkForInc(IncStmt: CFI.Current.Increment, InitVar: CurInitVar, /*DIag=*/Diag: true);
1504 } else {
1505 const ValueDecl *UninstInitVar = nullptr;
1506 // Checking the 'init' section first. We have to always run both versions,
1507 // at minimum with the 'diag' off, so that we can ensure we get the correct
1508 // instantiation var for checking by later ones.
1509 bool UninstInitFailed =
1510 checkForInit(InitStmt: CFI.Uninst.Init, InitVar&: UninstInitVar, /*Diag=*/false);
1511
1512 // VarDecls are always rebuild because they are dependent, so we can do a
1513 // little work to suppress some of the double checking based on whether the
1514 // type is instantiation dependent. This is imperfect, but will get us most
1515 // cases suppressed. Currently this only handles the 'T t =' case.
1516 auto InitChanged = [=]() {
1517 if (CFI.Uninst.Init == CFI.Current.Init)
1518 return false;
1519
1520 QualType OldVDTy;
1521 QualType NewVDTy;
1522
1523 if (const auto *DS = dyn_cast<DeclStmt>(Val: CFI.Uninst.Init))
1524 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1525 Val: DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1526 OldVDTy = VD->getType();
1527 if (const auto *DS = dyn_cast<DeclStmt>(Val: CFI.Current.Init))
1528 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1529 Val: DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1530 NewVDTy = VD->getType();
1531
1532 if (OldVDTy.isNull() || NewVDTy.isNull())
1533 return true;
1534
1535 return OldVDTy->isInstantiationDependentType() !=
1536 NewVDTy->isInstantiationDependentType();
1537 };
1538
1539 // Only diagnose the new 'init' if the previous version didn't fail, AND the
1540 // current init changed meaningfully.
1541 bool ShouldDiagNewInit = !UninstInitFailed && InitChanged();
1542 const ValueDecl *CurInitVar = nullptr;
1543 checkForInit(InitStmt: CFI.Current.Init, InitVar&: CurInitVar, /*Diag=*/ShouldDiagNewInit);
1544
1545 // Check the condition and increment only if the previous version passed,
1546 // and this changed.
1547 if (CFI.Uninst.Condition != CFI.Current.Condition &&
1548 !checkForCond(CondStmt: CFI.Uninst.Condition, InitVar: UninstInitVar, /*Diag=*/false))
1549 checkForCond(CondStmt: CFI.Current.Condition, InitVar: CurInitVar, /*Diag=*/true);
1550 if (CFI.Uninst.Increment != CFI.Current.Increment &&
1551 !checkForInc(IncStmt: CFI.Uninst.Increment, InitVar: UninstInitVar, /*Diag=*/false))
1552 checkForInc(IncStmt: CFI.Current.Increment, InitVar: CurInitVar, /*Diag=*/true);
1553 }
1554}
1555
1556void SemaOpenACC::ForStmtBeginChecker::check() {
1557 // If this isn't an active loop without a seq, immediately return, nothing to
1558 // check.
1559 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
1560 return;
1561
1562 // If we've already checked, because this is a 'top level' one (and asking
1563 // again because 'tile' and 'collapse' might apply), just return, nothing to
1564 // do here.
1565 if (AlreadyChecked)
1566 return;
1567 AlreadyChecked = true;
1568
1569 // OpenACC3.3 2.1:
1570 // A loop associated with a loop construct that does not have a seq clause
1571 // must be written to meet all the following conditions:
1572 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
1573 // iterator type.
1574 // - The loop variable must monotonically increase or decrease in the
1575 // direction of its termination condition.
1576 // - The loop trip count must be computable in constant time when entering the
1577 // loop construct.
1578 //
1579 // For a C++ range-based for loop, the loop variable
1580 // identified by the above conditions is the internal iterator, such as a
1581 // pointer, that the compiler generates to iterate the range. it is not the
1582 // variable declared by the for loop.
1583
1584 if (std::holds_alternative<RangeForInfo>(v: Info))
1585 return checkRangeFor();
1586
1587 return checkFor();
1588}
1589
1590void SemaOpenACC::ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *OldFirst,
1591 const Stmt *First, const Stmt *OldSecond,
1592 const Stmt *Second, const Stmt *OldThird,
1593 const Stmt *Third) {
1594 if (!getLangOpts().OpenACC)
1595 return;
1596
1597 ForStmtBeginChecker FSBC{*this, ForLoc, OldFirst, OldSecond,
1598 OldThird, First, Second, Third};
1599 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1600 // as a part of the helper if a tile/collapse applies.
1601 if (!LoopInfo.TopLevelLoopSeen) {
1602 FSBC.check();
1603 }
1604
1605 ForStmtBeginHelper(ForLoc, C&: FSBC);
1606}
1607
1608void SemaOpenACC::ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First,
1609 const Stmt *Second, const Stmt *Third) {
1610 if (!getLangOpts().OpenACC)
1611 return;
1612
1613 ForStmtBeginChecker FSBC{*this, ForLoc, First, Second, Third};
1614
1615 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1616 // as a part of the helper if a tile/collapse applies.
1617 if (!LoopInfo.TopLevelLoopSeen)
1618 FSBC.check();
1619
1620 ForStmtBeginHelper(ForLoc, C&: FSBC);
1621}
1622
1623void SemaOpenACC::ActOnRangeForStmtBegin(SourceLocation ForLoc,
1624 const Stmt *OldRangeFor,
1625 const Stmt *RangeFor) {
1626 if (!getLangOpts().OpenACC || OldRangeFor == nullptr || RangeFor == nullptr)
1627 return;
1628
1629 ForStmtBeginChecker FSBC{*this, ForLoc,
1630 cast_if_present<CXXForRangeStmt>(Val: OldRangeFor),
1631 cast_if_present<CXXForRangeStmt>(Val: RangeFor)};
1632 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1633 // as a part of the helper if a tile/collapse applies.
1634 if (!LoopInfo.TopLevelLoopSeen) {
1635 FSBC.check();
1636 }
1637 ForStmtBeginHelper(ForLoc, C&: FSBC);
1638}
1639
1640void SemaOpenACC::ActOnRangeForStmtBegin(SourceLocation ForLoc,
1641 const Stmt *RangeFor) {
1642 if (!getLangOpts().OpenACC || RangeFor == nullptr)
1643 return;
1644
1645 ForStmtBeginChecker FSBC = {*this, ForLoc,
1646 cast_if_present<CXXForRangeStmt>(Val: RangeFor)};
1647
1648 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1649 // as a part of the helper if a tile/collapse applies.
1650 if (!LoopInfo.TopLevelLoopSeen)
1651 FSBC.check();
1652
1653 ForStmtBeginHelper(ForLoc, C&: FSBC);
1654}
1655
1656namespace {
1657SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
1658 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
1659 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
1660 // `DoStmt`, as those are caught as a violation elsewhere.
1661 // For `CompoundStmt` we need to search inside of it.
1662 if (!CurStmt ||
1663 isa<ForStmt, NullStmt, ForStmt, CXXForRangeStmt, WhileStmt, DoStmt>(
1664 Val: CurStmt))
1665 return SourceLocation{};
1666
1667 // Any other construct is an error anyway, so it has already been diagnosed.
1668 if (isa<OpenACCConstructStmt>(Val: CurStmt))
1669 return SourceLocation{};
1670
1671 // Search inside the compound statement, this allows for arbitrary nesting
1672 // of compound statements, as long as there isn't any code inside.
1673 if (const auto *CS = dyn_cast<CompoundStmt>(Val: CurStmt)) {
1674 for (const auto *ChildStmt : CS->children()) {
1675 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(CurStmt: ChildStmt);
1676 if (ChildStmtLoc.isValid())
1677 return ChildStmtLoc;
1678 }
1679 // Empty/not invalid compound statements are legal.
1680 return SourceLocation{};
1681 }
1682 return CurStmt->getBeginLoc();
1683}
1684} // namespace
1685
1686void SemaOpenACC::ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body) {
1687 if (!getLangOpts().OpenACC)
1688 return;
1689
1690 // Set this to 'true' so if we find another one at this level we can diagnose.
1691 LoopInfo.CurLevelHasLoopAlready = true;
1692
1693 if (!Body.isUsable())
1694 return;
1695
1696 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1697 *CollapseInfo.CurCollapseCount > 0 &&
1698 !CollapseInfo.ActiveCollapse->hasForce();
1699 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1700
1701 if (IsActiveCollapse || IsActiveTile) {
1702 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(CurStmt: Body.get());
1703
1704 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
1705 Diag(Loc: OtherStmtLoc, DiagID: diag::err_acc_intervening_code)
1706 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
1707 Diag(Loc: CollapseInfo.ActiveCollapse->getBeginLoc(),
1708 DiagID: diag::note_acc_active_clause_here)
1709 << OpenACCClauseKind::Collapse;
1710 }
1711
1712 if (OtherStmtLoc.isValid() && IsActiveTile) {
1713 Diag(Loc: OtherStmtLoc, DiagID: diag::err_acc_intervening_code)
1714 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
1715 Diag(Loc: TileInfo.ActiveTile->getBeginLoc(),
1716 DiagID: diag::note_acc_active_clause_here)
1717 << OpenACCClauseKind::Tile;
1718 }
1719 }
1720}
1721
1722namespace {
1723// Helper that should mirror ActOnRoutineName to get the FunctionDecl out for
1724// magic-static checking.
1725FunctionDecl *getFunctionFromRoutineName(Expr *RoutineName) {
1726 if (!RoutineName)
1727 return nullptr;
1728 RoutineName = RoutineName->IgnoreParenImpCasts();
1729 if (isa<RecoveryExpr>(Val: RoutineName)) {
1730 // There is nothing we can do here, this isn't a function we can count on.
1731 return nullptr;
1732 } else if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(
1733 Val: RoutineName)) {
1734 // The lookup is dependent, so we'll have to figure this out later.
1735 return nullptr;
1736 } else if (auto *DRE = dyn_cast<DeclRefExpr>(Val: RoutineName)) {
1737 ValueDecl *VD = DRE->getDecl();
1738
1739 if (auto *FD = dyn_cast<FunctionDecl>(Val: VD))
1740 return FD;
1741
1742 // Allow lambdas.
1743 if (auto *VarD = dyn_cast<VarDecl>(Val: VD)) {
1744 QualType VarDTy = VarD->getType();
1745 if (!VarDTy.isNull()) {
1746 if (auto *RD = VarDTy->getAsCXXRecordDecl()) {
1747 if (RD->isGenericLambda())
1748 return nullptr;
1749 if (RD->isLambda())
1750 return RD->getLambdaCallOperator();
1751 } else if (VarDTy->isDependentType()) {
1752 // We don't really know what this is going to be.
1753 return nullptr;
1754 }
1755 }
1756 return nullptr;
1757 } else if (isa<OverloadExpr>(Val: RoutineName)) {
1758 return nullptr;
1759 }
1760 }
1761 return nullptr;
1762}
1763} // namespace
1764
1765ExprResult SemaOpenACC::ActOnRoutineName(Expr *RoutineName) {
1766 assert(RoutineName && "Routine name cannot be null here");
1767 RoutineName = RoutineName->IgnoreParenImpCasts();
1768
1769 if (isa<RecoveryExpr>(Val: RoutineName)) {
1770 // This has already been diagnosed, so we can skip it.
1771 return ExprError();
1772 } else if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(
1773 Val: RoutineName)) {
1774 // These are dependent and we can't really check them, so delay until
1775 // instantiation.
1776 return RoutineName;
1777 } else if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: RoutineName)) {
1778 const ValueDecl *VD = DRE->getDecl();
1779
1780 if (isa<FunctionDecl>(Val: VD))
1781 return RoutineName;
1782
1783 // Allow lambdas.
1784 if (const auto *VarD = dyn_cast<VarDecl>(Val: VD)) {
1785 QualType VarDTy = VarD->getType();
1786 if (!VarDTy.isNull()) {
1787 if (const auto *RD = VarDTy->getAsCXXRecordDecl()) {
1788 if (RD->isGenericLambda()) {
1789 Diag(Loc: RoutineName->getBeginLoc(), DiagID: diag::err_acc_routine_overload_set)
1790 << RoutineName;
1791 return ExprError();
1792 }
1793 if (RD->isLambda())
1794 return RoutineName;
1795 } else if (VarDTy->isDependentType()) {
1796 // If this is a dependent variable, it might be a lambda. So we just
1797 // accept this and catch it next time.
1798 return RoutineName;
1799 }
1800 }
1801 }
1802
1803 Diag(Loc: RoutineName->getBeginLoc(), DiagID: diag::err_acc_routine_not_func)
1804 << RoutineName;
1805 return ExprError();
1806 } else if (isa<OverloadExpr>(Val: RoutineName)) {
1807 // This happens in function templates, even when the template arguments are
1808 // fully specified. We could possibly do some sort of matching to make sure
1809 // that this is looked up/deduced, but GCC does not do this, so there
1810 // doesn't seem to be a good reason for us to do it either.
1811 Diag(Loc: RoutineName->getBeginLoc(), DiagID: diag::err_acc_routine_overload_set)
1812 << RoutineName;
1813 return ExprError();
1814 }
1815
1816 Diag(Loc: RoutineName->getBeginLoc(), DiagID: diag::err_acc_routine_not_func)
1817 << RoutineName;
1818 return ExprError();
1819}
1820void SemaOpenACC::ActOnVariableDeclarator(VarDecl *VD) {
1821 if (!getLangOpts().OpenACC || VD->isInvalidDecl() || !VD->isStaticLocal())
1822 return;
1823
1824 // This cast should be safe, since a static-local can only happen in a
1825 // function declaration.
1826 auto *ContextDecl = cast<FunctionDecl>(Val: getCurContext());
1827
1828 // OpenACC 3.3 2.15:
1829 // In C and C++, function static variables are not supported in functions to
1830 // which a routine directive applies.
1831 for (const auto *A : ContextDecl->attrs()) {
1832 if (isa<OpenACCRoutineDeclAttr, OpenACCRoutineAnnotAttr>(Val: A)) {
1833 Diag(Loc: VD->getBeginLoc(), DiagID: diag::err_acc_magic_static_in_routine);
1834 Diag(Loc: A->getLocation(), DiagID: diag::note_acc_construct_here)
1835 << OpenACCDirectiveKind::Routine;
1836 return;
1837 }
1838 }
1839
1840 MagicStaticLocs.insert(KV: {ContextDecl->getCanonicalDecl(), VD->getBeginLoc()});
1841}
1842void SemaOpenACC::CheckLastRoutineDeclNameConflict(const NamedDecl *ND) {
1843 // OpenACC 3.3 A.3.4
1844 // When a procedure with that name is in scope and it is not the same
1845 // procedure as the immediately following procedure declaration or
1846 // definition, the resolution of the name can be confusing. Implementations
1847 // should then issue a compile-time warning diagnostic even though the
1848 // application is conforming.
1849
1850 // If we haven't created one, also can't diagnose.
1851 if (!LastRoutineDecl)
1852 return;
1853
1854 // If the currently created function doesn't have a name, we can't diagnose on
1855 // a match.
1856 if (!ND->getDeclName().isIdentifier())
1857 return;
1858
1859 // If the two are in different decl contexts, it doesn't make sense to
1860 // diagnose.
1861 if (LastRoutineDecl->getDeclContext() != ND->getLexicalDeclContext())
1862 return;
1863
1864 // If we don't have a referenced thing yet, we can't diagnose.
1865 FunctionDecl *RoutineTarget =
1866 getFunctionFromRoutineName(RoutineName: LastRoutineDecl->getFunctionReference());
1867 if (!RoutineTarget)
1868 return;
1869
1870 // If the Routine target doesn't have a name, we can't diagnose.
1871 if (!RoutineTarget->getDeclName().isIdentifier())
1872 return;
1873
1874 // Of course don't diagnose if the names don't match.
1875 if (ND->getName() != RoutineTarget->getName())
1876 return;
1877
1878 long NDLine = SemaRef.SourceMgr.getSpellingLineNumber(Loc: ND->getBeginLoc());
1879 long LastLine =
1880 SemaRef.SourceMgr.getSpellingLineNumber(Loc: LastRoutineDecl->getBeginLoc());
1881
1882 // Do some line-number math to make sure they are within a line of eachother.
1883 // Comments or newlines can be inserted to clarify intent.
1884 if (NDLine - LastLine > 1)
1885 return;
1886
1887 // Don't warn if it actually DOES apply to this function via redecls.
1888 if (ND->getCanonicalDecl() == RoutineTarget->getCanonicalDecl())
1889 return;
1890
1891 Diag(Loc: LastRoutineDecl->getFunctionReference()->getBeginLoc(),
1892 DiagID: diag::warn_acc_confusing_routine_name);
1893 Diag(Loc: RoutineTarget->getBeginLoc(), DiagID: diag::note_previous_decl) << ND;
1894}
1895
1896void SemaOpenACC::ActOnVariableInit(VarDecl *VD, QualType InitType) {
1897 if (!VD || !getLangOpts().OpenACC || InitType.isNull())
1898 return;
1899
1900 // To avoid double-diagnostic, just diagnose this during instantiation. We'll
1901 // get 1 warning per instantiation, but this permits us to be more sensible
1902 // for cases where the lookup is confusing.
1903 if (VD->getLexicalDeclContext()->isDependentContext())
1904 return;
1905
1906 const auto *RD = InitType->getAsCXXRecordDecl();
1907 // If this isn't a lambda, no sense in diagnosing.
1908 if (!RD || !RD->isLambda())
1909 return;
1910
1911 CheckLastRoutineDeclNameConflict(ND: VD);
1912}
1913
1914void SemaOpenACC::ActOnFunctionDeclarator(FunctionDecl *FD) {
1915 if (!FD || !getLangOpts().OpenACC)
1916 return;
1917 CheckLastRoutineDeclNameConflict(ND: FD);
1918}
1919
1920bool SemaOpenACC::ActOnStartStmtDirective(
1921 OpenACCDirectiveKind K, SourceLocation StartLoc,
1922 ArrayRef<const OpenACCClause *> Clauses) {
1923
1924 // Declaration directives an appear in a statement location, so call into that
1925 // function here.
1926 if (K == OpenACCDirectiveKind::Declare || K == OpenACCDirectiveKind::Routine)
1927 return ActOnStartDeclDirective(K, StartLoc, Clauses);
1928
1929 SemaRef.DiscardCleanupsInEvaluationContext();
1930 SemaRef.PopExpressionEvaluationContext();
1931
1932 // OpenACC 3.3 2.9.1:
1933 // Intervening code must not contain other OpenACC directives or calls to API
1934 // routines.
1935 //
1936 // ALL constructs are ill-formed if there is an active 'collapse'
1937 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1938 Diag(Loc: StartLoc, DiagID: diag::err_acc_invalid_in_loop)
1939 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
1940 << OpenACCClauseKind::Collapse << K;
1941 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1942 Diag(Loc: CollapseInfo.ActiveCollapse->getBeginLoc(),
1943 DiagID: diag::note_acc_active_clause_here)
1944 << OpenACCClauseKind::Collapse;
1945 }
1946 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1947 Diag(Loc: StartLoc, DiagID: diag::err_acc_invalid_in_loop)
1948 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
1949 << OpenACCClauseKind::Tile << K;
1950 assert(TileInfo.ActiveTile && "Tile count without object?");
1951 Diag(Loc: TileInfo.ActiveTile->getBeginLoc(), DiagID: diag::note_acc_active_clause_here)
1952 << OpenACCClauseKind::Tile;
1953 }
1954
1955 if (DiagnoseRequiredClauses(DK: K, DirLoc: StartLoc, Clauses))
1956 return true;
1957 return diagnoseConstructAppertainment(S&: *this, K, StartLoc, /*IsStmt=*/true);
1958}
1959
1960StmtResult SemaOpenACC::ActOnEndStmtDirective(
1961 OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
1962 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
1963 OpenACCAtomicKind AtomicKind, SourceLocation RParenLoc,
1964 SourceLocation EndLoc, ArrayRef<OpenACCClause *> Clauses,
1965 StmtResult AssocStmt) {
1966 switch (K) {
1967 case OpenACCDirectiveKind::Invalid:
1968 return StmtError();
1969 case OpenACCDirectiveKind::Parallel:
1970 case OpenACCDirectiveKind::Serial:
1971 case OpenACCDirectiveKind::Kernels: {
1972 return OpenACCComputeConstruct::Create(
1973 C: getASTContext(), K, BeginLoc: StartLoc, DirectiveLoc: DirLoc, EndLoc, Clauses,
1974 StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1975 }
1976 case OpenACCDirectiveKind::ParallelLoop:
1977 case OpenACCDirectiveKind::SerialLoop:
1978 case OpenACCDirectiveKind::KernelsLoop: {
1979 return OpenACCCombinedConstruct::Create(
1980 C: getASTContext(), K, Start: StartLoc, DirectiveLoc: DirLoc, End: EndLoc, Clauses,
1981 StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1982 }
1983 case OpenACCDirectiveKind::Loop: {
1984 return OpenACCLoopConstruct::Create(
1985 C: getASTContext(), ParentKind: ActiveComputeConstructInfo.Kind, BeginLoc: StartLoc, DirLoc,
1986 EndLoc, Clauses, Loop: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1987 }
1988 case OpenACCDirectiveKind::Data: {
1989 return OpenACCDataConstruct::Create(
1990 C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc, End: EndLoc, Clauses,
1991 StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1992 }
1993 case OpenACCDirectiveKind::EnterData: {
1994 return OpenACCEnterDataConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1995 End: EndLoc, Clauses);
1996 }
1997 case OpenACCDirectiveKind::ExitData: {
1998 return OpenACCExitDataConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1999 End: EndLoc, Clauses);
2000 }
2001 case OpenACCDirectiveKind::HostData: {
2002 return OpenACCHostDataConstruct::Create(
2003 C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc, End: EndLoc, Clauses,
2004 StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2005 }
2006 case OpenACCDirectiveKind::Wait: {
2007 return OpenACCWaitConstruct::Create(
2008 C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc, LParenLoc, DevNumExpr: Exprs.front(), QueuesLoc: MiscLoc,
2009 QueueIdExprs: Exprs.drop_front(), RParenLoc, End: EndLoc, Clauses);
2010 }
2011 case OpenACCDirectiveKind::Init: {
2012 return OpenACCInitConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
2013 End: EndLoc, Clauses);
2014 }
2015 case OpenACCDirectiveKind::Shutdown: {
2016 return OpenACCShutdownConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
2017 End: EndLoc, Clauses);
2018 }
2019 case OpenACCDirectiveKind::Set: {
2020 return OpenACCSetConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
2021 End: EndLoc, Clauses);
2022 }
2023 case OpenACCDirectiveKind::Update: {
2024 return OpenACCUpdateConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
2025 End: EndLoc, Clauses);
2026 }
2027 case OpenACCDirectiveKind::Atomic: {
2028 return OpenACCAtomicConstruct::Create(
2029 C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc, AtKind: AtomicKind, End: EndLoc, Clauses,
2030 AssociatedStmt: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2031 }
2032 case OpenACCDirectiveKind::Cache: {
2033 assert(Clauses.empty() && "Cache doesn't allow clauses");
2034 return OpenACCCacheConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
2035 LParenLoc, ReadOnlyLoc: MiscLoc, VarList: Exprs, RParenLoc,
2036 End: EndLoc);
2037 }
2038 case OpenACCDirectiveKind::Routine:
2039 llvm_unreachable("routine shouldn't handled here");
2040 case OpenACCDirectiveKind::Declare: {
2041 // Declare and routine arei declaration directives, but can be used here as
2042 // long as we wrap it in a DeclStmt. So make sure we do that here.
2043 DeclGroupRef DR = ActOnEndDeclDirective(K, StartLoc, DirLoc, LParenLoc,
2044 RParenLoc, EndLoc, Clauses);
2045
2046 return SemaRef.ActOnDeclStmt(Decl: DeclGroupPtrTy::make(P: DR), StartLoc, EndLoc);
2047 }
2048 }
2049 llvm_unreachable("Unhandled case in directive handling?");
2050}
2051
2052StmtResult SemaOpenACC::ActOnAssociatedStmt(
2053 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
2054 OpenACCAtomicKind AtKind, ArrayRef<const OpenACCClause *> Clauses,
2055 StmtResult AssocStmt) {
2056 switch (K) {
2057 default:
2058 llvm_unreachable("Unimplemented associated statement application");
2059 case OpenACCDirectiveKind::EnterData:
2060 case OpenACCDirectiveKind::ExitData:
2061 case OpenACCDirectiveKind::Wait:
2062 case OpenACCDirectiveKind::Init:
2063 case OpenACCDirectiveKind::Shutdown:
2064 case OpenACCDirectiveKind::Set:
2065 case OpenACCDirectiveKind::Cache:
2066 llvm_unreachable(
2067 "these don't have associated statements, so shouldn't get here");
2068 case OpenACCDirectiveKind::Atomic:
2069 return CheckAtomicAssociatedStmt(AtomicDirLoc: DirectiveLoc, AtKind, AssocStmt);
2070 case OpenACCDirectiveKind::Parallel:
2071 case OpenACCDirectiveKind::Serial:
2072 case OpenACCDirectiveKind::Kernels:
2073 case OpenACCDirectiveKind::Data:
2074 case OpenACCDirectiveKind::HostData:
2075 // There really isn't any checking here that could happen. As long as we
2076 // have a statement to associate, this should be fine.
2077 // OpenACC 3.3 Section 6:
2078 // Structured Block: in C or C++, an executable statement, possibly
2079 // compound, with a single entry at the top and a single exit at the
2080 // bottom.
2081 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
2082 // an interpretation of it is to allow this and treat the initializer as
2083 // the 'structured block'.
2084 return AssocStmt;
2085 case OpenACCDirectiveKind::Loop:
2086 case OpenACCDirectiveKind::ParallelLoop:
2087 case OpenACCDirectiveKind::SerialLoop:
2088 case OpenACCDirectiveKind::KernelsLoop:
2089 if (!AssocStmt.isUsable())
2090 return StmtError();
2091
2092 if (!isa<CXXForRangeStmt, ForStmt>(Val: AssocStmt.get())) {
2093 Diag(Loc: AssocStmt.get()->getBeginLoc(), DiagID: diag::err_acc_loop_not_for_loop)
2094 << K;
2095 Diag(Loc: DirectiveLoc, DiagID: diag::note_acc_construct_here) << K;
2096 return StmtError();
2097 }
2098
2099 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
2100 if (!CollapseInfo.CollapseDepthSatisfied) {
2101 Diag(Loc: DirectiveLoc, DiagID: diag::err_acc_insufficient_loops)
2102 << OpenACCClauseKind::Collapse;
2103 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2104 Diag(Loc: CollapseInfo.ActiveCollapse->getBeginLoc(),
2105 DiagID: diag::note_acc_active_clause_here)
2106 << OpenACCClauseKind::Collapse;
2107 }
2108
2109 if (!TileInfo.TileDepthSatisfied) {
2110 Diag(Loc: DirectiveLoc, DiagID: diag::err_acc_insufficient_loops)
2111 << OpenACCClauseKind::Tile;
2112 assert(TileInfo.ActiveTile && "Collapse count without object?");
2113 Diag(Loc: TileInfo.ActiveTile->getBeginLoc(),
2114 DiagID: diag::note_acc_active_clause_here)
2115 << OpenACCClauseKind::Tile;
2116 }
2117 return StmtError();
2118 }
2119
2120 return AssocStmt.get();
2121 }
2122 llvm_unreachable("Invalid associated statement application");
2123}
2124
2125namespace {
2126
2127// Routine has some pretty complicated set of rules for how device_type
2128// interacts with 'gang', 'worker', 'vector', and 'seq'. Enforce part of it
2129// here.
2130bool CheckValidRoutineGangWorkerVectorSeqClauses(
2131 SemaOpenACC &SemaRef, SourceLocation DirectiveLoc,
2132 ArrayRef<const OpenACCClause *> Clauses) {
2133 auto RequiredPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
2134 OpenACCVectorClause, OpenACCSeqClause>;
2135 // The clause handling has assured us that there is no duplicates. That is,
2136 // if there is 1 before a device_type, there are none after a device_type.
2137 // If not, there is at most 1 applying to each device_type.
2138
2139 // What is left to legalize is that either:
2140 // 1- there is 1 before the first device_type.
2141 // 2- there is 1 AFTER each device_type.
2142 auto *FirstDeviceType =
2143 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCDeviceTypeClause>);
2144
2145 // If there is 1 before the first device_type (or at all if no device_type),
2146 // we are legal.
2147 auto *ClauseItr =
2148 std::find_if(first: Clauses.begin(), last: FirstDeviceType, pred: RequiredPred);
2149
2150 if (ClauseItr != FirstDeviceType)
2151 return false;
2152
2153 // If there IS no device_type, and no clause, diagnose.
2154 if (FirstDeviceType == Clauses.end())
2155 return SemaRef.Diag(Loc: DirectiveLoc, DiagID: diag::err_acc_construct_one_clause_of)
2156 << OpenACCDirectiveKind::Routine
2157 << "'gang', 'seq', 'vector', or 'worker'";
2158
2159 // Else, we have to check EACH device_type group. PrevDeviceType is the
2160 // device-type before the current group.
2161 auto *PrevDeviceType = FirstDeviceType;
2162
2163 while (PrevDeviceType != Clauses.end()) {
2164 auto *NextDeviceType =
2165 std::find_if(first: std::next(x: PrevDeviceType), last: Clauses.end(),
2166 pred: llvm::IsaPred<OpenACCDeviceTypeClause>);
2167
2168 ClauseItr = std::find_if(first: PrevDeviceType, last: NextDeviceType, pred: RequiredPred);
2169
2170 if (ClauseItr == NextDeviceType)
2171 return SemaRef.Diag(Loc: (*PrevDeviceType)->getBeginLoc(),
2172 DiagID: diag::err_acc_clause_routine_one_of_in_region);
2173
2174 PrevDeviceType = NextDeviceType;
2175 }
2176
2177 return false;
2178}
2179} // namespace
2180
2181bool SemaOpenACC::ActOnStartDeclDirective(
2182 OpenACCDirectiveKind K, SourceLocation StartLoc,
2183 ArrayRef<const OpenACCClause *> Clauses) {
2184 // OpenCC3.3 2.1 (line 889)
2185 // A program must not depend on the order of evaluation of expressions in
2186 // clause arguments or on any side effects of the evaluations.
2187 SemaRef.DiscardCleanupsInEvaluationContext();
2188 SemaRef.PopExpressionEvaluationContext();
2189
2190 if (DiagnoseRequiredClauses(DK: K, DirLoc: StartLoc, Clauses))
2191 return true;
2192 if (K == OpenACCDirectiveKind::Routine &&
2193 CheckValidRoutineGangWorkerVectorSeqClauses(SemaRef&: *this, DirectiveLoc: StartLoc, Clauses))
2194 return true;
2195
2196 return diagnoseConstructAppertainment(S&: *this, K, StartLoc, /*IsStmt=*/false);
2197}
2198
2199DeclGroupRef SemaOpenACC::ActOnEndDeclDirective(
2200 OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
2201 SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc,
2202 ArrayRef<OpenACCClause *> Clauses) {
2203 switch (K) {
2204 default:
2205 case OpenACCDirectiveKind::Invalid:
2206 return DeclGroupRef{};
2207 case OpenACCDirectiveKind::Declare: {
2208 // OpenACC3.3 2.13: At least one clause must appear on a declare directive.
2209 if (Clauses.empty()) {
2210 Diag(Loc: EndLoc, DiagID: diag::err_acc_declare_required_clauses);
2211 // No reason to add this to the AST, as we would just end up trying to
2212 // instantiate this, which would double-diagnose here, which we wouldn't
2213 // want to do.
2214 return DeclGroupRef{};
2215 }
2216
2217 auto *DeclareDecl = OpenACCDeclareDecl::Create(
2218 Ctx&: getASTContext(), DC: getCurContext(), StartLoc, DirLoc, EndLoc, Clauses);
2219 DeclareDecl->setAccess(AS_public);
2220 getCurContext()->addDecl(D: DeclareDecl);
2221 return DeclGroupRef{DeclareDecl};
2222 }
2223 case OpenACCDirectiveKind::Routine:
2224 llvm_unreachable("routine shouldn't be handled here");
2225 }
2226 llvm_unreachable("unhandled case in directive handling?");
2227}
2228
2229namespace {
2230// Given the decl on the next line, figure out if it is one that is acceptable
2231// to `routine`, or looks like the sort of decl we should be diagnosing against.
2232FunctionDecl *LegalizeNextParsedDecl(Decl *D) {
2233 if (!D)
2234 return nullptr;
2235
2236 // Functions are per-fact acceptable as-is.
2237 if (auto *FD = dyn_cast<FunctionDecl>(Val: D))
2238 return FD;
2239
2240 // Function templates are functions, so attach to the templated decl.
2241 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
2242 return FTD->getTemplatedDecl();
2243
2244 if (auto *FD = dyn_cast<FieldDecl>(Val: D)) {
2245 auto *RD =
2246 FD->getType().isNull() ? nullptr : FD->getType()->getAsCXXRecordDecl();
2247
2248 if (RD && RD->isGenericLambda())
2249 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2250 if (RD && RD->isLambda())
2251 return RD->getLambdaCallOperator();
2252 }
2253 // VarDecl we can look at the init instead of the type of the variable, this
2254 // makes us more tolerant of the 'auto' deduced type.
2255 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
2256 Expr *Init = VD->getInit();
2257 if (!Init || Init->getType().isNull())
2258 return nullptr;
2259
2260 const auto *RD = Init->getType()->getAsCXXRecordDecl();
2261 if (RD && RD->isGenericLambda())
2262 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2263 if (RD && RD->isLambda())
2264 return RD->getLambdaCallOperator();
2265
2266 // FIXME: We could try harder in the case where this is a dependent thing
2267 // that ends up being a lambda (that is, the init is an unresolved lookup
2268 // expr), but we can't attach to the call/lookup expr. If we instead try to
2269 // attach to the VarDecl, when we go to instantiate it, attributes are
2270 // instantiated before the init, so we can't actually see the type at any
2271 // point where it would be relevant/able to be checked. We could perhaps do
2272 // some sort of 'after-init' instantiation/checking here, but that doesn't
2273 // seem valuable for a situation that other compilers don't handle.
2274 }
2275 return nullptr;
2276}
2277
2278void CreateRoutineDeclAttr(SemaOpenACC &SemaRef, SourceLocation DirLoc,
2279 ArrayRef<const OpenACCClause *> Clauses,
2280 ValueDecl *AddTo) {
2281 OpenACCRoutineDeclAttr *A =
2282 OpenACCRoutineDeclAttr::Create(Ctx&: SemaRef.getASTContext(), Range: DirLoc);
2283 A->Clauses.assign(in_start: Clauses.begin(), in_end: Clauses.end());
2284 AddTo->addAttr(A);
2285}
2286} // namespace
2287
2288// Variant that adds attributes, because this is the unnamed case.
2289void SemaOpenACC::CheckRoutineDecl(SourceLocation DirLoc,
2290 ArrayRef<const OpenACCClause *> Clauses,
2291 Decl *NextParsedDecl) {
2292
2293 FunctionDecl *NextParsedFDecl = LegalizeNextParsedDecl(D: NextParsedDecl);
2294
2295 if (!NextParsedFDecl) {
2296 // If we don't have a valid 'next thing', just diagnose.
2297 SemaRef.Diag(Loc: DirLoc, DiagID: diag::err_acc_decl_for_routine);
2298 return;
2299 }
2300
2301 // OpenACC 3.3 2.15:
2302 // In C and C++, function static variables are not supported in functions to
2303 // which a routine directive applies.
2304 if (auto Itr = MagicStaticLocs.find(Val: NextParsedFDecl->getCanonicalDecl());
2305 Itr != MagicStaticLocs.end()) {
2306 Diag(Loc: Itr->second, DiagID: diag::err_acc_magic_static_in_routine);
2307 Diag(Loc: DirLoc, DiagID: diag::note_acc_construct_here)
2308 << OpenACCDirectiveKind::Routine;
2309
2310 return;
2311 }
2312
2313 auto BindItr = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCBindClause>);
2314 for (auto *A : NextParsedFDecl->attrs()) {
2315 // OpenACC 3.3 2.15:
2316 // If a procedure has a bind clause on both the declaration and definition
2317 // than they both must bind to the same name.
2318 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(Val: A)) {
2319 auto OtherBindItr =
2320 llvm::find_if(Range&: RA->Clauses, P: llvm::IsaPred<OpenACCBindClause>);
2321 if (OtherBindItr != RA->Clauses.end() &&
2322 (*cast<OpenACCBindClause>(Val: *BindItr)) !=
2323 (*cast<OpenACCBindClause>(Val: *OtherBindItr))) {
2324 Diag(Loc: (*BindItr)->getBeginLoc(), DiagID: diag::err_acc_duplicate_unnamed_bind);
2325 Diag(Loc: (*OtherBindItr)->getEndLoc(), DiagID: diag::note_acc_previous_clause_here)
2326 << (*BindItr)->getClauseKind();
2327 return;
2328 }
2329 }
2330
2331 // OpenACC 3.3 2.15:
2332 // A bind clause may not bind to a routine name that has a visible bind
2333 // clause.
2334 // We take the combo of these two 2.15 restrictions to mean that the
2335 // 'declaration'/'definition' quote is an exception to this. So we're going
2336 // to disallow mixing of the two types entirely.
2337 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(Val: A);
2338 RA && RA->getRange().getEnd().isValid()) {
2339 Diag(Loc: (*BindItr)->getBeginLoc(), DiagID: diag::err_acc_duplicate_bind);
2340 Diag(Loc: RA->getRange().getEnd(), DiagID: diag::note_acc_previous_clause_here)
2341 << "bind";
2342 return;
2343 }
2344 }
2345
2346 CreateRoutineDeclAttr(SemaRef&: *this, DirLoc, Clauses, AddTo: NextParsedFDecl);
2347}
2348
2349// Variant that adds a decl, because this is the named case.
2350OpenACCRoutineDecl *SemaOpenACC::CheckRoutineDecl(
2351 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2352 Expr *FuncRef, SourceLocation RParenLoc,
2353 ArrayRef<const OpenACCClause *> Clauses, SourceLocation EndLoc) {
2354 assert(LParenLoc.isValid());
2355
2356 if (FunctionDecl *FD = getFunctionFromRoutineName(RoutineName: FuncRef)) {
2357 // OpenACC 3.3 2.15:
2358 // In C and C++, function static variables are not supported in functions to
2359 // which a routine directive applies.
2360 if (auto Itr = MagicStaticLocs.find(Val: FD->getCanonicalDecl());
2361 Itr != MagicStaticLocs.end()) {
2362 Diag(Loc: Itr->second, DiagID: diag::err_acc_magic_static_in_routine);
2363 Diag(Loc: DirLoc, DiagID: diag::note_acc_construct_here)
2364 << OpenACCDirectiveKind::Routine;
2365
2366 return nullptr;
2367 }
2368
2369 // OpenACC 3.3 2.15:
2370 // A bind clause may not bind to a routine name that has a visible bind
2371 // clause.
2372 auto BindItr = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCBindClause>);
2373 SourceLocation BindLoc;
2374 if (BindItr != Clauses.end()) {
2375 BindLoc = (*BindItr)->getBeginLoc();
2376 // Since this is adding a 'named' routine, we aren't allowed to combine
2377 // with ANY other visible bind clause. Error if we see either.
2378
2379 for (auto *A : FD->attrs()) {
2380 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(Val: A)) {
2381 auto OtherBindItr =
2382 llvm::find_if(Range&: RA->Clauses, P: llvm::IsaPred<OpenACCBindClause>);
2383 if (OtherBindItr != RA->Clauses.end()) {
2384 Diag(Loc: (*BindItr)->getBeginLoc(), DiagID: diag::err_acc_duplicate_bind);
2385 Diag(Loc: (*OtherBindItr)->getEndLoc(),
2386 DiagID: diag::note_acc_previous_clause_here)
2387 << (*BindItr)->getClauseKind();
2388 return nullptr;
2389 }
2390 }
2391
2392 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(Val: A);
2393 RA && RA->getRange().getEnd().isValid()) {
2394 Diag(Loc: (*BindItr)->getBeginLoc(), DiagID: diag::err_acc_duplicate_bind);
2395 Diag(Loc: RA->getRange().getEnd(), DiagID: diag::note_acc_previous_clause_here)
2396 << (*BindItr)->getClauseKind();
2397 return nullptr;
2398 }
2399 }
2400 }
2401
2402 // Set the end-range to the 'bind' clause here, so we can look it up
2403 // later.
2404 auto *RAA = OpenACCRoutineAnnotAttr::CreateImplicit(Ctx&: getASTContext(),
2405 Range: {DirLoc, BindLoc});
2406 FD->addAttr(A: RAA);
2407 // In case we are referencing not the 'latest' version, make sure we add
2408 // the attribute to all declarations.
2409 while (FD != FD->getMostRecentDecl()) {
2410 FD = FD->getMostRecentDecl();
2411 FD->addAttr(A: RAA);
2412 }
2413 }
2414
2415 LastRoutineDecl = OpenACCRoutineDecl::Create(
2416 Ctx&: getASTContext(), DC: getCurContext(), StartLoc, DirLoc, LParenLoc, FuncRef,
2417 RParenLoc, EndLoc, Clauses);
2418 LastRoutineDecl->setAccess(AS_public);
2419 getCurContext()->addDecl(D: LastRoutineDecl);
2420
2421 return LastRoutineDecl;
2422}
2423
2424DeclGroupRef SemaOpenACC::ActOnEndRoutineDeclDirective(
2425 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2426 Expr *ReferencedFunc, SourceLocation RParenLoc,
2427 ArrayRef<const OpenACCClause *> Clauses, SourceLocation EndLoc,
2428 DeclGroupPtrTy NextDecl) {
2429 assert((!ReferencedFunc || !NextDecl) &&
2430 "Only one of these should be filled");
2431
2432 if (LParenLoc.isInvalid()) {
2433 Decl *NextLineDecl = nullptr;
2434 if (NextDecl && NextDecl.get().isSingleDecl())
2435 NextLineDecl = NextDecl.get().getSingleDecl();
2436
2437 CheckRoutineDecl(DirLoc, Clauses, NextParsedDecl: NextLineDecl);
2438
2439 return NextDecl.get();
2440 }
2441
2442 return DeclGroupRef{CheckRoutineDecl(
2443 StartLoc, DirLoc, LParenLoc, FuncRef: ReferencedFunc, RParenLoc, Clauses, EndLoc)};
2444}
2445
2446StmtResult SemaOpenACC::ActOnEndRoutineStmtDirective(
2447 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2448 Expr *ReferencedFunc, SourceLocation RParenLoc,
2449 ArrayRef<const OpenACCClause *> Clauses, SourceLocation EndLoc,
2450 Stmt *NextStmt) {
2451 assert((!ReferencedFunc || !NextStmt) &&
2452 "Only one of these should be filled");
2453
2454 if (LParenLoc.isInvalid()) {
2455 Decl *NextLineDecl = nullptr;
2456 if (NextStmt)
2457 if (DeclStmt *DS = dyn_cast<DeclStmt>(Val: NextStmt); DS && DS->isSingleDecl())
2458 NextLineDecl = DS->getSingleDecl();
2459
2460 CheckRoutineDecl(DirLoc, Clauses, NextParsedDecl: NextLineDecl);
2461 return NextStmt;
2462 }
2463
2464 DeclGroupRef DR{CheckRoutineDecl(StartLoc, DirLoc, LParenLoc, FuncRef: ReferencedFunc,
2465 RParenLoc, Clauses, EndLoc)};
2466 return SemaRef.ActOnDeclStmt(Decl: DeclGroupPtrTy::make(P: DR), StartLoc, EndLoc);
2467}
2468
2469OpenACCRoutineDeclAttr *
2470SemaOpenACC::mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old) {
2471 OpenACCRoutineDeclAttr *New =
2472 OpenACCRoutineDeclAttr::Create(Ctx&: getASTContext(), Range: Old.getLocation());
2473 // We should jsut be able to copy these, there isn't really any
2474 // merging/inheriting we have to do, so no worry about doing a deep copy.
2475 New->Clauses = Old.Clauses;
2476 return New;
2477}
2478ExprResult
2479SemaOpenACC::BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
2480 return OpenACCAsteriskSizeExpr::Create(C: getASTContext(), Loc: AsteriskLoc);
2481}
2482
2483ExprResult
2484SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
2485 return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
2486}
2487