clang 20.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::ParallelLoop:
34 case OpenACCDirectiveKind::SerialLoop:
35 case OpenACCDirectiveKind::KernelsLoop:
36 case OpenACCDirectiveKind::Parallel:
37 case OpenACCDirectiveKind::Serial:
38 case OpenACCDirectiveKind::Kernels:
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 if (!IsStmt)
46 return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
47 break;
48 }
49 return false;
50}
51
52void CollectActiveReductionClauses(
54 ArrayRef<OpenACCClause *> CurClauses) {
55 for (auto *CurClause : CurClauses) {
56 if (auto *RedClause = dyn_cast<OpenACCReductionClause>(CurClause);
57 RedClause && !RedClause->getVarList().empty())
58 ActiveClauses.push_back(RedClause);
59 }
60}
61
62// Depth needs to be preserved for all associated statements that aren't
63// supposed to modify the compute/combined/loop construct information.
64bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
65 switch (DK) {
66 case OpenACCDirectiveKind::Parallel:
67 case OpenACCDirectiveKind::ParallelLoop:
68 case OpenACCDirectiveKind::Serial:
69 case OpenACCDirectiveKind::SerialLoop:
70 case OpenACCDirectiveKind::Kernels:
71 case OpenACCDirectiveKind::KernelsLoop:
72 case OpenACCDirectiveKind::Loop:
73 return false;
74 case OpenACCDirectiveKind::Data:
75 case OpenACCDirectiveKind::HostData:
76 return true;
77 case OpenACCDirectiveKind::EnterData:
78 case OpenACCDirectiveKind::ExitData:
79 case OpenACCDirectiveKind::Wait:
80 case OpenACCDirectiveKind::Init:
81 case OpenACCDirectiveKind::Shutdown:
82 case OpenACCDirectiveKind::Set:
83 case OpenACCDirectiveKind::Update:
84 llvm_unreachable("Doesn't have an associated stmt");
85 default:
86 case OpenACCDirectiveKind::Invalid:
87 llvm_unreachable("Unhandled directive kind?");
88 }
89 llvm_unreachable("Unhandled directive kind?");
90}
91
92} // namespace
93
95
100 : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
101 DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel),
102 OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
103 OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
104 OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo),
105 ActiveReductionClauses(S.ActiveReductionClauses),
106 LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DirKind)) {
107
108 // Compute constructs end up taking their 'loop'.
109 if (DirKind == OpenACCDirectiveKind::Parallel ||
110 DirKind == OpenACCDirectiveKind::Serial ||
112 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
113 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
114 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
115
116 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
117 // construct, the gang clause behaves as follows. ... The region of a loop
118 // with a gang clause may not contain another loop with a gang clause unless
119 // within a nested compute region.
120 //
121 // Implement the 'unless within a nested compute region' part.
122 SemaRef.LoopGangClauseOnKernel = {};
123 SemaRef.LoopWorkerClauseLoc = {};
124 SemaRef.LoopVectorClauseLoc = {};
125 SemaRef.LoopWithoutSeqInfo = {};
126 } else if (DirKind == OpenACCDirectiveKind::ParallelLoop ||
129 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
130 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
131
132 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
133 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
134 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
135
136 SemaRef.LoopGangClauseOnKernel = {};
137 SemaRef.LoopWorkerClauseLoc = {};
138 SemaRef.LoopVectorClauseLoc = {};
139
140 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
141 // diagnose the for loops.
142 SemaRef.LoopWithoutSeqInfo = {};
143 if (Clauses.end() ==
144 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
145 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
146
147 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
148 // construct, the gang clause behaves as follows. ... The region of a loop
149 // with a gang clause may not contain another loop with a gang clause unless
150 // within a nested compute region.
151 //
152 // We don't bother doing this when this is a template instantiation, as
153 // there is no reason to do these checks: the existance of a
154 // gang/kernels/etc cannot be dependent.
155 if (DirKind == OpenACCDirectiveKind::KernelsLoop && UnInstClauses.empty()) {
156 // This handles the 'outer loop' part of this.
157 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
158 if (Itr != Clauses.end())
159 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), DirKind};
160 }
161
162 if (UnInstClauses.empty()) {
163 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
164 if (Itr != Clauses.end())
165 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
166
167 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
168 if (Itr2 != Clauses.end())
169 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
170 }
171 } else if (DirKind == OpenACCDirectiveKind::Loop) {
172 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
173 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
174 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
175
176 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
177 // diagnose the for loops.
178 SemaRef.LoopWithoutSeqInfo = {};
179 if (Clauses.end() ==
180 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
181 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
182
183 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
184 // construct, the gang clause behaves as follows. ... The region of a loop
185 // with a gang clause may not contain another loop with a gang clause unless
186 // within a nested compute region.
187 //
188 // We don't bother doing this when this is a template instantiation, as
189 // there is no reason to do these checks: the existance of a
190 // gang/kernels/etc cannot be dependent.
191 if (SemaRef.getActiveComputeConstructInfo().Kind ==
193 UnInstClauses.empty()) {
194 // This handles the 'outer loop' part of this.
195 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
196 if (Itr != Clauses.end())
197 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(),
199 }
200
201 if (UnInstClauses.empty()) {
202 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
203 if (Itr != Clauses.end())
204 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
205
206 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
207 if (Itr2 != Clauses.end())
208 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
209 }
210 }
211}
212
216
217 // Reset this checking for loops that aren't covered in a RAII object.
218 SemaRef.LoopInfo.CurLevelHasLoopAlready = false;
219 SemaRef.CollapseInfo.CollapseDepthSatisfied = true;
220 SemaRef.TileInfo.TileDepthSatisfied = true;
221
222 // We make sure to take an optional list of uninstantiated clauses, so that
223 // we can check to make sure we don't 'double diagnose' in the event that
224 // the value of 'N' was not dependent in a template. We also ensure during
225 // Sema that there is only 1 collapse on each construct, so we can count on
226 // the fact that if both find a 'collapse', that they are the same one.
227 auto *CollapseClauseItr =
228 llvm::find_if(Clauses, llvm::IsaPred<OpenACCCollapseClause>);
229 auto *UnInstCollapseClauseItr =
230 llvm::find_if(UnInstClauses, llvm::IsaPred<OpenACCCollapseClause>);
231
232 if (Clauses.end() == CollapseClauseItr)
233 return;
234
235 OpenACCCollapseClause *CollapseClause =
236 cast<OpenACCCollapseClause>(*CollapseClauseItr);
237
238 SemaRef.CollapseInfo.ActiveCollapse = CollapseClause;
239 Expr *LoopCount = CollapseClause->getLoopCount();
240
241 // If the loop count is still instantiation dependent, setting the depth
242 // counter isn't necessary, so return here.
243 if (!LoopCount || LoopCount->isInstantiationDependent())
244 return;
245
246 // Suppress diagnostics if we've done a 'transform' where the previous version
247 // wasn't dependent, meaning we already diagnosed it.
248 if (UnInstCollapseClauseItr != UnInstClauses.end() &&
249 !cast<OpenACCCollapseClause>(*UnInstCollapseClauseItr)
250 ->getLoopCount()
251 ->isInstantiationDependent())
252 return;
253
254 SemaRef.CollapseInfo.CollapseDepthSatisfied = false;
255 SemaRef.CollapseInfo.CurCollapseCount =
256 cast<ConstantExpr>(LoopCount)->getResultAsAPSInt();
257 SemaRef.CollapseInfo.DirectiveKind = DirKind;
258}
259
263 // We don't diagnose if this is during instantiation, since the only thing we
264 // care about is the number of arguments, which we can figure out without
265 // instantiation, so we don't want to double-diagnose.
266 if (UnInstClauses.size() > 0)
267 return;
268 auto *TileClauseItr =
269 llvm::find_if(Clauses, llvm::IsaPred<OpenACCTileClause>);
270
271 if (Clauses.end() == TileClauseItr)
272 return;
273
274 OpenACCTileClause *TileClause = cast<OpenACCTileClause>(*TileClauseItr);
275 SemaRef.TileInfo.ActiveTile = TileClause;
276 SemaRef.TileInfo.TileDepthSatisfied = false;
277 SemaRef.TileInfo.CurTileCount = TileClause->getSizeExprs().size();
278 SemaRef.TileInfo.DirectiveKind = DirKind;
279}
280
282 if (DirKind == OpenACCDirectiveKind::Parallel ||
283 DirKind == OpenACCDirectiveKind::Serial ||
285 DirKind == OpenACCDirectiveKind::Loop ||
289 SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
290 SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;
291 SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
292 SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
293 SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;
294 SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);
295 } else if (DirKind == OpenACCDirectiveKind::Data ||
297 // Intentionally doesn't reset the Loop, Compute Construct, or reduction
298 // effects.
299 }
300}
301
303 SourceLocation DirLoc) {
304 // Start an evaluation context to parse the clause arguments on.
307
308 switch (K) {
310 // Nothing to do here, an invalid kind has nothing we can check here. We
311 // want to continue parsing clauses as far as we can, so we will just
312 // ensure that we can still work and don't check any construct-specific
313 // rules anywhere.
314 break;
330 // Nothing to do here, there is no real legalization that needs to happen
331 // here as these constructs do not take any arguments.
332 break;
334 // Nothing really to do here, the arguments to the 'wait' should have
335 // already been handled by the time we get here.
336 break;
337 default:
338 Diag(DirLoc, diag::warn_acc_construct_unimplemented) << K;
339 break;
340 }
341}
342
345 Expr *IntExpr) {
346
347 assert(((DK != OpenACCDirectiveKind::Invalid &&
353 "Only one of directive or clause kind should be provided");
354
355 class IntExprConverter : public Sema::ICEConvertDiagnoser {
356 OpenACCDirectiveKind DirectiveKind;
357 OpenACCClauseKind ClauseKind;
358 Expr *IntExpr;
359
360 // gets the index into the diagnostics so we can use this for clauses,
361 // directives, and sub array.s
362 unsigned getDiagKind() const {
363 if (ClauseKind != OpenACCClauseKind::Invalid)
364 return 0;
365 if (DirectiveKind != OpenACCDirectiveKind::Invalid)
366 return 1;
367 return 2;
368 }
369
370 public:
371 IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
372 Expr *IntExpr)
373 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false,
374 /*Suppress=*/false,
375 /*SuppressConversion=*/true),
376 DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
377
378 bool match(QualType T) override {
379 // OpenACC spec just calls this 'integer expression' as having an
380 // 'integer type', so fall back on C99's 'integer type'.
381 return T->isIntegerType();
382 }
384 QualType T) override {
385 return S.Diag(Loc, diag::err_acc_int_expr_requires_integer)
386 << getDiagKind() << ClauseKind << DirectiveKind << T;
387 }
388
390 diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override {
391 return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type)
392 << T << IntExpr->getSourceRange();
393 }
394
396 diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T,
397 QualType ConvTy) override {
398 return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion)
399 << T << ConvTy;
400 }
401
402 SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
403 CXXConversionDecl *Conv,
404 QualType ConvTy) override {
405 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
406 << ConvTy->isEnumeralType() << ConvTy;
407 }
408
410 diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override {
411 return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T;
412 }
413
415 noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
416 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
417 << ConvTy->isEnumeralType() << ConvTy;
418 }
419
421 diagnoseConversion(Sema &S, SourceLocation Loc, QualType T,
422 QualType ConvTy) override {
423 llvm_unreachable("conversion functions are permitted");
424 }
425 } IntExprDiagnoser(DK, CK, IntExpr);
426
427 if (!IntExpr)
428 return ExprError();
429
431 Loc, IntExpr, IntExprDiagnoser);
432 if (IntExprResult.isInvalid())
433 return ExprError();
434
435 IntExpr = IntExprResult.get();
436 if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType())
437 return ExprError();
438
439 // TODO OpenACC: Do we want to perform usual unary conversions here? When
440 // doing codegen we might find that is necessary, but skip it for now.
441 return IntExpr;
442}
443
445 Expr *VarExpr) {
446 // We already know that VarExpr is a proper reference to a variable, so we
447 // should be able to just take the type of the expression to get the type of
448 // the referenced variable.
449
450 // We've already seen an error, don't diagnose anything else.
451 if (!VarExpr || VarExpr->containsErrors())
452 return false;
453
454 if (isa<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()) ||
455 VarExpr->hasPlaceholderType(BuiltinType::ArraySection)) {
456 Diag(VarExpr->getExprLoc(), diag::err_array_section_use) << /*OpenACC=*/0;
457 Diag(VarExpr->getExprLoc(), diag::note_acc_expected_pointer_var);
458 return true;
459 }
460
461 QualType Ty = VarExpr->getType();
463
464 // Nothing we can do if this is a dependent type.
465 if (Ty->isDependentType())
466 return false;
467
468 if (!Ty->isPointerType())
469 return Diag(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)
470 << ClauseKind << Ty;
471 return false;
472}
473
475 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
476
477 // 'use_device' doesn't allow array subscript or array sections.
478 // OpenACC3.3 2.8:
479 // A 'var' in a 'use_device' clause must be the name of a variable or array.
481 isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
482 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
483 return ExprError();
484 }
485
486 // Sub-arrays/subscript-exprs are fine as long as the base is a
487 // VarExpr/MemberExpr. So strip all of those off.
488 while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
489 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
490 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
491 else
492 CurVarExpr =
493 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
494 }
495
496 // References to a VarDecl are fine.
497 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
498 if (isa<VarDecl, NonTypeTemplateParmDecl>(
499 DRE->getFoundDecl()->getCanonicalDecl()))
500 return VarExpr;
501 }
502
503 // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
504 // reduction clause must be a scalar variable name, an aggregate variable
505 // name, an array element, or a subarray.
506 // If CK is a 'use_device', this also isn't valid, as it isn' the name of a
507 // variable or array.
508 // A MemberExpr that references a Field is valid for other clauses.
511 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
512 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl()))
513 return VarExpr;
514 }
515 }
516
517 // Referring to 'this' is ok for the most part, but for 'use_device' doesn't
518 // fall into 'variable or array name'
519 if (CK != OpenACCClauseKind::UseDevice && isa<CXXThisExpr>(CurVarExpr))
520 return VarExpr;
521
522 // Nothing really we can do here, as these are dependent. So just return they
523 // are valid.
524 if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
526 isa<CXXDependentScopeMemberExpr>(CurVarExpr)))
527 return VarExpr;
528
529 // There isn't really anything we can do in the case of a recovery expr, so
530 // skip the diagnostic rather than produce a confusing diagnostic.
531 if (isa<RecoveryExpr>(CurVarExpr))
532 return ExprError();
533
535 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
536 else
537 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
539 return ExprError();
540}
541
543 Expr *LowerBound,
544 SourceLocation ColonLoc,
545 Expr *Length,
546 SourceLocation RBLoc) {
547 ASTContext &Context = getASTContext();
548
549 // Handle placeholders.
550 if (Base->hasPlaceholderType() &&
551 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
553 if (Result.isInvalid())
554 return ExprError();
555 Base = Result.get();
556 }
557 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
559 if (Result.isInvalid())
560 return ExprError();
562 if (Result.isInvalid())
563 return ExprError();
564 LowerBound = Result.get();
565 }
566 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
568 if (Result.isInvalid())
569 return ExprError();
571 if (Result.isInvalid())
572 return ExprError();
573 Length = Result.get();
574 }
575
576 // Check the 'base' value, it must be an array or pointer type, and not to/of
577 // a function type.
579 QualType ResultTy;
580 if (!Base->isTypeDependent()) {
581 if (OriginalBaseTy->isAnyPointerType()) {
582 ResultTy = OriginalBaseTy->getPointeeType();
583 } else if (OriginalBaseTy->isArrayType()) {
584 ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
585 } else {
586 return ExprError(
587 Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
588 << Base->getSourceRange());
589 }
590
591 if (ResultTy->isFunctionType()) {
592 Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
593 << ResultTy << Base->getSourceRange();
594 return ExprError();
595 }
596
597 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
598 diag::err_acc_subarray_incomplete_type,
599 Base))
600 return ExprError();
601
602 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
604 if (Result.isInvalid())
605 return ExprError();
606 Base = Result.get();
607 }
608 }
609
610 auto GetRecovery = [&](Expr *E, QualType Ty) {
611 ExprResult Recovery =
613 return Recovery.isUsable() ? Recovery.get() : nullptr;
614 };
615
616 // Ensure both of the expressions are int-exprs.
617 if (LowerBound && !LowerBound->isTypeDependent()) {
618 ExprResult LBRes =
620 LowerBound->getExprLoc(), LowerBound);
621
622 if (LBRes.isUsable())
623 LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
624 LowerBound =
625 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
626 }
627
628 if (Length && !Length->isTypeDependent()) {
629 ExprResult LenRes =
631 Length->getExprLoc(), Length);
632
633 if (LenRes.isUsable())
634 LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
635 Length =
636 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
637 }
638
639 // Length is required if the base type is not an array of known bounds.
640 if (!Length && (OriginalBaseTy.isNull() ||
641 (!OriginalBaseTy->isDependentType() &&
642 !OriginalBaseTy->isConstantArrayType() &&
643 !OriginalBaseTy->isDependentSizedArrayType()))) {
644 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
645 Diag(ColonLoc, diag::err_acc_subarray_no_length) << IsArray;
646 // Fill in a dummy 'length' so that when we instantiate this we don't
647 // double-diagnose here.
649 ColonLoc, SourceLocation(), ArrayRef<Expr *>(), Context.IntTy);
650 Length = Recovery.isUsable() ? Recovery.get() : nullptr;
651 }
652
653 // Check the values of each of the arguments, they cannot be negative(we
654 // assume), and if the array bound is known, must be within range. As we do
655 // so, do our best to continue with evaluation, we can set the
656 // value/expression to nullptr/nullopt if they are invalid, and treat them as
657 // not present for the rest of evaluation.
658
659 // We don't have to check for dependence, because the dependent size is
660 // represented as a different AST node.
661 std::optional<llvm::APSInt> BaseSize;
662 if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
663 const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);
664 BaseSize = ArrayTy->getSize();
665 }
666
667 auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
668 if (!E || E->isInstantiationDependent())
669 return std::nullopt;
670
672 if (!E->EvaluateAsInt(Res, Context))
673 return std::nullopt;
674 return Res.Val.getInt();
675 };
676
677 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
678 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
679
680 // Check lower bound for negative or out of range.
681 if (LowerBoundValue.has_value()) {
682 if (LowerBoundValue->isNegative()) {
683 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
684 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
685 LowerBoundValue.reset();
686 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
687 } else if (BaseSize.has_value() &&
688 llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
689 // Lower bound (start index) must be less than the size of the array.
690 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
691 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
692 << toString(*BaseSize, /*Radix=*/10);
693 LowerBoundValue.reset();
694 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
695 }
696 }
697
698 // Check length for negative or out of range.
699 if (LengthValue.has_value()) {
700 if (LengthValue->isNegative()) {
701 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
702 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
703 LengthValue.reset();
704 Length = GetRecovery(Length, Length->getType());
705 } else if (BaseSize.has_value() &&
706 llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
707 // Length must be lessthan or EQUAL to the size of the array.
708 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
709 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
710 << toString(*BaseSize, /*Radix=*/10);
711 LengthValue.reset();
712 Length = GetRecovery(Length, Length->getType());
713 }
714 }
715
716 // Adding two APSInts requires matching sign, so extract that here.
717 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
718 if (LHS.isSigned() == RHS.isSigned())
719 return LHS + RHS;
720
721 unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
722 return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), /*Signed=*/true);
723 };
724
725 // If we know all 3 values, we can diagnose that the total value would be out
726 // of range.
727 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
728 LengthValue.has_value() &&
729 llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
730 *BaseSize) > 0) {
731 Diag(Base->getExprLoc(),
732 diag::err_acc_subarray_base_plus_length_out_of_range)
733 << toString(*LowerBoundValue, /*Radix=*/10)
734 << toString(*LengthValue, /*Radix=*/10)
735 << toString(*BaseSize, /*Radix=*/10);
736
737 LowerBoundValue.reset();
738 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
739 LengthValue.reset();
740 Length = GetRecovery(Length, Length->getType());
741 }
742
743 // If any part of the expression is dependent, return a dependent sub-array.
744 QualType ArrayExprTy = Context.ArraySectionTy;
745 if (Base->isTypeDependent() ||
746 (LowerBound && LowerBound->isInstantiationDependent()) ||
747 (Length && Length->isInstantiationDependent()))
748 ArrayExprTy = Context.DependentTy;
749
750 return new (Context)
751 ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
752 OK_Ordinary, ColonLoc, RBLoc);
753}
754
756 if (!getLangOpts().OpenACC)
757 return;
758
759 if (!LoopInfo.TopLevelLoopSeen)
760 return;
761
762 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
763 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
764 << /*while loop*/ 1 << CollapseInfo.DirectiveKind
766 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
767 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
768 diag::note_acc_active_clause_here)
770
771 // Remove the value so that we don't get cascading errors in the body. The
772 // caller RAII object will restore this.
773 CollapseInfo.CurCollapseCount = std::nullopt;
774 }
775
776 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
777 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
778 << /*while loop*/ 1 << TileInfo.DirectiveKind
780 assert(TileInfo.ActiveTile && "tile count without object?");
781 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
783
784 // Remove the value so that we don't get cascading errors in the body. The
785 // caller RAII object will restore this.
786 TileInfo.CurTileCount = std::nullopt;
787 }
788}
789
791 if (!getLangOpts().OpenACC)
792 return;
793
794 if (!LoopInfo.TopLevelLoopSeen)
795 return;
796
797 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
798 Diag(DoLoc, diag::err_acc_invalid_in_loop)
799 << /*do loop*/ 2 << CollapseInfo.DirectiveKind
801 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
802 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
803 diag::note_acc_active_clause_here)
805
806 // Remove the value so that we don't get cascading errors in the body. The
807 // caller RAII object will restore this.
808 CollapseInfo.CurCollapseCount = std::nullopt;
809 }
810
811 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
812 Diag(DoLoc, diag::err_acc_invalid_in_loop)
813 << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
814 assert(TileInfo.ActiveTile && "tile count without object?");
815 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
817
818 // Remove the value so that we don't get cascading errors in the body. The
819 // caller RAII object will restore this.
820 TileInfo.CurTileCount = std::nullopt;
821 }
822}
823
824void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
825 ForStmtBeginChecker &C) {
826 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
827
828 // Enable the while/do-while checking.
829 LoopInfo.TopLevelLoopSeen = true;
830
831 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
832 C.check();
833
834 // OpenACC 3.3 2.9.1:
835 // Each associated loop, except the innermost, must contain exactly one loop
836 // or loop nest.
837 // This checks for more than 1 loop at the current level, the
838 // 'depth'-satisifed checking manages the 'not zero' case.
839 if (LoopInfo.CurLevelHasLoopAlready) {
840 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
841 << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
842 assert(CollapseInfo.ActiveCollapse && "No collapse object?");
843 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
844 diag::note_acc_active_clause_here)
846 } else {
847 --(*CollapseInfo.CurCollapseCount);
848
849 // Once we've hit zero here, we know we have deep enough 'for' loops to
850 // get to the bottom.
851 if (*CollapseInfo.CurCollapseCount == 0)
852 CollapseInfo.CollapseDepthSatisfied = true;
853 }
854 }
855
856 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
857 C.check();
858
859 if (LoopInfo.CurLevelHasLoopAlready) {
860 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
861 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
862 assert(TileInfo.ActiveTile && "No tile object?");
863 Diag(TileInfo.ActiveTile->getBeginLoc(),
864 diag::note_acc_active_clause_here)
866 } else {
867 --(*TileInfo.CurTileCount);
868 // Once we've hit zero here, we know we have deep enough 'for' loops to
869 // get to the bottom.
870 if (*TileInfo.CurTileCount == 0)
871 TileInfo.TileDepthSatisfied = true;
872 }
873 }
874
875 // Set this to 'false' for the body of this loop, so that the next level
876 // checks independently.
877 LoopInfo.CurLevelHasLoopAlready = false;
878}
879
880namespace {
881bool isValidLoopVariableType(QualType LoopVarTy) {
882 // Just skip if it is dependent, it could be any of the below.
883 if (LoopVarTy->isDependentType())
884 return true;
885
886 // The loop variable must be of integer,
887 if (LoopVarTy->isIntegerType())
888 return true;
889
890 // C/C++ pointer,
891 if (LoopVarTy->isPointerType())
892 return true;
893
894 // or C++ random-access iterator type.
895 if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
896 // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
897 // iterator type!
898
899 // We could either do a lot of work to see if this matches
900 // random-access-iterator, but it seems that just checking that the
901 // 'iterator_category' typedef is more than sufficient. If programmers are
902 // willing to lie about this, we can let them.
903
904 for (const auto *TD :
905 llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
906 const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
907
908 if (TDND->getName() != "iterator_category")
909 continue;
910
911 // If there is no type for this decl, return false.
912 if (TDND->getUnderlyingType().isNull())
913 return false;
914
915 const CXXRecordDecl *ItrCategoryDecl =
916 TDND->getUnderlyingType()->getAsCXXRecordDecl();
917
918 // If the category isn't a record decl, it isn't the tag type.
919 if (!ItrCategoryDecl)
920 return false;
921
922 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
923 if (RD->getName() != "random_access_iterator_tag")
924 return false;
925 // Checks just for std::random_access_iterator_tag.
927 };
928
929 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
930 return true;
931
932 // We can also support types inherited from the
933 // random_access_iterator_tag.
934 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases()) {
935
936 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
937 return true;
938 }
939
940 return false;
941 }
942 }
943
944 return false;
945}
946
947} // namespace
948
949void SemaOpenACC::ForStmtBeginChecker::check() {
950 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
951 return;
952
953 if (AlreadyChecked)
954 return;
955 AlreadyChecked = true;
956
957 // OpenACC3.3 2.1:
958 // A loop associated with a loop construct that does not have a seq clause
959 // must be written to meet all the following conditions:
960 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
961 // iterator type.
962 // - The loop variable must monotonically increase or decrease in the
963 // direction of its termination condition.
964 // - The loop trip count must be computable in constant time when entering the
965 // loop construct.
966 //
967 // For a C++ range-based for loop, the loop variable
968 // identified by the above conditions is the internal iterator, such as a
969 // pointer, that the compiler generates to iterate the range. it is not the
970 // variable declared by the for loop.
971
972 if (IsRangeFor) {
973 // If the range-for is being instantiated and didn't change, don't
974 // re-diagnose.
975 if (!RangeFor.has_value())
976 return;
977 // For a range-for, we can assume everything is 'corect' other than the type
978 // of the iterator, so check that.
979 const DeclStmt *RangeStmt = (*RangeFor)->getBeginStmt();
980
981 // In some dependent contexts, the autogenerated range statement doesn't get
982 // included until instantiation, so skip for now.
983 if (!RangeStmt)
984 return;
985
986 const ValueDecl *InitVar = cast<ValueDecl>(RangeStmt->getSingleDecl());
987 QualType VarType = InitVar->getType().getNonReferenceType();
988 if (!isValidLoopVariableType(VarType)) {
989 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
990 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
991 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
992 diag::note_acc_construct_here)
993 << SemaRef.LoopWithoutSeqInfo.Kind;
994 }
995 return;
996 }
997
998 // Else we are in normal 'ForStmt', so we can diagnose everything.
999 // We only have to check cond/inc if they have changed, but 'init' needs to
1000 // just suppress its diagnostics if it hasn't changed.
1001 const ValueDecl *InitVar = checkInit();
1002 if (Cond.has_value())
1003 checkCond();
1004 if (Inc.has_value())
1005 checkInc(InitVar);
1006}
1007const ValueDecl *SemaOpenACC::ForStmtBeginChecker::checkInit() {
1008 if (!Init) {
1009 if (InitChanged) {
1010 SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)
1011 << SemaRef.LoopWithoutSeqInfo.Kind;
1012 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1013 diag::note_acc_construct_here)
1014 << SemaRef.LoopWithoutSeqInfo.Kind;
1015 }
1016 return nullptr;
1017 }
1018
1019 auto DiagLoopVar = [&]() {
1020 if (InitChanged) {
1021 SemaRef.Diag(Init->getBeginLoc(), diag::err_acc_loop_variable)
1022 << SemaRef.LoopWithoutSeqInfo.Kind;
1023 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1024 diag::note_acc_construct_here)
1025 << SemaRef.LoopWithoutSeqInfo.Kind;
1026 }
1027 return nullptr;
1028 };
1029
1030 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
1031 Init = ExprTemp->getSubExpr();
1032 if (const auto *E = dyn_cast<Expr>(Init))
1034
1035 const ValueDecl *InitVar = nullptr;
1036
1037 if (const auto *BO = dyn_cast<BinaryOperator>(Init)) {
1038 // Allow assignment operator here.
1039
1040 if (!BO->isAssignmentOp())
1041 return DiagLoopVar();
1042
1043 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
1044
1045 if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS))
1046 InitVar = DRE->getDecl();
1047 } else if (const auto *DS = dyn_cast<DeclStmt>(Init)) {
1048 // Allow T t = <whatever>
1049 if (!DS->isSingleDecl())
1050 return DiagLoopVar();
1051
1052 InitVar = dyn_cast<ValueDecl>(DS->getSingleDecl());
1053
1054 // Ensure we have an initializer, unless this is a record/dependent type.
1055
1056 if (InitVar) {
1057 if (!isa<VarDecl>(InitVar))
1058 return DiagLoopVar();
1059
1060 if (!InitVar->getType()->isRecordType() &&
1061 !InitVar->getType()->isDependentType() &&
1062 !cast<VarDecl>(InitVar)->hasInit())
1063 return DiagLoopVar();
1064 }
1065 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Init)) {
1066 // Allow assignment operator call.
1067 if (CE->getOperator() != OO_Equal)
1068 return DiagLoopVar();
1069
1070 const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
1071
1072 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1073 InitVar = DRE->getDecl();
1074 } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
1075 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1076 InitVar = ME->getMemberDecl();
1077 }
1078 }
1079
1080 if (!InitVar)
1081 return DiagLoopVar();
1082
1083 InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
1084 QualType VarType = InitVar->getType().getNonReferenceType();
1085
1086 // Since we have one, all we need to do is ensure it is the right type.
1087 if (!isValidLoopVariableType(VarType)) {
1088 if (InitChanged) {
1089 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1090 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1091 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1092 diag::note_acc_construct_here)
1093 << SemaRef.LoopWithoutSeqInfo.Kind;
1094 }
1095 return nullptr;
1096 }
1097
1098 return InitVar;
1099}
1100void SemaOpenACC::ForStmtBeginChecker::checkCond() {
1101 if (!*Cond) {
1102 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
1103 << SemaRef.LoopWithoutSeqInfo.Kind;
1104 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
1105 << SemaRef.LoopWithoutSeqInfo.Kind;
1106 }
1107 // Nothing else to do here. we could probably do some additional work to look
1108 // into the termination condition, but that error-prone. For now, we don't
1109 // implement anything other than 'there is a termination condition', and if
1110 // codegen/MLIR comes up with some necessary restrictions, we can implement
1111 // them here.
1112}
1113
1114void SemaOpenACC::ForStmtBeginChecker::checkInc(const ValueDecl *Init) {
1115
1116 if (!*Inc) {
1117 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
1118 << SemaRef.LoopWithoutSeqInfo.Kind;
1119 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
1120 << SemaRef.LoopWithoutSeqInfo.Kind;
1121 return;
1122 }
1123 auto DiagIncVar = [this] {
1124 SemaRef.Diag((*Inc)->getBeginLoc(), 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
1131 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(*Inc))
1132 Inc = ExprTemp->getSubExpr();
1133 if (const auto *E = dyn_cast<Expr>(*Inc))
1135
1136 auto getDeclFromExpr = [](const Expr *E) -> const ValueDecl * {
1137 E = E->IgnoreParenImpCasts();
1138 if (const auto *FE = dyn_cast<FullExpr>(E))
1139 E = FE->getSubExpr();
1140
1141 E = E->IgnoreParenImpCasts();
1142
1143 if (!E)
1144 return nullptr;
1145 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
1146 return dyn_cast<ValueDecl>(DRE->getDecl());
1147
1148 if (const auto *ME = dyn_cast<MemberExpr>(E))
1149 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1150 return ME->getMemberDecl();
1151
1152 return nullptr;
1153 };
1154
1155 const ValueDecl *IncVar = nullptr;
1156
1157 // Here we enforce the monotonically increase/decrease:
1158 if (const auto *UO = dyn_cast<UnaryOperator>(*Inc)) {
1159 // Allow increment/decrement ops.
1160 if (!UO->isIncrementDecrementOp())
1161 return DiagIncVar();
1162 IncVar = getDeclFromExpr(UO->getSubExpr());
1163 } else if (const auto *BO = dyn_cast<BinaryOperator>(*Inc)) {
1164 switch (BO->getOpcode()) {
1165 default:
1166 return DiagIncVar();
1167 case BO_AddAssign:
1168 case BO_SubAssign:
1169 case BO_MulAssign:
1170 case BO_DivAssign:
1171 case BO_Assign:
1172 // += -= *= /= should all be fine here, this should be all of the
1173 // 'monotonical' compound-assign ops.
1174 // Assignment we just give up on, we could do better, and ensure that it
1175 // is a binary/operator expr doing more work, but that seems like a lot
1176 // of work for an error prone check.
1177 break;
1178 }
1179 IncVar = getDeclFromExpr(BO->getLHS());
1180 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(*Inc)) {
1181 switch (CE->getOperator()) {
1182 default:
1183 return DiagIncVar();
1184 case OO_PlusPlus:
1185 case OO_MinusMinus:
1186 case OO_PlusEqual:
1187 case OO_MinusEqual:
1188 case OO_StarEqual:
1189 case OO_SlashEqual:
1190 case OO_Equal:
1191 // += -= *= /= should all be fine here, this should be all of the
1192 // 'monotonical' compound-assign ops.
1193 // Assignment we just give up on, we could do better, and ensure that it
1194 // is a binary/operator expr doing more work, but that seems like a lot
1195 // of work for an error prone check.
1196 break;
1197 }
1198
1199 IncVar = getDeclFromExpr(CE->getArg(0));
1200
1201 } else if (const auto *ME = dyn_cast<CXXMemberCallExpr>(*Inc)) {
1202 IncVar = getDeclFromExpr(ME->getImplicitObjectArgument());
1203 // We can't really do much for member expressions, other than hope they are
1204 // doing the right thing, so give up here.
1205 }
1206
1207 if (!IncVar)
1208 return DiagIncVar();
1209
1210 // InitVar shouldn't be null unless there was an error, so don't diagnose if
1211 // that is the case. Else we should ensure that it refers to the loop
1212 // value.
1213 if (Init && IncVar->getCanonicalDecl() != Init->getCanonicalDecl())
1214 return DiagIncVar();
1215
1216 return;
1217}
1218
1220 const Stmt *First, const Stmt *OldSecond,
1221 const Stmt *Second, const Stmt *OldThird,
1222 const Stmt *Third) {
1223 if (!getLangOpts().OpenACC)
1224 return;
1225
1226 std::optional<const Stmt *> S;
1227 if (OldSecond == Second)
1228 S = std::nullopt;
1229 else
1230 S = Second;
1231 std::optional<const Stmt *> T;
1232 if (OldThird == Third)
1233 S = std::nullopt;
1234 else
1235 S = Third;
1236
1237 bool InitChanged = false;
1238 if (OldFirst != First) {
1239 InitChanged = true;
1240
1241 // VarDecls are always rebuild because they are dependent, so we can do a
1242 // little work to suppress some of the double checking based on whether the
1243 // type is instantiation dependent.
1244 QualType OldVDTy;
1245 QualType NewVDTy;
1246 if (const auto *DS = dyn_cast<DeclStmt>(OldFirst))
1247 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1248 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1249 OldVDTy = VD->getType();
1250 if (const auto *DS = dyn_cast<DeclStmt>(First))
1251 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1252 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1253 NewVDTy = VD->getType();
1254
1255 if (!OldVDTy.isNull() && !NewVDTy.isNull())
1256 InitChanged = OldVDTy->isInstantiationDependentType() !=
1258 }
1259
1260 ForStmtBeginChecker FSBC{*this, ForLoc, First, InitChanged, S, T};
1261 if (!LoopInfo.TopLevelLoopSeen) {
1262 FSBC.check();
1263 }
1264
1265 ForStmtBeginHelper(ForLoc, FSBC);
1266}
1267
1269 const Stmt *Second, const Stmt *Third) {
1270 if (!getLangOpts().OpenACC)
1271 return;
1272
1273 ForStmtBeginChecker FSBC{*this, ForLoc, First, /*InitChanged=*/true,
1274 Second, Third};
1275 if (!LoopInfo.TopLevelLoopSeen) {
1276 FSBC.check();
1277 }
1278
1279 ForStmtBeginHelper(ForLoc, FSBC);
1280}
1281
1283 const Stmt *OldRangeFor,
1284 const Stmt *RangeFor) {
1285 if (!getLangOpts().OpenACC)
1286 return;
1287
1288 std::optional<const CXXForRangeStmt *> RF;
1289
1290 if (OldRangeFor == RangeFor)
1291 RF = std::nullopt;
1292 else
1293 RF = cast<CXXForRangeStmt>(RangeFor);
1294
1295 ForStmtBeginChecker FSBC{*this, ForLoc, RF};
1296 if (!LoopInfo.TopLevelLoopSeen) {
1297 FSBC.check();
1298 }
1299 ForStmtBeginHelper(ForLoc, FSBC);
1300}
1301
1303 const Stmt *RangeFor) {
1304 if (!getLangOpts().OpenACC)
1305 return;
1306
1307 ForStmtBeginChecker FSBC{*this, ForLoc, cast<CXXForRangeStmt>(RangeFor)};
1308 if (!LoopInfo.TopLevelLoopSeen) {
1309 FSBC.check();
1310 }
1311 ForStmtBeginHelper(ForLoc, FSBC);
1312}
1313
1314namespace {
1315SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
1316 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
1317 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
1318 // `DoStmt`, as those are caught as a violation elsewhere.
1319 // For `CompoundStmt` we need to search inside of it.
1320 if (!CurStmt ||
1321 isa<ForStmt, NullStmt, ForStmt, CXXForRangeStmt, WhileStmt, DoStmt>(
1322 CurStmt))
1323 return SourceLocation{};
1324
1325 // Any other construct is an error anyway, so it has already been diagnosed.
1326 if (isa<OpenACCConstructStmt>(CurStmt))
1327 return SourceLocation{};
1328
1329 // Search inside the compound statement, this allows for arbitrary nesting
1330 // of compound statements, as long as there isn't any code inside.
1331 if (const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
1332 for (const auto *ChildStmt : CS->children()) {
1333 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
1334 if (ChildStmtLoc.isValid())
1335 return ChildStmtLoc;
1336 }
1337 // Empty/not invalid compound statements are legal.
1338 return SourceLocation{};
1339 }
1340 return CurStmt->getBeginLoc();
1341}
1342} // namespace
1343
1345 if (!getLangOpts().OpenACC)
1346 return;
1347
1348 // Set this to 'true' so if we find another one at this level we can diagnose.
1349 LoopInfo.CurLevelHasLoopAlready = true;
1350
1351 if (!Body.isUsable())
1352 return;
1353
1354 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1355 *CollapseInfo.CurCollapseCount > 0 &&
1356 !CollapseInfo.ActiveCollapse->hasForce();
1357 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1358
1359 if (IsActiveCollapse || IsActiveTile) {
1360 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());
1361
1362 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
1363 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1364 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
1365 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1366 diag::note_acc_active_clause_here)
1368 }
1369
1370 if (OtherStmtLoc.isValid() && IsActiveTile) {
1371 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1372 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
1373 Diag(TileInfo.ActiveTile->getBeginLoc(),
1374 diag::note_acc_active_clause_here)
1376 }
1377 }
1378}
1379
1380namespace {
1381// Get a list of clause Kinds for diagnosing a list, joined by a commas and an
1382// 'or'.
1383std::string GetListOfClauses(llvm::ArrayRef<OpenACCClauseKind> Clauses) {
1384 assert(!Clauses.empty() && "empty clause list not supported");
1385
1386 std::string Output;
1387 llvm::raw_string_ostream OS{Output};
1388
1389 if (Clauses.size() == 1) {
1390 OS << '\'' << Clauses[0] << '\'';
1391 return Output;
1392 }
1393
1394 llvm::ArrayRef<OpenACCClauseKind> AllButLast{Clauses.begin(),
1395 Clauses.end() - 1};
1396
1397 llvm::interleave(
1398 AllButLast, [&](OpenACCClauseKind K) { OS << '\'' << K << '\''; },
1399 [&] { OS << ", "; });
1400
1401 OS << " or \'" << Clauses.back() << '\'';
1402 return Output;
1403}
1404} // namespace
1405
1411
1412 // OpenACC 3.3 2.9.1:
1413 // Intervening code must not contain other OpenACC directives or calls to API
1414 // routines.
1415 //
1416 // ALL constructs are ill-formed if there is an active 'collapse'
1417 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1418 Diag(StartLoc, diag::err_acc_invalid_in_loop)
1419 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
1421 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1422 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1423 diag::note_acc_active_clause_here)
1425 }
1426 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1427 Diag(StartLoc, diag::err_acc_invalid_in_loop)
1428 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
1430 assert(TileInfo.ActiveTile && "Tile count without object?");
1431 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1433 }
1434
1435 // OpenACC3.3 2.6.5: At least one copy, copyin, copyout, create, no_create,
1436 // present, deviceptr, attach, or default clause must appear on a 'data'
1437 // construct.
1438 if (K == OpenACCDirectiveKind::Data &&
1439 llvm::find_if(Clauses,
1444 OpenACCDefaultClause>) == Clauses.end())
1445 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1446 << K
1447 << GetListOfClauses(
1453
1454 // OpenACC3.3 2.6.6: At least one copyin, create, or attach clause must appear
1455 // on an enter data directive.
1457 llvm::find_if(Clauses,
1459 OpenACCAttachClause>) == Clauses.end())
1460 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1461 << K
1462 << GetListOfClauses({
1466 });
1467 // OpenACC3.3 2.6.6: At least one copyout, delete, or detach clause must
1468 // appear on an exit data directive.
1470 llvm::find_if(Clauses,
1472 OpenACCDetachClause>) == Clauses.end())
1473 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1474 << K
1475 << GetListOfClauses({
1479 });
1480
1481 // OpenACC3.3 2.8: At least 'one use_device' clause must appear.
1483 llvm::find_if(Clauses, llvm::IsaPred<OpenACCUseDeviceClause>) ==
1484 Clauses.end())
1485 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1486 << K << GetListOfClauses({OpenACCClauseKind::UseDevice});
1487
1488 // OpenACC3.3 2.14.3: At least one default_async, device_num, or device_type
1489 // clause must appear.
1490 if (K == OpenACCDirectiveKind::Set &&
1491 llvm::find_if(
1492 Clauses,
1495 Clauses.end())
1496 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1497 << K
1498 << GetListOfClauses({OpenACCClauseKind::DefaultAsync,
1502
1503 // OpenACC3.3 2.14.4: At least one self, host, or device clause must appear on
1504 // an update directive.
1506 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSelfClause, OpenACCHostClause,
1508 Clauses.end())
1509 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1510 << K
1511 << GetListOfClauses({OpenACCClauseKind::Self,
1514
1515 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
1516}
1517
1520 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
1521 SourceLocation RParenLoc, SourceLocation EndLoc,
1522 ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt) {
1523 switch (K) {
1524 default:
1525 return StmtEmpty();
1527 return StmtError();
1532 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
1533 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1534 }
1539 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
1540 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1541 }
1544 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
1545 EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1546 }
1549 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
1550 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1551 }
1553 return OpenACCEnterDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
1554 EndLoc, Clauses);
1555 }
1557 return OpenACCExitDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
1558 EndLoc, Clauses);
1559 }
1562 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
1563 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1564 }
1567 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
1568 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
1569 }
1571 return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc,
1572 EndLoc, Clauses);
1573 }
1575 return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
1576 EndLoc, Clauses);
1577 }
1579 return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
1580 EndLoc, Clauses);
1581 }
1583 return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
1584 EndLoc, Clauses);
1585 }
1586 }
1587 llvm_unreachable("Unhandled case in directive handling?");
1588}
1589
1591 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
1592 ArrayRef<const OpenACCClause *> Clauses, StmtResult AssocStmt) {
1593 switch (K) {
1594 default:
1595 llvm_unreachable("Unimplemented associated statement application");
1602 llvm_unreachable(
1603 "these don't have associated statements, so shouldn't get here");
1609 // There really isn't any checking here that could happen. As long as we
1610 // have a statement to associate, this should be fine.
1611 // OpenACC 3.3 Section 6:
1612 // Structured Block: in C or C++, an executable statement, possibly
1613 // compound, with a single entry at the top and a single exit at the
1614 // bottom.
1615 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
1616 // an interpretation of it is to allow this and treat the initializer as
1617 // the 'structured block'.
1618 return AssocStmt;
1623 if (!AssocStmt.isUsable())
1624 return StmtError();
1625
1626 if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
1627 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
1628 << K;
1629 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
1630 return StmtError();
1631 }
1632
1633 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
1634 if (!CollapseInfo.CollapseDepthSatisfied) {
1635 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
1637 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1638 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1639 diag::note_acc_active_clause_here)
1641 }
1642
1643 if (!TileInfo.TileDepthSatisfied) {
1644 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
1646 assert(TileInfo.ActiveTile && "Collapse count without object?");
1647 Diag(TileInfo.ActiveTile->getBeginLoc(),
1648 diag::note_acc_active_clause_here)
1650 }
1651 return StmtError();
1652 }
1653
1654 return AssocStmt.get();
1655 }
1656 llvm_unreachable("Invalid associated statement application");
1657}
1658
1660 SourceLocation StartLoc) {
1661 // OpenCC3.3 2.1 (line 889)
1662 // A program must not depend on the order of evaluation of expressions in
1663 // clause arguments or on any side effects of the evaluations.
1666 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
1667}
1668
1670
1673 return OpenACCAsteriskSizeExpr::Create(getASTContext(), AsteriskLoc);
1674}
1675
1678 return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
1679}
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:14673
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:465
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:2915
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:5184
QualType getElementType() const
Definition: Type.h:3589
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2885
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:3671
bool isStdNamespace() const
Definition: DeclBase.cpp:1318
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
Definition: DeclBase.cpp:2016
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:967
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:3097
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:5431
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:8139
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:8030
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 * >)
Definition: SemaOpenACC.cpp:96
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
struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)
Called after the directive has been completely parsed, including the declaration group or associated ...
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)
void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)
Called when we encounter an associated statement for our construct, this should check legality of the...
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:464
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17394
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:17827
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:20971
@ 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:9119
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:17904
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:21168
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:357
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:333
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:345
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:8283
bool isConstantArrayType() const
Definition: Type.h:8267
bool isArrayType() const
Definition: Type.h:8263
bool isPointerType() const
Definition: Type.h:8191
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8555
bool isEnumeralType() const
Definition: Type.h:8295
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:8509
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2714
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2706
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8791
bool isFunctionType() const
Definition: Type.h:8187
bool isAnyPointerType() const
Definition: Type.h:8199
bool isRecordType() const
Definition: Type.h:8291
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:882
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:824
The JSON file list parser is used to communicate input to InstallAPI.
OpenACCDirectiveKind
Definition: OpenACCKinds.h:25
@ 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:178
@ 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