clang 21.0.0git
SemaOpenACC.cpp
Go to the documentation of this file.
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
17#include "clang/Sema/Sema.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Support/Casting.h"
21
22using namespace clang;
23
24namespace {
25bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,
26 SourceLocation StartLoc, bool IsStmt) {
27 switch (K) {
28 default:
29 case OpenACCDirectiveKind::Invalid:
30 // Nothing to do here, both invalid and unimplemented don't really need to
31 // do anything.
32 break;
33 case OpenACCDirectiveKind::Parallel:
34 case OpenACCDirectiveKind::ParallelLoop:
35 case OpenACCDirectiveKind::Serial:
36 case OpenACCDirectiveKind::SerialLoop:
37 case OpenACCDirectiveKind::Kernels:
38 case OpenACCDirectiveKind::KernelsLoop:
39 case OpenACCDirectiveKind::Loop:
40 case OpenACCDirectiveKind::Data:
41 case OpenACCDirectiveKind::EnterData:
42 case OpenACCDirectiveKind::ExitData:
43 case OpenACCDirectiveKind::HostData:
44 case OpenACCDirectiveKind::Wait:
45 case OpenACCDirectiveKind::Update:
46 case OpenACCDirectiveKind::Init:
47 case OpenACCDirectiveKind::Shutdown:
48 case OpenACCDirectiveKind::Cache:
49 case OpenACCDirectiveKind::Atomic:
50 if (!IsStmt)
51 return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
52 break;
53 }
54 return false;
55}
56
57void CollectActiveReductionClauses(
59 ArrayRef<OpenACCClause *> CurClauses) {
60 for (auto *CurClause : CurClauses) {
61 if (auto *RedClause = dyn_cast<OpenACCReductionClause>(CurClause);
62 RedClause && !RedClause->getVarList().empty())
63 ActiveClauses.push_back(RedClause);
64 }
65}
66
67// Depth needs to be preserved for all associated statements that aren't
68// supposed to modify the compute/combined/loop construct information.
69bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
70 switch (DK) {
71 case OpenACCDirectiveKind::Parallel:
72 case OpenACCDirectiveKind::ParallelLoop:
73 case OpenACCDirectiveKind::Serial:
74 case OpenACCDirectiveKind::SerialLoop:
75 case OpenACCDirectiveKind::Kernels:
76 case OpenACCDirectiveKind::KernelsLoop:
77 case OpenACCDirectiveKind::Loop:
78 return false;
79 case OpenACCDirectiveKind::Data:
80 case OpenACCDirectiveKind::HostData:
81 case OpenACCDirectiveKind::Atomic:
82 return true;
83 case OpenACCDirectiveKind::EnterData:
84 case OpenACCDirectiveKind::ExitData:
85 case OpenACCDirectiveKind::Wait:
86 case OpenACCDirectiveKind::Init:
87 case OpenACCDirectiveKind::Shutdown:
88 case OpenACCDirectiveKind::Set:
89 case OpenACCDirectiveKind::Update:
90 llvm_unreachable("Doesn't have an associated stmt");
91 default:
92 case OpenACCDirectiveKind::Invalid:
93 llvm_unreachable("Unhandled directive kind?");
94 }
95 llvm_unreachable("Unhandled directive kind?");
96}
97
98} // namespace
99
101
106 : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
107 DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel),
108 OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
109 OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
110 OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo),
111 ActiveReductionClauses(S.ActiveReductionClauses),
112 LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DirKind)) {
113
114 // Compute constructs end up taking their 'loop'.
115 if (DirKind == OpenACCDirectiveKind::Parallel ||
116 DirKind == OpenACCDirectiveKind::Serial ||
118 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
119 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
120 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
121
122 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
123 // construct, the gang clause behaves as follows. ... The region of a loop
124 // with a gang clause may not contain another loop with a gang clause unless
125 // within a nested compute region.
126 //
127 // Implement the 'unless within a nested compute region' part.
128 SemaRef.LoopGangClauseOnKernel = {};
129 SemaRef.LoopWorkerClauseLoc = {};
130 SemaRef.LoopVectorClauseLoc = {};
131 SemaRef.LoopWithoutSeqInfo = {};
132 } else if (DirKind == OpenACCDirectiveKind::ParallelLoop ||
135 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
136 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
137
138 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
139 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
140 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
141
142 SemaRef.LoopGangClauseOnKernel = {};
143 SemaRef.LoopWorkerClauseLoc = {};
144 SemaRef.LoopVectorClauseLoc = {};
145
146 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
147 // diagnose the for loops.
148 SemaRef.LoopWithoutSeqInfo = {};
149 if (Clauses.end() ==
150 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
151 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
152
153 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
154 // construct, the gang clause behaves as follows. ... The region of a loop
155 // with a gang clause may not contain another loop with a gang clause unless
156 // within a nested compute region.
157 //
158 // We don't bother doing this when this is a template instantiation, as
159 // there is no reason to do these checks: the existance of a
160 // gang/kernels/etc cannot be dependent.
161 if (DirKind == OpenACCDirectiveKind::KernelsLoop && UnInstClauses.empty()) {
162 // This handles the 'outer loop' part of this.
163 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
164 if (Itr != Clauses.end())
165 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), DirKind};
166 }
167
168 if (UnInstClauses.empty()) {
169 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
170 if (Itr != Clauses.end())
171 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
172
173 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
174 if (Itr2 != Clauses.end())
175 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
176 }
177 } else if (DirKind == OpenACCDirectiveKind::Loop) {
178 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
179 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
180 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
181
182 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
183 // diagnose the for loops.
184 SemaRef.LoopWithoutSeqInfo = {};
185 if (Clauses.end() ==
186 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
187 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
188
189 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
190 // construct, the gang clause behaves as follows. ... The region of a loop
191 // with a gang clause may not contain another loop with a gang clause unless
192 // within a nested compute region.
193 //
194 // We don't bother doing this when this is a template instantiation, as
195 // there is no reason to do these checks: the existance of a
196 // gang/kernels/etc cannot be dependent.
197 if (SemaRef.getActiveComputeConstructInfo().Kind ==
199 UnInstClauses.empty()) {
200 // This handles the 'outer loop' part of this.
201 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
202 if (Itr != Clauses.end())
203 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(),
205 }
206
207 if (UnInstClauses.empty()) {
208 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
209 if (Itr != Clauses.end())
210 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
211
212 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
213 if (Itr2 != Clauses.end())
214 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
215 }
216 }
217}
218
222
223 // Reset this checking for loops that aren't covered in a RAII object.
224 SemaRef.LoopInfo.CurLevelHasLoopAlready = false;
225 SemaRef.CollapseInfo.CollapseDepthSatisfied = true;
226 SemaRef.TileInfo.TileDepthSatisfied = true;
227
228 // We make sure to take an optional list of uninstantiated clauses, so that
229 // we can check to make sure we don't 'double diagnose' in the event that
230 // the value of 'N' was not dependent in a template. We also ensure during
231 // Sema that there is only 1 collapse on each construct, so we can count on
232 // the fact that if both find a 'collapse', that they are the same one.
233 auto *CollapseClauseItr =
234 llvm::find_if(Clauses, llvm::IsaPred<OpenACCCollapseClause>);
235 auto *UnInstCollapseClauseItr =
236 llvm::find_if(UnInstClauses, llvm::IsaPred<OpenACCCollapseClause>);
237
238 if (Clauses.end() == CollapseClauseItr)
239 return;
240
241 OpenACCCollapseClause *CollapseClause =
242 cast<OpenACCCollapseClause>(*CollapseClauseItr);
243
244 SemaRef.CollapseInfo.ActiveCollapse = CollapseClause;
245 Expr *LoopCount = CollapseClause->getLoopCount();
246
247 // If the loop count is still instantiation dependent, setting the depth
248 // counter isn't necessary, so return here.
249 if (!LoopCount || LoopCount->isInstantiationDependent())
250 return;
251
252 // Suppress diagnostics if we've done a 'transform' where the previous version
253 // wasn't dependent, meaning we already diagnosed it.
254 if (UnInstCollapseClauseItr != UnInstClauses.end() &&
255 !cast<OpenACCCollapseClause>(*UnInstCollapseClauseItr)
256 ->getLoopCount()
257 ->isInstantiationDependent())
258 return;
259
260 SemaRef.CollapseInfo.CollapseDepthSatisfied = false;
261 SemaRef.CollapseInfo.CurCollapseCount =
262 cast<ConstantExpr>(LoopCount)->getResultAsAPSInt();
263 SemaRef.CollapseInfo.DirectiveKind = DirKind;
264}
265
269 // We don't diagnose if this is during instantiation, since the only thing we
270 // care about is the number of arguments, which we can figure out without
271 // instantiation, so we don't want to double-diagnose.
272 if (UnInstClauses.size() > 0)
273 return;
274 auto *TileClauseItr =
275 llvm::find_if(Clauses, llvm::IsaPred<OpenACCTileClause>);
276
277 if (Clauses.end() == TileClauseItr)
278 return;
279
280 OpenACCTileClause *TileClause = cast<OpenACCTileClause>(*TileClauseItr);
281 SemaRef.TileInfo.ActiveTile = TileClause;
282 SemaRef.TileInfo.TileDepthSatisfied = false;
283 SemaRef.TileInfo.CurTileCount = TileClause->getSizeExprs().size();
284 SemaRef.TileInfo.DirectiveKind = DirKind;
285}
286
288 if (DirKind == OpenACCDirectiveKind::Parallel ||
289 DirKind == OpenACCDirectiveKind::Serial ||
291 DirKind == OpenACCDirectiveKind::Loop ||
295 SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
296 SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;
297 SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
298 SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
299 SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;
300 SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);
301 } else if (DirKind == OpenACCDirectiveKind::Data ||
303 // Intentionally doesn't reset the Loop, Compute Construct, or reduction
304 // effects.
305 }
306}
307
309 SourceLocation DirLoc) {
310 // Start an evaluation context to parse the clause arguments on.
313
314 switch (K) {
316 // Nothing to do here, an invalid kind has nothing we can check here. We
317 // want to continue parsing clauses as far as we can, so we will just
318 // ensure that we can still work and don't check any construct-specific
319 // rules anywhere.
320 break;
337 // Nothing to do here, there is no real legalization that needs to happen
338 // here as these constructs do not take any arguments.
339 break;
341 // Nothing really to do here, the arguments to the 'wait' should have
342 // already been handled by the time we get here.
343 break;
344 default:
345 Diag(DirLoc, diag::warn_acc_construct_unimplemented) << K;
346 break;
347 }
348}
349
352 Expr *IntExpr) {
353
354 assert(((DK != OpenACCDirectiveKind::Invalid &&
360 "Only one of directive or clause kind should be provided");
361
362 class IntExprConverter : public Sema::ICEConvertDiagnoser {
363 OpenACCDirectiveKind DirectiveKind;
364 OpenACCClauseKind ClauseKind;
365 Expr *IntExpr;
366
367 // gets the index into the diagnostics so we can use this for clauses,
368 // directives, and sub array.s
369 unsigned getDiagKind() const {
370 if (ClauseKind != OpenACCClauseKind::Invalid)
371 return 0;
372 if (DirectiveKind != OpenACCDirectiveKind::Invalid)
373 return 1;
374 return 2;
375 }
376
377 public:
378 IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
379 Expr *IntExpr)
380 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false,
381 /*Suppress=*/false,
382 /*SuppressConversion=*/true),
383 DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
384
385 bool match(QualType T) override {
386 // OpenACC spec just calls this 'integer expression' as having an
387 // 'integer type', so fall back on C99's 'integer type'.
388 return T->isIntegerType();
389 }
391 QualType T) override {
392 return S.Diag(Loc, diag::err_acc_int_expr_requires_integer)
393 << getDiagKind() << ClauseKind << DirectiveKind << T;
394 }
395
397 diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override {
398 return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type)
399 << T << IntExpr->getSourceRange();
400 }
401
403 diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T,
404 QualType ConvTy) override {
405 return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion)
406 << T << ConvTy;
407 }
408
409 SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
410 CXXConversionDecl *Conv,
411 QualType ConvTy) override {
412 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
413 << ConvTy->isEnumeralType() << ConvTy;
414 }
415
417 diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override {
418 return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T;
419 }
420
422 noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
423 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
424 << ConvTy->isEnumeralType() << ConvTy;
425 }
426
428 diagnoseConversion(Sema &S, SourceLocation Loc, QualType T,
429 QualType ConvTy) override {
430 llvm_unreachable("conversion functions are permitted");
431 }
432 } IntExprDiagnoser(DK, CK, IntExpr);
433
434 if (!IntExpr)
435 return ExprError();
436
438 Loc, IntExpr, IntExprDiagnoser);
439 if (IntExprResult.isInvalid())
440 return ExprError();
441
442 IntExpr = IntExprResult.get();
443 if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType())
444 return ExprError();
445
446 // TODO OpenACC: Do we want to perform usual unary conversions here? When
447 // doing codegen we might find that is necessary, but skip it for now.
448 return IntExpr;
449}
450
452 Expr *VarExpr) {
453 // We already know that VarExpr is a proper reference to a variable, so we
454 // should be able to just take the type of the expression to get the type of
455 // the referenced variable.
456
457 // We've already seen an error, don't diagnose anything else.
458 if (!VarExpr || VarExpr->containsErrors())
459 return false;
460
461 if (isa<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()) ||
462 VarExpr->hasPlaceholderType(BuiltinType::ArraySection)) {
463 Diag(VarExpr->getExprLoc(), diag::err_array_section_use) << /*OpenACC=*/0;
464 Diag(VarExpr->getExprLoc(), diag::note_acc_expected_pointer_var);
465 return true;
466 }
467
468 QualType Ty = VarExpr->getType();
470
471 // Nothing we can do if this is a dependent type.
472 if (Ty->isDependentType())
473 return false;
474
475 if (!Ty->isPointerType())
476 return Diag(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)
477 << ClauseKind << Ty;
478 return false;
479}
480
482 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
483
484 // 'use_device' doesn't allow array subscript or array sections.
485 // OpenACC3.3 2.8:
486 // A 'var' in a 'use_device' clause must be the name of a variable or array.
488 isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
489 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
490 return ExprError();
491 }
492
493 // Sub-arrays/subscript-exprs are fine as long as the base is a
494 // VarExpr/MemberExpr. So strip all of those off.
495 while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
496 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
497 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
498 else
499 CurVarExpr =
500 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
501 }
502
503 // References to a VarDecl are fine.
504 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
505 if (isa<VarDecl, NonTypeTemplateParmDecl>(
506 DRE->getFoundDecl()->getCanonicalDecl()))
507 return VarExpr;
508 }
509
510 // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
511 // reduction clause must be a scalar variable name, an aggregate variable
512 // name, an array element, or a subarray.
513 // If CK is a 'use_device', this also isn't valid, as it isn' the name of a
514 // variable or array.
515 // A MemberExpr that references a Field is valid for other clauses.
518 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
519 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl()))
520 return VarExpr;
521 }
522 }
523
524 // Referring to 'this' is ok for the most part, but for 'use_device' doesn't
525 // fall into 'variable or array name'
526 if (CK != OpenACCClauseKind::UseDevice && isa<CXXThisExpr>(CurVarExpr))
527 return VarExpr;
528
529 // Nothing really we can do here, as these are dependent. So just return they
530 // are valid.
531 if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
533 isa<CXXDependentScopeMemberExpr>(CurVarExpr)))
534 return VarExpr;
535
536 // There isn't really anything we can do in the case of a recovery expr, so
537 // skip the diagnostic rather than produce a confusing diagnostic.
538 if (isa<RecoveryExpr>(CurVarExpr))
539 return ExprError();
540
542 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
543 else
544 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
546 return ExprError();
547}
548
550 Expr *LowerBound,
551 SourceLocation ColonLoc,
552 Expr *Length,
553 SourceLocation RBLoc) {
554 ASTContext &Context = getASTContext();
555
556 // Handle placeholders.
557 if (Base->hasPlaceholderType() &&
558 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
560 if (Result.isInvalid())
561 return ExprError();
562 Base = Result.get();
563 }
564 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
566 if (Result.isInvalid())
567 return ExprError();
569 if (Result.isInvalid())
570 return ExprError();
571 LowerBound = Result.get();
572 }
573 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
575 if (Result.isInvalid())
576 return ExprError();
578 if (Result.isInvalid())
579 return ExprError();
580 Length = Result.get();
581 }
582
583 // Check the 'base' value, it must be an array or pointer type, and not to/of
584 // a function type.
586 QualType ResultTy;
587 if (!Base->isTypeDependent()) {
588 if (OriginalBaseTy->isAnyPointerType()) {
589 ResultTy = OriginalBaseTy->getPointeeType();
590 } else if (OriginalBaseTy->isArrayType()) {
591 ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
592 } else {
593 return ExprError(
594 Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
595 << Base->getSourceRange());
596 }
597
598 if (ResultTy->isFunctionType()) {
599 Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
600 << ResultTy << Base->getSourceRange();
601 return ExprError();
602 }
603
604 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
605 diag::err_acc_subarray_incomplete_type,
606 Base))
607 return ExprError();
608
609 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
611 if (Result.isInvalid())
612 return ExprError();
613 Base = Result.get();
614 }
615 }
616
617 auto GetRecovery = [&](Expr *E, QualType Ty) {
618 ExprResult Recovery =
620 return Recovery.isUsable() ? Recovery.get() : nullptr;
621 };
622
623 // Ensure both of the expressions are int-exprs.
624 if (LowerBound && !LowerBound->isTypeDependent()) {
625 ExprResult LBRes =
627 LowerBound->getExprLoc(), LowerBound);
628
629 if (LBRes.isUsable())
630 LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
631 LowerBound =
632 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
633 }
634
635 if (Length && !Length->isTypeDependent()) {
636 ExprResult LenRes =
638 Length->getExprLoc(), Length);
639
640 if (LenRes.isUsable())
641 LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
642 Length =
643 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
644 }
645
646 // Length is required if the base type is not an array of known bounds.
647 if (!Length && (OriginalBaseTy.isNull() ||
648 (!OriginalBaseTy->isDependentType() &&
649 !OriginalBaseTy->isConstantArrayType() &&
650 !OriginalBaseTy->isDependentSizedArrayType()))) {
651 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
652 Diag(ColonLoc, diag::err_acc_subarray_no_length) << IsArray;
653 // Fill in a dummy 'length' so that when we instantiate this we don't
654 // double-diagnose here.
656 ColonLoc, SourceLocation(), ArrayRef<Expr *>(), Context.IntTy);
657 Length = Recovery.isUsable() ? Recovery.get() : nullptr;
658 }
659
660 // Check the values of each of the arguments, they cannot be negative(we
661 // assume), and if the array bound is known, must be within range. As we do
662 // so, do our best to continue with evaluation, we can set the
663 // value/expression to nullptr/nullopt if they are invalid, and treat them as
664 // not present for the rest of evaluation.
665
666 // We don't have to check for dependence, because the dependent size is
667 // represented as a different AST node.
668 std::optional<llvm::APSInt> BaseSize;
669 if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
670 const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);
671 BaseSize = ArrayTy->getSize();
672 }
673
674 auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
675 if (!E || E->isInstantiationDependent())
676 return std::nullopt;
677
679 if (!E->EvaluateAsInt(Res, Context))
680 return std::nullopt;
681 return Res.Val.getInt();
682 };
683
684 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
685 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
686
687 // Check lower bound for negative or out of range.
688 if (LowerBoundValue.has_value()) {
689 if (LowerBoundValue->isNegative()) {
690 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
691 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
692 LowerBoundValue.reset();
693 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
694 } else if (BaseSize.has_value() &&
695 llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
696 // Lower bound (start index) must be less than the size of the array.
697 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
698 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
699 << toString(*BaseSize, /*Radix=*/10);
700 LowerBoundValue.reset();
701 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
702 }
703 }
704
705 // Check length for negative or out of range.
706 if (LengthValue.has_value()) {
707 if (LengthValue->isNegative()) {
708 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
709 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
710 LengthValue.reset();
711 Length = GetRecovery(Length, Length->getType());
712 } else if (BaseSize.has_value() &&
713 llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
714 // Length must be lessthan or EQUAL to the size of the array.
715 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
716 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
717 << toString(*BaseSize, /*Radix=*/10);
718 LengthValue.reset();
719 Length = GetRecovery(Length, Length->getType());
720 }
721 }
722
723 // Adding two APSInts requires matching sign, so extract that here.
724 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
725 if (LHS.isSigned() == RHS.isSigned())
726 return LHS + RHS;
727
728 unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
729 return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), /*Signed=*/true);
730 };
731
732 // If we know all 3 values, we can diagnose that the total value would be out
733 // of range.
734 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
735 LengthValue.has_value() &&
736 llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
737 *BaseSize) > 0) {
738 Diag(Base->getExprLoc(),
739 diag::err_acc_subarray_base_plus_length_out_of_range)
740 << toString(*LowerBoundValue, /*Radix=*/10)
741 << toString(*LengthValue, /*Radix=*/10)
742 << toString(*BaseSize, /*Radix=*/10);
743
744 LowerBoundValue.reset();
745 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
746 LengthValue.reset();
747 Length = GetRecovery(Length, Length->getType());
748 }
749
750 // If any part of the expression is dependent, return a dependent sub-array.
751 QualType ArrayExprTy = Context.ArraySectionTy;
752 if (Base->isTypeDependent() ||
753 (LowerBound && LowerBound->isInstantiationDependent()) ||
754 (Length && Length->isInstantiationDependent()))
755 ArrayExprTy = Context.DependentTy;
756
757 return new (Context)
758 ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
759 OK_Ordinary, ColonLoc, RBLoc);
760}
761
763 if (!getLangOpts().OpenACC)
764 return;
765
766 if (!LoopInfo.TopLevelLoopSeen)
767 return;
768
769 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
770 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
771 << /*while loop*/ 1 << CollapseInfo.DirectiveKind
773 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
774 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
775 diag::note_acc_active_clause_here)
777
778 // Remove the value so that we don't get cascading errors in the body. The
779 // caller RAII object will restore this.
780 CollapseInfo.CurCollapseCount = std::nullopt;
781 }
782
783 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
784 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
785 << /*while loop*/ 1 << TileInfo.DirectiveKind
787 assert(TileInfo.ActiveTile && "tile count without object?");
788 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
790
791 // Remove the value so that we don't get cascading errors in the body. The
792 // caller RAII object will restore this.
793 TileInfo.CurTileCount = std::nullopt;
794 }
795}
796
798 if (!getLangOpts().OpenACC)
799 return;
800
801 if (!LoopInfo.TopLevelLoopSeen)
802 return;
803
804 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
805 Diag(DoLoc, diag::err_acc_invalid_in_loop)
806 << /*do loop*/ 2 << CollapseInfo.DirectiveKind
808 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
809 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
810 diag::note_acc_active_clause_here)
812
813 // Remove the value so that we don't get cascading errors in the body. The
814 // caller RAII object will restore this.
815 CollapseInfo.CurCollapseCount = std::nullopt;
816 }
817
818 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
819 Diag(DoLoc, diag::err_acc_invalid_in_loop)
820 << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
821 assert(TileInfo.ActiveTile && "tile count without object?");
822 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
824
825 // Remove the value so that we don't get cascading errors in the body. The
826 // caller RAII object will restore this.
827 TileInfo.CurTileCount = std::nullopt;
828 }
829}
830
831void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
832 ForStmtBeginChecker &C) {
833 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
834
835 // Enable the while/do-while checking.
836 LoopInfo.TopLevelLoopSeen = true;
837
838 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
839 C.check();
840
841 // OpenACC 3.3 2.9.1:
842 // Each associated loop, except the innermost, must contain exactly one loop
843 // or loop nest.
844 // This checks for more than 1 loop at the current level, the
845 // 'depth'-satisifed checking manages the 'not zero' case.
846 if (LoopInfo.CurLevelHasLoopAlready) {
847 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
848 << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
849 assert(CollapseInfo.ActiveCollapse && "No collapse object?");
850 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
851 diag::note_acc_active_clause_here)
853 } else {
854 --(*CollapseInfo.CurCollapseCount);
855
856 // Once we've hit zero here, we know we have deep enough 'for' loops to
857 // get to the bottom.
858 if (*CollapseInfo.CurCollapseCount == 0)
859 CollapseInfo.CollapseDepthSatisfied = true;
860 }
861 }
862
863 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
864 C.check();
865
866 if (LoopInfo.CurLevelHasLoopAlready) {
867 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
868 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
869 assert(TileInfo.ActiveTile && "No tile object?");
870 Diag(TileInfo.ActiveTile->getBeginLoc(),
871 diag::note_acc_active_clause_here)
873 } else {
874 --(*TileInfo.CurTileCount);
875 // Once we've hit zero here, we know we have deep enough 'for' loops to
876 // get to the bottom.
877 if (*TileInfo.CurTileCount == 0)
878 TileInfo.TileDepthSatisfied = true;
879 }
880 }
881
882 // Set this to 'false' for the body of this loop, so that the next level
883 // checks independently.
884 LoopInfo.CurLevelHasLoopAlready = false;
885}
886
887namespace {
888bool isValidLoopVariableType(QualType LoopVarTy) {
889 // Just skip if it is dependent, it could be any of the below.
890 if (LoopVarTy->isDependentType())
891 return true;
892
893 // The loop variable must be of integer,
894 if (LoopVarTy->isIntegerType())
895 return true;
896
897 // C/C++ pointer,
898 if (LoopVarTy->isPointerType())
899 return true;
900
901 // or C++ random-access iterator type.
902 if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
903 // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
904 // iterator type!
905
906 // We could either do a lot of work to see if this matches
907 // random-access-iterator, but it seems that just checking that the
908 // 'iterator_category' typedef is more than sufficient. If programmers are
909 // willing to lie about this, we can let them.
910
911 for (const auto *TD :
912 llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
913 const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
914
915 if (TDND->getName() != "iterator_category")
916 continue;
917
918 // If there is no type for this decl, return false.
919 if (TDND->getUnderlyingType().isNull())
920 return false;
921
922 const CXXRecordDecl *ItrCategoryDecl =
923 TDND->getUnderlyingType()->getAsCXXRecordDecl();
924
925 // If the category isn't a record decl, it isn't the tag type.
926 if (!ItrCategoryDecl)
927 return false;
928
929 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
930 if (RD->getName() != "random_access_iterator_tag")
931 return false;
932 // Checks just for std::random_access_iterator_tag.
934 };
935
936 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
937 return true;
938
939 // We can also support types inherited from the
940 // random_access_iterator_tag.
941 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases()) {
942
943 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
944 return true;
945 }
946
947 return false;
948 }
949 }
950
951 return false;
952}
953
954} // namespace
955
956void SemaOpenACC::ForStmtBeginChecker::check() {
957 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
958 return;
959
960 if (AlreadyChecked)
961 return;
962 AlreadyChecked = true;
963
964 // OpenACC3.3 2.1:
965 // A loop associated with a loop construct that does not have a seq clause
966 // must be written to meet all the following conditions:
967 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
968 // iterator type.
969 // - The loop variable must monotonically increase or decrease in the
970 // direction of its termination condition.
971 // - The loop trip count must be computable in constant time when entering the
972 // loop construct.
973 //
974 // For a C++ range-based for loop, the loop variable
975 // identified by the above conditions is the internal iterator, such as a
976 // pointer, that the compiler generates to iterate the range. it is not the
977 // variable declared by the for loop.
978
979 if (IsRangeFor) {
980 // If the range-for is being instantiated and didn't change, don't
981 // re-diagnose.
982 if (!RangeFor.has_value())
983 return;
984 // For a range-for, we can assume everything is 'corect' other than the type
985 // of the iterator, so check that.
986 const DeclStmt *RangeStmt = (*RangeFor)->getBeginStmt();
987
988 // In some dependent contexts, the autogenerated range statement doesn't get
989 // included until instantiation, so skip for now.
990 if (!RangeStmt)
991 return;
992
993 const ValueDecl *InitVar = cast<ValueDecl>(RangeStmt->getSingleDecl());
994 QualType VarType = InitVar->getType().getNonReferenceType();
995 if (!isValidLoopVariableType(VarType)) {
996 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
997 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
998 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
999 diag::note_acc_construct_here)
1000 << SemaRef.LoopWithoutSeqInfo.Kind;
1001 }
1002 return;
1003 }
1004
1005 // Else we are in normal 'ForStmt', so we can diagnose everything.
1006 // We only have to check cond/inc if they have changed, but 'init' needs to
1007 // just suppress its diagnostics if it hasn't changed.
1008 const ValueDecl *InitVar = checkInit();
1009 if (Cond.has_value())
1010 checkCond();
1011 if (Inc.has_value())
1012 checkInc(InitVar);
1013}
1014const ValueDecl *SemaOpenACC::ForStmtBeginChecker::checkInit() {
1015 if (!Init) {
1016 if (InitChanged) {
1017 SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)
1018 << SemaRef.LoopWithoutSeqInfo.Kind;
1019 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1020 diag::note_acc_construct_here)
1021 << SemaRef.LoopWithoutSeqInfo.Kind;
1022 }
1023 return nullptr;
1024 }
1025
1026 auto DiagLoopVar = [&]() {
1027 if (InitChanged) {
1028 SemaRef.Diag(Init->getBeginLoc(), diag::err_acc_loop_variable)
1029 << SemaRef.LoopWithoutSeqInfo.Kind;
1030 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1031 diag::note_acc_construct_here)
1032 << SemaRef.LoopWithoutSeqInfo.Kind;
1033 }
1034 return nullptr;
1035 };
1036
1037 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
1038 Init = ExprTemp->getSubExpr();
1039 if (const auto *E = dyn_cast<Expr>(Init))
1041
1042 const ValueDecl *InitVar = nullptr;
1043
1044 if (const auto *BO = dyn_cast<BinaryOperator>(Init)) {
1045 // Allow assignment operator here.
1046
1047 if (!BO->isAssignmentOp())
1048 return DiagLoopVar();
1049
1050 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
1051
1052 if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS))
1053 InitVar = DRE->getDecl();
1054 } else if (const auto *DS = dyn_cast<DeclStmt>(Init)) {
1055 // Allow T t = <whatever>
1056 if (!DS->isSingleDecl())
1057 return DiagLoopVar();
1058
1059 InitVar = dyn_cast<ValueDecl>(DS->getSingleDecl());
1060
1061 // Ensure we have an initializer, unless this is a record/dependent type.
1062
1063 if (InitVar) {
1064 if (!isa<VarDecl>(InitVar))
1065 return DiagLoopVar();
1066
1067 if (!InitVar->getType()->isRecordType() &&
1068 !InitVar->getType()->isDependentType() &&
1069 !cast<VarDecl>(InitVar)->hasInit())
1070 return DiagLoopVar();
1071 }
1072 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Init)) {
1073 // Allow assignment operator call.
1074 if (CE->getOperator() != OO_Equal)
1075 return DiagLoopVar();
1076
1077 const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
1078
1079 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1080 InitVar = DRE->getDecl();
1081 } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
1082 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1083 InitVar = ME->getMemberDecl();
1084 }
1085 }
1086
1087 if (!InitVar)
1088 return DiagLoopVar();
1089
1090 InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
1091 QualType VarType = InitVar->getType().getNonReferenceType();
1092
1093 // Since we have one, all we need to do is ensure it is the right type.
1094 if (!isValidLoopVariableType(VarType)) {
1095 if (InitChanged) {
1096 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1097 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1098 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1099 diag::note_acc_construct_here)
1100 << SemaRef.LoopWithoutSeqInfo.Kind;
1101 }
1102 return nullptr;
1103 }
1104
1105 return InitVar;
1106}
1107void SemaOpenACC::ForStmtBeginChecker::checkCond() {
1108 if (!*Cond) {
1109 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
1110 << SemaRef.LoopWithoutSeqInfo.Kind;
1111 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
1112 << SemaRef.LoopWithoutSeqInfo.Kind;
1113 }
1114 // Nothing else to do here. we could probably do some additional work to look
1115 // into the termination condition, but that error-prone. For now, we don't
1116 // implement anything other than 'there is a termination condition', and if
1117 // codegen/MLIR comes up with some necessary restrictions, we can implement
1118 // them here.
1119}
1120
1121void SemaOpenACC::ForStmtBeginChecker::checkInc(const ValueDecl *Init) {
1122
1123 if (!*Inc) {
1124 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
1125 << SemaRef.LoopWithoutSeqInfo.Kind;
1126 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
1127 << SemaRef.LoopWithoutSeqInfo.Kind;
1128 return;
1129 }
1130 auto DiagIncVar = [this] {
1131 SemaRef.Diag((*Inc)->getBeginLoc(), diag::err_acc_loop_not_monotonic)
1132 << SemaRef.LoopWithoutSeqInfo.Kind;
1133 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
1134 << SemaRef.LoopWithoutSeqInfo.Kind;
1135 return;
1136 };
1137
1138 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(*Inc))
1139 Inc = ExprTemp->getSubExpr();
1140 if (const auto *E = dyn_cast<Expr>(*Inc))
1142
1143 auto getDeclFromExpr = [](const Expr *E) -> const ValueDecl * {
1144 E = E->IgnoreParenImpCasts();
1145 if (const auto *FE = dyn_cast<FullExpr>(E))
1146 E = FE->getSubExpr();
1147
1148 E = E->IgnoreParenImpCasts();
1149
1150 if (!E)
1151 return nullptr;
1152 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
1153 return dyn_cast<ValueDecl>(DRE->getDecl());
1154
1155 if (const auto *ME = dyn_cast<MemberExpr>(E))
1156 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1157 return ME->getMemberDecl();
1158
1159 return nullptr;
1160 };
1161
1162 const ValueDecl *IncVar = nullptr;
1163
1164 // Here we enforce the monotonically increase/decrease:
1165 if (const auto *UO = dyn_cast<UnaryOperator>(*Inc)) {
1166 // Allow increment/decrement ops.
1167 if (!UO->isIncrementDecrementOp())
1168 return DiagIncVar();
1169 IncVar = getDeclFromExpr(UO->getSubExpr());
1170 } else if (const auto *BO = dyn_cast<BinaryOperator>(*Inc)) {
1171 switch (BO->getOpcode()) {
1172 default:
1173 return DiagIncVar();
1174 case BO_AddAssign:
1175 case BO_SubAssign:
1176 case BO_MulAssign:
1177 case BO_DivAssign:
1178 case BO_Assign:
1179 // += -= *= /= should all be fine here, this should be all of the
1180 // 'monotonical' compound-assign ops.
1181 // Assignment we just give up on, we could do better, and ensure that it
1182 // is a binary/operator expr doing more work, but that seems like a lot
1183 // of work for an error prone check.
1184 break;
1185 }
1186 IncVar = getDeclFromExpr(BO->getLHS());
1187 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(*Inc)) {
1188 switch (CE->getOperator()) {
1189 default:
1190 return DiagIncVar();
1191 case OO_PlusPlus:
1192 case OO_MinusMinus:
1193 case OO_PlusEqual:
1194 case OO_MinusEqual:
1195 case OO_StarEqual:
1196 case OO_SlashEqual:
1197 case OO_Equal:
1198 // += -= *= /= should all be fine here, this should be all of the
1199 // 'monotonical' compound-assign ops.
1200 // Assignment we just give up on, we could do better, and ensure that it
1201 // is a binary/operator expr doing more work, but that seems like a lot
1202 // of work for an error prone check.
1203 break;
1204 }
1205
1206 IncVar = getDeclFromExpr(CE->getArg(0));
1207
1208 } else if (const auto *ME = dyn_cast<CXXMemberCallExpr>(*Inc)) {
1209 IncVar = getDeclFromExpr(ME->getImplicitObjectArgument());
1210 // We can't really do much for member expressions, other than hope they are
1211 // doing the right thing, so give up here.
1212 }
1213
1214 if (!IncVar)
1215 return DiagIncVar();
1216
1217 // InitVar shouldn't be null unless there was an error, so don't diagnose if
1218 // that is the case. Else we should ensure that it refers to the loop
1219 // value.
1220 if (Init && IncVar->getCanonicalDecl() != Init->getCanonicalDecl())
1221 return DiagIncVar();
1222
1223 return;
1224}
1225
1227 const Stmt *First, const Stmt *OldSecond,
1228 const Stmt *Second, const Stmt *OldThird,
1229 const Stmt *Third) {
1230 if (!getLangOpts().OpenACC)
1231 return;
1232
1233 std::optional<const Stmt *> S;
1234 if (OldSecond == Second)
1235 S = std::nullopt;
1236 else
1237 S = Second;
1238 std::optional<const Stmt *> T;
1239 if (OldThird == Third)
1240 S = std::nullopt;
1241 else
1242 S = Third;
1243
1244 bool InitChanged = false;
1245 if (OldFirst != First) {
1246 InitChanged = true;
1247
1248 // VarDecls are always rebuild because they are dependent, so we can do a
1249 // little work to suppress some of the double checking based on whether the
1250 // type is instantiation dependent.
1251 QualType OldVDTy;
1252 QualType NewVDTy;
1253 if (const auto *DS = dyn_cast<DeclStmt>(OldFirst))
1254 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1255 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1256 OldVDTy = VD->getType();
1257 if (const auto *DS = dyn_cast<DeclStmt>(First))
1258 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1259 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1260 NewVDTy = VD->getType();
1261
1262 if (!OldVDTy.isNull() && !NewVDTy.isNull())
1263 InitChanged = OldVDTy->isInstantiationDependentType() !=
1265 }
1266
1267 ForStmtBeginChecker FSBC{*this, ForLoc, First, InitChanged, S, T};
1268 if (!LoopInfo.TopLevelLoopSeen) {
1269 FSBC.check();
1270 }
1271
1272 ForStmtBeginHelper(ForLoc, FSBC);
1273}
1274
1276 const Stmt *Second, const Stmt *Third) {
1277 if (!getLangOpts().OpenACC)
1278 return;
1279
1280 ForStmtBeginChecker FSBC{*this, ForLoc, First, /*InitChanged=*/true,
1281 Second, Third};
1282 if (!LoopInfo.TopLevelLoopSeen) {
1283 FSBC.check();
1284 }
1285
1286 ForStmtBeginHelper(ForLoc, FSBC);
1287}
1288
1290 const Stmt *OldRangeFor,
1291 const Stmt *RangeFor) {
1292 if (!getLangOpts().OpenACC)
1293 return;
1294
1295 std::optional<const CXXForRangeStmt *> RF;
1296
1297 if (OldRangeFor == RangeFor)
1298 RF = std::nullopt;
1299 else
1300 RF = cast<CXXForRangeStmt>(RangeFor);
1301
1302 ForStmtBeginChecker FSBC{*this, ForLoc, RF};
1303 if (!LoopInfo.TopLevelLoopSeen) {
1304 FSBC.check();
1305 }
1306 ForStmtBeginHelper(ForLoc, FSBC);
1307}
1308
1310 const Stmt *RangeFor) {
1311 if (!getLangOpts().OpenACC)
1312 return;
1313
1314 ForStmtBeginChecker FSBC{*this, ForLoc, cast<CXXForRangeStmt>(RangeFor)};
1315 if (!LoopInfo.TopLevelLoopSeen) {
1316 FSBC.check();
1317 }
1318 ForStmtBeginHelper(ForLoc, FSBC);
1319}
1320
1321namespace {
1322SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
1323 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
1324 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
1325 // `DoStmt`, as those are caught as a violation elsewhere.
1326 // For `CompoundStmt` we need to search inside of it.
1327 if (!CurStmt ||
1328 isa<ForStmt, NullStmt, ForStmt, CXXForRangeStmt, WhileStmt, DoStmt>(
1329 CurStmt))
1330 return SourceLocation{};
1331
1332 // Any other construct is an error anyway, so it has already been diagnosed.
1333 if (isa<OpenACCConstructStmt>(CurStmt))
1334 return SourceLocation{};
1335
1336 // Search inside the compound statement, this allows for arbitrary nesting
1337 // of compound statements, as long as there isn't any code inside.
1338 if (const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
1339 for (const auto *ChildStmt : CS->children()) {
1340 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
1341 if (ChildStmtLoc.isValid())
1342 return ChildStmtLoc;
1343 }
1344 // Empty/not invalid compound statements are legal.
1345 return SourceLocation{};
1346 }
1347 return CurStmt->getBeginLoc();
1348}
1349} // namespace
1350
1352 if (!getLangOpts().OpenACC)
1353 return;
1354
1355 // Set this to 'true' so if we find another one at this level we can diagnose.
1356 LoopInfo.CurLevelHasLoopAlready = true;
1357
1358 if (!Body.isUsable())
1359 return;
1360
1361 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1362 *CollapseInfo.CurCollapseCount > 0 &&
1363 !CollapseInfo.ActiveCollapse->hasForce();
1364 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1365
1366 if (IsActiveCollapse || IsActiveTile) {
1367 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());
1368
1369 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
1370 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1371 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
1372 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1373 diag::note_acc_active_clause_here)
1375 }
1376
1377 if (OtherStmtLoc.isValid() && IsActiveTile) {
1378 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1379 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
1380 Diag(TileInfo.ActiveTile->getBeginLoc(),
1381 diag::note_acc_active_clause_here)
1383 }
1384 }
1385}
1386
1387namespace {
1388// Get a list of clause Kinds for diagnosing a list, joined by a commas and an
1389// 'or'.
1390std::string GetListOfClauses(llvm::ArrayRef<OpenACCClauseKind> Clauses) {
1391 assert(!Clauses.empty() && "empty clause list not supported");
1392
1393 std::string Output;
1394 llvm::raw_string_ostream OS{Output};
1395
1396 if (Clauses.size() == 1) {
1397 OS << '\'' << Clauses[0] << '\'';
1398 return Output;
1399 }
1400
1401 llvm::ArrayRef<OpenACCClauseKind> AllButLast{Clauses.begin(),
1402 Clauses.end() - 1};
1403
1404 llvm::interleave(
1405 AllButLast, [&](OpenACCClauseKind K) { OS << '\'' << K << '\''; },
1406 [&] { OS << ", "; });
1407
1408 OS << " or \'" << Clauses.back() << '\'';
1409 return Output;
1410}
1411} // namespace
1412
1418
1419 // OpenACC 3.3 2.9.1:
1420 // Intervening code must not contain other OpenACC directives or calls to API
1421 // routines.
1422 //
1423 // ALL constructs are ill-formed if there is an active 'collapse'
1424 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1425 Diag(StartLoc, diag::err_acc_invalid_in_loop)
1426 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
1428 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1429 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1430 diag::note_acc_active_clause_here)
1432 }
1433 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1434 Diag(StartLoc, diag::err_acc_invalid_in_loop)
1435 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
1437 assert(TileInfo.ActiveTile && "Tile count without object?");
1438 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1440 }
1441
1442 // OpenACC3.3 2.6.5: At least one copy, copyin, copyout, create, no_create,
1443 // present, deviceptr, attach, or default clause must appear on a 'data'
1444 // construct.
1445 if (K == OpenACCDirectiveKind::Data &&
1446 llvm::find_if(Clauses,
1451 OpenACCDefaultClause>) == Clauses.end())
1452 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1453 << K
1454 << GetListOfClauses(
1460
1461 // OpenACC3.3 2.6.6: At least one copyin, create, or attach clause must appear
1462 // on an enter data directive.
1464 llvm::find_if(Clauses,
1466 OpenACCAttachClause>) == Clauses.end())
1467 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1468 << K
1469 << GetListOfClauses({
1473 });
1474 // OpenACC3.3 2.6.6: At least one copyout, delete, or detach clause must
1475 // appear on an exit data directive.
1477 llvm::find_if(Clauses,
1479 OpenACCDetachClause>) == Clauses.end())
1480 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1481 << K
1482 << GetListOfClauses({
1486 });
1487
1488 // OpenACC3.3 2.8: At least 'one use_device' clause must appear.
1490 llvm::find_if(Clauses, llvm::IsaPred<OpenACCUseDeviceClause>) ==
1491 Clauses.end())
1492 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1493 << K << GetListOfClauses({OpenACCClauseKind::UseDevice});
1494
1495 // OpenACC3.3 2.14.3: At least one default_async, device_num, or device_type
1496 // clause must appear.
1497 if (K == OpenACCDirectiveKind::Set &&
1498 llvm::find_if(
1499 Clauses,
1502 Clauses.end())
1503 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1504 << K
1505 << GetListOfClauses({OpenACCClauseKind::DefaultAsync,
1509
1510 // OpenACC3.3 2.14.4: At least one self, host, or device clause must appear on
1511 // an update directive.
1513 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSelfClause, OpenACCHostClause,
1515 Clauses.end())
1516 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1517 << K
1518 << GetListOfClauses({OpenACCClauseKind::Self,
1521
1522 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
1523}
1524
1527 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
1528 OpenACCAtomicKind AtomicKind, SourceLocation RParenLoc,
1530 StmtResult AssocStmt) {
1531 switch (K) {
1532 default:
1533 return StmtEmpty();
1535 return StmtError();
1540 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
1541 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1542 }
1547 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
1548 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1549 }
1552 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
1553 EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1554 }
1557 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
1558 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1559 }
1561 return OpenACCEnterDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
1562 EndLoc, Clauses);
1563 }
1565 return OpenACCExitDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
1566 EndLoc, Clauses);
1567 }
1570 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
1571 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1572 }
1575 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
1576 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
1577 }
1579 return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc,
1580 EndLoc, Clauses);
1581 }
1583 return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
1584 EndLoc, Clauses);
1585 }
1587 return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
1588 EndLoc, Clauses);
1589 }
1591 return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
1592 EndLoc, Clauses);
1593 }
1595 assert(Clauses.empty() && "Atomic doesn't allow clauses");
1597 getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc,
1598 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1599 }
1600 }
1601 llvm_unreachable("Unhandled case in directive handling?");
1602}
1603
1605 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
1607 StmtResult AssocStmt) {
1608 switch (K) {
1609 default:
1610 llvm_unreachable("Unimplemented associated statement application");
1617 llvm_unreachable(
1618 "these don't have associated statements, so shouldn't get here");
1620 return CheckAtomicAssociatedStmt(DirectiveLoc, AtKind, AssocStmt);
1626 // There really isn't any checking here that could happen. As long as we
1627 // have a statement to associate, this should be fine.
1628 // OpenACC 3.3 Section 6:
1629 // Structured Block: in C or C++, an executable statement, possibly
1630 // compound, with a single entry at the top and a single exit at the
1631 // bottom.
1632 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
1633 // an interpretation of it is to allow this and treat the initializer as
1634 // the 'structured block'.
1635 return AssocStmt;
1640 if (!AssocStmt.isUsable())
1641 return StmtError();
1642
1643 if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
1644 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
1645 << K;
1646 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
1647 return StmtError();
1648 }
1649
1650 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
1651 if (!CollapseInfo.CollapseDepthSatisfied) {
1652 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
1654 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1655 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1656 diag::note_acc_active_clause_here)
1658 }
1659
1660 if (!TileInfo.TileDepthSatisfied) {
1661 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
1663 assert(TileInfo.ActiveTile && "Collapse count without object?");
1664 Diag(TileInfo.ActiveTile->getBeginLoc(),
1665 diag::note_acc_active_clause_here)
1667 }
1668 return StmtError();
1669 }
1670
1671 return AssocStmt.get();
1672 }
1673 llvm_unreachable("Invalid associated statement application");
1674}
1675
1677 SourceLocation StartLoc) {
1678 // OpenCC3.3 2.1 (line 889)
1679 // A program must not depend on the order of evaluation of expressions in
1680 // clause arguments or on any side effects of the evaluations.
1683 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
1684}
1685
1687
1690 return OpenACCAsteriskSizeExpr::Create(getASTContext(), AsteriskLoc);
1691}
1692
1695 return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
1696}
Expr * E
Defines some OpenACC-specific enums and functions.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static NamedDecl * getDeclFromExpr(Expr *E)
Definition: SemaExpr.cpp:14697
SourceLocation Loc
Definition: SemaObjC.cpp:759
This file declares semantic analysis for OpenACC constructs and clauses.
This file defines OpenACC AST classes for statement-level contructs.
APSInt & getInt()
Definition: APValue.h:489
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Definition: ASTContext.h:2922
CanQualType DependentTy
Definition: ASTContext.h:1188
CanQualType ArraySectionTy
Definition: ASTContext.h:1200
CanQualType IntTy
Definition: ASTContext.h:1169
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition: Expr.h:6986
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5186
QualType getElementType() const
Definition: Type.h:3590
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2924
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
base_class_range bases()
Definition: DeclCXX.h:620
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition: Type.h:3672
bool isStdNamespace() const
Definition: DeclBase.cpp:1331
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
Definition: DeclBase.cpp:2030
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1519
const Decl * getSingleDecl() const
Definition: Stmt.h:1534
SourceLocation getLocation() const
Definition: DeclBase.h:442
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:434
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:971
This represents one expression.
Definition: Expr.h:110
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3096
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition: Expr.h:245
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:276
QualType getType() const
Definition: Expr.h:142
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Definition: Expr.h:516
static OpenACCAsteriskSizeExpr * Create(const ASTContext &C, SourceLocation Loc)
Definition: Expr.cpp:5433
static OpenACCAtomicConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, OpenACCAtomicKind AtKind, SourceLocation End, Stmt *AssociatedStmt)
Represents a 'collapse' clause on a 'loop' construct.
const Expr * getLoopCount() const
static OpenACCCombinedConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCComputeConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, SourceLocation DirectiveLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
Definition: StmtOpenACC.cpp:27
static OpenACCDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
A 'default' clause, has the optional 'none' or 'present' argument.
A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or an identifier.
static OpenACCEnterDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCExitDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCHostDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
An 'if' clause, which has a required condition expression.
static OpenACCInitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCLoopConstruct * Create(const ASTContext &C, OpenACCDirectiveKind ParentKind, SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *Loop)
Definition: StmtOpenACC.cpp:80
A 'self' clause, which has an optional condition expression, or, in the event of an 'update' directiv...
static OpenACCSetConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCShutdownConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
llvm::ArrayRef< Expr * > getSizeExprs()
static OpenACCUpdateConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCWaitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef< Expr * > QueueIdExprs, SourceLocation RParenLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
A (possibly-)qualified type.
Definition: Type.h:929
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:996
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: Type.h:8140
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:8031
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:110
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind, SourceLocation, ArrayRef< const OpenACCClause * >, ArrayRef< OpenACCClause * >)
void SetTileInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
void SetCollapseInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr)
Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...
ComputeConstructInfo & getActiveComputeConstructInfo()
Definition: SemaOpenACC.h:162
bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation Loc, Expr *IntExpr)
Called when encountering an 'int-expr' for OpenACC, and manages conversions and diagnostics to 'int'.
void ActOnWhileStmt(SourceLocation WhileLoc)
SourceLocation LoopWorkerClauseLoc
If there is a current 'active' loop construct with a 'worker' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:179
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr)
Called to check the 'var' type is a variable of pointer type, necessary for 'deviceptr' and 'attach' ...
struct clang::SemaOpenACC::LoopGangOnKernelTy LoopGangClauseOnKernel
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, OpenACCAtomicKind AtKind, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)
Called when we encounter an associated statement for our construct, this should check legality of the...
struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo
DeclGroupRef ActOnEndDeclDirective()
Called after the directive has been completely parsed, including the declaration group or associated ...
SourceLocation LoopVectorClauseLoc
If there is a current 'active' loop construct with a 'vector' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:184
void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)
Called after the construct has been parsed, but clauses haven't been parsed.
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
void ActOnDoStmt(SourceLocation DoLoc)
void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, OpenACCAtomicKind AK, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)
Called after the directive has been completely parsed, including the declaration group or associated ...
void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)
StmtResult CheckAtomicAssociatedStmt(SourceLocation AtomicDirLoc, OpenACCAtomicKind AtKind, StmtResult AssocStmt)
Called to check the form of the atomic construct which has some fairly sizable restrictions.
void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First, const Stmt *Second, const Stmt *Third)
ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, Expr *Length, SourceLocation RBLoc)
Checks and creates an Array Section used in an OpenACC construct/clause.
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:466
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17418
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:752
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:17851
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:640
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:20995
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9122
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:17928
ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef< Expr * > SubExprs, QualType T=QualType())
Attempts to produce a RecoveryExpr after some AST node cannot be created.
Definition: SemaExpr.cpp:21192
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:358
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1916
bool isDependentSizedArrayType() const
Definition: Type.h:8284
bool isConstantArrayType() const
Definition: Type.h:8268
bool isArrayType() const
Definition: Type.h:8264
bool isPointerType() const
Definition: Type.h:8192
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8560
bool isEnumeralType() const
Definition: Type.h:8296
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:738
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: Type.h:8510
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2715
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2707
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8796
bool isFunctionType() const
Definition: Type.h:8188
bool isAnyPointerType() const
Definition: Type.h:8200
bool isRecordType() const
Definition: Type.h:8292
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:671
QualType getType() const
Definition: Decl.h:682
Represents a variable declaration or definition.
Definition: Decl.h:886
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
bool Inc(InterpState &S, CodePtr OpPC)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Definition: Interp.h:820
The JSON file list parser is used to communicate input to InstallAPI.
OpenACCDirectiveKind
Definition: OpenACCKinds.h:25
OpenACCAtomicKind
Definition: OpenACCKinds.h:169
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
OpenACCClauseKind
Represents the kind of an OpenACC clause.
Definition: OpenACCKinds.h:202
@ DevicePtr
'deviceptr' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ DeviceNum
'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
@ Invalid
Represents an invalid clause, for the purposes of parsing.
@ Copy
'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Create
'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ DeviceType
'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown', 'set', update',...
@ DefaultAsync
'default_async' clause, allowed on 'set' construct.
@ Attach
'attach' clause, allowed on Compute and Combined constructs, plus 'data' and 'enter data'.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Default
'default' clause, allowed on parallel, serial, kernel (and compound) constructs.
@ UseDevice
'use_device' clause, allowed on 'host_data' construct.
@ NoCreate
'no_create' clause, allowed on allowed on Compute and Combined constructs, plus 'data'.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
@ CopyOut
'copyout' clause, allowed on Compute and Combined constructs, plus 'data', 'exit data',...
@ Host
'host' clause, allowed on 'update' construct.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
@ CopyIn
'copyin' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ Device
'device' clause, allowed on the 'update' construct.
@ Detach
'detach' clause, allowed on the 'exit data' construct.
@ Delete
'delete' clause, allowed on the 'exit data' construct.
StmtResult StmtError()
Definition: Ownership.h:265
@ Result
The result type of a method or function.
ExprResult ExprError()
Definition: Ownership.h:264
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
const FunctionProtoType * T
StmtResult StmtEmpty()
Definition: Ownership.h:272
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:642
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:644