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(StartLoc, 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, 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, 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, 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(Conv->getLocation(), 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, 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(Conv->getLocation(), 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(VarExpr->getExprLoc(), diag::err_array_section_use) << /*OpenACC=*/0;
505 Diag(VarExpr->getExprLoc(), 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(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)
518 << ClauseKind << Ty;
519 return false;
520}
521
522ExprResult SemaOpenACC::ActOnCacheVar(Expr *VarExpr) {
523 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
524 if (!isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) {
525 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
526 return ExprError();
527 }
528
529 // It isn't clear what 'simple array element or simple subarray' means, so we
530 // will just allow arbitrary depth.
531 while (isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) {
532 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(Val: CurVarExpr))
533 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
534 else
535 CurVarExpr =
536 cast<ArraySectionExpr>(Val: CurVarExpr)->getBase()->IgnoreParenImpCasts();
537 }
538
539 // References to a VarDecl are fine.
540 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: CurVarExpr)) {
541 if (isa<VarDecl, NonTypeTemplateParmDecl>(
542 DRE->getFoundDecl()->getCanonicalDecl()))
543 return VarExpr;
544 }
545
546 if (const auto *ME = dyn_cast<MemberExpr>(Val: CurVarExpr)) {
547 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
548 return VarExpr;
549 }
550 }
551
552 // Nothing really we can do here, as these are dependent. So just return they
553 // are valid.
554 if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(Val: CurVarExpr))
555 return VarExpr;
556
557 // There isn't really anything we can do in the case of a recovery expr, so
558 // skip the diagnostic rather than produce a confusing diagnostic.
559 if (isa<RecoveryExpr>(Val: CurVarExpr))
560 return ExprError();
561
562 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
563 return ExprError();
564}
565ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
566 Expr *VarExpr) {
567 // This has unique enough restrictions that we should split it to a separate
568 // function.
569 if (DK == OpenACCDirectiveKind::Cache)
570 return ActOnCacheVar(VarExpr);
571
572 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
573
574 // 'use_device' doesn't allow array subscript or array sections.
575 // OpenACC3.3 2.8:
576 // A 'var' in a 'use_device' clause must be the name of a variable or array.
577 // OpenACC3.3 2.13:
578 // A 'var' in a 'declare' directive must be a variable or array name.
579 if ((CK == OpenACCClauseKind::UseDevice ||
580 DK == OpenACCDirectiveKind::Declare) &&
581 isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) {
582 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
583 << (DK == OpenACCDirectiveKind::Declare);
584 return ExprError();
585 }
586
587 // Sub-arrays/subscript-exprs are fine as long as the base is a
588 // VarExpr/MemberExpr. So strip all of those off.
589 while (isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) {
590 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(Val: CurVarExpr))
591 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
592 else
593 CurVarExpr =
594 cast<ArraySectionExpr>(Val: CurVarExpr)->getBase()->IgnoreParenImpCasts();
595 }
596
597 // References to a VarDecl are fine.
598 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: CurVarExpr)) {
599 if (isa<VarDecl, NonTypeTemplateParmDecl>(
600 DRE->getFoundDecl()->getCanonicalDecl()))
601 return VarExpr;
602 }
603
604 // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
605 // reduction clause must be a scalar variable name, an aggregate variable
606 // name, an array element, or a subarray.
607 // If CK is a 'use_device', this also isn't valid, as it isn't the name of a
608 // variable or array, if not done as a member expr.
609 // A MemberExpr that references a Field is valid for other clauses.
610 if (const auto *ME = dyn_cast<MemberExpr>(Val: CurVarExpr)) {
611 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
612 if (DK == OpenACCDirectiveKind::Declare ||
613 CK == OpenACCClauseKind::Reduction ||
614 CK == OpenACCClauseKind::UseDevice) {
615
616 // We can allow 'member expr' if the 'this' is implicit in the case of
617 // declare, reduction, and use_device.
618 const auto *This = dyn_cast<CXXThisExpr>(Val: ME->getBase());
619 if (This && This->isImplicit())
620 return VarExpr;
621 } else {
622 return VarExpr;
623 }
624 }
625 }
626
627 // Referring to 'this' is ok for the most part, but for 'use_device'/'declare'
628 // doesn't fall into 'variable or array name'
629 if (CK != OpenACCClauseKind::UseDevice &&
630 DK != OpenACCDirectiveKind::Declare && isa<CXXThisExpr>(Val: CurVarExpr))
631 return VarExpr;
632
633 // Nothing really we can do here, as these are dependent. So just return they
634 // are valid.
635 if (isa<DependentScopeDeclRefExpr>(Val: CurVarExpr) ||
636 (CK != OpenACCClauseKind::Reduction &&
637 isa<CXXDependentScopeMemberExpr>(Val: CurVarExpr)))
638 return VarExpr;
639
640 // There isn't really anything we can do in the case of a recovery expr, so
641 // skip the diagnostic rather than produce a confusing diagnostic.
642 if (isa<RecoveryExpr>(Val: CurVarExpr))
643 return ExprError();
644
645 if (DK == OpenACCDirectiveKind::Declare)
646 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
647 << /*declare*/ 1;
648 else if (CK == OpenACCClauseKind::UseDevice)
649 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
650 << /*use_device*/ 0;
651 else
652 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
653 << (CK != OpenACCClauseKind::Reduction);
654 return ExprError();
655}
656
657ExprResult SemaOpenACC::ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
658 Expr *LowerBound,
659 SourceLocation ColonLoc,
660 Expr *Length,
661 SourceLocation RBLoc) {
662 ASTContext &Context = getASTContext();
663
664 // Handle placeholders.
665 if (Base->hasPlaceholderType() &&
666 !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
667 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base);
668 if (Result.isInvalid())
669 return ExprError();
670 Base = Result.get();
671 }
672 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
673 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound);
674 if (Result.isInvalid())
675 return ExprError();
676 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
677 if (Result.isInvalid())
678 return ExprError();
679 LowerBound = Result.get();
680 }
681 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
682 ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length);
683 if (Result.isInvalid())
684 return ExprError();
685 Result = SemaRef.DefaultLvalueConversion(E: Result.get());
686 if (Result.isInvalid())
687 return ExprError();
688 Length = Result.get();
689 }
690
691 // Check the 'base' value, it must be an array or pointer type, and not to/of
692 // a function type.
693 QualType OriginalBaseTy = ArraySectionExpr::getBaseOriginalType(Base);
694 QualType ResultTy;
695 if (!Base->isTypeDependent()) {
696 if (OriginalBaseTy->isAnyPointerType()) {
697 ResultTy = OriginalBaseTy->getPointeeType();
698 } else if (OriginalBaseTy->isArrayType()) {
699 ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
700 } else {
701 return ExprError(
702 Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
703 << Base->getSourceRange());
704 }
705
706 if (ResultTy->isFunctionType()) {
707 Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
708 << ResultTy << Base->getSourceRange();
709 return ExprError();
710 }
711
712 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
713 diag::err_acc_subarray_incomplete_type,
714 Base))
715 return ExprError();
716
717 if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) {
718 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base);
719 if (Result.isInvalid())
720 return ExprError();
721 Base = Result.get();
722 }
723 }
724
725 auto GetRecovery = [&](Expr *E, QualType Ty) {
726 ExprResult Recovery =
727 SemaRef.CreateRecoveryExpr(Begin: E->getBeginLoc(), End: E->getEndLoc(), SubExprs: E, T: Ty);
728 return Recovery.isUsable() ? Recovery.get() : nullptr;
729 };
730
731 // Ensure both of the expressions are int-exprs.
732 if (LowerBound && !LowerBound->isTypeDependent()) {
733 ExprResult LBRes =
734 ActOnIntExpr(DK: OpenACCDirectiveKind::Invalid, CK: OpenACCClauseKind::Invalid,
735 Loc: LowerBound->getExprLoc(), IntExpr: LowerBound);
736
737 if (LBRes.isUsable())
738 LBRes = SemaRef.DefaultLvalueConversion(E: LBRes.get());
739 LowerBound =
740 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
741 }
742
743 if (Length && !Length->isTypeDependent()) {
744 ExprResult LenRes =
745 ActOnIntExpr(DK: OpenACCDirectiveKind::Invalid, CK: OpenACCClauseKind::Invalid,
746 Loc: Length->getExprLoc(), IntExpr: Length);
747
748 if (LenRes.isUsable())
749 LenRes = SemaRef.DefaultLvalueConversion(E: LenRes.get());
750 Length =
751 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
752 }
753
754 // Length is required if the base type is not an array of known bounds.
755 if (!Length && (OriginalBaseTy.isNull() ||
756 (!OriginalBaseTy->isDependentType() &&
757 !OriginalBaseTy->isConstantArrayType() &&
758 !OriginalBaseTy->isDependentSizedArrayType()))) {
759 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
760 SourceLocation DiagLoc = ColonLoc.isInvalid() ? LBLoc : ColonLoc;
761 Diag(DiagLoc, diag::err_acc_subarray_no_length) << IsArray;
762 // Fill in a dummy 'length' so that when we instantiate this we don't
763 // double-diagnose here.
764 ExprResult Recovery = SemaRef.CreateRecoveryExpr(
765 Begin: DiagLoc, End: SourceLocation(), SubExprs: ArrayRef<Expr *>(), T: Context.IntTy);
766 Length = Recovery.isUsable() ? Recovery.get() : nullptr;
767 }
768
769 // Check the values of each of the arguments, they cannot be negative(we
770 // assume), and if the array bound is known, must be within range. As we do
771 // so, do our best to continue with evaluation, we can set the
772 // value/expression to nullptr/nullopt if they are invalid, and treat them as
773 // not present for the rest of evaluation.
774
775 // We don't have to check for dependence, because the dependent size is
776 // represented as a different AST node.
777 std::optional<llvm::APSInt> BaseSize;
778 if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
779 const auto *ArrayTy = Context.getAsConstantArrayType(T: OriginalBaseTy);
780 BaseSize = ArrayTy->getSize();
781 }
782
783 auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
784 if (!E || E->isInstantiationDependent())
785 return std::nullopt;
786
787 Expr::EvalResult Res;
788 if (!E->EvaluateAsInt(Result&: Res, Ctx: Context))
789 return std::nullopt;
790 return Res.Val.getInt();
791 };
792
793 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
794 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
795
796 // Check lower bound for negative or out of range.
797 if (LowerBoundValue.has_value()) {
798 if (LowerBoundValue->isNegative()) {
799 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
800 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
801 LowerBoundValue.reset();
802 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
803 } else if (BaseSize.has_value() &&
804 llvm::APSInt::compareValues(I1: *LowerBoundValue, I2: *BaseSize) >= 0) {
805 // Lower bound (start index) must be less than the size of the array.
806 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
807 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
808 << toString(*BaseSize, /*Radix=*/10);
809 LowerBoundValue.reset();
810 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
811 }
812 }
813
814 // Check length for negative or out of range.
815 if (LengthValue.has_value()) {
816 if (LengthValue->isNegative()) {
817 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
818 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
819 LengthValue.reset();
820 Length = GetRecovery(Length, Length->getType());
821 } else if (BaseSize.has_value() &&
822 llvm::APSInt::compareValues(I1: *LengthValue, I2: *BaseSize) > 0) {
823 // Length must be lessthan or EQUAL to the size of the array.
824 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
825 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
826 << toString(*BaseSize, /*Radix=*/10);
827 LengthValue.reset();
828 Length = GetRecovery(Length, Length->getType());
829 }
830 }
831
832 // Adding two APSInts requires matching sign, so extract that here.
833 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
834 if (LHS.isSigned() == RHS.isSigned())
835 return LHS + RHS;
836
837 unsigned Width = std::max(a: LHS.getBitWidth(), b: RHS.getBitWidth()) + 1;
838 return llvm::APSInt(LHS.sext(width: Width) + RHS.sext(width: Width), /*Signed=*/true);
839 };
840
841 // If we know all 3 values, we can diagnose that the total value would be out
842 // of range.
843 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
844 LengthValue.has_value() &&
845 llvm::APSInt::compareValues(I1: AddAPSInt(*LowerBoundValue, *LengthValue),
846 I2: *BaseSize) > 0) {
847 Diag(Base->getExprLoc(),
848 diag::err_acc_subarray_base_plus_length_out_of_range)
849 << toString(*LowerBoundValue, /*Radix=*/10)
850 << toString(*LengthValue, /*Radix=*/10)
851 << toString(*BaseSize, /*Radix=*/10);
852
853 LowerBoundValue.reset();
854 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
855 LengthValue.reset();
856 Length = GetRecovery(Length, Length->getType());
857 }
858
859 // If any part of the expression is dependent, return a dependent sub-array.
860 QualType ArrayExprTy = Context.ArraySectionTy;
861 if (Base->isTypeDependent() ||
862 (LowerBound && LowerBound->isInstantiationDependent()) ||
863 (Length && Length->isInstantiationDependent()))
864 ArrayExprTy = Context.DependentTy;
865
866 return new (Context)
867 ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
868 OK_Ordinary, ColonLoc, RBLoc);
869}
870
871void SemaOpenACC::ActOnWhileStmt(SourceLocation WhileLoc) {
872 if (!getLangOpts().OpenACC)
873 return;
874
875 if (!LoopInfo.TopLevelLoopSeen)
876 return;
877
878 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
879 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
880 << /*while loop*/ 1 << CollapseInfo.DirectiveKind
881 << OpenACCClauseKind::Collapse;
882 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
883 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
884 diag::note_acc_active_clause_here)
885 << OpenACCClauseKind::Collapse;
886
887 // Remove the value so that we don't get cascading errors in the body. The
888 // caller RAII object will restore this.
889 CollapseInfo.CurCollapseCount = std::nullopt;
890 }
891
892 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
893 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
894 << /*while loop*/ 1 << TileInfo.DirectiveKind
895 << OpenACCClauseKind::Tile;
896 assert(TileInfo.ActiveTile && "tile count without object?");
897 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
898 << OpenACCClauseKind::Tile;
899
900 // Remove the value so that we don't get cascading errors in the body. The
901 // caller RAII object will restore this.
902 TileInfo.CurTileCount = std::nullopt;
903 }
904}
905
906void SemaOpenACC::ActOnDoStmt(SourceLocation DoLoc) {
907 if (!getLangOpts().OpenACC)
908 return;
909
910 if (!LoopInfo.TopLevelLoopSeen)
911 return;
912
913 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
914 Diag(DoLoc, diag::err_acc_invalid_in_loop)
915 << /*do loop*/ 2 << CollapseInfo.DirectiveKind
916 << OpenACCClauseKind::Collapse;
917 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
918 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
919 diag::note_acc_active_clause_here)
920 << OpenACCClauseKind::Collapse;
921
922 // Remove the value so that we don't get cascading errors in the body. The
923 // caller RAII object will restore this.
924 CollapseInfo.CurCollapseCount = std::nullopt;
925 }
926
927 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
928 Diag(DoLoc, diag::err_acc_invalid_in_loop)
929 << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
930 assert(TileInfo.ActiveTile && "tile count without object?");
931 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
932 << OpenACCClauseKind::Tile;
933
934 // Remove the value so that we don't get cascading errors in the body. The
935 // caller RAII object will restore this.
936 TileInfo.CurTileCount = std::nullopt;
937 }
938}
939
940void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
941 ForStmtBeginChecker &C) {
942 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
943
944 // Enable the while/do-while checking.
945 LoopInfo.TopLevelLoopSeen = true;
946
947 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
948 // Check the format of this loop if it is affected by the collapse.
949 C.check();
950
951 // OpenACC 3.3 2.9.1:
952 // Each associated loop, except the innermost, must contain exactly one loop
953 // or loop nest.
954 // This checks for more than 1 loop at the current level, the
955 // 'depth'-satisifed checking manages the 'not zero' case.
956 if (LoopInfo.CurLevelHasLoopAlready) {
957 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
958 << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
959 assert(CollapseInfo.ActiveCollapse && "No collapse object?");
960 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
961 diag::note_acc_active_clause_here)
962 << OpenACCClauseKind::Collapse;
963 } else {
964 --(*CollapseInfo.CurCollapseCount);
965
966 // Once we've hit zero here, we know we have deep enough 'for' loops to
967 // get to the bottom.
968 if (*CollapseInfo.CurCollapseCount == 0)
969 CollapseInfo.CollapseDepthSatisfied = true;
970 }
971 }
972
973 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
974 // Check the format of this loop if it is affected by the tile.
975 C.check();
976
977 if (LoopInfo.CurLevelHasLoopAlready) {
978 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
979 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
980 assert(TileInfo.ActiveTile && "No tile object?");
981 Diag(TileInfo.ActiveTile->getBeginLoc(),
982 diag::note_acc_active_clause_here)
983 << OpenACCClauseKind::Tile;
984 } else {
985 TileInfo.CurTileCount = *TileInfo.CurTileCount - 1;
986 // Once we've hit zero here, we know we have deep enough 'for' loops to
987 // get to the bottom.
988 if (*TileInfo.CurTileCount == 0)
989 TileInfo.TileDepthSatisfied = true;
990 }
991 }
992
993 // Set this to 'false' for the body of this loop, so that the next level
994 // checks independently.
995 LoopInfo.CurLevelHasLoopAlready = false;
996}
997
998namespace {
999bool isValidLoopVariableType(QualType LoopVarTy) {
1000 // Just skip if it is dependent, it could be any of the below.
1001 if (LoopVarTy->isDependentType())
1002 return true;
1003
1004 // The loop variable must be of integer,
1005 if (LoopVarTy->isIntegerType())
1006 return true;
1007
1008 // C/C++ pointer,
1009 if (LoopVarTy->isPointerType())
1010 return true;
1011
1012 // or C++ random-access iterator type.
1013 if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
1014 // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
1015 // iterator type!
1016
1017 // We could either do a lot of work to see if this matches
1018 // random-access-iterator, but it seems that just checking that the
1019 // 'iterator_category' typedef is more than sufficient. If programmers are
1020 // willing to lie about this, we can let them.
1021
1022 for (const auto *TD :
1023 llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
1024 const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
1025
1026 if (TDND->getName() != "iterator_category")
1027 continue;
1028
1029 // If there is no type for this decl, return false.
1030 if (TDND->getUnderlyingType().isNull())
1031 return false;
1032
1033 const CXXRecordDecl *ItrCategoryDecl =
1034 TDND->getUnderlyingType()->getAsCXXRecordDecl();
1035
1036 // If the category isn't a record decl, it isn't the tag type.
1037 if (!ItrCategoryDecl)
1038 return false;
1039
1040 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
1041 if (RD->getName() != "random_access_iterator_tag")
1042 return false;
1043 // Checks just for std::random_access_iterator_tag.
1044 return RD->getEnclosingNamespaceContext()->isStdNamespace();
1045 };
1046
1047 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
1048 return true;
1049
1050 // We can also support tag-types inherited from the
1051 // random_access_iterator_tag.
1052 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases())
1053 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
1054 return true;
1055
1056 return false;
1057 }
1058 }
1059
1060 return false;
1061}
1062const ValueDecl *getDeclFromExpr(const Expr *E) {
1063 E = E->IgnoreParenImpCasts();
1064 if (const auto *FE = dyn_cast<FullExpr>(Val: E))
1065 E = FE->getSubExpr();
1066
1067 E = E->IgnoreParenImpCasts();
1068
1069 if (!E)
1070 return nullptr;
1071 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: E))
1072 return dyn_cast<ValueDecl>(Val: DRE->getDecl());
1073
1074 if (const auto *ME = dyn_cast<MemberExpr>(Val: E))
1075 if (isa<CXXThisExpr>(Val: ME->getBase()->IgnoreParenImpCasts()))
1076 return ME->getMemberDecl();
1077
1078 return nullptr;
1079}
1080} // namespace
1081
1082void SemaOpenACC::ForStmtBeginChecker::checkRangeFor() {
1083 const RangeForInfo &RFI = std::get<RangeForInfo>(Info);
1084 // If this hasn't changed since last instantiated we're done.
1085 if (RFI.Uninstantiated == RFI.CurrentVersion)
1086 return;
1087
1088 const DeclStmt *UninstRangeStmt =
1089 IsInstantiation ? RFI.Uninstantiated->getBeginStmt() : nullptr;
1090 const DeclStmt *RangeStmt = RFI.CurrentVersion->getBeginStmt();
1091
1092 // If this isn't the first time we've checked this loop, suppress any cases
1093 // where we previously diagnosed.
1094 if (UninstRangeStmt) {
1095 const ValueDecl *InitVar =
1096 cast<ValueDecl>(Val: UninstRangeStmt->getSingleDecl());
1097 QualType VarType = InitVar->getType().getNonReferenceType();
1098
1099 if (!isValidLoopVariableType(LoopVarTy: VarType))
1100 return;
1101 }
1102
1103 // In some dependent contexts, the autogenerated range statement doesn't get
1104 // included until instantiation, so skip for now.
1105 if (RangeStmt) {
1106 const ValueDecl *InitVar = cast<ValueDecl>(Val: RangeStmt->getSingleDecl());
1107 QualType VarType = InitVar->getType().getNonReferenceType();
1108
1109 if (!isValidLoopVariableType(LoopVarTy: VarType)) {
1110 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1111 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1112 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1113 diag::note_acc_construct_here)
1114 << SemaRef.LoopWithoutSeqInfo.Kind;
1115 return;
1116 }
1117 }
1118}
1119bool SemaOpenACC::ForStmtBeginChecker::checkForInit(const Stmt *InitStmt,
1120 const ValueDecl *&InitVar,
1121 bool Diag) {
1122 // Init statement is required.
1123 if (!InitStmt) {
1124 if (Diag) {
1125 SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)
1126 << SemaRef.LoopWithoutSeqInfo.Kind;
1127 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1128 diag::note_acc_construct_here)
1129 << SemaRef.LoopWithoutSeqInfo.Kind;
1130 }
1131 return true;
1132 }
1133 auto DiagLoopVar = [this, Diag, InitStmt]() {
1134 if (Diag) {
1135 SemaRef.Diag(InitStmt->getBeginLoc(), diag::err_acc_loop_variable)
1136 << SemaRef.LoopWithoutSeqInfo.Kind;
1137 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1138 diag::note_acc_construct_here)
1139 << SemaRef.LoopWithoutSeqInfo.Kind;
1140 }
1141 return true;
1142 };
1143
1144 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: InitStmt))
1145 InitStmt = ExprTemp->getSubExpr();
1146 if (const auto *E = dyn_cast<Expr>(Val: InitStmt))
1147 InitStmt = E->IgnoreParenImpCasts();
1148
1149 InitVar = nullptr;
1150 if (const auto *BO = dyn_cast<BinaryOperator>(Val: InitStmt)) {
1151 // Allow assignment operator here.
1152
1153 if (!BO->isAssignmentOp())
1154 return DiagLoopVar();
1155
1156 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
1157 if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: LHS))
1158 InitVar = DRE->getDecl();
1159 } else if (const auto *DS = dyn_cast<DeclStmt>(Val: InitStmt)) {
1160 // Allow T t = <whatever>
1161 if (!DS->isSingleDecl())
1162 return DiagLoopVar();
1163 InitVar = dyn_cast<ValueDecl>(Val: DS->getSingleDecl());
1164
1165 // Ensure we have an initializer, unless this is a record/dependent type.
1166 if (InitVar) {
1167 if (!isa<VarDecl>(Val: InitVar))
1168 return DiagLoopVar();
1169
1170 if (!InitVar->getType()->isRecordType() &&
1171 !InitVar->getType()->isDependentType() &&
1172 !cast<VarDecl>(Val: InitVar)->hasInit())
1173 return DiagLoopVar();
1174 }
1175 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: InitStmt)) {
1176 // Allow assignment operator call.
1177 if (CE->getOperator() != OO_Equal)
1178 return DiagLoopVar();
1179
1180 const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
1181 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1182 InitVar = DRE->getDecl();
1183 } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
1184 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1185 InitVar = ME->getMemberDecl();
1186 }
1187 }
1188
1189 // If after all of that, we haven't found a variable, give up.
1190 if (!InitVar)
1191 return DiagLoopVar();
1192
1193 InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
1194 QualType VarType = InitVar->getType().getNonReferenceType();
1195
1196 // Since we have one, all we need to do is ensure it is the right type.
1197 if (!isValidLoopVariableType(LoopVarTy: VarType)) {
1198 if (Diag) {
1199 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1200 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1201 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1202 diag::note_acc_construct_here)
1203 << SemaRef.LoopWithoutSeqInfo.Kind;
1204 }
1205 return true;
1206 }
1207
1208 return false;
1209}
1210
1211bool SemaOpenACC::ForStmtBeginChecker::checkForCond(const Stmt *CondStmt,
1212 const ValueDecl *InitVar,
1213 bool Diag) {
1214 // A condition statement is required.
1215 if (!CondStmt) {
1216 if (Diag) {
1217 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
1218 << SemaRef.LoopWithoutSeqInfo.Kind;
1219 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1220 diag::note_acc_construct_here)
1221 << SemaRef.LoopWithoutSeqInfo.Kind;
1222 }
1223
1224 return true;
1225 }
1226 auto DiagCondVar = [this, Diag, CondStmt] {
1227 if (Diag) {
1228 SemaRef.Diag(CondStmt->getBeginLoc(),
1229 diag::err_acc_loop_terminating_condition)
1230 << SemaRef.LoopWithoutSeqInfo.Kind;
1231 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1232 diag::note_acc_construct_here)
1233 << SemaRef.LoopWithoutSeqInfo.Kind;
1234 }
1235 return true;
1236 };
1237
1238 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: CondStmt))
1239 CondStmt = ExprTemp->getSubExpr();
1240 if (const auto *E = dyn_cast<Expr>(Val: CondStmt))
1241 CondStmt = E->IgnoreParenImpCasts();
1242
1243 const ValueDecl *CondVar = nullptr;
1244 if (const auto *BO = dyn_cast<BinaryOperator>(Val: CondStmt)) {
1245 switch (BO->getOpcode()) {
1246 default:
1247 return DiagCondVar();
1248 case BO_EQ:
1249 case BO_LT:
1250 case BO_GT:
1251 case BO_NE:
1252 case BO_LE:
1253 case BO_GE:
1254 break;
1255 }
1256
1257 // Assign the condition-var to the LHS. If it either comes back null, or
1258 // the LHS doesn't match the InitVar, assign it to the RHS so that 5 < N is
1259 // allowed.
1260 CondVar = getDeclFromExpr(E: BO->getLHS());
1261 if (!CondVar ||
1262 (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl()))
1263 CondVar = getDeclFromExpr(E: BO->getRHS());
1264
1265 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: CondStmt)) {
1266 // Any of the comparison ops should be ok here, but we don't know how to
1267 // handle spaceship, so disallow for now.
1268 if (!CE->isComparisonOp() || CE->getOperator() == OO_Spaceship)
1269 return DiagCondVar();
1270
1271 // Same logic here: Assign it to the LHS, unless the LHS comes back null or
1272 // not equal to the init var.
1273 CondVar = getDeclFromExpr(CE->getArg(0));
1274 if (!CondVar ||
1275 (InitVar &&
1276 CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl() &&
1277 CE->getNumArgs() > 1))
1278 CondVar = getDeclFromExpr(CE->getArg(1));
1279 } else {
1280 return DiagCondVar();
1281 }
1282
1283 if (!CondVar)
1284 return DiagCondVar();
1285
1286 // Don't consider this an error unless the init variable was properly set,
1287 // else check to make sure they are the same variable.
1288 if (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1289 return DiagCondVar();
1290
1291 return false;
1292}
1293
1294namespace {
1295// Helper to check the RHS of an assignment during for's step. We can allow
1296// InitVar = InitVar + N, InitVar = N + InitVar, and Initvar = Initvar - N,
1297// where N is an integer.
1298bool isValidForIncRHSAssign(const ValueDecl *InitVar, const Expr *RHS) {
1299
1300 auto isValid = [](const ValueDecl *InitVar, const Expr *InnerLHS,
1301 const Expr *InnerRHS, bool IsAddition) {
1302 // ONE of the sides has to be an integer type.
1303 if (!InnerLHS->getType()->isIntegerType() &&
1304 !InnerRHS->getType()->isIntegerType())
1305 return false;
1306
1307 // If the init var is already an error, don't bother trying to check for
1308 // it.
1309 if (!InitVar)
1310 return true;
1311
1312 const ValueDecl *LHSDecl = getDeclFromExpr(E: InnerLHS);
1313 const ValueDecl *RHSDecl = getDeclFromExpr(E: InnerRHS);
1314 // If we can't get a declaration, this is probably an error, so give up.
1315 if (!LHSDecl || !RHSDecl)
1316 return true;
1317
1318 // If the LHS is the InitVar, the other must be int, so this is valid.
1319 if (LHSDecl->getCanonicalDecl() ==
1320 InitVar->getCanonicalDecl())
1321 return true;
1322
1323 // Subtraction doesn't allow the RHS to be init var, so this is invalid.
1324 if (!IsAddition)
1325 return false;
1326
1327 return RHSDecl->getCanonicalDecl() ==
1328 InitVar->getCanonicalDecl();
1329 };
1330
1331 if (const auto *BO = dyn_cast<BinaryOperator>(Val: RHS)) {
1332 BinaryOperatorKind OpC = BO->getOpcode();
1333 if (OpC != BO_Add && OpC != BO_Sub)
1334 return false;
1335 return isValid(InitVar, BO->getLHS(), BO->getRHS(), OpC == BO_Add);
1336 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: RHS)) {
1337 OverloadedOperatorKind Op = CE->getOperator();
1338 if (Op != OO_Plus && Op != OO_Minus)
1339 return false;
1340 return isValid(InitVar, CE->getArg(0), CE->getArg(1), Op == OO_Plus);
1341 }
1342
1343 return false;
1344}
1345} // namespace
1346
1347bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,
1348 const ValueDecl *InitVar,
1349 bool Diag) {
1350 if (!IncStmt) {
1351 if (Diag) {
1352 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
1353 << SemaRef.LoopWithoutSeqInfo.Kind;
1354 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1355 diag::note_acc_construct_here)
1356 << SemaRef.LoopWithoutSeqInfo.Kind;
1357 }
1358 return true;
1359 }
1360 auto DiagIncVar = [this, Diag, IncStmt] {
1361 if (Diag) {
1362 SemaRef.Diag(IncStmt->getBeginLoc(), diag::err_acc_loop_not_monotonic)
1363 << SemaRef.LoopWithoutSeqInfo.Kind;
1364 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1365 diag::note_acc_construct_here)
1366 << SemaRef.LoopWithoutSeqInfo.Kind;
1367 }
1368 return true;
1369 };
1370
1371 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Val: IncStmt))
1372 IncStmt = ExprTemp->getSubExpr();
1373 if (const auto *E = dyn_cast<Expr>(Val: IncStmt))
1374 IncStmt = E->IgnoreParenImpCasts();
1375
1376 const ValueDecl *IncVar = nullptr;
1377 // Here we enforce the monotonically increase/decrease:
1378 if (const auto *UO = dyn_cast<UnaryOperator>(Val: IncStmt)) {
1379 // Allow increment/decrement ops.
1380 if (!UO->isIncrementDecrementOp())
1381 return DiagIncVar();
1382 IncVar = getDeclFromExpr(E: UO->getSubExpr());
1383 } else if (const auto *BO = dyn_cast<BinaryOperator>(Val: IncStmt)) {
1384 switch (BO->getOpcode()) {
1385 default:
1386 return DiagIncVar();
1387 case BO_AddAssign:
1388 case BO_SubAssign:
1389 break;
1390 case BO_Assign:
1391 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1392 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1393 if (!isValidForIncRHSAssign(InitVar, RHS: BO->getRHS()))
1394 return DiagIncVar();
1395 break;
1396 }
1397 IncVar = getDeclFromExpr(E: BO->getLHS());
1398 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(Val: IncStmt)) {
1399 switch (CE->getOperator()) {
1400 default:
1401 return DiagIncVar();
1402 case OO_PlusPlus:
1403 case OO_MinusMinus:
1404 case OO_PlusEqual:
1405 case OO_MinusEqual:
1406 break;
1407 case OO_Equal:
1408 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1409 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1410 if (!isValidForIncRHSAssign(InitVar, CE->getArg(1)))
1411 return DiagIncVar();
1412 break;
1413 }
1414
1415 IncVar = getDeclFromExpr(CE->getArg(0));
1416 } else {
1417 return DiagIncVar();
1418 }
1419
1420 if (!IncVar)
1421 return DiagIncVar();
1422
1423 // InitVar shouldn't be null unless there was an error, so don't diagnose if
1424 // that is the case. Else we should ensure that it refers to the loop
1425 // value.
1426 if (InitVar && IncVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1427 return DiagIncVar();
1428
1429 return false;
1430}
1431
1432void SemaOpenACC::ForStmtBeginChecker::checkFor() {
1433 const CheckForInfo &CFI = std::get<CheckForInfo>(Info);
1434
1435 if (!IsInstantiation) {
1436 // If this isn't an instantiation, we can just check all of these and
1437 // diagnose.
1438 const ValueDecl *CurInitVar = nullptr;
1439 checkForInit(InitStmt: CFI.Current.Init, InitVar&: CurInitVar, /*Diag=*/true);
1440 checkForCond(CondStmt: CFI.Current.Condition, InitVar: CurInitVar, /*Diag=*/true);
1441 checkForInc(IncStmt: CFI.Current.Increment, InitVar: CurInitVar, /*DIag=*/Diag: true);
1442 } else {
1443 const ValueDecl *UninstInitVar = nullptr;
1444 // Checking the 'init' section first. We have to always run both versions,
1445 // at minimum with the 'diag' off, so that we can ensure we get the correct
1446 // instantiation var for checking by later ones.
1447 bool UninstInitFailed =
1448 checkForInit(InitStmt: CFI.Uninst.Init, InitVar&: UninstInitVar, /*Diag=*/false);
1449
1450 // VarDecls are always rebuild because they are dependent, so we can do a
1451 // little work to suppress some of the double checking based on whether the
1452 // type is instantiation dependent. This is imperfect, but will get us most
1453 // cases suppressed. Currently this only handles the 'T t =' case.
1454 auto InitChanged = [=]() {
1455 if (CFI.Uninst.Init == CFI.Current.Init)
1456 return false;
1457
1458 QualType OldVDTy;
1459 QualType NewVDTy;
1460
1461 if (const auto *DS = dyn_cast<DeclStmt>(Val: CFI.Uninst.Init))
1462 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1463 Val: DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1464 OldVDTy = VD->getType();
1465 if (const auto *DS = dyn_cast<DeclStmt>(Val: CFI.Current.Init))
1466 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1467 Val: DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1468 NewVDTy = VD->getType();
1469
1470 if (OldVDTy.isNull() || NewVDTy.isNull())
1471 return true;
1472
1473 return OldVDTy->isInstantiationDependentType() !=
1474 NewVDTy->isInstantiationDependentType();
1475 };
1476
1477 // Only diagnose the new 'init' if the previous version didn't fail, AND the
1478 // current init changed meaningfully.
1479 bool ShouldDiagNewInit = !UninstInitFailed && InitChanged();
1480 const ValueDecl *CurInitVar = nullptr;
1481 checkForInit(InitStmt: CFI.Current.Init, InitVar&: CurInitVar, /*Diag=*/ShouldDiagNewInit);
1482
1483 // Check the condition and increment only if the previous version passed,
1484 // and this changed.
1485 if (CFI.Uninst.Condition != CFI.Current.Condition &&
1486 !checkForCond(CondStmt: CFI.Uninst.Condition, InitVar: UninstInitVar, /*Diag=*/false))
1487 checkForCond(CondStmt: CFI.Current.Condition, InitVar: CurInitVar, /*Diag=*/true);
1488 if (CFI.Uninst.Increment != CFI.Current.Increment &&
1489 !checkForInc(IncStmt: CFI.Uninst.Increment, InitVar: UninstInitVar, /*Diag=*/false))
1490 checkForInc(IncStmt: CFI.Current.Increment, InitVar: CurInitVar, /*Diag=*/true);
1491 }
1492}
1493
1494void SemaOpenACC::ForStmtBeginChecker::check() {
1495 // If this isn't an active loop without a seq, immediately return, nothing to
1496 // check.
1497 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
1498 return;
1499
1500 // If we've already checked, because this is a 'top level' one (and asking
1501 // again because 'tile' and 'collapse' might apply), just return, nothing to
1502 // do here.
1503 if (AlreadyChecked)
1504 return;
1505 AlreadyChecked = true;
1506
1507 // OpenACC3.3 2.1:
1508 // A loop associated with a loop construct that does not have a seq clause
1509 // must be written to meet all the following conditions:
1510 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
1511 // iterator type.
1512 // - The loop variable must monotonically increase or decrease in the
1513 // direction of its termination condition.
1514 // - The loop trip count must be computable in constant time when entering the
1515 // loop construct.
1516 //
1517 // For a C++ range-based for loop, the loop variable
1518 // identified by the above conditions is the internal iterator, such as a
1519 // pointer, that the compiler generates to iterate the range. it is not the
1520 // variable declared by the for loop.
1521
1522 if (std::holds_alternative<RangeForInfo>(Info))
1523 return checkRangeFor();
1524
1525 return checkFor();
1526}
1527
1528void SemaOpenACC::ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *OldFirst,
1529 const Stmt *First, const Stmt *OldSecond,
1530 const Stmt *Second, const Stmt *OldThird,
1531 const Stmt *Third) {
1532 if (!getLangOpts().OpenACC)
1533 return;
1534
1535 ForStmtBeginChecker FSBC{*this, ForLoc, OldFirst, OldSecond,
1536 OldThird, First, Second, Third};
1537 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1538 // as a part of the helper if a tile/collapse applies.
1539 if (!LoopInfo.TopLevelLoopSeen) {
1540 FSBC.check();
1541 }
1542
1543 ForStmtBeginHelper(ForLoc, C&: FSBC);
1544}
1545
1546void SemaOpenACC::ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First,
1547 const Stmt *Second, const Stmt *Third) {
1548 if (!getLangOpts().OpenACC)
1549 return;
1550
1551 ForStmtBeginChecker FSBC{*this, ForLoc, First, Second, Third};
1552
1553 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1554 // as a part of the helper if a tile/collapse applies.
1555 if (!LoopInfo.TopLevelLoopSeen)
1556 FSBC.check();
1557
1558 ForStmtBeginHelper(ForLoc, C&: FSBC);
1559}
1560
1561void SemaOpenACC::ActOnRangeForStmtBegin(SourceLocation ForLoc,
1562 const Stmt *OldRangeFor,
1563 const Stmt *RangeFor) {
1564 if (!getLangOpts().OpenACC || OldRangeFor == nullptr || RangeFor == nullptr)
1565 return;
1566
1567 ForStmtBeginChecker FSBC{*this, ForLoc,
1568 cast_if_present<CXXForRangeStmt>(Val: OldRangeFor),
1569 cast_if_present<CXXForRangeStmt>(Val: RangeFor)};
1570 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1571 // as a part of the helper if a tile/collapse applies.
1572 if (!LoopInfo.TopLevelLoopSeen) {
1573 FSBC.check();
1574 }
1575 ForStmtBeginHelper(ForLoc, C&: FSBC);
1576}
1577
1578void SemaOpenACC::ActOnRangeForStmtBegin(SourceLocation ForLoc,
1579 const Stmt *RangeFor) {
1580 if (!getLangOpts().OpenACC || RangeFor == nullptr)
1581 return;
1582
1583 ForStmtBeginChecker FSBC = {*this, ForLoc,
1584 cast_if_present<CXXForRangeStmt>(Val: RangeFor)};
1585
1586 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1587 // as a part of the helper if a tile/collapse applies.
1588 if (!LoopInfo.TopLevelLoopSeen)
1589 FSBC.check();
1590
1591 ForStmtBeginHelper(ForLoc, C&: FSBC);
1592}
1593
1594namespace {
1595SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
1596 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
1597 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
1598 // `DoStmt`, as those are caught as a violation elsewhere.
1599 // For `CompoundStmt` we need to search inside of it.
1600 if (!CurStmt ||
1601 isa<ForStmt, NullStmt, ForStmt, CXXForRangeStmt, WhileStmt, DoStmt>(
1602 Val: CurStmt))
1603 return SourceLocation{};
1604
1605 // Any other construct is an error anyway, so it has already been diagnosed.
1606 if (isa<OpenACCConstructStmt>(Val: CurStmt))
1607 return SourceLocation{};
1608
1609 // Search inside the compound statement, this allows for arbitrary nesting
1610 // of compound statements, as long as there isn't any code inside.
1611 if (const auto *CS = dyn_cast<CompoundStmt>(Val: CurStmt)) {
1612 for (const auto *ChildStmt : CS->children()) {
1613 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(CurStmt: ChildStmt);
1614 if (ChildStmtLoc.isValid())
1615 return ChildStmtLoc;
1616 }
1617 // Empty/not invalid compound statements are legal.
1618 return SourceLocation{};
1619 }
1620 return CurStmt->getBeginLoc();
1621}
1622} // namespace
1623
1624void SemaOpenACC::ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body) {
1625 if (!getLangOpts().OpenACC)
1626 return;
1627
1628 // Set this to 'true' so if we find another one at this level we can diagnose.
1629 LoopInfo.CurLevelHasLoopAlready = true;
1630
1631 if (!Body.isUsable())
1632 return;
1633
1634 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1635 *CollapseInfo.CurCollapseCount > 0 &&
1636 !CollapseInfo.ActiveCollapse->hasForce();
1637 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1638
1639 if (IsActiveCollapse || IsActiveTile) {
1640 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(CurStmt: Body.get());
1641
1642 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
1643 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1644 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
1645 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1646 diag::note_acc_active_clause_here)
1647 << OpenACCClauseKind::Collapse;
1648 }
1649
1650 if (OtherStmtLoc.isValid() && IsActiveTile) {
1651 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1652 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
1653 Diag(TileInfo.ActiveTile->getBeginLoc(),
1654 diag::note_acc_active_clause_here)
1655 << OpenACCClauseKind::Tile;
1656 }
1657 }
1658}
1659
1660namespace {
1661// Helper that should mirror ActOnRoutineName to get the FunctionDecl out for
1662// magic-static checking.
1663FunctionDecl *getFunctionFromRoutineName(Expr *RoutineName) {
1664 if (!RoutineName)
1665 return nullptr;
1666 RoutineName = RoutineName->IgnoreParenImpCasts();
1667 if (isa<RecoveryExpr>(Val: RoutineName)) {
1668 // There is nothing we can do here, this isn't a function we can count on.
1669 return nullptr;
1670 } else if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(
1671 Val: RoutineName)) {
1672 // The lookup is dependent, so we'll have to figure this out later.
1673 return nullptr;
1674 } else if (auto *DRE = dyn_cast<DeclRefExpr>(Val: RoutineName)) {
1675 ValueDecl *VD = DRE->getDecl();
1676
1677 if (auto *FD = dyn_cast<FunctionDecl>(Val: VD))
1678 return FD;
1679
1680 // Allow lambdas.
1681 if (auto *VarD = dyn_cast<VarDecl>(Val: VD)) {
1682 QualType VarDTy = VarD->getType();
1683 if (!VarDTy.isNull()) {
1684 if (auto *RD = VarDTy->getAsCXXRecordDecl()) {
1685 if (RD->isGenericLambda())
1686 return nullptr;
1687 if (RD->isLambda())
1688 return RD->getLambdaCallOperator();
1689 } else if (VarDTy->isDependentType()) {
1690 // We don't really know what this is going to be.
1691 return nullptr;
1692 }
1693 }
1694 return nullptr;
1695 } else if (isa<OverloadExpr>(Val: RoutineName)) {
1696 return nullptr;
1697 }
1698 }
1699 return nullptr;
1700}
1701} // namespace
1702
1703ExprResult SemaOpenACC::ActOnRoutineName(Expr *RoutineName) {
1704 assert(RoutineName && "Routine name cannot be null here");
1705 RoutineName = RoutineName->IgnoreParenImpCasts();
1706
1707 if (isa<RecoveryExpr>(Val: RoutineName)) {
1708 // This has already been diagnosed, so we can skip it.
1709 return ExprError();
1710 } else if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(
1711 Val: RoutineName)) {
1712 // These are dependent and we can't really check them, so delay until
1713 // instantiation.
1714 return RoutineName;
1715 } else if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: RoutineName)) {
1716 const ValueDecl *VD = DRE->getDecl();
1717
1718 if (isa<FunctionDecl>(Val: VD))
1719 return RoutineName;
1720
1721 // Allow lambdas.
1722 if (const auto *VarD = dyn_cast<VarDecl>(Val: VD)) {
1723 QualType VarDTy = VarD->getType();
1724 if (!VarDTy.isNull()) {
1725 if (const auto *RD = VarDTy->getAsCXXRecordDecl()) {
1726 if (RD->isGenericLambda()) {
1727 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1728 << RoutineName;
1729 return ExprError();
1730 }
1731 if (RD->isLambda())
1732 return RoutineName;
1733 } else if (VarDTy->isDependentType()) {
1734 // If this is a dependent variable, it might be a lambda. So we just
1735 // accept this and catch it next time.
1736 return RoutineName;
1737 }
1738 }
1739 }
1740
1741 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1742 << RoutineName;
1743 return ExprError();
1744 } else if (isa<OverloadExpr>(Val: RoutineName)) {
1745 // This happens in function templates, even when the template arguments are
1746 // fully specified. We could possibly do some sort of matching to make sure
1747 // that this is looked up/deduced, but GCC does not do this, so there
1748 // doesn't seem to be a good reason for us to do it either.
1749 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1750 << RoutineName;
1751 return ExprError();
1752 }
1753
1754 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1755 << RoutineName;
1756 return ExprError();
1757}
1758void SemaOpenACC::ActOnVariableDeclarator(VarDecl *VD) {
1759 if (!getLangOpts().OpenACC || VD->isInvalidDecl() || !VD->isStaticLocal())
1760 return;
1761
1762 // This cast should be safe, since a static-local can only happen in a
1763 // function declaration.
1764 auto *ContextDecl = cast<FunctionDecl>(getCurContext());
1765
1766 // OpenACC 3.3 2.15:
1767 // In C and C++, function static variables are not supported in functions to
1768 // which a routine directive applies.
1769 for (const auto *A : ContextDecl->attrs()) {
1770 if (isa<OpenACCRoutineDeclAttr, OpenACCRoutineAnnotAttr>(A)) {
1771 Diag(VD->getBeginLoc(), diag::err_acc_magic_static_in_routine);
1772 Diag(A->getLocation(), diag::note_acc_construct_here)
1773 << OpenACCDirectiveKind::Routine;
1774 return;
1775 }
1776 }
1777
1778 MagicStaticLocs.insert({ContextDecl->getCanonicalDecl(), VD->getBeginLoc()});
1779}
1780void SemaOpenACC::CheckLastRoutineDeclNameConflict(const NamedDecl *ND) {
1781 // OpenACC 3.3 A.3.4
1782 // When a procedure with that name is in scope and it is not the same
1783 // procedure as the immediately following procedure declaration or
1784 // definition, the resolution of the name can be confusing. Implementations
1785 // should then issue a compile-time warning diagnostic even though the
1786 // application is conforming.
1787
1788 // If we haven't created one, also can't diagnose.
1789 if (!LastRoutineDecl)
1790 return;
1791
1792 // If the currently created function doesn't have a name, we can't diagnose on
1793 // a match.
1794 if (!ND->getDeclName().isIdentifier())
1795 return;
1796
1797 // If the two are in different decl contexts, it doesn't make sense to
1798 // diagnose.
1799 if (LastRoutineDecl->getDeclContext() != ND->getLexicalDeclContext())
1800 return;
1801
1802 // If we don't have a referenced thing yet, we can't diagnose.
1803 FunctionDecl *RoutineTarget =
1804 getFunctionFromRoutineName(LastRoutineDecl->getFunctionReference());
1805 if (!RoutineTarget)
1806 return;
1807
1808 // If the Routine target doesn't have a name, we can't diagnose.
1809 if (!RoutineTarget->getDeclName().isIdentifier())
1810 return;
1811
1812 // Of course don't diagnose if the names don't match.
1813 if (ND->getName() != RoutineTarget->getName())
1814 return;
1815
1816 long NDLine = SemaRef.SourceMgr.getSpellingLineNumber(Loc: ND->getBeginLoc());
1817 long LastLine =
1818 SemaRef.SourceMgr.getSpellingLineNumber(LastRoutineDecl->getBeginLoc());
1819
1820 // Do some line-number math to make sure they are within a line of eachother.
1821 // Comments or newlines can be inserted to clarify intent.
1822 if (NDLine - LastLine > 1)
1823 return;
1824
1825 // Don't warn if it actually DOES apply to this function via redecls.
1826 if (ND->getCanonicalDecl() == RoutineTarget->getCanonicalDecl())
1827 return;
1828
1829 Diag(LastRoutineDecl->getFunctionReference()->getBeginLoc(),
1830 diag::warn_acc_confusing_routine_name);
1831 Diag(RoutineTarget->getBeginLoc(), diag::note_previous_decl) << ND;
1832}
1833
1834void SemaOpenACC::ActOnVariableInit(VarDecl *VD, QualType InitType) {
1835 if (!VD || !getLangOpts().OpenACC || InitType.isNull())
1836 return;
1837
1838 // To avoid double-diagnostic, just diagnose this during instantiation. We'll
1839 // get 1 warning per instantiation, but this permits us to be more sensible
1840 // for cases where the lookup is confusing.
1841 if (VD->getLexicalDeclContext()->isDependentContext())
1842 return;
1843
1844 const auto *RD = InitType->getAsCXXRecordDecl();
1845 // If this isn't a lambda, no sense in diagnosing.
1846 if (!RD || !RD->isLambda())
1847 return;
1848
1849 CheckLastRoutineDeclNameConflict(VD);
1850}
1851
1852void SemaOpenACC::ActOnFunctionDeclarator(FunctionDecl *FD) {
1853 if (!FD || !getLangOpts().OpenACC)
1854 return;
1855 CheckLastRoutineDeclNameConflict(FD);
1856}
1857
1858bool SemaOpenACC::ActOnStartStmtDirective(
1859 OpenACCDirectiveKind K, SourceLocation StartLoc,
1860 ArrayRef<const OpenACCClause *> Clauses) {
1861
1862 // Declaration directives an appear in a statement location, so call into that
1863 // function here.
1864 if (K == OpenACCDirectiveKind::Declare || K == OpenACCDirectiveKind::Routine)
1865 return ActOnStartDeclDirective(K, StartLoc, Clauses);
1866
1867 SemaRef.DiscardCleanupsInEvaluationContext();
1868 SemaRef.PopExpressionEvaluationContext();
1869
1870 // OpenACC 3.3 2.9.1:
1871 // Intervening code must not contain other OpenACC directives or calls to API
1872 // routines.
1873 //
1874 // ALL constructs are ill-formed if there is an active 'collapse'
1875 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1876 Diag(StartLoc, diag::err_acc_invalid_in_loop)
1877 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
1878 << OpenACCClauseKind::Collapse << K;
1879 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1880 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1881 diag::note_acc_active_clause_here)
1882 << OpenACCClauseKind::Collapse;
1883 }
1884 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1885 Diag(StartLoc, diag::err_acc_invalid_in_loop)
1886 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
1887 << OpenACCClauseKind::Tile << K;
1888 assert(TileInfo.ActiveTile && "Tile count without object?");
1889 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1890 << OpenACCClauseKind::Tile;
1891 }
1892
1893 if (DiagnoseRequiredClauses(DK: K, DirLoc: StartLoc, Clauses))
1894 return true;
1895 return diagnoseConstructAppertainment(S&: *this, K, StartLoc, /*IsStmt=*/true);
1896}
1897
1898StmtResult SemaOpenACC::ActOnEndStmtDirective(
1899 OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
1900 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
1901 OpenACCAtomicKind AtomicKind, SourceLocation RParenLoc,
1902 SourceLocation EndLoc, ArrayRef<OpenACCClause *> Clauses,
1903 StmtResult AssocStmt) {
1904 switch (K) {
1905 case OpenACCDirectiveKind::Invalid:
1906 return StmtError();
1907 case OpenACCDirectiveKind::Parallel:
1908 case OpenACCDirectiveKind::Serial:
1909 case OpenACCDirectiveKind::Kernels: {
1910 return OpenACCComputeConstruct::Create(
1911 C: getASTContext(), K, BeginLoc: StartLoc, DirectiveLoc: DirLoc, EndLoc, Clauses,
1912 StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1913 }
1914 case OpenACCDirectiveKind::ParallelLoop:
1915 case OpenACCDirectiveKind::SerialLoop:
1916 case OpenACCDirectiveKind::KernelsLoop: {
1917 return OpenACCCombinedConstruct::Create(
1918 C: getASTContext(), K, Start: StartLoc, DirectiveLoc: DirLoc, End: EndLoc, Clauses,
1919 StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1920 }
1921 case OpenACCDirectiveKind::Loop: {
1922 return OpenACCLoopConstruct::Create(
1923 C: getASTContext(), ParentKind: ActiveComputeConstructInfo.Kind, BeginLoc: StartLoc, DirLoc,
1924 EndLoc, Clauses, Loop: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1925 }
1926 case OpenACCDirectiveKind::Data: {
1927 return OpenACCDataConstruct::Create(
1928 C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc, End: EndLoc, Clauses,
1929 StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1930 }
1931 case OpenACCDirectiveKind::EnterData: {
1932 return OpenACCEnterDataConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1933 End: EndLoc, Clauses);
1934 }
1935 case OpenACCDirectiveKind::ExitData: {
1936 return OpenACCExitDataConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1937 End: EndLoc, Clauses);
1938 }
1939 case OpenACCDirectiveKind::HostData: {
1940 return OpenACCHostDataConstruct::Create(
1941 C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc, End: EndLoc, Clauses,
1942 StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1943 }
1944 case OpenACCDirectiveKind::Wait: {
1945 return OpenACCWaitConstruct::Create(
1946 C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc, LParenLoc, DevNumExpr: Exprs.front(), QueuesLoc: MiscLoc,
1947 QueueIdExprs: Exprs.drop_front(), RParenLoc, End: EndLoc, Clauses);
1948 }
1949 case OpenACCDirectiveKind::Init: {
1950 return OpenACCInitConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1951 End: EndLoc, Clauses);
1952 }
1953 case OpenACCDirectiveKind::Shutdown: {
1954 return OpenACCShutdownConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1955 End: EndLoc, Clauses);
1956 }
1957 case OpenACCDirectiveKind::Set: {
1958 return OpenACCSetConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1959 End: EndLoc, Clauses);
1960 }
1961 case OpenACCDirectiveKind::Update: {
1962 return OpenACCUpdateConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1963 End: EndLoc, Clauses);
1964 }
1965 case OpenACCDirectiveKind::Atomic: {
1966 return OpenACCAtomicConstruct::Create(
1967 C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc, AtKind: AtomicKind, End: EndLoc, Clauses,
1968 AssociatedStmt: AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1969 }
1970 case OpenACCDirectiveKind::Cache: {
1971 assert(Clauses.empty() && "Cache doesn't allow clauses");
1972 return OpenACCCacheConstruct::Create(C: getASTContext(), Start: StartLoc, DirectiveLoc: DirLoc,
1973 LParenLoc, ReadOnlyLoc: MiscLoc, VarList: Exprs, RParenLoc,
1974 End: EndLoc);
1975 }
1976 case OpenACCDirectiveKind::Routine:
1977 llvm_unreachable("routine shouldn't handled here");
1978 case OpenACCDirectiveKind::Declare: {
1979 // Declare and routine arei declaration directives, but can be used here as
1980 // long as we wrap it in a DeclStmt. So make sure we do that here.
1981 DeclGroupRef DR = ActOnEndDeclDirective(K, StartLoc, DirLoc, LParenLoc,
1982 RParenLoc, EndLoc, Clauses);
1983
1984 return SemaRef.ActOnDeclStmt(Decl: DeclGroupPtrTy::make(P: DR), StartLoc, EndLoc);
1985 }
1986 }
1987 llvm_unreachable("Unhandled case in directive handling?");
1988}
1989
1990StmtResult SemaOpenACC::ActOnAssociatedStmt(
1991 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
1992 OpenACCAtomicKind AtKind, ArrayRef<const OpenACCClause *> Clauses,
1993 StmtResult AssocStmt) {
1994 switch (K) {
1995 default:
1996 llvm_unreachable("Unimplemented associated statement application");
1997 case OpenACCDirectiveKind::EnterData:
1998 case OpenACCDirectiveKind::ExitData:
1999 case OpenACCDirectiveKind::Wait:
2000 case OpenACCDirectiveKind::Init:
2001 case OpenACCDirectiveKind::Shutdown:
2002 case OpenACCDirectiveKind::Set:
2003 case OpenACCDirectiveKind::Cache:
2004 llvm_unreachable(
2005 "these don't have associated statements, so shouldn't get here");
2006 case OpenACCDirectiveKind::Atomic:
2007 return CheckAtomicAssociatedStmt(AtomicDirLoc: DirectiveLoc, AtKind, AssocStmt);
2008 case OpenACCDirectiveKind::Parallel:
2009 case OpenACCDirectiveKind::Serial:
2010 case OpenACCDirectiveKind::Kernels:
2011 case OpenACCDirectiveKind::Data:
2012 case OpenACCDirectiveKind::HostData:
2013 // There really isn't any checking here that could happen. As long as we
2014 // have a statement to associate, this should be fine.
2015 // OpenACC 3.3 Section 6:
2016 // Structured Block: in C or C++, an executable statement, possibly
2017 // compound, with a single entry at the top and a single exit at the
2018 // bottom.
2019 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
2020 // an interpretation of it is to allow this and treat the initializer as
2021 // the 'structured block'.
2022 return AssocStmt;
2023 case OpenACCDirectiveKind::Loop:
2024 case OpenACCDirectiveKind::ParallelLoop:
2025 case OpenACCDirectiveKind::SerialLoop:
2026 case OpenACCDirectiveKind::KernelsLoop:
2027 if (!AssocStmt.isUsable())
2028 return StmtError();
2029
2030 if (!isa<CXXForRangeStmt, ForStmt>(Val: AssocStmt.get())) {
2031 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
2032 << K;
2033 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
2034 return StmtError();
2035 }
2036
2037 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
2038 if (!CollapseInfo.CollapseDepthSatisfied) {
2039 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2040 << OpenACCClauseKind::Collapse;
2041 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2042 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2043 diag::note_acc_active_clause_here)
2044 << OpenACCClauseKind::Collapse;
2045 }
2046
2047 if (!TileInfo.TileDepthSatisfied) {
2048 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2049 << OpenACCClauseKind::Tile;
2050 assert(TileInfo.ActiveTile && "Collapse count without object?");
2051 Diag(TileInfo.ActiveTile->getBeginLoc(),
2052 diag::note_acc_active_clause_here)
2053 << OpenACCClauseKind::Tile;
2054 }
2055 return StmtError();
2056 }
2057
2058 return AssocStmt.get();
2059 }
2060 llvm_unreachable("Invalid associated statement application");
2061}
2062
2063namespace {
2064
2065// Routine has some pretty complicated set of rules for how device_type
2066// interacts with 'gang', 'worker', 'vector', and 'seq'. Enforce part of it
2067// here.
2068bool CheckValidRoutineGangWorkerVectorSeqClauses(
2069 SemaOpenACC &SemaRef, SourceLocation DirectiveLoc,
2070 ArrayRef<const OpenACCClause *> Clauses) {
2071 auto RequiredPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
2072 OpenACCVectorClause, OpenACCSeqClause>;
2073 // The clause handling has assured us that there is no duplicates. That is,
2074 // if there is 1 before a device_type, there are none after a device_type.
2075 // If not, there is at most 1 applying to each device_type.
2076
2077 // What is left to legalize is that either:
2078 // 1- there is 1 before the first device_type.
2079 // 2- there is 1 AFTER each device_type.
2080 auto *FirstDeviceType =
2081 llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCDeviceTypeClause>);
2082
2083 // If there is 1 before the first device_type (or at all if no device_type),
2084 // we are legal.
2085 auto *ClauseItr =
2086 std::find_if(first: Clauses.begin(), last: FirstDeviceType, pred: RequiredPred);
2087
2088 if (ClauseItr != FirstDeviceType)
2089 return false;
2090
2091 // If there IS no device_type, and no clause, diagnose.
2092 if (FirstDeviceType == Clauses.end())
2093 return SemaRef.Diag(DirectiveLoc, diag::err_acc_construct_one_clause_of)
2094 << OpenACCDirectiveKind::Routine
2095 << "'gang', 'seq', 'vector', or 'worker'";
2096
2097 // Else, we have to check EACH device_type group. PrevDeviceType is the
2098 // device-type before the current group.
2099 auto *PrevDeviceType = FirstDeviceType;
2100
2101 while (PrevDeviceType != Clauses.end()) {
2102 auto *NextDeviceType =
2103 std::find_if(first: std::next(x: PrevDeviceType), last: Clauses.end(),
2104 pred: llvm::IsaPred<OpenACCDeviceTypeClause>);
2105
2106 ClauseItr = std::find_if(first: PrevDeviceType, last: NextDeviceType, pred: RequiredPred);
2107
2108 if (ClauseItr == NextDeviceType)
2109 return SemaRef.Diag((*PrevDeviceType)->getBeginLoc(),
2110 diag::err_acc_clause_routine_one_of_in_region);
2111
2112 PrevDeviceType = NextDeviceType;
2113 }
2114
2115 return false;
2116}
2117} // namespace
2118
2119bool SemaOpenACC::ActOnStartDeclDirective(
2120 OpenACCDirectiveKind K, SourceLocation StartLoc,
2121 ArrayRef<const OpenACCClause *> Clauses) {
2122 // OpenCC3.3 2.1 (line 889)
2123 // A program must not depend on the order of evaluation of expressions in
2124 // clause arguments or on any side effects of the evaluations.
2125 SemaRef.DiscardCleanupsInEvaluationContext();
2126 SemaRef.PopExpressionEvaluationContext();
2127
2128 if (DiagnoseRequiredClauses(DK: K, DirLoc: StartLoc, Clauses))
2129 return true;
2130 if (K == OpenACCDirectiveKind::Routine &&
2131 CheckValidRoutineGangWorkerVectorSeqClauses(SemaRef&: *this, DirectiveLoc: StartLoc, Clauses))
2132 return true;
2133
2134 return diagnoseConstructAppertainment(S&: *this, K, StartLoc, /*IsStmt=*/false);
2135}
2136
2137DeclGroupRef SemaOpenACC::ActOnEndDeclDirective(
2138 OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
2139 SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc,
2140 ArrayRef<OpenACCClause *> Clauses) {
2141 switch (K) {
2142 default:
2143 case OpenACCDirectiveKind::Invalid:
2144 return DeclGroupRef{};
2145 case OpenACCDirectiveKind::Declare: {
2146 // OpenACC3.3 2.13: At least one clause must appear on a declare directive.
2147 if (Clauses.empty()) {
2148 Diag(EndLoc, diag::err_acc_declare_required_clauses);
2149 // No reason to add this to the AST, as we would just end up trying to
2150 // instantiate this, which would double-diagnose here, which we wouldn't
2151 // want to do.
2152 return DeclGroupRef{};
2153 }
2154
2155 auto *DeclareDecl = OpenACCDeclareDecl::Create(
2156 Ctx&: getASTContext(), DC: getCurContext(), StartLoc, DirLoc, EndLoc, Clauses);
2157 DeclareDecl->setAccess(AS_public);
2158 getCurContext()->addDecl(DeclareDecl);
2159 return DeclGroupRef{DeclareDecl};
2160 }
2161 case OpenACCDirectiveKind::Routine:
2162 llvm_unreachable("routine shouldn't be handled here");
2163 }
2164 llvm_unreachable("unhandled case in directive handling?");
2165}
2166
2167namespace {
2168// Given the decl on the next line, figure out if it is one that is acceptable
2169// to `routine`, or looks like the sort of decl we should be diagnosing against.
2170FunctionDecl *LegalizeNextParsedDecl(Decl *D) {
2171 if (!D)
2172 return nullptr;
2173
2174 // Functions are per-fact acceptable as-is.
2175 if (auto *FD = dyn_cast<FunctionDecl>(Val: D))
2176 return FD;
2177
2178 // Function templates are functions, so attach to the templated decl.
2179 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(Val: D))
2180 return FTD->getTemplatedDecl();
2181
2182 if (auto *FD = dyn_cast<FieldDecl>(Val: D)) {
2183 auto *RD =
2184 FD->getType().isNull() ? nullptr : FD->getType()->getAsCXXRecordDecl();
2185
2186 if (RD && RD->isGenericLambda())
2187 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2188 if (RD && RD->isLambda())
2189 return RD->getLambdaCallOperator();
2190 }
2191 // VarDecl we can look at the init instead of the type of the variable, this
2192 // makes us more tolerant of the 'auto' deduced type.
2193 if (auto *VD = dyn_cast<VarDecl>(Val: D)) {
2194 Expr *Init = VD->getInit();
2195 if (!Init || Init->getType().isNull())
2196 return nullptr;
2197
2198 const auto *RD = Init->getType()->getAsCXXRecordDecl();
2199 if (RD && RD->isGenericLambda())
2200 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2201 if (RD && RD->isLambda())
2202 return RD->getLambdaCallOperator();
2203
2204 // FIXME: We could try harder in the case where this is a dependent thing
2205 // that ends up being a lambda (that is, the init is an unresolved lookup
2206 // expr), but we can't attach to the call/lookup expr. If we instead try to
2207 // attach to the VarDecl, when we go to instantiate it, attributes are
2208 // instantiated before the init, so we can't actually see the type at any
2209 // point where it would be relevant/able to be checked. We could perhaps do
2210 // some sort of 'after-init' instantiation/checking here, but that doesn't
2211 // seem valuable for a situation that other compilers don't handle.
2212 }
2213 return nullptr;
2214}
2215
2216void CreateRoutineDeclAttr(SemaOpenACC &SemaRef, SourceLocation DirLoc,
2217 ArrayRef<const OpenACCClause *> Clauses,
2218 ValueDecl *AddTo) {
2219 OpenACCRoutineDeclAttr *A =
2220 OpenACCRoutineDeclAttr::Create(SemaRef.getASTContext(), DirLoc);
2221 A->Clauses.assign(Clauses.begin(), Clauses.end());
2222 AddTo->addAttr(A: A);
2223}
2224} // namespace
2225
2226// Variant that adds attributes, because this is the unnamed case.
2227void SemaOpenACC::CheckRoutineDecl(SourceLocation DirLoc,
2228 ArrayRef<const OpenACCClause *> Clauses,
2229 Decl *NextParsedDecl) {
2230
2231 FunctionDecl *NextParsedFDecl = LegalizeNextParsedDecl(D: NextParsedDecl);
2232
2233 if (!NextParsedFDecl) {
2234 // If we don't have a valid 'next thing', just diagnose.
2235 SemaRef.Diag(DirLoc, diag::err_acc_decl_for_routine);
2236 return;
2237 }
2238
2239 // OpenACC 3.3 2.15:
2240 // In C and C++, function static variables are not supported in functions to
2241 // which a routine directive applies.
2242 if (auto Itr = MagicStaticLocs.find(Val: NextParsedFDecl->getCanonicalDecl());
2243 Itr != MagicStaticLocs.end()) {
2244 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2245 Diag(DirLoc, diag::note_acc_construct_here)
2246 << OpenACCDirectiveKind::Routine;
2247
2248 return;
2249 }
2250
2251 auto BindItr = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCBindClause>);
2252 for (auto *A : NextParsedFDecl->attrs()) {
2253 // OpenACC 3.3 2.15:
2254 // If a procedure has a bind clause on both the declaration and definition
2255 // than they both must bind to the same name.
2256 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2257 auto OtherBindItr =
2258 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2259 if (OtherBindItr != RA->Clauses.end() &&
2260 (*cast<OpenACCBindClause>(*BindItr)) !=
2261 (*cast<OpenACCBindClause>(*OtherBindItr))) {
2262 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_unnamed_bind);
2263 Diag((*OtherBindItr)->getEndLoc(), diag::note_acc_previous_clause_here)
2264 << (*BindItr)->getClauseKind();
2265 return;
2266 }
2267 }
2268
2269 // OpenACC 3.3 2.15:
2270 // A bind clause may not bind to a routine name that has a visible bind
2271 // clause.
2272 // We take the combo of these two 2.15 restrictions to mean that the
2273 // 'declaration'/'definition' quote is an exception to this. So we're going
2274 // to disallow mixing of the two types entirely.
2275 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2276 RA && RA->getRange().getEnd().isValid()) {
2277 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2278 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2279 << "bind";
2280 return;
2281 }
2282 }
2283
2284 CreateRoutineDeclAttr(*this, DirLoc, Clauses, NextParsedFDecl);
2285}
2286
2287// Variant that adds a decl, because this is the named case.
2288OpenACCRoutineDecl *SemaOpenACC::CheckRoutineDecl(
2289 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2290 Expr *FuncRef, SourceLocation RParenLoc,
2291 ArrayRef<const OpenACCClause *> Clauses, SourceLocation EndLoc) {
2292 assert(LParenLoc.isValid());
2293
2294 if (FunctionDecl *FD = getFunctionFromRoutineName(RoutineName: FuncRef)) {
2295 // OpenACC 3.3 2.15:
2296 // In C and C++, function static variables are not supported in functions to
2297 // which a routine directive applies.
2298 if (auto Itr = MagicStaticLocs.find(Val: FD->getCanonicalDecl());
2299 Itr != MagicStaticLocs.end()) {
2300 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2301 Diag(DirLoc, diag::note_acc_construct_here)
2302 << OpenACCDirectiveKind::Routine;
2303
2304 return nullptr;
2305 }
2306
2307 // OpenACC 3.3 2.15:
2308 // A bind clause may not bind to a routine name that has a visible bind
2309 // clause.
2310 auto BindItr = llvm::find_if(Range&: Clauses, P: llvm::IsaPred<OpenACCBindClause>);
2311 SourceLocation BindLoc;
2312 if (BindItr != Clauses.end()) {
2313 BindLoc = (*BindItr)->getBeginLoc();
2314 // Since this is adding a 'named' routine, we aren't allowed to combine
2315 // with ANY other visible bind clause. Error if we see either.
2316
2317 for (auto *A : FD->attrs()) {
2318 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2319 auto OtherBindItr =
2320 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2321 if (OtherBindItr != RA->Clauses.end()) {
2322 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2323 Diag((*OtherBindItr)->getEndLoc(),
2324 diag::note_acc_previous_clause_here)
2325 << (*BindItr)->getClauseKind();
2326 return nullptr;
2327 }
2328 }
2329
2330 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2331 RA && RA->getRange().getEnd().isValid()) {
2332 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2333 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2334 << (*BindItr)->getClauseKind();
2335 return nullptr;
2336 }
2337 }
2338 }
2339
2340 // Set the end-range to the 'bind' clause here, so we can look it up
2341 // later.
2342 auto *RAA = OpenACCRoutineAnnotAttr::CreateImplicit(getASTContext(),
2343 {DirLoc, BindLoc});
2344 FD->addAttr(A: RAA);
2345 // In case we are referencing not the 'latest' version, make sure we add
2346 // the attribute to all declarations.
2347 while (FD != FD->getMostRecentDecl()) {
2348 FD = FD->getMostRecentDecl();
2349 FD->addAttr(A: RAA);
2350 }
2351 }
2352
2353 LastRoutineDecl = OpenACCRoutineDecl::Create(
2354 getASTContext(), getCurContext(), StartLoc, DirLoc, LParenLoc, FuncRef,
2355 RParenLoc, EndLoc, Clauses);
2356 LastRoutineDecl->setAccess(AS_public);
2357 getCurContext()->addDecl(LastRoutineDecl);
2358
2359 return LastRoutineDecl;
2360}
2361
2362DeclGroupRef SemaOpenACC::ActOnEndRoutineDeclDirective(
2363 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2364 Expr *ReferencedFunc, SourceLocation RParenLoc,
2365 ArrayRef<const OpenACCClause *> Clauses, SourceLocation EndLoc,
2366 DeclGroupPtrTy NextDecl) {
2367 assert((!ReferencedFunc || !NextDecl) &&
2368 "Only one of these should be filled");
2369
2370 if (LParenLoc.isInvalid()) {
2371 Decl *NextLineDecl = nullptr;
2372 if (NextDecl && NextDecl.get().isSingleDecl())
2373 NextLineDecl = NextDecl.get().getSingleDecl();
2374
2375 CheckRoutineDecl(DirLoc, Clauses, NextParsedDecl: NextLineDecl);
2376
2377 return NextDecl.get();
2378 }
2379
2380 return DeclGroupRef{CheckRoutineDecl(
2381 StartLoc, DirLoc, LParenLoc, ReferencedFunc, RParenLoc, Clauses, EndLoc)};
2382}
2383
2384StmtResult SemaOpenACC::ActOnEndRoutineStmtDirective(
2385 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2386 Expr *ReferencedFunc, SourceLocation RParenLoc,
2387 ArrayRef<const OpenACCClause *> Clauses, SourceLocation EndLoc,
2388 Stmt *NextStmt) {
2389 assert((!ReferencedFunc || !NextStmt) &&
2390 "Only one of these should be filled");
2391
2392 if (LParenLoc.isInvalid()) {
2393 Decl *NextLineDecl = nullptr;
2394 if (NextStmt)
2395 if (DeclStmt *DS = dyn_cast<DeclStmt>(Val: NextStmt); DS && DS->isSingleDecl())
2396 NextLineDecl = DS->getSingleDecl();
2397
2398 CheckRoutineDecl(DirLoc, Clauses, NextParsedDecl: NextLineDecl);
2399 return NextStmt;
2400 }
2401
2402 DeclGroupRef DR{CheckRoutineDecl(StartLoc, DirLoc, LParenLoc, ReferencedFunc,
2403 RParenLoc, Clauses, EndLoc)};
2404 return SemaRef.ActOnDeclStmt(Decl: DeclGroupPtrTy::make(P: DR), StartLoc, EndLoc);
2405}
2406
2407OpenACCRoutineDeclAttr *
2408SemaOpenACC::mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old) {
2409 OpenACCRoutineDeclAttr *New =
2410 OpenACCRoutineDeclAttr::Create(getASTContext(), Old.getLocation());
2411 // We should jsut be able to copy these, there isn't really any
2412 // merging/inheriting we have to do, so no worry about doing a deep copy.
2413 New->Clauses = Old.Clauses;
2414 return New;
2415}
2416ExprResult
2417SemaOpenACC::BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
2418 return OpenACCAsteriskSizeExpr::Create(C: getASTContext(), Loc: AsteriskLoc);
2419}
2420
2421ExprResult
2422SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
2423 return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
2424}
2425

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Sema/SemaOpenACC.cpp