clang 24.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
22#include "clang/Sema/Scope.h"
23#include "clang/Sema/Sema.h"
24#include "llvm/ADT/StringExtras.h"
25#include "llvm/Support/Casting.h"
26
27using namespace clang;
28
29namespace {
30bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,
31 SourceLocation StartLoc, bool IsStmt) {
32 switch (K) {
33 default:
35 // Nothing to do here, both invalid and unimplemented don't really need to
36 // do anything.
37 break;
55 if (!IsStmt)
56 return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
57 break;
58 }
59 return false;
60}
61
62void CollectActiveReductionClauses(
64 ArrayRef<OpenACCClause *> CurClauses) {
65 for (auto *CurClause : CurClauses) {
66 if (auto *RedClause = dyn_cast<OpenACCReductionClause>(CurClause);
67 RedClause && !RedClause->getVarList().empty())
68 ActiveClauses.push_back(RedClause);
69 }
70}
71
72// Depth needs to be preserved for all associated statements that aren't
73// supposed to modify the compute/combined/loop construct information.
74bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
75 switch (DK) {
83 return false;
87 return true;
98 llvm_unreachable("Doesn't have an associated stmt");
100 llvm_unreachable("Unhandled directive kind?");
101 }
102 llvm_unreachable("Unhandled directive kind?");
103}
104
105} // namespace
106
108
113 : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
114 DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel),
115 OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
116 OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
117 OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo),
118 ActiveReductionClauses(S.ActiveReductionClauses),
119 LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DirKind)) {
120
121 // Compute constructs end up taking their 'loop'.
122 if (DirKind == OpenACCDirectiveKind::Parallel ||
123 DirKind == OpenACCDirectiveKind::Serial ||
125 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
126 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
127 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
128
129 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
130 // construct, the gang clause behaves as follows. ... The region of a loop
131 // with a gang clause may not contain another loop with a gang clause unless
132 // within a nested compute region.
133 //
134 // Implement the 'unless within a nested compute region' part.
135 SemaRef.LoopGangClauseOnKernel = {};
136 SemaRef.LoopWorkerClauseLoc = {};
137 SemaRef.LoopVectorClauseLoc = {};
138 SemaRef.LoopWithoutSeqInfo = {};
139 } else if (DirKind == OpenACCDirectiveKind::ParallelLoop ||
142 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
143 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
144
145 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
146 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
147 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
148
149 SemaRef.LoopGangClauseOnKernel = {};
150 SemaRef.LoopWorkerClauseLoc = {};
151 SemaRef.LoopVectorClauseLoc = {};
152
153 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
154 // diagnose the for loops.
155 SemaRef.LoopWithoutSeqInfo = {};
156 if (Clauses.end() ==
157 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
158 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
159
160 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
161 // construct, the gang clause behaves as follows. ... The region of a loop
162 // with a gang clause may not contain another loop with a gang clause unless
163 // within a nested compute region.
164 //
165 // We don't bother doing this when this is a template instantiation, as
166 // there is no reason to do these checks: the existance of a
167 // gang/kernels/etc cannot be dependent.
168 if (DirKind == OpenACCDirectiveKind::KernelsLoop && UnInstClauses.empty()) {
169 // This handles the 'outer loop' part of this.
170 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
171 if (Itr != Clauses.end())
172 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), DirKind};
173 }
174
175 if (UnInstClauses.empty()) {
176 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
177 if (Itr != Clauses.end())
178 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
179
180 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
181 if (Itr2 != Clauses.end())
182 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
183 }
184 } else if (DirKind == OpenACCDirectiveKind::Loop) {
185 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
186 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
187 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
188
189 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
190 // diagnose the for loops.
191 SemaRef.LoopWithoutSeqInfo = {};
192 if (Clauses.end() ==
193 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
194 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
195
196 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
197 // construct, the gang clause behaves as follows. ... The region of a loop
198 // with a gang clause may not contain another loop with a gang clause unless
199 // within a nested compute region.
200 //
201 // We don't bother doing this when this is a template instantiation, as
202 // there is no reason to do these checks: the existance of a
203 // gang/kernels/etc cannot be dependent.
204 if (SemaRef.getActiveComputeConstructInfo().Kind ==
206 UnInstClauses.empty()) {
207 // This handles the 'outer loop' part of this.
208 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
209 if (Itr != Clauses.end())
210 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(),
212 }
213
214 if (UnInstClauses.empty()) {
215 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
216 if (Itr != Clauses.end())
217 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
218
219 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
220 if (Itr2 != Clauses.end())
221 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
222 }
223 }
224}
225
226namespace {
227// Given two collapse clauses, and the uninstanted version of the new one,
228// return the 'best' one for the purposes of setting the collapse checking
229// values.
231getBestCollapseCandidate(const OpenACCCollapseClause *Old,
233 const OpenACCCollapseClause *UnInstNew) {
234 // If the loop count is nullptr, it is because instantiation failed, so this
235 // can't be the best one.
236 if (!New->getLoopCount())
237 return Old;
238
239 // If the loop-count had an error, than 'new' isn't a candidate.
240 if (!New->getLoopCount())
241 return Old;
242
243 // Don't consider uninstantiated ones, since we can't really check these.
244 if (New->getLoopCount()->isInstantiationDependent())
245 return Old;
246
247 // If this is an instantiation, and the old version wasn't instantation
248 // dependent, than nothing has changed and we've already done a diagnostic
249 // based on this one, so don't consider it.
250 if (UnInstNew && !UnInstNew->getLoopCount()->isInstantiationDependent())
251 return Old;
252
253 // New is now a valid candidate, so if there isn't an old one at this point,
254 // New is the only valid one.
255 if (!Old)
256 return New;
257
258 // If the 'New' expression has a larger value than 'Old', then it is the new
259 // best candidate.
260 if (cast<ConstantExpr>(Old->getLoopCount())->getResultAsAPSInt() <
261 cast<ConstantExpr>(New->getLoopCount())->getResultAsAPSInt())
262 return New;
263
264 return Old;
265}
266} // namespace
267
271
272 // Reset this checking for loops that aren't covered in a RAII object.
273 SemaRef.LoopInfo.CurLevelHasLoopAlready = false;
274 SemaRef.CollapseInfo.CollapseDepthSatisfied = true;
275 SemaRef.CollapseInfo.CurCollapseCount = 0;
276 SemaRef.TileInfo.TileDepthSatisfied = true;
277
278 // We make sure to take an optional list of uninstantiated clauses, so that
279 // we can check to make sure we don't 'double diagnose' in the event that
280 // the value of 'N' was not dependent in a template. Since we cannot count on
281 // there only being a single collapse clause, we count on the order to make
282 // sure get the matching ones, and we count on TreeTransform not removing
283 // these, even if loop-count instantiation failed. We can check the
284 // non-dependent ones right away, and realize that subsequent instantiation
285 // can only make it more specific.
286
287 auto *UnInstClauseItr =
288 llvm::find_if(UnInstClauses, llvm::IsaPred<OpenACCCollapseClause>);
289 auto *ClauseItr =
290 llvm::find_if(Clauses, llvm::IsaPred<OpenACCCollapseClause>);
291 const OpenACCCollapseClause *FoundClause = nullptr;
292
293 // Loop through the list of Collapse clauses and find the one that:
294 // 1- Has a non-dependent, non-null loop count (null means error, likely
295 // during instantiation).
296 // 2- If UnInstClauses isn't empty, its corresponding
297 // loop count was dependent.
298 // 3- Has the largest 'loop count' of all.
299 while (ClauseItr != Clauses.end()) {
300 const OpenACCCollapseClause *CurClause =
301 cast<OpenACCCollapseClause>(*ClauseItr);
302 const OpenACCCollapseClause *UnInstCurClause =
303 UnInstClauseItr == UnInstClauses.end()
304 ? nullptr
305 : cast<OpenACCCollapseClause>(*UnInstClauseItr);
306
307 FoundClause =
308 getBestCollapseCandidate(FoundClause, CurClause, UnInstCurClause);
309
310 UnInstClauseItr =
311 UnInstClauseItr == UnInstClauses.end()
312 ? UnInstClauseItr
313 : std::find_if(std::next(UnInstClauseItr), UnInstClauses.end(),
314 llvm::IsaPred<OpenACCCollapseClause>);
315 ClauseItr = std::find_if(std::next(ClauseItr), Clauses.end(),
316 llvm::IsaPred<OpenACCCollapseClause>);
317 }
318
319 if (!FoundClause)
320 return;
321
322 SemaRef.CollapseInfo.ActiveCollapse = FoundClause;
323 SemaRef.CollapseInfo.CollapseDepthSatisfied = false;
324 SemaRef.CollapseInfo.CurCollapseCount =
325 cast<ConstantExpr>(FoundClause->getLoopCount())->getResultAsAPSInt();
326 SemaRef.CollapseInfo.DirectiveKind = DirKind;
327}
328
332 // We don't diagnose if this is during instantiation, since the only thing we
333 // care about is the number of arguments, which we can figure out without
334 // instantiation, so we don't want to double-diagnose.
335 if (UnInstClauses.size() > 0)
336 return;
337 auto *TileClauseItr =
338 llvm::find_if(Clauses, llvm::IsaPred<OpenACCTileClause>);
339
340 if (Clauses.end() == TileClauseItr)
341 return;
342
343 OpenACCTileClause *TileClause = cast<OpenACCTileClause>(*TileClauseItr);
344
345 // Multiple tile clauses are allowed, so ensure that we use the one with the
346 // largest 'tile count'.
347 while (Clauses.end() !=
348 (TileClauseItr = std::find_if(std::next(TileClauseItr), Clauses.end(),
349 llvm::IsaPred<OpenACCTileClause>))) {
350 OpenACCTileClause *NewClause = cast<OpenACCTileClause>(*TileClauseItr);
351 if (NewClause->getSizeExprs().size() > TileClause->getSizeExprs().size())
352 TileClause = NewClause;
353 }
354
355 SemaRef.TileInfo.ActiveTile = TileClause;
356 SemaRef.TileInfo.TileDepthSatisfied = false;
357 SemaRef.TileInfo.CurTileCount =
358 static_cast<unsigned>(TileClause->getSizeExprs().size());
359 SemaRef.TileInfo.DirectiveKind = DirKind;
360}
361
363 if (DirKind == OpenACCDirectiveKind::Parallel ||
364 DirKind == OpenACCDirectiveKind::Serial ||
366 DirKind == OpenACCDirectiveKind::Loop ||
370 SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
371 SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;
372 SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
373 SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
374 SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;
375 SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);
376 } else if (DirKind == OpenACCDirectiveKind::Data ||
378 // Intentionally doesn't reset the Loop, Compute Construct, or reduction
379 // effects.
380 }
381}
382
384 SourceLocation DirLoc) {
385 // Start an evaluation context to parse the clause arguments on.
386 SemaRef.PushExpressionEvaluationContext(
388
389 // There is nothing do do here as all we have at this point is the name of the
390 // construct itself.
391}
392
395 Expr *IntExpr) {
396
397 assert(((DK != OpenACCDirectiveKind::Invalid &&
403 "Only one of directive or clause kind should be provided");
404
405 class IntExprConverter : public Sema::ICEConvertDiagnoser {
406 OpenACCDirectiveKind DirectiveKind;
407 OpenACCClauseKind ClauseKind;
408 Expr *IntExpr;
409
410 // gets the index into the diagnostics so we can use this for clauses,
411 // directives, and sub array.s
412 unsigned getDiagKind() const {
413 if (ClauseKind != OpenACCClauseKind::Invalid)
414 return 0;
415 if (DirectiveKind != OpenACCDirectiveKind::Invalid)
416 return 1;
417 return 2;
418 }
419
420 public:
421 IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
422 Expr *IntExpr)
423 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false,
424 /*Suppress=*/false,
425 /*SuppressConversion=*/true),
426 DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
427
428 bool match(QualType T) override {
429 // OpenACC spec just calls this 'integer expression' as having an
430 // 'integer type', so fall back on C99's 'integer type'.
431 return T->isIntegerType();
432 }
434 QualType T) override {
435 return S.Diag(Loc, diag::err_acc_int_expr_requires_integer)
436 << getDiagKind() << ClauseKind << DirectiveKind << T;
437 }
438
440 diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override {
441 return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type)
442 << T << IntExpr->getSourceRange();
443 }
444
446 diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T,
447 QualType ConvTy) override {
448 return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion)
449 << T << ConvTy;
450 }
451
452 SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
453 CXXConversionDecl *Conv,
454 QualType ConvTy) override {
455 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
456 << ConvTy->isEnumeralType() << ConvTy;
457 }
458
460 diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override {
461 return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T;
462 }
463
465 noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
466 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
467 << ConvTy->isEnumeralType() << ConvTy;
468 }
469
471 diagnoseConversion(Sema &S, SourceLocation Loc, QualType T,
472 QualType ConvTy) override {
473 llvm_unreachable("conversion functions are permitted");
474 }
475 } IntExprDiagnoser(DK, CK, IntExpr);
476
477 if (!IntExpr)
478 return ExprError();
479
480 ExprResult IntExprResult = SemaRef.PerformContextualImplicitConversion(
481 Loc, IntExpr, IntExprDiagnoser);
482 if (IntExprResult.isInvalid())
483 return ExprError();
484
485 IntExpr = IntExprResult.get();
486 if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType())
487 return ExprError();
488
489 // TODO OpenACC: Do we want to perform usual unary conversions here? When
490 // doing codegen we might find that is necessary, but skip it for now.
491 return IntExpr;
492}
493
495 Expr *VarExpr) {
496 // We already know that VarExpr is a proper reference to a variable, so we
497 // should be able to just take the type of the expression to get the type of
498 // the referenced variable.
499
500 // We've already seen an error, don't diagnose anything else.
501 if (!VarExpr || VarExpr->containsErrors())
502 return false;
503
505 VarExpr->hasPlaceholderType(BuiltinType::ArraySection)) {
506 Diag(VarExpr->getExprLoc(), diag::err_array_section_use) << /*OpenACC=*/0;
507 Diag(VarExpr->getExprLoc(), diag::note_acc_expected_pointer_var);
508 return true;
509 }
510
511 QualType Ty = VarExpr->getType();
513
514 // Nothing we can do if this is a dependent type.
515 if (Ty->isDependentType())
516 return false;
517
518 if (!Ty->isPointerType())
519 return Diag(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)
520 << ClauseKind << Ty;
521 return false;
522}
523
526 if (DK == OpenACCDirectiveKind::Cache) {
527 CacheInfo.ParsingCacheVarList = true;
528 CacheInfo.IsInvalidCacheRef = false;
529 }
530}
531
533 CacheInfo.ParsingCacheVarList = false;
534 CacheInfo.IsInvalidCacheRef = false;
535 // This makes sure that we properly mark variables 'used' that are referenced.
536 SemaRef.CleanupVarDeclMarking();
537}
538
540 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
541 // Clear this here, so we can do the returns based on the invalid cache ref
542 // here. Note all return statements in this function must return ExprError if
543 // IsInvalidCacheRef. However, instead of doing an 'early return' in that
544 // case, we can let the rest of the diagnostics happen, as the invalid decl
545 // ref is a warning.
546 bool WasParsingInvalidCacheRef =
547 CacheInfo.ParsingCacheVarList && CacheInfo.IsInvalidCacheRef;
548 CacheInfo.ParsingCacheVarList = false;
549 CacheInfo.IsInvalidCacheRef = false;
550
552 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
553 return ExprError();
554 }
555
556 // It isn't clear what 'simple array element or simple subarray' means, so we
557 // will just allow arbitrary depth.
559 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
560 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
561 else
562 CurVarExpr =
563 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
564 }
565
566 // References to a VarDecl are fine.
567 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
569 DRE->getFoundDecl()->getCanonicalDecl()))
570 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
571 }
572
573 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
574 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
575 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
576 }
577 }
578
579 // Nothing really we can do here, as these are dependent. So just return they
580 // are valid.
582 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
583
584 // There isn't really anything we can do in the case of a recovery expr, so
585 // skip the diagnostic rather than produce a confusing diagnostic.
586 if (isa<RecoveryExpr>(CurVarExpr))
587 return ExprError();
588
589 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
590 return ExprError();
591}
592
594 if (!getLangOpts().OpenACC || !CacheInfo.ParsingCacheVarList || !D ||
595 D->isInvalidDecl())
596 return;
597 // A 'cache' variable reference MUST be declared before the 'acc.loop' we
598 // generate in codegen, so we have to mark it invalid here in some way. We do
599 // so in a bit of a convoluted way as there is no good way to put this into
600 // the AST, so we store it in SemaOpenACC State. We can check the Scope
601 // during parsing to make sure there is a 'loop' before the decl is
602 // declared(and skip during instantiation).
603 // We only diagnose this as a warning, as this isn't required by the standard
604 // (unless you take a VERY awkward reading of some awkward prose).
605
606 Scope *CurScope = SemaRef.getCurScope();
607
608 // if we are at TU level, we are either doing some EXTRA wacky, or are in a
609 // template instantiation, so just give up.
610 if (CurScope->getDepth() == 0)
611 return;
612
613 while (CurScope) {
614 // If we run into a loop construct scope, than this is 'correct' in that the
615 // declaration is outside of the loop.
616 if (CurScope->isOpenACCLoopConstructScope())
617 return;
618
619 if (CurScope->isDeclScope(D)) {
620 Diag(Loc, diag::warn_acc_cache_var_not_outside_loop);
621
622 CacheInfo.IsInvalidCacheRef = true;
623 }
624
625 CurScope = CurScope->getParent();
626 }
627 // If we don't find the decl at all, we assume that it must be outside of the
628 // loop (or we aren't in a loop!) so skip the diagnostic.
629}
630
631namespace {
632// Check whether the type of the thing we are referencing is OK for things like
633// private, firstprivate, and reduction, which require certain operators to be
634// available.
635ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
636 SourceLocation InnerLoc, QualType InnerTy) {
637 // There is nothing to do here, only these three have these sorts of
638 // restrictions.
639 if (CK != OpenACCClauseKind::Private &&
642 return VarExpr;
643
644 // We can't test this if it isn't here, or if the type isn't clear yet.
645 if (InnerTy.isNull() || InnerTy->isDependentType())
646 return VarExpr;
647
648 InnerTy = InnerTy.getUnqualifiedType();
649 if (auto *RefTy = InnerTy->getAs<ReferenceType>())
650 InnerTy = RefTy->getPointeeType();
651
652 if (auto *ArrTy = InnerTy->getAsArrayTypeUnsafe()) {
653 // Non constant arrays decay to 'pointer', so warn and return that we're
654 // successful.
655 if (!ArrTy->isConstantArrayType()) {
656 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_non_const_array)
657 << InnerTy << CK;
658 return VarExpr;
659 }
660
661 return CheckVarType(S, CK, VarExpr, InnerLoc, ArrTy->getElementType());
662 }
663
664 if (S.SemaRef.RequireCompleteType(InnerLoc, InnerTy,
666 diag::err_incomplete_type))
667 return ExprError();
668
669 auto *RD = InnerTy->getAsCXXRecordDecl();
670
671 // if this isn't a C++ record decl, we can create/copy/destroy this thing at
672 // will without problem, so this is a success.
673 if (!RD)
674 return VarExpr;
675
676 if (CK == OpenACCClauseKind::Private) {
677 bool HasNonDeletedDefaultCtor =
678 llvm::find_if(RD->ctors(), [](const CXXConstructorDecl *CD) {
679 return CD->isDefaultConstructor() && !CD->isDeleted();
680 }) != RD->ctors().end();
681 if (!HasNonDeletedDefaultCtor && !RD->needsImplicitDefaultConstructor()) {
682 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
683 << InnerTy << CK << clang::diag::AccVarReferencedReason::DefCtor;
684 return ExprError();
685 }
686 } else if (CK == OpenACCClauseKind::FirstPrivate) {
687 if (!RD->hasSimpleCopyConstructor()) {
688 Sema::SpecialMemberOverloadResult SMOR = S.SemaRef.LookupSpecialMember(
689 RD, CXXSpecialMemberKind::CopyConstructor, /*ConstArg=*/true,
690 /*VolatileArg=*/false, /*RValueThis=*/false, /*ConstThis=*/false,
691 /*VolatileThis=*/false);
692
694 SMOR.getMethod()->isDeleted()) {
695 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
696 << InnerTy << CK << clang::diag::AccVarReferencedReason::CopyCtor;
697 return ExprError();
698 }
699 }
700 } else if (CK == OpenACCClauseKind::Reduction) {
701 // TODO: Reduction needs to be an aggregate, which gets checked later, so
702 // construction here isn't a problem. However, we need to make sure that we
703 // can compare it correctly still.
704 }
705
706 // All 3 things need to make sure they have a dtor.
707 bool DestructorDeleted =
708 RD->getDestructor() && RD->getDestructor()->isDeleted();
709 if (DestructorDeleted && !RD->needsImplicitDestructor()) {
710 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
711 << InnerTy << CK << clang::diag::AccVarReferencedReason::Dtor;
712 return ExprError();
713 }
714 return VarExpr;
715}
716
717ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
718 Expr *InnerExpr) {
719 if (!InnerExpr)
720 return VarExpr;
721 return CheckVarType(S, CK, VarExpr, InnerExpr->getBeginLoc(),
722 InnerExpr->getType());
723}
724} // namespace
725
727 Expr *VarExpr) {
728 // This makes sure that we properly mark variables 'used' that are referenced.
729 SemaRef.CleanupVarDeclMarking();
730
731 // This has unique enough restrictions that we should split it to a separate
732 // function.
734 return ActOnCacheVar(VarExpr);
735
736 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
737
738 // 'use_device' doesn't allow array subscript or array sections.
739 // OpenACC3.3 2.8:
740 // A 'var' in a 'use_device' clause must be the name of a variable or array.
741 // OpenACC3.3 2.13:
742 // A 'var' in a 'declare' directive must be a variable or array name.
743 if ((CK == OpenACCClauseKind::UseDevice ||
745 if (isa<ArraySubscriptExpr>(CurVarExpr)) {
746 Diag(VarExpr->getExprLoc(),
747 diag::err_acc_not_a_var_ref_use_device_declare)
749 return ExprError();
750 }
751 // As an extension, we allow 'array sections'/'sub-arrays' here, as that is
752 // effectively defining an array, and are in common use.
753 if (isa<ArraySectionExpr>(CurVarExpr))
754 Diag(VarExpr->getExprLoc(),
755 diag::ext_acc_array_section_use_device_declare)
757 }
758
759 // Sub-arrays/subscript-exprs are fine as long as the base is a
760 // VarExpr/MemberExpr. So strip all of those off.
762 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
763 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
764 else
765 CurVarExpr =
766 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
767 }
768
769 // References to a VarDecl are fine.
770 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
772 DRE->getFoundDecl()->getCanonicalDecl()))
773 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
774 }
775
776 // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
777 // reduction clause must be a scalar variable name, an aggregate variable
778 // name, an array element, or a subarray.
779 // If CK is a 'use_device', this also isn't valid, as it isn't the name of a
780 // variable or array, if not done as a member expr.
781 // A MemberExpr that references a Field is valid for other clauses.
782 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
783 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
787
788 // We can allow 'member expr' if the 'this' is implicit in the case of
789 // declare, reduction, and use_device.
790 const auto *This = dyn_cast<CXXThisExpr>(ME->getBase());
791 if (This && This->isImplicit())
792 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
793 } else {
794 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
795 }
796 }
797 }
798
799 // Referring to 'this' is ok for the most part, but for 'use_device'/'declare'
800 // doesn't fall into 'variable or array name'
803 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
804
805 // Nothing really we can do here, as these are dependent. So just return they
806 // are valid.
807 if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
810 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
811
812 // There isn't really anything we can do in the case of a recovery expr, so
813 // skip the diagnostic rather than produce a confusing diagnostic.
814 if (isa<RecoveryExpr>(CurVarExpr))
815 return ExprError();
816
818 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
819 << /*declare*/ 1;
820 else if (CK == OpenACCClauseKind::UseDevice)
821 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
822 << /*use_device*/ 0;
823 else
824 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
826 return ExprError();
827}
828
830 Expr *LowerBound,
831 SourceLocation ColonLoc,
832 Expr *Length,
833 SourceLocation RBLoc) {
834 ASTContext &Context = getASTContext();
835
836 // Handle placeholders.
837 if (Base->hasPlaceholderType() &&
838 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
839 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
840 if (Result.isInvalid())
841 return ExprError();
842 Base = Result.get();
843 }
844 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
845 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
846 if (Result.isInvalid())
847 return ExprError();
848 Result = SemaRef.DefaultLvalueConversion(Result.get());
849 if (Result.isInvalid())
850 return ExprError();
851 LowerBound = Result.get();
852 }
853 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
854 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
855 if (Result.isInvalid())
856 return ExprError();
857 Result = SemaRef.DefaultLvalueConversion(Result.get());
858 if (Result.isInvalid())
859 return ExprError();
860 Length = Result.get();
861 }
862
863 // Check the 'base' value, it must be an array or pointer type, and not to/of
864 // a function type.
866 QualType ResultTy;
867 if (!Base->isTypeDependent()) {
868 if (OriginalBaseTy->isAnyPointerType()) {
869 ResultTy = OriginalBaseTy->getPointeeType();
870 } else if (OriginalBaseTy->isArrayType()) {
871 ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
872 } else {
873 return ExprError(
874 Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
875 << Base->getSourceRange());
876 }
877
878 if (ResultTy->isFunctionType()) {
879 Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
880 << ResultTy << Base->getSourceRange();
881 return ExprError();
882 }
883
884 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
885 diag::err_acc_subarray_incomplete_type,
886 Base))
887 return ExprError();
888
889 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
890 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
891 if (Result.isInvalid())
892 return ExprError();
893 Base = Result.get();
894 }
895 }
896
897 auto GetRecovery = [&](Expr *E, QualType Ty) {
898 ExprResult Recovery =
899 SemaRef.CreateRecoveryExpr(E->getBeginLoc(), E->getEndLoc(), E, Ty);
900 return Recovery.isUsable() ? Recovery.get() : nullptr;
901 };
902
903 // Ensure both of the expressions are int-exprs.
904 if (LowerBound && !LowerBound->isTypeDependent()) {
905 ExprResult LBRes =
907 LowerBound->getExprLoc(), LowerBound);
908
909 if (LBRes.isUsable())
910 LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
911 LowerBound =
912 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
913 }
914
915 if (Length && !Length->isTypeDependent()) {
916 ExprResult LenRes =
918 Length->getExprLoc(), Length);
919
920 if (LenRes.isUsable())
921 LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
922 Length =
923 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
924 }
925
926 // Length is required if the base type is not an array of known bounds.
927 if (!Length && (OriginalBaseTy.isNull() ||
928 (!OriginalBaseTy->isDependentType() &&
929 !OriginalBaseTy->isConstantArrayType() &&
930 !OriginalBaseTy->isDependentSizedArrayType()))) {
931 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
932 SourceLocation DiagLoc = ColonLoc.isInvalid() ? LBLoc : ColonLoc;
933 Diag(DiagLoc, diag::err_acc_subarray_no_length) << IsArray;
934 // Fill in a dummy 'length' so that when we instantiate this we don't
935 // double-diagnose here.
936 ExprResult Recovery = SemaRef.CreateRecoveryExpr(
937 DiagLoc, SourceLocation(), ArrayRef<Expr *>(), Context.IntTy);
938 Length = Recovery.isUsable() ? Recovery.get() : nullptr;
939 }
940
941 // Check the values of each of the arguments, they cannot be negative(we
942 // assume), and if the array bound is known, must be within range. As we do
943 // so, do our best to continue with evaluation, we can set the
944 // value/expression to nullptr/nullopt if they are invalid, and treat them as
945 // not present for the rest of evaluation.
946
947 // We don't have to check for dependence, because the dependent size is
948 // represented as a different AST node.
949 std::optional<llvm::APSInt> BaseSize;
950 if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
951 const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);
952 BaseSize = ArrayTy->getSize();
953 }
954
955 auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
956 if (!E || E->isInstantiationDependent())
957 return std::nullopt;
958
960 if (!E->EvaluateAsInt(Res, Context))
961 return std::nullopt;
962 return Res.Val.getInt();
963 };
964
965 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
966 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
967
968 // Check lower bound for negative or out of range.
969 if (LowerBoundValue.has_value()) {
970 if (LowerBoundValue->isNegative()) {
971 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
972 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
973 LowerBoundValue.reset();
974 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
975 } else if (BaseSize.has_value() &&
976 llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
977 // Lower bound (start index) must be less than the size of the array.
978 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
979 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
980 << toString(*BaseSize, /*Radix=*/10);
981 LowerBoundValue.reset();
982 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
983 }
984 }
985
986 // Check length for negative or out of range.
987 if (LengthValue.has_value()) {
988 if (LengthValue->isNegative()) {
989 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
990 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
991 LengthValue.reset();
992 Length = GetRecovery(Length, Length->getType());
993 } else if (BaseSize.has_value() &&
994 llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
995 // Length must be lessthan or EQUAL to the size of the array.
996 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
997 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
998 << toString(*BaseSize, /*Radix=*/10);
999 LengthValue.reset();
1000 Length = GetRecovery(Length, Length->getType());
1001 }
1002 }
1003
1004 // Adding two APSInts requires matching sign and width, so extract those here.
1005 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
1006 if (LHS.isSigned() == RHS.isSigned() &&
1007 LHS.getBitWidth() == RHS.getBitWidth())
1008 return LHS + RHS;
1009
1010 // Width is + 1 so that unsigned->signed conversion just works.
1011 unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
1012 return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), /*Signed=*/true);
1013 };
1014
1015 // If we know all 3 values, we can diagnose that the total value would be out
1016 // of range.
1017 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
1018 LengthValue.has_value() &&
1019 llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
1020 *BaseSize) > 0) {
1021 Diag(Base->getExprLoc(),
1022 diag::err_acc_subarray_base_plus_length_out_of_range)
1023 << toString(*LowerBoundValue, /*Radix=*/10)
1024 << toString(*LengthValue, /*Radix=*/10)
1025 << toString(*BaseSize, /*Radix=*/10);
1026
1027 LowerBoundValue.reset();
1028 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
1029 LengthValue.reset();
1030 Length = GetRecovery(Length, Length->getType());
1031 }
1032
1033 // If any part of the expression is dependent, return a dependent sub-array.
1034 QualType ArrayExprTy = Context.ArraySectionTy;
1035 if (Base->isTypeDependent() ||
1036 (LowerBound && LowerBound->isTypeDependent()) ||
1037 (Length && Length->isTypeDependent()))
1038 ArrayExprTy = Context.DependentTy;
1039
1040 return new (Context)
1041 ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
1042 OK_Ordinary, ColonLoc, RBLoc);
1043}
1044
1046 if (!getLangOpts().OpenACC)
1047 return;
1048
1049 if (!LoopInfo.TopLevelLoopSeen)
1050 return;
1051
1052 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1053 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
1054 << /*while loop*/ 1 << CollapseInfo.DirectiveKind
1056 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1057 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1058 diag::note_acc_active_clause_here)
1060
1061 // Remove the value so that we don't get cascading errors in the body. The
1062 // caller RAII object will restore this.
1063 CollapseInfo.CurCollapseCount = std::nullopt;
1064 }
1065
1066 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1067 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
1068 << /*while loop*/ 1 << TileInfo.DirectiveKind
1070 assert(TileInfo.ActiveTile && "tile count without object?");
1071 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1073
1074 // Remove the value so that we don't get cascading errors in the body. The
1075 // caller RAII object will restore this.
1076 TileInfo.CurTileCount = std::nullopt;
1077 }
1078}
1079
1081 if (!getLangOpts().OpenACC)
1082 return;
1083
1084 if (!LoopInfo.TopLevelLoopSeen)
1085 return;
1086
1087 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1088 Diag(DoLoc, diag::err_acc_invalid_in_loop)
1089 << /*do loop*/ 2 << CollapseInfo.DirectiveKind
1091 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1092 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1093 diag::note_acc_active_clause_here)
1095
1096 // Remove the value so that we don't get cascading errors in the body. The
1097 // caller RAII object will restore this.
1098 CollapseInfo.CurCollapseCount = std::nullopt;
1099 }
1100
1101 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1102 Diag(DoLoc, diag::err_acc_invalid_in_loop)
1103 << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
1104 assert(TileInfo.ActiveTile && "tile count without object?");
1105 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1107
1108 // Remove the value so that we don't get cascading errors in the body. The
1109 // caller RAII object will restore this.
1110 TileInfo.CurTileCount = std::nullopt;
1111 }
1112}
1113
1114void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
1115 ForStmtBeginChecker &C) {
1116 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
1117
1118 // Enable the while/do-while checking.
1119 LoopInfo.TopLevelLoopSeen = true;
1120
1121 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1122 // Check the format of this loop if it is affected by the collapse.
1123 C.check();
1124
1125 // OpenACC 3.3 2.9.1:
1126 // Each associated loop, except the innermost, must contain exactly one loop
1127 // or loop nest.
1128 // This checks for more than 1 loop at the current level, the
1129 // 'depth'-satisifed checking manages the 'not zero' case.
1130 if (LoopInfo.CurLevelHasLoopAlready) {
1131 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
1132 << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
1133 assert(CollapseInfo.ActiveCollapse && "No collapse object?");
1134 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1135 diag::note_acc_active_clause_here)
1137 } else {
1138 --(*CollapseInfo.CurCollapseCount);
1139
1140 // Once we've hit zero here, we know we have deep enough 'for' loops to
1141 // get to the bottom.
1142 if (*CollapseInfo.CurCollapseCount == 0)
1143 CollapseInfo.CollapseDepthSatisfied = true;
1144 }
1145 }
1146
1147 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1148 // Check the format of this loop if it is affected by the tile.
1149 C.check();
1150
1151 if (LoopInfo.CurLevelHasLoopAlready) {
1152 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
1153 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
1154 assert(TileInfo.ActiveTile && "No tile object?");
1155 Diag(TileInfo.ActiveTile->getBeginLoc(),
1156 diag::note_acc_active_clause_here)
1158 } else {
1159 TileInfo.CurTileCount = *TileInfo.CurTileCount - 1;
1160 // Once we've hit zero here, we know we have deep enough 'for' loops to
1161 // get to the bottom.
1162 if (*TileInfo.CurTileCount == 0)
1163 TileInfo.TileDepthSatisfied = true;
1164 }
1165 }
1166
1167 // Set this to 'false' for the body of this loop, so that the next level
1168 // checks independently.
1169 LoopInfo.CurLevelHasLoopAlready = false;
1170}
1171
1172namespace {
1173bool isValidLoopVariableType(QualType LoopVarTy) {
1174 // Just skip if it is dependent, it could be any of the below.
1175 if (LoopVarTy->isDependentType())
1176 return true;
1177
1178 // The loop variable must be of integer,
1179 if (LoopVarTy->isIntegerType())
1180 return true;
1181
1182 // C/C++ pointer,
1183 if (LoopVarTy->isPointerType())
1184 return true;
1185
1186 // or C++ random-access iterator type.
1187 if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
1188 // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
1189 // iterator type!
1190
1191 // We could either do a lot of work to see if this matches
1192 // random-access-iterator, but it seems that just checking that the
1193 // 'iterator_category' typedef is more than sufficient. If programmers are
1194 // willing to lie about this, we can let them.
1195
1196 for (const auto *TD :
1197 llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
1198 const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
1199
1200 if (TDND->getName() != "iterator_category")
1201 continue;
1202
1203 // If there is no type for this decl, return false.
1204 if (TDND->getUnderlyingType().isNull())
1205 return false;
1206
1207 const CXXRecordDecl *ItrCategoryDecl =
1208 TDND->getUnderlyingType()->getAsCXXRecordDecl();
1209
1210 // If the category isn't a record decl, it isn't the tag type.
1211 if (!ItrCategoryDecl)
1212 return false;
1213
1214 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
1215 if (RD->getName() != "random_access_iterator_tag")
1216 return false;
1217 // Checks just for std::random_access_iterator_tag.
1218 return RD->getEnclosingNamespaceContext()->isStdNamespace();
1219 };
1220
1221 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
1222 return true;
1223
1224 // We can also support tag-types inherited from the
1225 // random_access_iterator_tag.
1226 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases())
1227 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
1228 return true;
1229
1230 return false;
1231 }
1232 }
1233
1234 return false;
1235}
1236const ValueDecl *getDeclFromExpr(const Expr *E) {
1237 E = E->IgnoreParenImpCasts();
1238 if (const auto *FE = dyn_cast<FullExpr>(E))
1239 E = FE->getSubExpr();
1240
1241 E = E->IgnoreParenImpCasts();
1242
1243 if (!E)
1244 return nullptr;
1245 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
1246 return DRE->getDecl();
1247
1248 if (const auto *ME = dyn_cast<MemberExpr>(E))
1249 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1250 return ME->getMemberDecl();
1251
1252 return nullptr;
1253}
1254} // namespace
1255
1256void SemaOpenACC::ForStmtBeginChecker::checkRangeFor() {
1257 const RangeForInfo &RFI = std::get<RangeForInfo>(Info);
1258 // If this hasn't changed since last instantiated we're done.
1259 if (RFI.Uninstantiated == RFI.CurrentVersion)
1260 return;
1261
1262 const DeclStmt *UninstRangeStmt =
1263 IsInstantiation ? RFI.Uninstantiated->getBeginStmt() : nullptr;
1264 const DeclStmt *RangeStmt = RFI.CurrentVersion->getBeginStmt();
1265
1266 // If this isn't the first time we've checked this loop, suppress any cases
1267 // where we previously diagnosed.
1268 if (UninstRangeStmt) {
1269 const ValueDecl *InitVar =
1270 cast<ValueDecl>(UninstRangeStmt->getSingleDecl());
1271 QualType VarType = InitVar->getType().getNonReferenceType();
1272
1273 if (!isValidLoopVariableType(VarType))
1274 return;
1275 }
1276
1277 // In some dependent contexts, the autogenerated range statement doesn't get
1278 // included until instantiation, so skip for now.
1279 if (RangeStmt) {
1280 const ValueDecl *InitVar = cast<ValueDecl>(RangeStmt->getSingleDecl());
1281 QualType VarType = InitVar->getType().getNonReferenceType();
1282
1283 if (!isValidLoopVariableType(VarType)) {
1284 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1285 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1286 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1287 diag::note_acc_construct_here)
1288 << SemaRef.LoopWithoutSeqInfo.Kind;
1289 return;
1290 }
1291 }
1292}
1293bool SemaOpenACC::ForStmtBeginChecker::checkForInit(const Stmt *InitStmt,
1294 const ValueDecl *&InitVar,
1295 bool Diag) {
1296 // Init statement is required.
1297 if (!InitStmt) {
1298 if (Diag) {
1299 SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)
1300 << SemaRef.LoopWithoutSeqInfo.Kind;
1301 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1302 diag::note_acc_construct_here)
1303 << SemaRef.LoopWithoutSeqInfo.Kind;
1304 }
1305 return true;
1306 }
1307 auto DiagLoopVar = [this, Diag, InitStmt]() {
1308 if (Diag) {
1309 SemaRef.Diag(InitStmt->getBeginLoc(), diag::err_acc_loop_variable)
1310 << SemaRef.LoopWithoutSeqInfo.Kind;
1311 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1312 diag::note_acc_construct_here)
1313 << SemaRef.LoopWithoutSeqInfo.Kind;
1314 }
1315 return true;
1316 };
1317
1318 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(InitStmt))
1319 InitStmt = ExprTemp->getSubExpr();
1320 if (const auto *E = dyn_cast<Expr>(InitStmt))
1321 InitStmt = E->IgnoreParenImpCasts();
1322
1323 InitVar = nullptr;
1324 if (const auto *BO = dyn_cast<BinaryOperator>(InitStmt)) {
1325 // Allow assignment operator here.
1326
1327 if (!BO->isAssignmentOp())
1328 return DiagLoopVar();
1329
1330 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
1331 if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS))
1332 InitVar = DRE->getDecl();
1333 } else if (const auto *DS = dyn_cast<DeclStmt>(InitStmt)) {
1334 // Allow T t = <whatever>
1335 if (!DS->isSingleDecl())
1336 return DiagLoopVar();
1337 InitVar = dyn_cast<ValueDecl>(DS->getSingleDecl());
1338
1339 // Ensure we have an initializer, unless this is a record/dependent type.
1340 if (InitVar) {
1341 if (!isa<VarDecl>(InitVar))
1342 return DiagLoopVar();
1343
1344 if (!InitVar->getType()->isRecordType() &&
1345 !InitVar->getType()->isDependentType() &&
1346 !cast<VarDecl>(InitVar)->hasInit())
1347 return DiagLoopVar();
1348 }
1349 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(InitStmt)) {
1350 // Allow assignment operator call.
1351 if (CE->getOperator() != OO_Equal)
1352 return DiagLoopVar();
1353 if (CE->getNumArgs() < 1)
1354 return DiagLoopVar();
1355
1356 const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
1357 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1358 InitVar = DRE->getDecl();
1359 } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
1360 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1361 InitVar = ME->getMemberDecl();
1362 }
1363 }
1364
1365 // If after all of that, we haven't found a variable, give up.
1366 if (!InitVar)
1367 return DiagLoopVar();
1368
1369 InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
1370 QualType VarType = InitVar->getType().getNonReferenceType();
1371
1372 // Since we have one, all we need to do is ensure it is the right type.
1373 if (!isValidLoopVariableType(VarType)) {
1374 if (Diag) {
1375 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1376 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1377 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1378 diag::note_acc_construct_here)
1379 << SemaRef.LoopWithoutSeqInfo.Kind;
1380 }
1381 return true;
1382 }
1383
1384 return false;
1385}
1386
1387bool SemaOpenACC::ForStmtBeginChecker::checkForCond(const Stmt *CondStmt,
1388 const ValueDecl *InitVar,
1389 bool Diag) {
1390 // A condition statement is required.
1391 if (!CondStmt) {
1392 if (Diag) {
1393 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
1394 << SemaRef.LoopWithoutSeqInfo.Kind;
1395 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1396 diag::note_acc_construct_here)
1397 << SemaRef.LoopWithoutSeqInfo.Kind;
1398 }
1399
1400 return true;
1401 }
1402 auto DiagCondVar = [this, Diag, CondStmt] {
1403 if (Diag) {
1404 SemaRef.Diag(CondStmt->getBeginLoc(),
1405 diag::err_acc_loop_terminating_condition)
1406 << SemaRef.LoopWithoutSeqInfo.Kind;
1407 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1408 diag::note_acc_construct_here)
1409 << SemaRef.LoopWithoutSeqInfo.Kind;
1410 }
1411 return true;
1412 };
1413
1414 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(CondStmt))
1415 CondStmt = ExprTemp->getSubExpr();
1416 if (const auto *E = dyn_cast<Expr>(CondStmt))
1417 CondStmt = E->IgnoreParenImpCasts();
1418
1419 const ValueDecl *CondVar = nullptr;
1420 if (const auto *BO = dyn_cast<BinaryOperator>(CondStmt)) {
1421 switch (BO->getOpcode()) {
1422 default:
1423 return DiagCondVar();
1424 case BO_EQ:
1425 case BO_LT:
1426 case BO_GT:
1427 case BO_NE:
1428 case BO_LE:
1429 case BO_GE:
1430 break;
1431 }
1432
1433 // Assign the condition-var to the LHS. If it either comes back null, or
1434 // the LHS doesn't match the InitVar, assign it to the RHS so that 5 < N is
1435 // allowed.
1436 CondVar = getDeclFromExpr(BO->getLHS());
1437 if (!CondVar ||
1438 (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl()))
1439 CondVar = getDeclFromExpr(BO->getRHS());
1440
1441 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(CondStmt)) {
1442 // Any of the comparison ops should be ok here, but we don't know how to
1443 // handle spaceship, so disallow for now.
1444 if (!CE->isComparisonOp() || CE->getOperator() == OO_Spaceship)
1445 return DiagCondVar();
1446
1447 if (CE->getNumArgs() < 1)
1448 DiagCondVar();
1449
1450 // Same logic here: Assign it to the LHS, unless the LHS comes back null or
1451 // not equal to the init var.
1452 CondVar = getDeclFromExpr(CE->getArg(0));
1453 if (!CondVar ||
1454 (InitVar &&
1455 CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl() &&
1456 CE->getNumArgs() > 1))
1457 CondVar = getDeclFromExpr(CE->getArg(1));
1458 } else {
1459 return DiagCondVar();
1460 }
1461
1462 if (!CondVar)
1463 return DiagCondVar();
1464
1465 // Don't consider this an error unless the init variable was properly set,
1466 // else check to make sure they are the same variable.
1467 if (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1468 return DiagCondVar();
1469
1470 return false;
1471}
1472
1473namespace {
1474// Helper to check the RHS of an assignment during for's step. We can allow
1475// InitVar = InitVar + N, InitVar = N + InitVar, and Initvar = Initvar - N,
1476// where N is an integer.
1477bool isValidForIncRHSAssign(const ValueDecl *InitVar, const Expr *RHS) {
1478
1479 auto isValid = [](const ValueDecl *InitVar, const Expr *InnerLHS,
1480 const Expr *InnerRHS, bool IsAddition) {
1481 // ONE of the sides has to be an integer type.
1482 if (!InnerLHS->getType()->isIntegerType() &&
1483 !InnerRHS->getType()->isIntegerType())
1484 return false;
1485
1486 // If the init var is already an error, don't bother trying to check for
1487 // it.
1488 if (!InitVar)
1489 return true;
1490
1491 const ValueDecl *LHSDecl = getDeclFromExpr(InnerLHS);
1492 const ValueDecl *RHSDecl = getDeclFromExpr(InnerRHS);
1493 // If we can't get a declaration, this is probably an error, so give up.
1494 if (!LHSDecl || !RHSDecl)
1495 return true;
1496
1497 // If the LHS is the InitVar, the other must be int, so this is valid.
1498 if (LHSDecl->getCanonicalDecl() ==
1499 InitVar->getCanonicalDecl())
1500 return true;
1501
1502 // Subtraction doesn't allow the RHS to be init var, so this is invalid.
1503 if (!IsAddition)
1504 return false;
1505
1506 return RHSDecl->getCanonicalDecl() ==
1507 InitVar->getCanonicalDecl();
1508 };
1509
1510 if (const auto *BO = dyn_cast<BinaryOperator>(RHS)) {
1511 BinaryOperatorKind OpC = BO->getOpcode();
1512 if (OpC != BO_Add && OpC != BO_Sub)
1513 return false;
1514 return isValid(InitVar, BO->getLHS(), BO->getRHS(), OpC == BO_Add);
1515 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
1516 OverloadedOperatorKind Op = CE->getOperator();
1517 if (Op != OO_Plus && Op != OO_Minus)
1518 return false;
1519 // Despite Plus/Minus otherwise only being possible with 2 arguments, error
1520 // recovery will sometimes leave us with only 1 here, so fail out if we
1521 // don't have the correct number of args.
1522 if (CE->getNumArgs() != 2)
1523 return false;
1524 return isValid(InitVar, CE->getArg(0), CE->getArg(1), Op == OO_Plus);
1525 }
1526
1527 return false;
1528}
1529} // namespace
1530
1531bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,
1532 const ValueDecl *InitVar,
1533 bool Diag) {
1534 if (!IncStmt) {
1535 if (Diag) {
1536 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
1537 << SemaRef.LoopWithoutSeqInfo.Kind;
1538 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1539 diag::note_acc_construct_here)
1540 << SemaRef.LoopWithoutSeqInfo.Kind;
1541 }
1542 return true;
1543 }
1544 auto DiagIncVar = [this, Diag, IncStmt] {
1545 if (Diag) {
1546 SemaRef.Diag(IncStmt->getBeginLoc(), diag::err_acc_loop_not_monotonic)
1547 << SemaRef.LoopWithoutSeqInfo.Kind;
1548 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1549 diag::note_acc_construct_here)
1550 << SemaRef.LoopWithoutSeqInfo.Kind;
1551 }
1552 return true;
1553 };
1554
1555 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(IncStmt))
1556 IncStmt = ExprTemp->getSubExpr();
1557 if (const auto *E = dyn_cast<Expr>(IncStmt))
1558 IncStmt = E->IgnoreParenImpCasts();
1559
1560 const ValueDecl *IncVar = nullptr;
1561 // Here we enforce the monotonically increase/decrease:
1562 if (const auto *UO = dyn_cast<UnaryOperator>(IncStmt)) {
1563 // Allow increment/decrement ops.
1564 if (!UO->isIncrementDecrementOp())
1565 return DiagIncVar();
1566 IncVar = getDeclFromExpr(UO->getSubExpr());
1567 } else if (const auto *BO = dyn_cast<BinaryOperator>(IncStmt)) {
1568 switch (BO->getOpcode()) {
1569 default:
1570 return DiagIncVar();
1571 case BO_AddAssign:
1572 case BO_SubAssign:
1573 break;
1574 case BO_Assign:
1575 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1576 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1577 if (!isValidForIncRHSAssign(InitVar, BO->getRHS()))
1578 return DiagIncVar();
1579 break;
1580 }
1581 IncVar = getDeclFromExpr(BO->getLHS());
1582 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(IncStmt)) {
1583 if (CE->getNumArgs() < 1)
1584 return DiagIncVar();
1585
1586 switch (CE->getOperator()) {
1587 default:
1588 return DiagIncVar();
1589 case OO_PlusPlus:
1590 case OO_MinusMinus:
1591 case OO_PlusEqual:
1592 case OO_MinusEqual:
1593 break;
1594 case OO_Equal:
1595 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1596 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1597 if (CE->getNumArgs() != 2 ||
1598 !isValidForIncRHSAssign(InitVar, CE->getArg(1)))
1599 return DiagIncVar();
1600 break;
1601 }
1602
1603 IncVar = getDeclFromExpr(CE->getArg(0));
1604 } else {
1605 return DiagIncVar();
1606 }
1607
1608 if (!IncVar)
1609 return DiagIncVar();
1610
1611 // InitVar shouldn't be null unless there was an error, so don't diagnose if
1612 // that is the case. Else we should ensure that it refers to the loop
1613 // value.
1614 if (InitVar && IncVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1615 return DiagIncVar();
1616
1617 return false;
1618}
1619
1620void SemaOpenACC::ForStmtBeginChecker::checkFor() {
1621 const CheckForInfo &CFI = std::get<CheckForInfo>(Info);
1622
1623 if (!IsInstantiation) {
1624 // If this isn't an instantiation, we can just check all of these and
1625 // diagnose.
1626 const ValueDecl *CurInitVar = nullptr;
1627 checkForInit(CFI.Current.Init, CurInitVar, /*Diag=*/true);
1628 checkForCond(CFI.Current.Condition, CurInitVar, /*Diag=*/true);
1629 checkForInc(CFI.Current.Increment, CurInitVar, /*DIag=*/true);
1630 } else {
1631 const ValueDecl *UninstInitVar = nullptr;
1632 // Checking the 'init' section first. We have to always run both versions,
1633 // at minimum with the 'diag' off, so that we can ensure we get the correct
1634 // instantiation var for checking by later ones.
1635 bool UninstInitFailed =
1636 checkForInit(CFI.Uninst.Init, UninstInitVar, /*Diag=*/false);
1637
1638 // VarDecls are always rebuild because they are dependent, so we can do a
1639 // little work to suppress some of the double checking based on whether the
1640 // type is instantiation dependent. This is imperfect, but will get us most
1641 // cases suppressed. Currently this only handles the 'T t =' case.
1642 auto InitChanged = [=]() {
1643 if (CFI.Uninst.Init == CFI.Current.Init)
1644 return false;
1645
1646 QualType OldVDTy;
1647 QualType NewVDTy;
1648
1649 if (const auto *DS = dyn_cast<DeclStmt>(CFI.Uninst.Init))
1650 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1651 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1652 OldVDTy = VD->getType();
1653 if (const auto *DS = dyn_cast<DeclStmt>(CFI.Current.Init))
1654 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1655 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1656 NewVDTy = VD->getType();
1657
1658 if (OldVDTy.isNull() || NewVDTy.isNull())
1659 return true;
1660
1661 return OldVDTy->isInstantiationDependentType() !=
1663 };
1664
1665 // Only diagnose the new 'init' if the previous version didn't fail, AND the
1666 // current init changed meaningfully.
1667 bool ShouldDiagNewInit = !UninstInitFailed && InitChanged();
1668 const ValueDecl *CurInitVar = nullptr;
1669 checkForInit(CFI.Current.Init, CurInitVar, /*Diag=*/ShouldDiagNewInit);
1670
1671 // Check the condition and increment only if the previous version passed,
1672 // and this changed.
1673 if (CFI.Uninst.Condition != CFI.Current.Condition &&
1674 !checkForCond(CFI.Uninst.Condition, UninstInitVar, /*Diag=*/false))
1675 checkForCond(CFI.Current.Condition, CurInitVar, /*Diag=*/true);
1676 if (CFI.Uninst.Increment != CFI.Current.Increment &&
1677 !checkForInc(CFI.Uninst.Increment, UninstInitVar, /*Diag=*/false))
1678 checkForInc(CFI.Current.Increment, CurInitVar, /*Diag=*/true);
1679 }
1680}
1681
1682void SemaOpenACC::ForStmtBeginChecker::check() {
1683 // If this isn't an active loop without a seq, immediately return, nothing to
1684 // check.
1685 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
1686 return;
1687
1688 // If we've already checked, because this is a 'top level' one (and asking
1689 // again because 'tile' and 'collapse' might apply), just return, nothing to
1690 // do here.
1691 if (AlreadyChecked)
1692 return;
1693 AlreadyChecked = true;
1694
1695 // OpenACC3.3 2.1:
1696 // A loop associated with a loop construct that does not have a seq clause
1697 // must be written to meet all the following conditions:
1698 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
1699 // iterator type.
1700 // - The loop variable must monotonically increase or decrease in the
1701 // direction of its termination condition.
1702 // - The loop trip count must be computable in constant time when entering the
1703 // loop construct.
1704 //
1705 // For a C++ range-based for loop, the loop variable
1706 // identified by the above conditions is the internal iterator, such as a
1707 // pointer, that the compiler generates to iterate the range. it is not the
1708 // variable declared by the for loop.
1709
1710 if (std::holds_alternative<RangeForInfo>(Info))
1711 return checkRangeFor();
1712
1713 return checkFor();
1714}
1715
1717 const Stmt *First, const Stmt *OldSecond,
1718 const Stmt *Second, const Stmt *OldThird,
1719 const Stmt *Third) {
1720 if (!getLangOpts().OpenACC)
1721 return;
1722
1723 ForStmtBeginChecker FSBC{*this, ForLoc, OldFirst, OldSecond,
1724 OldThird, First, Second, Third};
1725 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1726 // as a part of the helper if a tile/collapse applies.
1727 if (!LoopInfo.TopLevelLoopSeen) {
1728 FSBC.check();
1729 }
1730
1731 ForStmtBeginHelper(ForLoc, FSBC);
1732}
1733
1735 const Stmt *Second, const Stmt *Third) {
1736 if (!getLangOpts().OpenACC)
1737 return;
1738
1739 ForStmtBeginChecker FSBC{*this, ForLoc, First, Second, Third};
1740
1741 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1742 // as a part of the helper if a tile/collapse applies.
1743 if (!LoopInfo.TopLevelLoopSeen)
1744 FSBC.check();
1745
1746 ForStmtBeginHelper(ForLoc, FSBC);
1747}
1748
1750 const Stmt *OldRangeFor,
1751 const Stmt *RangeFor) {
1752 if (!getLangOpts().OpenACC || OldRangeFor == nullptr || RangeFor == nullptr)
1753 return;
1754
1755 ForStmtBeginChecker FSBC{*this, ForLoc,
1756 cast_if_present<CXXForRangeStmt>(OldRangeFor),
1757 cast_if_present<CXXForRangeStmt>(RangeFor)};
1758 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1759 // as a part of the helper if a tile/collapse applies.
1760 if (!LoopInfo.TopLevelLoopSeen) {
1761 FSBC.check();
1762 }
1763 ForStmtBeginHelper(ForLoc, FSBC);
1764}
1765
1767 const Stmt *RangeFor) {
1768 if (!getLangOpts().OpenACC || RangeFor == nullptr)
1769 return;
1770
1771 ForStmtBeginChecker FSBC = {*this, ForLoc,
1772 cast_if_present<CXXForRangeStmt>(RangeFor)};
1773
1774 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1775 // as a part of the helper if a tile/collapse applies.
1776 if (!LoopInfo.TopLevelLoopSeen)
1777 FSBC.check();
1778
1779 ForStmtBeginHelper(ForLoc, FSBC);
1780}
1781
1782namespace {
1783SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
1784 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
1785 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
1786 // `DoStmt`, as those are caught as a violation elsewhere.
1787 // For `CompoundStmt` we need to search inside of it.
1788 if (!CurStmt ||
1790 CurStmt))
1791 return SourceLocation{};
1792
1793 // Any other construct is an error anyway, so it has already been diagnosed.
1794 if (isa<OpenACCConstructStmt>(CurStmt))
1795 return SourceLocation{};
1796
1797 // Search inside the compound statement, this allows for arbitrary nesting
1798 // of compound statements, as long as there isn't any code inside.
1799 if (const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
1800 for (const auto *ChildStmt : CS->children()) {
1801 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
1802 if (ChildStmtLoc.isValid())
1803 return ChildStmtLoc;
1804 }
1805 // Empty/not invalid compound statements are legal.
1806 return SourceLocation{};
1807 }
1808 return CurStmt->getBeginLoc();
1809}
1810} // namespace
1811
1813 if (!getLangOpts().OpenACC)
1814 return;
1815
1816 // Set this to 'true' so if we find another one at this level we can diagnose.
1817 LoopInfo.CurLevelHasLoopAlready = true;
1818
1819 if (!Body.isUsable())
1820 return;
1821
1822 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1823 *CollapseInfo.CurCollapseCount > 0 &&
1824 !CollapseInfo.ActiveCollapse->hasForce();
1825 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1826
1827 if (IsActiveCollapse || IsActiveTile) {
1828 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());
1829
1830 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
1831 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1832 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
1833 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1834 diag::note_acc_active_clause_here)
1836 }
1837
1838 if (OtherStmtLoc.isValid() && IsActiveTile) {
1839 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1840 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
1841 Diag(TileInfo.ActiveTile->getBeginLoc(),
1842 diag::note_acc_active_clause_here)
1844 }
1845 }
1846}
1847
1848namespace {
1849// Helper that should mirror ActOnRoutineName to get the FunctionDecl out for
1850// magic-static checking.
1851FunctionDecl *getFunctionFromRoutineName(Expr *RoutineName) {
1852 if (!RoutineName)
1853 return nullptr;
1854 RoutineName = RoutineName->IgnoreParenImpCasts();
1855 if (isa<RecoveryExpr>(RoutineName)) {
1856 // There is nothing we can do here, this isn't a function we can count on.
1857 return nullptr;
1859 RoutineName)) {
1860 // The lookup is dependent, so we'll have to figure this out later.
1861 return nullptr;
1862 } else if (auto *DRE = dyn_cast<DeclRefExpr>(RoutineName)) {
1863 ValueDecl *VD = DRE->getDecl();
1864
1865 if (auto *FD = dyn_cast<FunctionDecl>(VD))
1866 return FD;
1867
1868 // Allow lambdas.
1869 if (auto *VarD = dyn_cast<VarDecl>(VD)) {
1870 QualType VarDTy = VarD->getType();
1871 if (!VarDTy.isNull()) {
1872 if (auto *RD = VarDTy->getAsCXXRecordDecl()) {
1873 if (RD->isGenericLambda())
1874 return nullptr;
1875 if (RD->isLambda())
1876 return RD->getLambdaCallOperator();
1877 } else if (VarDTy->isDependentType()) {
1878 // We don't really know what this is going to be.
1879 return nullptr;
1880 }
1881 }
1882 return nullptr;
1883 } else if (isa<OverloadExpr>(RoutineName)) {
1884 return nullptr;
1885 }
1886 }
1887 return nullptr;
1888}
1889} // namespace
1890
1892 assert(RoutineName && "Routine name cannot be null here");
1893 RoutineName = RoutineName->IgnoreParenImpCasts();
1894
1895 if (isa<RecoveryExpr>(RoutineName)) {
1896 // This has already been diagnosed, so we can skip it.
1897 return ExprError();
1899 RoutineName)) {
1900 // These are dependent and we can't really check them, so delay until
1901 // instantiation.
1902 return RoutineName;
1903 } else if (const auto *DRE = dyn_cast<DeclRefExpr>(RoutineName)) {
1904 const ValueDecl *VD = DRE->getDecl();
1905
1906 if (isa<FunctionDecl>(VD))
1907 return RoutineName;
1908
1909 // Allow lambdas.
1910 if (const auto *VarD = dyn_cast<VarDecl>(VD)) {
1911 QualType VarDTy = VarD->getType();
1912 if (!VarDTy.isNull()) {
1913 if (const auto *RD = VarDTy->getAsCXXRecordDecl()) {
1914 if (RD->isGenericLambda()) {
1915 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1916 << RoutineName;
1917 return ExprError();
1918 }
1919 if (RD->isLambda())
1920 return RoutineName;
1921 } else if (VarDTy->isDependentType()) {
1922 // If this is a dependent variable, it might be a lambda. So we just
1923 // accept this and catch it next time.
1924 return RoutineName;
1925 }
1926 }
1927 }
1928
1929 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1930 << RoutineName;
1931 return ExprError();
1932 } else if (isa<OverloadExpr>(RoutineName)) {
1933 // This happens in function templates, even when the template arguments are
1934 // fully specified. We could possibly do some sort of matching to make sure
1935 // that this is looked up/deduced, but GCC does not do this, so there
1936 // doesn't seem to be a good reason for us to do it either.
1937 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1938 << RoutineName;
1939 return ExprError();
1940 }
1941
1942 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1943 << RoutineName;
1944 return ExprError();
1945}
1947 if (!getLangOpts().OpenACC || VD->isInvalidDecl() || !VD->isStaticLocal())
1948 return;
1949
1950 // This cast should be safe, since a static-local can only happen in a
1951 // function declaration. However, in error cases (or perhaps ObjC/C++?), this
1952 // could possibly be something like a 'block' decl, so if this is NOT a
1953 // function decl, just give up.
1954 auto *ContextDecl = dyn_cast<FunctionDecl>(getCurContext());
1955
1956 if (!ContextDecl)
1957 return;
1958
1959 // OpenACC 3.3 2.15:
1960 // In C and C++, function static variables are not supported in functions to
1961 // which a routine directive applies.
1962 for (const auto *A : ContextDecl->attrs()) {
1964 Diag(VD->getBeginLoc(), diag::err_acc_magic_static_in_routine);
1965 Diag(A->getLocation(), diag::note_acc_construct_here)
1967 return;
1968 }
1969 }
1970
1971 MagicStaticLocs.insert({ContextDecl->getCanonicalDecl(), VD->getBeginLoc()});
1972}
1973void SemaOpenACC::CheckLastRoutineDeclNameConflict(const NamedDecl *ND) {
1974 // OpenACC 3.3 A.3.4
1975 // When a procedure with that name is in scope and it is not the same
1976 // procedure as the immediately following procedure declaration or
1977 // definition, the resolution of the name can be confusing. Implementations
1978 // should then issue a compile-time warning diagnostic even though the
1979 // application is conforming.
1980
1981 // If we haven't created one, also can't diagnose.
1982 if (!LastRoutineDecl)
1983 return;
1984
1985 // If the currently created function doesn't have a name, we can't diagnose on
1986 // a match.
1987 if (!ND->getDeclName().isIdentifier())
1988 return;
1989
1990 // If the two are in different decl contexts, it doesn't make sense to
1991 // diagnose.
1992 if (LastRoutineDecl->getDeclContext() != ND->getLexicalDeclContext())
1993 return;
1994
1995 // If we don't have a referenced thing yet, we can't diagnose.
1996 FunctionDecl *RoutineTarget =
1997 getFunctionFromRoutineName(LastRoutineDecl->getFunctionReference());
1998 if (!RoutineTarget)
1999 return;
2000
2001 // If the Routine target doesn't have a name, we can't diagnose.
2002 if (!RoutineTarget->getDeclName().isIdentifier())
2003 return;
2004
2005 // Of course don't diagnose if the names don't match.
2006 if (ND->getName() != RoutineTarget->getName())
2007 return;
2008
2010 long LastLine =
2012
2013 // Do some line-number math to make sure they are within a line of eachother.
2014 // Comments or newlines can be inserted to clarify intent.
2015 if (NDLine - LastLine > 1)
2016 return;
2017
2018 // Don't warn if it actually DOES apply to this function via redecls.
2019 if (ND->getCanonicalDecl() == RoutineTarget->getCanonicalDecl())
2020 return;
2021
2022 Diag(LastRoutineDecl->getFunctionReference()->getBeginLoc(),
2023 diag::warn_acc_confusing_routine_name);
2024 Diag(RoutineTarget->getBeginLoc(), diag::note_previous_decl) << ND;
2025}
2026
2028 if (!VD || !getLangOpts().OpenACC || InitType.isNull())
2029 return;
2030
2031 // To avoid double-diagnostic, just diagnose this during instantiation. We'll
2032 // get 1 warning per instantiation, but this permits us to be more sensible
2033 // for cases where the lookup is confusing.
2035 return;
2036
2037 const auto *RD = InitType->getAsCXXRecordDecl();
2038 // If this isn't a lambda, no sense in diagnosing.
2039 if (!RD || !RD->isLambda())
2040 return;
2041
2042 CheckLastRoutineDeclNameConflict(VD);
2043}
2044
2046 if (!FD || !getLangOpts().OpenACC)
2047 return;
2048 CheckLastRoutineDeclNameConflict(FD);
2049}
2050
2054
2055 // Declaration directives an appear in a statement location, so call into that
2056 // function here.
2058 return ActOnStartDeclDirective(K, StartLoc, Clauses);
2059
2060 SemaRef.DiscardCleanupsInEvaluationContext();
2061 SemaRef.PopExpressionEvaluationContext();
2062
2063 // OpenACC 3.3 2.9.1:
2064 // Intervening code must not contain other OpenACC directives or calls to API
2065 // routines.
2066 //
2067 // ALL constructs are ill-formed if there is an active 'collapse'
2068 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
2069 Diag(StartLoc, diag::err_acc_invalid_in_loop)
2070 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
2072 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2073 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2074 diag::note_acc_active_clause_here)
2076 }
2077 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
2078 Diag(StartLoc, diag::err_acc_invalid_in_loop)
2079 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
2081 assert(TileInfo.ActiveTile && "Tile count without object?");
2082 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
2084 }
2085
2086 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
2087 return true;
2088 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
2089}
2090
2093 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
2094 OpenACCAtomicKind AtomicKind, SourceLocation RParenLoc,
2096 StmtResult AssocStmt) {
2097 switch (K) {
2099 return StmtError();
2103 return OpenACCComputeConstruct::Create(
2104 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
2105 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2106 }
2111 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
2112 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2113 }
2116 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
2117 EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2118 }
2121 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
2122 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2123 }
2125 return OpenACCEnterDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
2126 EndLoc, Clauses);
2127 }
2129 return OpenACCExitDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
2130 EndLoc, Clauses);
2131 }
2134 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
2135 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2136 }
2139 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
2140 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
2141 }
2143 return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc,
2144 EndLoc, Clauses);
2145 }
2147 return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
2148 EndLoc, Clauses);
2149 }
2151 return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
2152 EndLoc, Clauses);
2153 }
2155 return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
2156 EndLoc, Clauses);
2157 }
2160 getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc, Clauses,
2161 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2162 }
2164 assert(Clauses.empty() && "Cache doesn't allow clauses");
2165 return OpenACCCacheConstruct::Create(getASTContext(), StartLoc, DirLoc,
2166 LParenLoc, MiscLoc, Exprs, RParenLoc,
2167 EndLoc);
2168 }
2170 llvm_unreachable("routine shouldn't handled here");
2172 // Declare and routine arei declaration directives, but can be used here as
2173 // long as we wrap it in a DeclStmt. So make sure we do that here.
2174 DeclGroupRef DR = ActOnEndDeclDirective(K, StartLoc, DirLoc, LParenLoc,
2175 RParenLoc, EndLoc, Clauses);
2176
2177 return SemaRef.ActOnDeclStmt(DeclGroupPtrTy::make(DR), StartLoc, EndLoc);
2178 }
2179 }
2180 llvm_unreachable("Unhandled case in directive handling?");
2181}
2182
2184 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
2186 StmtResult AssocStmt) {
2187 switch (K) {
2188 default:
2189 llvm_unreachable("Unimplemented associated statement application");
2197 llvm_unreachable(
2198 "these don't have associated statements, so shouldn't get here");
2200 return CheckAtomicAssociatedStmt(DirectiveLoc, AtKind, AssocStmt);
2206 // There really isn't any checking here that could happen. As long as we
2207 // have a statement to associate, this should be fine.
2208 // OpenACC 3.3 Section 6:
2209 // Structured Block: in C or C++, an executable statement, possibly
2210 // compound, with a single entry at the top and a single exit at the
2211 // bottom.
2212 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
2213 // an interpretation of it is to allow this and treat the initializer as
2214 // the 'structured block'.
2215 return AssocStmt;
2220 if (!AssocStmt.isUsable())
2221 return StmtError();
2222
2223 if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
2224 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
2225 << K;
2226 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
2227 return StmtError();
2228 }
2229
2230 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
2231 if (!CollapseInfo.CollapseDepthSatisfied) {
2232 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2234 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2235 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2236 diag::note_acc_active_clause_here)
2238 }
2239
2240 if (!TileInfo.TileDepthSatisfied) {
2241 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2243 assert(TileInfo.ActiveTile && "Collapse count without object?");
2244 Diag(TileInfo.ActiveTile->getBeginLoc(),
2245 diag::note_acc_active_clause_here)
2247 }
2248 return StmtError();
2249 }
2250
2251 return AssocStmt.get();
2252 }
2253 llvm_unreachable("Invalid associated statement application");
2254}
2255
2256namespace {
2257
2258// Routine has some pretty complicated set of rules for how device_type
2259// interacts with 'gang', 'worker', 'vector', and 'seq'. Enforce part of it
2260// here.
2261bool CheckValidRoutineGangWorkerVectorSeqClauses(
2262 SemaOpenACC &SemaRef, SourceLocation DirectiveLoc,
2264 auto RequiredPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
2266 // The clause handling has assured us that there is no duplicates. That is,
2267 // if there is 1 before a device_type, there are none after a device_type.
2268 // If not, there is at most 1 applying to each device_type.
2269
2270 // What is left to legalize is that either:
2271 // 1- there is 1 before the first device_type.
2272 // 2- there is 1 AFTER each device_type.
2273 auto *FirstDeviceType =
2274 llvm::find_if(Clauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
2275
2276 // If there is 1 before the first device_type (or at all if no device_type),
2277 // we are legal.
2278 auto *ClauseItr =
2279 std::find_if(Clauses.begin(), FirstDeviceType, RequiredPred);
2280
2281 if (ClauseItr != FirstDeviceType)
2282 return false;
2283
2284 // If there IS no device_type, and no clause, diagnose.
2285 if (FirstDeviceType == Clauses.end())
2286 return SemaRef.Diag(DirectiveLoc, diag::err_acc_construct_one_clause_of)
2288 << "'gang', 'seq', 'vector', or 'worker'";
2289
2290 // Else, we have to check EACH device_type group. PrevDeviceType is the
2291 // device-type before the current group.
2292 auto *PrevDeviceType = FirstDeviceType;
2293
2294 while (PrevDeviceType != Clauses.end()) {
2295 auto *NextDeviceType =
2296 std::find_if(std::next(PrevDeviceType), Clauses.end(),
2297 llvm::IsaPred<OpenACCDeviceTypeClause>);
2298
2299 ClauseItr = std::find_if(PrevDeviceType, NextDeviceType, RequiredPred);
2300
2301 if (ClauseItr == NextDeviceType)
2302 return SemaRef.Diag((*PrevDeviceType)->getBeginLoc(),
2303 diag::err_acc_clause_routine_one_of_in_region);
2304
2305 PrevDeviceType = NextDeviceType;
2306 }
2307
2308 return false;
2309}
2310} // namespace
2311
2315 // OpenCC3.3 2.1 (line 889)
2316 // A program must not depend on the order of evaluation of expressions in
2317 // clause arguments or on any side effects of the evaluations.
2318 SemaRef.DiscardCleanupsInEvaluationContext();
2319 SemaRef.PopExpressionEvaluationContext();
2320
2321 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
2322 return true;
2324 CheckValidRoutineGangWorkerVectorSeqClauses(*this, StartLoc, Clauses))
2325 return true;
2326
2327 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
2328}
2329
2332 SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc,
2333 ArrayRef<OpenACCClause *> Clauses) {
2334 switch (K) {
2335 default:
2337 return DeclGroupRef{};
2339 // OpenACC3.3 2.13: At least one clause must appear on a declare directive.
2340 if (Clauses.empty()) {
2341 Diag(EndLoc, diag::err_acc_declare_required_clauses);
2342 // No reason to add this to the AST, as we would just end up trying to
2343 // instantiate this, which would double-diagnose here, which we wouldn't
2344 // want to do.
2345 return DeclGroupRef{};
2346 }
2347
2348 auto *DeclareDecl = OpenACCDeclareDecl::Create(
2349 getASTContext(), getCurContext(), StartLoc, DirLoc, EndLoc, Clauses);
2350 DeclareDecl->setAccess(AS_public);
2351 getCurContext()->addDecl(DeclareDecl);
2352 return DeclGroupRef{DeclareDecl};
2353 }
2355 llvm_unreachable("routine shouldn't be handled here");
2356 }
2357 llvm_unreachable("unhandled case in directive handling?");
2358}
2359
2360namespace {
2361// Given the decl on the next line, figure out if it is one that is acceptable
2362// to `routine`, or looks like the sort of decl we should be diagnosing against.
2363FunctionDecl *LegalizeNextParsedDecl(Decl *D) {
2364 if (!D)
2365 return nullptr;
2366
2367 // Functions are per-fact acceptable as-is.
2368 if (auto *FD = dyn_cast<FunctionDecl>(D))
2369 return FD;
2370
2371 // Function templates are functions, so attach to the templated decl.
2372 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
2373 return FTD->getTemplatedDecl();
2374
2375 if (auto *FD = dyn_cast<FieldDecl>(D)) {
2376 auto *RD =
2377 FD->getType().isNull() ? nullptr : FD->getType()->getAsCXXRecordDecl();
2378
2379 if (RD && RD->isGenericLambda())
2380 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2381 if (RD && RD->isLambda())
2382 return RD->getLambdaCallOperator();
2383 }
2384 // VarDecl we can look at the init instead of the type of the variable, this
2385 // makes us more tolerant of the 'auto' deduced type.
2386 if (auto *VD = dyn_cast<VarDecl>(D)) {
2387 Expr *Init = VD->getInit();
2388 if (!Init || Init->getType().isNull())
2389 return nullptr;
2390
2391 const auto *RD = Init->getType()->getAsCXXRecordDecl();
2392 if (RD && RD->isGenericLambda())
2393 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2394 if (RD && RD->isLambda())
2395 return RD->getLambdaCallOperator();
2396
2397 // FIXME: We could try harder in the case where this is a dependent thing
2398 // that ends up being a lambda (that is, the init is an unresolved lookup
2399 // expr), but we can't attach to the call/lookup expr. If we instead try to
2400 // attach to the VarDecl, when we go to instantiate it, attributes are
2401 // instantiated before the init, so we can't actually see the type at any
2402 // point where it would be relevant/able to be checked. We could perhaps do
2403 // some sort of 'after-init' instantiation/checking here, but that doesn't
2404 // seem valuable for a situation that other compilers don't handle.
2405 }
2406 return nullptr;
2407}
2408
2409void CreateRoutineDeclAttr(SemaOpenACC &SemaRef, SourceLocation DirLoc,
2410 ArrayRef<const OpenACCClause *> Clauses,
2411 ValueDecl *AddTo) {
2412 OpenACCRoutineDeclAttr *A =
2413 OpenACCRoutineDeclAttr::Create(SemaRef.getASTContext(), DirLoc);
2414 A->Clauses.assign(Clauses.begin(), Clauses.end());
2415 AddTo->addAttr(A);
2416}
2417} // namespace
2418
2419// Variant that adds attributes, because this is the unnamed case.
2422 Decl *NextParsedDecl) {
2423
2424 FunctionDecl *NextParsedFDecl = LegalizeNextParsedDecl(NextParsedDecl);
2425
2426 if (!NextParsedFDecl) {
2427 // If we don't have a valid 'next thing', just diagnose.
2428 SemaRef.Diag(DirLoc, diag::err_acc_decl_for_routine);
2429 return;
2430 }
2431
2432 // OpenACC 3.3 2.15:
2433 // In C and C++, function static variables are not supported in functions to
2434 // which a routine directive applies.
2435 if (auto Itr = MagicStaticLocs.find(NextParsedFDecl->getCanonicalDecl());
2436 Itr != MagicStaticLocs.end()) {
2437 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2438 Diag(DirLoc, diag::note_acc_construct_here)
2440
2441 return;
2442 }
2443
2444 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
2445 if (BindItr != Clauses.end()) {
2446 for (auto *A : NextParsedFDecl->attrs()) {
2447 // OpenACC 3.3 2.15:
2448 // If a procedure has a bind clause on both the declaration and definition
2449 // than they both must bind to the same name.
2450 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2451 auto OtherBindItr =
2452 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2453 if (OtherBindItr != RA->Clauses.end() &&
2454 (*cast<OpenACCBindClause>(*BindItr)) !=
2455 (*cast<OpenACCBindClause>(*OtherBindItr))) {
2456 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_unnamed_bind);
2457 Diag((*OtherBindItr)->getEndLoc(),
2458 diag::note_acc_previous_clause_here)
2459 << (*BindItr)->getClauseKind();
2460 return;
2461 }
2462 }
2463
2464 // OpenACC 3.3 2.15:
2465 // A bind clause may not bind to a routine name that has a visible bind
2466 // clause.
2467 // We take the combo of these two 2.15 restrictions to mean that the
2468 // 'declaration'/'definition' quote is an exception to this. So we're
2469 // going to disallow mixing of the two types entirely.
2470 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2471 RA && RA->getRange().getEnd().isValid()) {
2472 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2473 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2474 << "bind";
2475 return;
2476 }
2477 }
2478 }
2479
2480 CreateRoutineDeclAttr(*this, DirLoc, Clauses, NextParsedFDecl);
2481}
2482
2483// Variant that adds a decl, because this is the named case.
2485 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2486 Expr *FuncRef, SourceLocation RParenLoc,
2488 assert(LParenLoc.isValid());
2489
2490 FunctionDecl *FD = nullptr;
2491 if ((FD = getFunctionFromRoutineName(FuncRef))) {
2492 // OpenACC 3.3 2.15:
2493 // In C and C++, function static variables are not supported in functions to
2494 // which a routine directive applies.
2495 if (auto Itr = MagicStaticLocs.find(FD->getCanonicalDecl());
2496 Itr != MagicStaticLocs.end()) {
2497 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2498 Diag(DirLoc, diag::note_acc_construct_here)
2500
2501 return nullptr;
2502 }
2503
2504 // OpenACC 3.3 2.15:
2505 // A bind clause may not bind to a routine name that has a visible bind
2506 // clause.
2507 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
2508 SourceLocation BindLoc;
2509 if (BindItr != Clauses.end()) {
2510 BindLoc = (*BindItr)->getBeginLoc();
2511 // Since this is adding a 'named' routine, we aren't allowed to combine
2512 // with ANY other visible bind clause. Error if we see either.
2513
2514 for (auto *A : FD->attrs()) {
2515 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2516 auto OtherBindItr =
2517 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2518 if (OtherBindItr != RA->Clauses.end()) {
2519 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2520 Diag((*OtherBindItr)->getEndLoc(),
2521 diag::note_acc_previous_clause_here)
2522 << (*BindItr)->getClauseKind();
2523 return nullptr;
2524 }
2525 }
2526
2527 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2528 RA && RA->getRange().getEnd().isValid()) {
2529 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2530 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2531 << (*BindItr)->getClauseKind();
2532 return nullptr;
2533 }
2534 }
2535 }
2536
2537 // Set the end-range to the 'bind' clause here, so we can look it up
2538 // later.
2539 auto *RAA = OpenACCRoutineAnnotAttr::CreateImplicit(getASTContext(),
2540 {DirLoc, BindLoc});
2541 FD->addAttr(RAA);
2542 // In case we are referencing not the 'latest' version, make sure we add
2543 // the attribute to all declarations after the 'found' one.
2544 for (auto *CurFD : FD->redecls())
2545 CurFD->addAttr(RAA->clone(getASTContext()));
2546 }
2547
2548 LastRoutineDecl = OpenACCRoutineDecl::Create(
2549 getASTContext(), getCurContext(), StartLoc, DirLoc, LParenLoc, FuncRef,
2550 RParenLoc, EndLoc, Clauses);
2551 LastRoutineDecl->setAccess(AS_public);
2552 getCurContext()->addDecl(LastRoutineDecl);
2553
2554 if (FD) {
2555 // Add this attribute to the list of annotations so that codegen can visit
2556 // it later. FD doesn't necessarily exist, but that case should be
2557 // diagnosed.
2558 RoutineRefList.emplace_back(FD, LastRoutineDecl);
2559 }
2560 return LastRoutineDecl;
2561}
2562
2564 for (auto [FD, RoutineDecl] : RoutineRefList)
2565 SemaRef.Consumer.HandleOpenACCRoutineReference(FD, RoutineDecl);
2566}
2567
2569 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2570 Expr *ReferencedFunc, SourceLocation RParenLoc,
2572 DeclGroupPtrTy NextDecl) {
2573 assert((!ReferencedFunc || !NextDecl) &&
2574 "Only one of these should be filled");
2575
2576 if (LParenLoc.isInvalid()) {
2577 Decl *NextLineDecl = nullptr;
2578 if (NextDecl && NextDecl.get().isSingleDecl())
2579 NextLineDecl = NextDecl.get().getSingleDecl();
2580
2581 CheckRoutineDecl(DirLoc, Clauses, NextLineDecl);
2582
2583 return NextDecl.get();
2584 }
2585
2587 StartLoc, DirLoc, LParenLoc, ReferencedFunc, RParenLoc, Clauses, EndLoc)};
2588}
2589
2591 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2592 Expr *ReferencedFunc, SourceLocation RParenLoc,
2594 Stmt *NextStmt) {
2595 assert((!ReferencedFunc || !NextStmt) &&
2596 "Only one of these should be filled");
2597
2598 if (LParenLoc.isInvalid()) {
2599 Decl *NextLineDecl = nullptr;
2600 if (NextStmt)
2601 if (DeclStmt *DS = dyn_cast<DeclStmt>(NextStmt); DS && DS->isSingleDecl())
2602 NextLineDecl = DS->getSingleDecl();
2603
2604 CheckRoutineDecl(DirLoc, Clauses, NextLineDecl);
2605 return NextStmt;
2606 }
2607
2608 DeclGroupRef DR{CheckRoutineDecl(StartLoc, DirLoc, LParenLoc, ReferencedFunc,
2609 RParenLoc, Clauses, EndLoc)};
2610 return SemaRef.ActOnDeclStmt(DeclGroupPtrTy::make(DR), StartLoc, EndLoc);
2611}
2612
2613OpenACCRoutineDeclAttr *
2614SemaOpenACC::mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old) {
2615 OpenACCRoutineDeclAttr *New =
2616 OpenACCRoutineDeclAttr::Create(getASTContext(), Old.getLocation());
2617 // We should jsut be able to copy these, there isn't really any
2618 // merging/inheriting we have to do, so no worry about doing a deep copy.
2619 New->Clauses = Old.Clauses;
2620 return New;
2621}
2626
2631
2632namespace {
2633enum class InitKind { Invalid, Zero, One, AllOnes, Least, Largest };
2634llvm::APFloat getInitFloatValue(ASTContext &Context, InitKind IK, QualType Ty) {
2635 switch (IK) {
2636 case InitKind::Invalid:
2637 llvm_unreachable("invalid init kind");
2638 case InitKind::Zero:
2639 return llvm::APFloat::getZero(Context.getFloatTypeSemantics(Ty));
2640 case InitKind::One:
2641 return llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty));
2642 case InitKind::AllOnes:
2643 return llvm::APFloat::getAllOnesValue(Context.getFloatTypeSemantics(Ty));
2644 case InitKind::Least:
2645 return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty),
2646 /*Negative=*/true);
2647 case InitKind::Largest:
2648 return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty));
2649 }
2650 llvm_unreachable("unknown init kind");
2651}
2652
2653llvm::APInt getInitIntValue(ASTContext &Context, InitKind IK, QualType Ty) {
2654 switch (IK) {
2655 case InitKind::Invalid:
2656 llvm_unreachable("invalid init kind");
2657 case InitKind::Zero:
2658 return llvm::APInt(Context.getIntWidth(Ty), 0);
2659 case InitKind::One:
2660 return llvm::APInt(Context.getIntWidth(Ty), 1);
2661 case InitKind::AllOnes:
2662 return llvm::APInt::getAllOnes(Context.getIntWidth(Ty));
2663 case InitKind::Least:
2665 return llvm::APInt::getSignedMinValue(Context.getIntWidth(Ty));
2666 return llvm::APInt::getMinValue(Context.getIntWidth(Ty));
2667 case InitKind::Largest:
2669 return llvm::APInt::getSignedMaxValue(Context.getIntWidth(Ty));
2670 return llvm::APInt::getMaxValue(Context.getIntWidth(Ty));
2671 }
2672 llvm_unreachable("unknown init kind");
2673}
2674
2675/// Loops through a type and generates an appropriate InitListExpr to
2676/// generate type initialization.
2677Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
2678 SourceRange ExprRange, QualType Ty,
2679 InitKind IK) {
2680 if (IK == InitKind::Invalid)
2681 return nullptr;
2682
2683 if (IK == InitKind::Zero) {
2684 Expr *InitExpr =
2685 new (Context) InitListExpr(Context, ExprRange.getBegin(), {},
2686 ExprRange.getEnd(), /*isExplicit=*/false);
2687 InitExpr->setType(Context.VoidTy);
2688 return InitExpr;
2689 }
2690
2691 Ty = Ty.getCanonicalType();
2692 llvm::SmallVector<Expr *> Exprs;
2693
2694 if (const RecordDecl *RD = Ty->getAsRecordDecl()) {
2695 for (auto *F : RD->fields()) {
2696 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
2697 F->getType(), IK))
2698 Exprs.push_back(NewExpr);
2699 else
2700 return nullptr;
2701 }
2702 } else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
2703 for (uint64_t Idx = 0; Idx < AT->getZExtSize(); ++Idx) {
2704 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(
2705 Context, ExprRange, AT->getElementType(), IK))
2706 Exprs.push_back(NewExpr);
2707 else
2708 return nullptr;
2709 }
2710
2711 } else if (Ty->isPointerType()) {
2712 // For now, we are going to punt/not initialize pointer types, as
2713 // discussions/designs are ongoing on how to express this behavior,
2714 // particularly since they probably need the 'bounds' passed to them
2715 // correctly. A future patch/patch set will go through all of the pointer
2716 // values for all of the recipes to make sure we have a sane behavior.
2717
2718 // For now, this will result in a NYI during code generation for
2719 // no-initializer.
2720 return nullptr;
2721 } else {
2722 assert(Ty->isScalarType());
2723
2724 if (const auto *Cplx = Ty->getAs<ComplexType>()) {
2725 // we can get here in error cases, so make sure we generate something that
2726 // will work if we find ourselves wanting to enable this, so emit '0,0'
2727 // for both ints and floats.
2728
2729 QualType EltTy = Cplx->getElementType();
2730 if (EltTy->isFloatingType()) {
2731 Exprs.push_back(FloatingLiteral::Create(
2732 Context, getInitFloatValue(Context, InitKind::Zero, EltTy),
2733 /*isExact=*/true, EltTy, ExprRange.getBegin()));
2734 Exprs.push_back(FloatingLiteral::Create(
2735 Context, getInitFloatValue(Context, InitKind::Zero, EltTy),
2736 /*isExact=*/true, EltTy, ExprRange.getBegin()));
2737 } else {
2738 Exprs.push_back(IntegerLiteral::Create(
2739 Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,
2740 ExprRange.getBegin()));
2741 Exprs.push_back(IntegerLiteral::Create(
2742 Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,
2743 ExprRange.getBegin()));
2744 }
2745
2746 } else if (Ty->isFloatingType()) {
2747 Exprs.push_back(
2748 FloatingLiteral::Create(Context, getInitFloatValue(Context, IK, Ty),
2749 /*isExact=*/true, Ty, ExprRange.getBegin()));
2750 } else if (Ty->isBooleanType()) {
2751 Exprs.push_back(CXXBoolLiteralExpr::Create(Context,
2752 (IK == InitKind::One ||
2753 IK == InitKind::AllOnes ||
2754 IK == InitKind::Largest),
2755 Ty, ExprRange.getBegin()));
2756 } else if (Ty->isNullPtrType()) {
2757 Exprs.push_back(new (Context)
2758 CXXNullPtrLiteralExpr(Ty, ExprRange.getBegin()));
2759 } else {
2760 Exprs.push_back(IntegerLiteral::Create(
2761 Context, getInitIntValue(Context, IK, Ty), Ty, ExprRange.getBegin()));
2762 }
2763 }
2764
2765 Expr *InitExpr =
2766 new (Context) InitListExpr(Context, ExprRange.getBegin(), Exprs,
2767 ExprRange.getEnd(), /*isExplicit=*/false);
2768 InitExpr->setType(Ty);
2769 return InitExpr;
2770}
2771
2772VarDecl *CreateAllocaDecl(ASTContext &Ctx, DeclContext *DC,
2773 SourceLocation BeginLoc, IdentifierInfo *VarName,
2774 QualType VarTy) {
2775 auto *VD = VarDecl::Create(Ctx, DC, BeginLoc, BeginLoc, VarName, VarTy,
2776 Ctx.getTrivialTypeSourceInfo(VarTy), SC_Auto);
2777 VD->markUsed(Ctx);
2778 return VD;
2779}
2780
2781ExprResult FinishValueInit(Sema &S, InitializedEntity &Entity,
2782 SourceLocation Loc, QualType VarTy, Expr *InitExpr) {
2783 if (!InitExpr)
2784 return ExprEmpty();
2785
2786 InitializationKind Kind =
2787 InitializationKind::CreateForInit(Loc, /*DirectInit=*/true, InitExpr);
2788 InitializationSequence InitSeq(S, Entity, Kind, InitExpr,
2789 /*TopLevelOfInitList=*/false,
2790 /*TreatUnavailableAsInvalid=*/false);
2791
2792 return InitSeq.Perform(S, Entity, Kind, InitExpr, &VarTy);
2793}
2794
2795} // namespace
2796
2798 // We don't strip bounds here, so that we are doing our recipe init at the
2799 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2800 if (!VarExpr || VarExpr->getType()->isDependentType())
2802
2803 QualType VarTy =
2805
2806 // Array sections are special, and we have to treat them that way.
2807 if (const auto *ASE =
2808 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2809 VarTy = ASE->getElementType();
2810
2811 VarDecl *AllocaDecl = CreateAllocaDecl(
2812 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2813 &getASTContext().Idents.get("openacc.private.init"), VarTy);
2814
2817 InitializationKind Kind =
2819 InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
2820 ExprResult Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
2821
2822 // For 'no bounds' version, we can use this as a shortcut, so set the init
2823 // anyway.
2824 if (Init.isUsable()) {
2825 AllocaDecl->setInit(Init.get());
2826 AllocaDecl->setInitStyle(VarDecl::CallInit);
2827 }
2828
2829 return OpenACCPrivateRecipe(AllocaDecl);
2830}
2831
2834 // We don't strip bounds here, so that we are doing our recipe init at the
2835 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2836 if (!VarExpr || VarExpr->getType()->isDependentType())
2838
2839 QualType VarTy =
2841
2842 // Array sections are special, and we have to treat them that way.
2843 if (const auto *ASE =
2844 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2845 VarTy = ASE->getElementType();
2846
2847 VarDecl *AllocaDecl = CreateAllocaDecl(
2848 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2849 &getASTContext().Idents.get("openacc.firstprivate.init"), VarTy);
2850
2851 VarDecl *Temporary = CreateAllocaDecl(
2852 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2853 &getASTContext().Idents.get("openacc.temp"), VarTy);
2854
2855 auto *TemporaryDRE = DeclRefExpr::Create(
2857 /*ReferstoEnclosingVariableOrCapture=*/false,
2859 VarExpr->getBeginLoc()},
2860 VarTy, clang::VK_LValue, Temporary, nullptr, NOUR_None);
2861
2864
2865 const auto *ArrTy = getASTContext().getAsConstantArrayType(VarTy);
2866 if (!ArrTy) {
2867 ExprResult Init = FinishValueInit(
2868 SemaRef.SemaRef, Entity, VarExpr->getBeginLoc(), VarTy, TemporaryDRE);
2869
2870 // For 'no bounds' version, we can use this as a shortcut, so set the init
2871 // anyway.
2872 if (Init.isUsable()) {
2873 AllocaDecl->setInit(Init.get());
2874 AllocaDecl->setInitStyle(VarDecl::CallInit);
2875 }
2876 return OpenACCFirstPrivateRecipe(AllocaDecl, Temporary);
2877 }
2878
2879 // Arrays need to have each individual element initialized as there
2880 // isn't a normal 'equals' feature in C/C++. This section sets these up
2881 // as an init list after 'initializing' each individual element.
2883 // Decay to pointer for the array subscript expression.
2884 auto *CastToPtr = ImplicitCastExpr::Create(
2885 getASTContext(), getASTContext().getPointerType(ArrTy->getElementType()),
2886 CK_ArrayToPointerDecay, TemporaryDRE, /*BasePath=*/nullptr,
2888
2889 for (std::size_t I = 0; I < ArrTy->getLimitedSize(); ++I) {
2890 // Each element needs to be some sort of copy initialization from an
2891 // array-index of the original temporary (referenced via a
2892 // DeclRefExpr).
2893 auto *Idx = IntegerLiteral::Create(
2894 getASTContext(),
2895 llvm::APInt(getASTContext().getTypeSize(getASTContext().getSizeType()),
2896 I),
2897 getASTContext().getSizeType(), VarExpr->getBeginLoc());
2898
2899 Expr *Subscript = new (getASTContext()) ArraySubscriptExpr(
2900 CastToPtr, Idx, ArrTy->getElementType(), clang::VK_LValue, OK_Ordinary,
2901 VarExpr->getBeginLoc());
2902 // Generate a simple copy from the result of the subscript. This will
2903 // do a bitwise copy or a copy-constructor, as necessary.
2904 InitializedEntity CopyEntity =
2906 InitializationKind CopyKind =
2908 InitializationSequence CopySeq(SemaRef.SemaRef, CopyEntity, CopyKind,
2909 Subscript,
2910 /*TopLevelOfInitList=*/true);
2911 ExprResult ElemRes =
2912 CopySeq.Perform(SemaRef.SemaRef, CopyEntity, CopyKind, Subscript);
2913 Args.push_back(ElemRes.get());
2914 }
2915
2916 Expr *InitExpr = new (getASTContext())
2917 InitListExpr(getASTContext(), VarExpr->getBeginLoc(), Args,
2918 VarExpr->getEndLoc(), /*isExplicit=*/false);
2919 InitExpr->setType(VarTy);
2920
2921 ExprResult Init = FinishValueInit(SemaRef.SemaRef, Entity,
2922 VarExpr->getBeginLoc(), VarTy, InitExpr);
2923
2924 // For 'no bounds' version, we can use this as a shortcut, so set the init
2925 // anyway.
2926 if (Init.isUsable()) {
2927 AllocaDecl->setInit(Init.get());
2928 AllocaDecl->setInitStyle(VarDecl::CallInit);
2929 }
2930
2931 return OpenACCFirstPrivateRecipe(AllocaDecl, Temporary);
2932}
2933
2935 OpenACCReductionOperator ReductionOperator, const Expr *VarExpr) {
2936 // We don't strip bounds here, so that we are doing our recipe init at the
2937 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2938 if (!VarExpr || VarExpr->getType()->isDependentType())
2940
2941 QualType VarTy =
2943
2944 // Array sections are special, and we have to treat them that way.
2945 if (const auto *ASE =
2946 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2947 VarTy = ASE->getElementType();
2948
2950
2951 // We use the 'set-ness' of the alloca-decl to determine whether the combiner
2952 // is 'set' or not, so we can skip any attempts at it if we're going to fail
2953 // at any of the combiners.
2954 if (CreateReductionCombinerRecipe(VarExpr->getBeginLoc(), ReductionOperator,
2955 VarTy, CombinerRecipes))
2957
2958 VarDecl *AllocaDecl = CreateAllocaDecl(
2959 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2960 &getASTContext().Idents.get("openacc.reduction.init"), VarTy);
2961
2964
2965 InitKind IK = InitKind::Invalid;
2966 switch (ReductionOperator) {
2968 // This can only happen when there is an error, and since these inits
2969 // are used for code generation, we can just ignore/not bother doing any
2970 // initialization here.
2971 IK = InitKind::Invalid;
2972 break;
2974 IK = InitKind::Least;
2975 break;
2977 IK = InitKind::Largest;
2978 break;
2980 IK = InitKind::AllOnes;
2981 break;
2984 IK = InitKind::One;
2985 break;
2990 IK = InitKind::Zero;
2991 break;
2992 }
2993
2994 Expr *InitExpr = GenerateReductionInitRecipeExpr(
2995 getASTContext(), VarExpr->getSourceRange(), VarTy, IK);
2996
2997 ExprResult Init = FinishValueInit(SemaRef.SemaRef, Entity,
2998 VarExpr->getBeginLoc(), VarTy, InitExpr);
2999
3000 // For 'no bounds' version, we can use this as a shortcut, so set the init
3001 // anyway.
3002 if (Init.isUsable()) {
3003 AllocaDecl->setInit(Init.get());
3004 AllocaDecl->setInitStyle(VarDecl::CallInit);
3005 }
3006
3007 return OpenACCReductionRecipeWithStorage(AllocaDecl, CombinerRecipes);
3008}
3009
3010bool SemaOpenACC::CreateReductionCombinerRecipe(
3011 SourceLocation Loc, OpenACCReductionOperator ReductionOperator,
3012 QualType VarTy,
3014 &CombinerRecipes) {
3015 // Now we can try to generate the 'combiner' recipe. This is a little
3016 // complicated in that if the 'VarTy' is an array type, we want to take its
3017 // element type so we can generate that. Additionally, if this is a struct,
3018 // we have two options: If there is overloaded operators, we want to take
3019 // THOSE, else we want to do the individual elements.
3020
3021 BinaryOperatorKind BinOp;
3022 switch (ReductionOperator) {
3024 // This can only happen when there is an error, and since these inits
3025 // are used for code generation, we can just ignore/not bother doing any
3026 // initialization here.
3027 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3028 return false;
3030 BinOp = BinaryOperatorKind::BO_AddAssign;
3031 break;
3033 BinOp = BinaryOperatorKind::BO_MulAssign;
3034 break;
3036 BinOp = BinaryOperatorKind::BO_AndAssign;
3037 break;
3039 BinOp = BinaryOperatorKind::BO_OrAssign;
3040 break;
3042 BinOp = BinaryOperatorKind::BO_XorAssign;
3043 break;
3044
3047 BinOp = BinaryOperatorKind::BO_LT;
3048 break;
3050 BinOp = BinaryOperatorKind::BO_LAnd;
3051 break;
3053 BinOp = BinaryOperatorKind::BO_LOr;
3054 break;
3055 }
3056
3057 // If VarTy is an array type, at the top level only, we want to do our
3058 // compares/decomp/etc at the element level.
3059 if (auto *AT = getASTContext().getAsArrayType(VarTy))
3060 VarTy = AT->getElementType();
3061
3062 assert(!VarTy->isArrayType() && "Only 1 level of array allowed");
3063
3064 enum class CombinerFailureKind {
3065 None = 0,
3066 BinOp = 1,
3067 Conditional = 2,
3068 Assignment = 3,
3069 };
3070
3071 auto genCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE)
3072 -> std::pair<ExprResult, CombinerFailureKind> {
3073 ExprResult BinOpRes =
3074 SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc, BinOp, LHSDRE, RHSDRE,
3075 /*ForFoldExpr=*/false);
3076 switch (ReductionOperator) {
3082 // These 5 are simple and are being done as compound operators, so we can
3083 // immediately quit here.
3084 return {BinOpRes, BinOpRes.isUsable() ? CombinerFailureKind::None
3085 : CombinerFailureKind::BinOp};
3088 // These are done as:
3089 // LHS = (LHS < RHS) ? LHS : RHS; and LHS = (LHS < RHS) ? RHS : LHS;
3090 //
3091 // The BinOpRes should have been created with the less-than, so we just
3092 // have to build the conditional and assignment.
3093 if (!BinOpRes.isUsable())
3094 return {BinOpRes, CombinerFailureKind::BinOp};
3095
3096 // Create the correct conditional operator, swapping the results
3097 // (true/false value) depending on min/max.
3098 ExprResult CondRes;
3099 if (ReductionOperator == OpenACCReductionOperator::Min)
3100 CondRes = SemaRef.ActOnConditionalOp(Loc, Loc, BinOpRes.get(), LHSDRE,
3101 RHSDRE);
3102 else
3103 CondRes = SemaRef.ActOnConditionalOp(Loc, Loc, BinOpRes.get(), RHSDRE,
3104 LHSDRE);
3105
3106 if (!CondRes.isUsable())
3107 return {CondRes, CombinerFailureKind::Conditional};
3108
3109 // Build assignment.
3110 ExprResult Assignment = SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc,
3111 BinaryOperatorKind::BO_Assign,
3112 LHSDRE, CondRes.get(),
3113 /*ForFoldExpr=*/false);
3114 return {Assignment, Assignment.isUsable()
3115 ? CombinerFailureKind::None
3116 : CombinerFailureKind::Assignment};
3117 }
3120 // These are done as LHS = LHS && RHS (or LHS = LHS || RHS). So after the
3121 // binop, all we have to do is the assignment.
3122 if (!BinOpRes.isUsable())
3123 return {BinOpRes, CombinerFailureKind::BinOp};
3124
3125 // Build assignment.
3126 ExprResult Assignment = SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc,
3127 BinaryOperatorKind::BO_Assign,
3128 LHSDRE, BinOpRes.get(),
3129 /*ForFoldExpr=*/false);
3130 return {Assignment, Assignment.isUsable()
3131 ? CombinerFailureKind::None
3132 : CombinerFailureKind::Assignment};
3133 }
3135 llvm_unreachable("Invalid should have been caught above");
3136 }
3137 llvm_unreachable("Unhandled case");
3138 };
3139
3140 auto tryCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE,
3141 bool IncludeTrap) {
3142 if (IncludeTrap) {
3143 // Trap all of the errors here, we'll emit our own at the end.
3144 Sema::TentativeAnalysisScope Trap{SemaRef};
3145 return genCombiner(LHSDRE, RHSDRE);
3146 }
3147 return genCombiner(LHSDRE, RHSDRE);
3148 };
3149
3150 struct CombinerAttemptTy {
3151 CombinerFailureKind FailKind;
3152 VarDecl *LHS;
3153 DeclRefExpr *LHSDRE;
3154 VarDecl *RHS;
3155 DeclRefExpr *RHSDRE;
3156 Expr *Op;
3157 };
3158
3159 auto formCombiner = [&, this](QualType Ty) -> CombinerAttemptTy {
3160 VarDecl *LHSDecl = CreateAllocaDecl(
3161 getASTContext(), SemaRef.getCurContext(), Loc,
3162 &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty);
3163 auto *LHSDRE = DeclRefExpr::Create(
3164 getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, LHSDecl,
3165 /*ReferstoEnclosingVariableOrCapture=*/false,
3166 DeclarationNameInfo{DeclarationName{LHSDecl->getDeclName()},
3167 LHSDecl->getBeginLoc()},
3168 Ty, clang::VK_LValue, LHSDecl, nullptr, NOUR_None);
3169 VarDecl *RHSDecl = CreateAllocaDecl(
3170 getASTContext(), SemaRef.getCurContext(), Loc,
3171 &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty);
3172 auto *RHSDRE = DeclRefExpr::Create(
3173 getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, RHSDecl,
3174 /*ReferstoEnclosingVariableOrCapture=*/false,
3175 DeclarationNameInfo{DeclarationName{RHSDecl->getDeclName()},
3176 RHSDecl->getBeginLoc()},
3177 Ty, clang::VK_LValue, RHSDecl, nullptr, NOUR_None);
3178
3179 std::pair<ExprResult, CombinerFailureKind> BinOpResult =
3180 tryCombiner(LHSDRE, RHSDRE, /*IncludeTrap=*/true);
3181
3182 return {BinOpResult.second, LHSDecl, LHSDRE, RHSDecl, RHSDRE,
3183 BinOpResult.first.get()};
3184 };
3185
3186 CombinerAttemptTy TopLevelCombinerInfo = formCombiner(VarTy);
3187
3188 if (TopLevelCombinerInfo.Op) {
3189 if (!TopLevelCombinerInfo.Op->containsErrors() &&
3190 TopLevelCombinerInfo.Op->isInstantiationDependent()) {
3191 // If this is instantiation dependent, we're just going to 'give up' here
3192 // and count on us to get it right during instantaition.
3193 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3194 return false;
3195 } else if (!TopLevelCombinerInfo.Op->containsErrors()) {
3196 // Else, we succeeded, we can just return this combiner.
3197 CombinerRecipes.push_back({TopLevelCombinerInfo.LHS,
3198 TopLevelCombinerInfo.RHS,
3199 TopLevelCombinerInfo.Op});
3200 return false;
3201 }
3202 }
3203
3204 auto EmitFailureNote = [&](CombinerFailureKind CFK) {
3205 if (CFK == CombinerFailureKind::BinOp)
3206 return Diag(Loc, diag::note_acc_reduction_combiner_forming)
3207 << CFK << BinaryOperator::getOpcodeStr(BinOp);
3208 return Diag(Loc, diag::note_acc_reduction_combiner_forming) << CFK;
3209 };
3210
3211 // Since the 'root' level didn't fail, the only thing that could be successful
3212 // is a struct that we decompose on its individual fields.
3213
3214 RecordDecl *RD = VarTy->getAsRecordDecl();
3215 if (!RD) {
3216 Diag(Loc, diag::err_acc_reduction_recipe_no_op) << VarTy;
3217 EmitFailureNote(TopLevelCombinerInfo.FailKind);
3218 tryCombiner(TopLevelCombinerInfo.LHSDRE, TopLevelCombinerInfo.RHSDRE,
3219 /*IncludeTrap=*/false);
3220 return true;
3221 }
3222
3223 for (const FieldDecl *FD : RD->fields()) {
3224 CombinerAttemptTy FieldCombinerInfo = formCombiner(FD->getType());
3225
3226 if (!FieldCombinerInfo.Op || FieldCombinerInfo.Op->containsErrors()) {
3227 Diag(Loc, diag::err_acc_reduction_recipe_no_op) << FD->getType();
3228 Diag(FD->getBeginLoc(), diag::note_acc_reduction_recipe_noop_field) << RD;
3229 EmitFailureNote(FieldCombinerInfo.FailKind);
3230 tryCombiner(FieldCombinerInfo.LHSDRE, FieldCombinerInfo.RHSDRE,
3231 /*IncludeTrap=*/false);
3232 return true;
3233 }
3234
3235 if (FieldCombinerInfo.Op->isInstantiationDependent()) {
3236 // If this is instantiation dependent, we're just going to 'give up' here
3237 // and count on us to get it right during instantaition.
3238 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3239 } else {
3240 CombinerRecipes.push_back(
3241 {FieldCombinerInfo.LHS, FieldCombinerInfo.RHS, FieldCombinerInfo.Op});
3242 }
3243 }
3244
3245 return false;
3246}
This file defines OpenACC nodes for declarative directives.
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.
This file declares semantic analysis for OpenACC constructs and clauses.
Defines the SourceManager interface.
This file defines OpenACC AST classes for statement-level contructs.
static OpenACCAtomicConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, OpenACCAtomicKind AtKind, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *AssociatedStmt)
static OpenACCCacheConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, SourceLocation ReadOnlyLoc, ArrayRef< Expr * > VarList, SourceLocation RParenLoc, SourceLocation End)
static OpenACCCombinedConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
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)
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)
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)
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 trap message and trap category.
APSInt & getInt()
Definition APValue.h:573
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
const ConstantArrayType * getAsConstantArrayType(QualType T) const
unsigned getIntWidth(QualType T) const
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType VoidTy
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
bool isUsable() const
Definition Ownership.h:169
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition Expr.h:7273
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5442
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2769
QualType getElementType() const
Definition TypeBase.h:3832
StringRef getOpcodeStr() const
Definition Expr.h:4152
static CXXBoolLiteralExpr * Create(const ASTContext &C, bool Val, QualType Ty, SourceLocation Loc)
Definition ExprCXX.h:740
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2977
base_class_range bases()
Definition DeclCXX.h:609
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
void addDecl(Decl *D)
Add the declaration D into this context.
Decl * getSingleDecl()
Definition DeclGroup.h:79
bool isSingleDecl() const
Definition DeclGroup.h:76
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:498
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1643
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition Stmt.h:1656
const Decl * getSingleDecl() const
Definition Stmt.h:1658
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
void addAttr(Attr *A)
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition DeclBase.cpp:594
bool isInvalidDecl() const
Definition DeclBase.h:596
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
attr_range attrs() const
Definition DeclBase.h:543
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:935
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:995
The name of a declaration.
bool isIdentifier() const
Predicate functions for querying what type of name this is.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:832
This represents one expression.
Definition Expr.h:113
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,...
void setType(QualType t)
Definition Expr.h:146
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:195
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3129
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition Expr.h:247
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:224
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:145
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Definition Expr.h:527
Represents difference between two FPOptions values.
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition Expr.cpp:1086
Represents a function declaration or definition.
Definition Decl.h:2059
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:3794
bool isDeleted() const
Whether this function has been deleted.
Definition Decl.h:2667
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2109
Describes an C or C++ initializer list.
Definition Expr.h:5356
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateDefault(SourceLocation InitLoc)
Create a default initialization.
static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init)
Create an initialization from an initializer (which, for direct initialization from a parenthesized l...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Describes an entity that is being initialized.
static InitializedEntity InitializeElement(ASTContext &Context, unsigned Index, const InitializedEntity &Parent)
Create the initialization entity for an array element.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition Expr.cpp:985
This represents a decl that may have a name.
Definition Decl.h:275
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:302
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:341
A C++ nested-name-specifier augmented with source location information.
PtrTy get() const
Definition Ownership.h:81
static OpaquePtr make(DeclGroupRef P)
Definition Ownership.h:61
static OpenACCAsteriskSizeExpr * Create(const ASTContext &C, SourceLocation Loc)
Definition Expr.cpp:5714
SourceLocation getBeginLoc() const
Represents a 'collapse' clause on a 'loop' construct.
const Expr * getLoopCount() const
static OpenACCDeclareDecl * Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCRoutineDecl * Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *FuncRef, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses)
const Expr * getFunctionReference() const
ArrayRef< Expr * > getSizeExprs() const
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8631
QualType getCanonicalType() const
Definition TypeBase.h:8498
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8540
field_range fields() const
Definition Decl.h:4667
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3678
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
unsigned getDepth() const
Returns the depth of this scope. The translation-unit has scope depth 0.
Definition Scope.h:325
bool isOpenACCLoopConstructScope() const
Definition Scope.h:554
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition Scope.h:384
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:280
A generic diagnostic builder for errors which may or may not be deferred.
Definition SemaBase.h:111
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
const LangOptions & getLangOpts() const
Definition SemaBase.cpp:11
DeclContext * getCurContext() const
Definition SemaBase.cpp:12
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
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 ActOnRoutineName(Expr *RoutineName)
OpenACCPrivateRecipe CreatePrivateInitRecipe(const Expr *VarExpr)
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
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 ActOnVariableDeclarator(VarDecl *VD)
Function called when a variable declarator is created, which lets us implement the 'routine' 'functio...
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)...
DeclGroupRef ActOnEndRoutineDeclDirective(SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *ReferencedFunc, SourceLocation RParenLoc, ArrayRef< const OpenACCClause * > Clauses, SourceLocation EndLoc, DeclGroupPtrTy NextDecl)
void ActOnInvalidParseVar()
Called only if the parse of a 'var' was invalid, else 'ActOnVar' should be called.
void CheckRoutineDecl(SourceLocation DirLoc, ArrayRef< const OpenACCClause * > Clauses, Decl *NextParsedDecl)
void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU)
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition SemaOpenACC.h:39
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 ActOnEndRoutineStmtDirective(SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *ReferencedFunc, SourceLocation RParenLoc, ArrayRef< const OpenACCClause * > Clauses, SourceLocation EndLoc, Stmt *NextStmt)
void CheckDeclReference(SourceLocation Loc, Expr *E, Decl *D)
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...
OpenACCRoutineDeclAttr * mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old)
void ActOnFunctionDeclarator(FunctionDecl *FD)
Called when a function decl is created, which lets us implement the 'routine' 'doesn't match next thi...
ExprResult ActOnCacheVar(Expr *VarExpr)
Helper function called by ActonVar that is used to check a 'cache' var.
struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo
DeclGroupRef ActOnEndDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses)
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)...
ExprResult ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, Expr *VarExpr)
Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...
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 ActOnVariableInit(VarDecl *VD, QualType InitType)
Called when a variable is initialized, so we can implement the 'routine 'doesn't match the next thing...
void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)
void ActOnStartParseVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK)
Called right before a 'var' is parsed, so we can set the state for parsing a 'cache' var.
OpenACCFirstPrivateRecipe CreateFirstPrivateInitRecipe(const Expr *VarExpr)
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.
OpenACCReductionRecipeWithStorage CreateReductionInitRecipe(OpenACCReductionOperator ReductionOperator, const Expr *VarExpr)
CXXMethodDecl * getMethod() const
Definition Sema.h:9468
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12717
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:863
@ Normal
Apply the normal rules for complete types.
Definition Sema.h:15355
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
Definition Sema.h:6882
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
SourceManager & SourceMgr
Definition Sema.h:1335
SpecialMemberOverloadResult LookupSpecialMember(CXXRecordDecl *D, CXXSpecialMemberKind SM, bool ConstArg, bool VolatileArg, bool RValueThis, bool ConstThis, bool VolatileThis)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
SourceLocation getEnd() const
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition Stmt.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
The top declaration context.
Definition Decl.h:106
bool isDependentSizedArrayType() const
Definition TypeBase.h:8802
bool isBooleanType() const
Definition TypeBase.h:9209
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2415
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isConstantArrayType() const
Definition TypeBase.h:8786
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArrayType() const
Definition TypeBase.h:8782
bool isPointerType() const
Definition TypeBase.h:8683
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9116
bool isEnumeralType() const
Definition TypeBase.h:8814
bool isScalarType() const
Definition TypeBase.h:9178
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:9062
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2871
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2863
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9352
bool isFunctionType() const
Definition TypeBase.h:8679
bool isFloatingType() const
Definition Type.cpp:2517
bool isAnyPointerType() const
Definition TypeBase.h:8691
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
bool isNullPtrType() const
Definition TypeBase.h:9109
bool isRecordType() const
Definition TypeBase.h:8810
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
QualType getType() const
Definition Decl.h:724
Represents a variable declaration or definition.
Definition Decl.h:933
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2131
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1477
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:941
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1215
void setInit(Expr *I)
Definition Decl.cpp:2462
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
Top level wrappers for InstallAPI frontend operations.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
OpenACCDirectiveKind
OpenACCReductionOperator
@ Invalid
Invalid Reduction Clause Kind.
bool isa(CodeGen::Address addr)
Definition Address.h:330
OpenACCAtomicKind
@ Conditional
A conditional (?:) operator.
Definition Sema.h:663
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:155
OpenACCClauseKind
Represents the kind of an OpenACC clause.
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Invalid
Represents an invalid clause, for the purposes of parsing.
@ UseDevice
'use_device' clause, allowed on 'host_data' construct.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ FirstPrivate
'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop', and 'serial loop' constructs...
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ AS_public
Definition Specifiers.h:128
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ SC_Auto
Definition Specifiers.h:260
ExprResult ExprEmpty()
Definition Ownership.h:272
StmtResult StmtError()
Definition Ownership.h:266
@ Result
The result type of a method or function.
Definition TypeBase.h:906
const FunctionProtoType * T
ExprResult ExprError()
Definition Ownership.h:265
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:143
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
@ NOUR_None
This is an odr-use.
Definition Specifiers.h:179
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
EvalResult is a struct with detailed info about an evaluated expression.
Definition Expr.h:666
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:668
static OpenACCFirstPrivateRecipe Empty()
static OpenACCPrivateRecipe Empty()
static OpenACCReductionRecipeWithStorage Empty()