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}
536
538 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
539 // Clear this here, so we can do the returns based on the invalid cache ref
540 // here. Note all return statements in this function must return ExprError if
541 // IsInvalidCacheRef. However, instead of doing an 'early return' in that
542 // case, we can let the rest of the diagnostics happen, as the invalid decl
543 // ref is a warning.
544 bool WasParsingInvalidCacheRef =
545 CacheInfo.ParsingCacheVarList && CacheInfo.IsInvalidCacheRef;
546 CacheInfo.ParsingCacheVarList = false;
547 CacheInfo.IsInvalidCacheRef = false;
548
550 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
551 return ExprError();
552 }
553
554 // It isn't clear what 'simple array element or simple subarray' means, so we
555 // will just allow arbitrary depth.
557 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
558 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
559 else
560 CurVarExpr =
561 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
562 }
563
564 // References to a VarDecl are fine.
565 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
567 DRE->getFoundDecl()->getCanonicalDecl()))
568 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
569 }
570
571 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
572 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
573 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
574 }
575 }
576
577 // Nothing really we can do here, as these are dependent. So just return they
578 // are valid.
580 return WasParsingInvalidCacheRef ? ExprEmpty() : VarExpr;
581
582 // There isn't really anything we can do in the case of a recovery expr, so
583 // skip the diagnostic rather than produce a confusing diagnostic.
584 if (isa<RecoveryExpr>(CurVarExpr))
585 return ExprError();
586
587 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_cache);
588 return ExprError();
589}
590
592 if (!getLangOpts().OpenACC || !CacheInfo.ParsingCacheVarList || !D ||
593 D->isInvalidDecl())
594 return;
595 // A 'cache' variable reference MUST be declared before the 'acc.loop' we
596 // generate in codegen, so we have to mark it invalid here in some way. We do
597 // so in a bit of a convoluted way as there is no good way to put this into
598 // the AST, so we store it in SemaOpenACC State. We can check the Scope
599 // during parsing to make sure there is a 'loop' before the decl is
600 // declared(and skip during instantiation).
601 // We only diagnose this as a warning, as this isn't required by the standard
602 // (unless you take a VERY awkward reading of some awkward prose).
603
604 Scope *CurScope = SemaRef.getCurScope();
605
606 // if we are at TU level, we are either doing some EXTRA wacky, or are in a
607 // template instantiation, so just give up.
608 if (CurScope->getDepth() == 0)
609 return;
610
611 while (CurScope) {
612 // If we run into a loop construct scope, than this is 'correct' in that the
613 // declaration is outside of the loop.
614 if (CurScope->isOpenACCLoopConstructScope())
615 return;
616
617 if (CurScope->isDeclScope(D)) {
618 Diag(Loc, diag::warn_acc_cache_var_not_outside_loop);
619
620 CacheInfo.IsInvalidCacheRef = true;
621 }
622
623 CurScope = CurScope->getParent();
624 }
625 // If we don't find the decl at all, we assume that it must be outside of the
626 // loop (or we aren't in a loop!) so skip the diagnostic.
627}
628
629namespace {
630// Check whether the type of the thing we are referencing is OK for things like
631// private, firstprivate, and reduction, which require certain operators to be
632// available.
633ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
634 SourceLocation InnerLoc, QualType InnerTy) {
635 // There is nothing to do here, only these three have these sorts of
636 // restrictions.
637 if (CK != OpenACCClauseKind::Private &&
640 return VarExpr;
641
642 // We can't test this if it isn't here, or if the type isn't clear yet.
643 if (InnerTy.isNull() || InnerTy->isDependentType())
644 return VarExpr;
645
646 InnerTy = InnerTy.getUnqualifiedType();
647 if (auto *RefTy = InnerTy->getAs<ReferenceType>())
648 InnerTy = RefTy->getPointeeType();
649
650 if (auto *ArrTy = InnerTy->getAsArrayTypeUnsafe()) {
651 // Non constant arrays decay to 'pointer', so warn and return that we're
652 // successful.
653 if (!ArrTy->isConstantArrayType()) {
654 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_non_const_array)
655 << InnerTy << CK;
656 return VarExpr;
657 }
658
659 return CheckVarType(S, CK, VarExpr, InnerLoc, ArrTy->getElementType());
660 }
661
662 if (S.SemaRef.RequireCompleteType(InnerLoc, InnerTy,
664 diag::err_incomplete_type))
665 return ExprError();
666
667 auto *RD = InnerTy->getAsCXXRecordDecl();
668
669 // if this isn't a C++ record decl, we can create/copy/destroy this thing at
670 // will without problem, so this is a success.
671 if (!RD)
672 return VarExpr;
673
674 if (CK == OpenACCClauseKind::Private) {
675 bool HasNonDeletedDefaultCtor =
676 llvm::find_if(RD->ctors(), [](const CXXConstructorDecl *CD) {
677 return CD->isDefaultConstructor() && !CD->isDeleted();
678 }) != RD->ctors().end();
679 if (!HasNonDeletedDefaultCtor && !RD->needsImplicitDefaultConstructor()) {
680 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
681 << InnerTy << CK << clang::diag::AccVarReferencedReason::DefCtor;
682 return ExprError();
683 }
684 } else if (CK == OpenACCClauseKind::FirstPrivate) {
685 if (!RD->hasSimpleCopyConstructor()) {
686 Sema::SpecialMemberOverloadResult SMOR = S.SemaRef.LookupSpecialMember(
687 RD, CXXSpecialMemberKind::CopyConstructor, /*ConstArg=*/true,
688 /*VolatileArg=*/false, /*RValueThis=*/false, /*ConstThis=*/false,
689 /*VolatileThis=*/false);
690
692 SMOR.getMethod()->isDeleted()) {
693 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
694 << InnerTy << CK << clang::diag::AccVarReferencedReason::CopyCtor;
695 return ExprError();
696 }
697 }
698 } else if (CK == OpenACCClauseKind::Reduction) {
699 // TODO: Reduction needs to be an aggregate, which gets checked later, so
700 // construction here isn't a problem. However, we need to make sure that we
701 // can compare it correctly still.
702 }
703
704 // All 3 things need to make sure they have a dtor.
705 bool DestructorDeleted =
706 RD->getDestructor() && RD->getDestructor()->isDeleted();
707 if (DestructorDeleted && !RD->needsImplicitDestructor()) {
708 S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
709 << InnerTy << CK << clang::diag::AccVarReferencedReason::Dtor;
710 return ExprError();
711 }
712 return VarExpr;
713}
714
715ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
716 Expr *InnerExpr) {
717 if (!InnerExpr)
718 return VarExpr;
719 return CheckVarType(S, CK, VarExpr, InnerExpr->getBeginLoc(),
720 InnerExpr->getType());
721}
722} // namespace
723
725 Expr *VarExpr) {
726 // This has unique enough restrictions that we should split it to a separate
727 // function.
729 return ActOnCacheVar(VarExpr);
730
731 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
732
733 // 'use_device' doesn't allow array subscript or array sections.
734 // OpenACC3.3 2.8:
735 // A 'var' in a 'use_device' clause must be the name of a variable or array.
736 // OpenACC3.3 2.13:
737 // A 'var' in a 'declare' directive must be a variable or array name.
738 if ((CK == OpenACCClauseKind::UseDevice ||
740 if (isa<ArraySubscriptExpr>(CurVarExpr)) {
741 Diag(VarExpr->getExprLoc(),
742 diag::err_acc_not_a_var_ref_use_device_declare)
744 return ExprError();
745 }
746 // As an extension, we allow 'array sections'/'sub-arrays' here, as that is
747 // effectively defining an array, and are in common use.
748 if (isa<ArraySectionExpr>(CurVarExpr))
749 Diag(VarExpr->getExprLoc(),
750 diag::ext_acc_array_section_use_device_declare)
752 }
753
754 // Sub-arrays/subscript-exprs are fine as long as the base is a
755 // VarExpr/MemberExpr. So strip all of those off.
757 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
758 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
759 else
760 CurVarExpr =
761 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
762 }
763
764 // References to a VarDecl are fine.
765 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
767 DRE->getFoundDecl()->getCanonicalDecl()))
768 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
769 }
770
771 // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
772 // reduction clause must be a scalar variable name, an aggregate variable
773 // name, an array element, or a subarray.
774 // If CK is a 'use_device', this also isn't valid, as it isn't the name of a
775 // variable or array, if not done as a member expr.
776 // A MemberExpr that references a Field is valid for other clauses.
777 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
778 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl())) {
782
783 // We can allow 'member expr' if the 'this' is implicit in the case of
784 // declare, reduction, and use_device.
785 const auto *This = dyn_cast<CXXThisExpr>(ME->getBase());
786 if (This && This->isImplicit())
787 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
788 } else {
789 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
790 }
791 }
792 }
793
794 // Referring to 'this' is ok for the most part, but for 'use_device'/'declare'
795 // doesn't fall into 'variable or array name'
798 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
799
800 // Nothing really we can do here, as these are dependent. So just return they
801 // are valid.
802 if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
805 return CheckVarType(*this, CK, VarExpr, CurVarExpr);
806
807 // There isn't really anything we can do in the case of a recovery expr, so
808 // skip the diagnostic rather than produce a confusing diagnostic.
809 if (isa<RecoveryExpr>(CurVarExpr))
810 return ExprError();
811
813 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
814 << /*declare*/ 1;
815 else if (CK == OpenACCClauseKind::UseDevice)
816 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare)
817 << /*use_device*/ 0;
818 else
819 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
821 return ExprError();
822}
823
825 Expr *LowerBound,
826 SourceLocation ColonLoc,
827 Expr *Length,
828 SourceLocation RBLoc) {
829 ASTContext &Context = getASTContext();
830
831 // Handle placeholders.
832 if (Base->hasPlaceholderType() &&
833 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
834 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
835 if (Result.isInvalid())
836 return ExprError();
837 Base = Result.get();
838 }
839 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
840 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
841 if (Result.isInvalid())
842 return ExprError();
843 Result = SemaRef.DefaultLvalueConversion(Result.get());
844 if (Result.isInvalid())
845 return ExprError();
846 LowerBound = Result.get();
847 }
848 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
849 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
850 if (Result.isInvalid())
851 return ExprError();
852 Result = SemaRef.DefaultLvalueConversion(Result.get());
853 if (Result.isInvalid())
854 return ExprError();
855 Length = Result.get();
856 }
857
858 // Check the 'base' value, it must be an array or pointer type, and not to/of
859 // a function type.
861 QualType ResultTy;
862 if (!Base->isTypeDependent()) {
863 if (OriginalBaseTy->isAnyPointerType()) {
864 ResultTy = OriginalBaseTy->getPointeeType();
865 } else if (OriginalBaseTy->isArrayType()) {
866 ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
867 } else {
868 return ExprError(
869 Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
870 << Base->getSourceRange());
871 }
872
873 if (ResultTy->isFunctionType()) {
874 Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
875 << ResultTy << Base->getSourceRange();
876 return ExprError();
877 }
878
879 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
880 diag::err_acc_subarray_incomplete_type,
881 Base))
882 return ExprError();
883
884 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
885 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
886 if (Result.isInvalid())
887 return ExprError();
888 Base = Result.get();
889 }
890 }
891
892 auto GetRecovery = [&](Expr *E, QualType Ty) {
893 ExprResult Recovery =
894 SemaRef.CreateRecoveryExpr(E->getBeginLoc(), E->getEndLoc(), E, Ty);
895 return Recovery.isUsable() ? Recovery.get() : nullptr;
896 };
897
898 // Ensure both of the expressions are int-exprs.
899 if (LowerBound && !LowerBound->isTypeDependent()) {
900 ExprResult LBRes =
902 LowerBound->getExprLoc(), LowerBound);
903
904 if (LBRes.isUsable())
905 LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
906 LowerBound =
907 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
908 }
909
910 if (Length && !Length->isTypeDependent()) {
911 ExprResult LenRes =
913 Length->getExprLoc(), Length);
914
915 if (LenRes.isUsable())
916 LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
917 Length =
918 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
919 }
920
921 // Length is required if the base type is not an array of known bounds.
922 if (!Length && (OriginalBaseTy.isNull() ||
923 (!OriginalBaseTy->isDependentType() &&
924 !OriginalBaseTy->isConstantArrayType() &&
925 !OriginalBaseTy->isDependentSizedArrayType()))) {
926 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
927 SourceLocation DiagLoc = ColonLoc.isInvalid() ? LBLoc : ColonLoc;
928 Diag(DiagLoc, diag::err_acc_subarray_no_length) << IsArray;
929 // Fill in a dummy 'length' so that when we instantiate this we don't
930 // double-diagnose here.
931 ExprResult Recovery = SemaRef.CreateRecoveryExpr(
932 DiagLoc, SourceLocation(), ArrayRef<Expr *>(), Context.IntTy);
933 Length = Recovery.isUsable() ? Recovery.get() : nullptr;
934 }
935
936 // Check the values of each of the arguments, they cannot be negative(we
937 // assume), and if the array bound is known, must be within range. As we do
938 // so, do our best to continue with evaluation, we can set the
939 // value/expression to nullptr/nullopt if they are invalid, and treat them as
940 // not present for the rest of evaluation.
941
942 // We don't have to check for dependence, because the dependent size is
943 // represented as a different AST node.
944 std::optional<llvm::APSInt> BaseSize;
945 if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
946 const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);
947 BaseSize = ArrayTy->getSize();
948 }
949
950 auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
951 if (!E || E->isInstantiationDependent())
952 return std::nullopt;
953
955 if (!E->EvaluateAsInt(Res, Context))
956 return std::nullopt;
957 return Res.Val.getInt();
958 };
959
960 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
961 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
962
963 // Check lower bound for negative or out of range.
964 if (LowerBoundValue.has_value()) {
965 if (LowerBoundValue->isNegative()) {
966 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
967 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
968 LowerBoundValue.reset();
969 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
970 } else if (BaseSize.has_value() &&
971 llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
972 // Lower bound (start index) must be less than the size of the array.
973 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
974 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
975 << toString(*BaseSize, /*Radix=*/10);
976 LowerBoundValue.reset();
977 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
978 }
979 }
980
981 // Check length for negative or out of range.
982 if (LengthValue.has_value()) {
983 if (LengthValue->isNegative()) {
984 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
985 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
986 LengthValue.reset();
987 Length = GetRecovery(Length, Length->getType());
988 } else if (BaseSize.has_value() &&
989 llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
990 // Length must be lessthan or EQUAL to the size of the array.
991 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
992 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
993 << toString(*BaseSize, /*Radix=*/10);
994 LengthValue.reset();
995 Length = GetRecovery(Length, Length->getType());
996 }
997 }
998
999 // Adding two APSInts requires matching sign and width, so extract those here.
1000 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
1001 if (LHS.isSigned() == RHS.isSigned() &&
1002 LHS.getBitWidth() == RHS.getBitWidth())
1003 return LHS + RHS;
1004
1005 // Width is + 1 so that unsigned->signed conversion just works.
1006 unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
1007 return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), /*Signed=*/true);
1008 };
1009
1010 // If we know all 3 values, we can diagnose that the total value would be out
1011 // of range.
1012 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
1013 LengthValue.has_value() &&
1014 llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
1015 *BaseSize) > 0) {
1016 Diag(Base->getExprLoc(),
1017 diag::err_acc_subarray_base_plus_length_out_of_range)
1018 << toString(*LowerBoundValue, /*Radix=*/10)
1019 << toString(*LengthValue, /*Radix=*/10)
1020 << toString(*BaseSize, /*Radix=*/10);
1021
1022 LowerBoundValue.reset();
1023 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
1024 LengthValue.reset();
1025 Length = GetRecovery(Length, Length->getType());
1026 }
1027
1028 // If any part of the expression is dependent, return a dependent sub-array.
1029 QualType ArrayExprTy = Context.ArraySectionTy;
1030 if (Base->isTypeDependent() ||
1031 (LowerBound && LowerBound->isTypeDependent()) ||
1032 (Length && Length->isTypeDependent()))
1033 ArrayExprTy = Context.DependentTy;
1034
1035 return new (Context)
1036 ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
1037 OK_Ordinary, ColonLoc, RBLoc);
1038}
1039
1041 if (!getLangOpts().OpenACC)
1042 return;
1043
1044 if (!LoopInfo.TopLevelLoopSeen)
1045 return;
1046
1047 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1048 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
1049 << /*while loop*/ 1 << CollapseInfo.DirectiveKind
1051 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1052 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1053 diag::note_acc_active_clause_here)
1055
1056 // Remove the value so that we don't get cascading errors in the body. The
1057 // caller RAII object will restore this.
1058 CollapseInfo.CurCollapseCount = std::nullopt;
1059 }
1060
1061 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1062 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
1063 << /*while loop*/ 1 << TileInfo.DirectiveKind
1065 assert(TileInfo.ActiveTile && "tile count without object?");
1066 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1068
1069 // Remove the value so that we don't get cascading errors in the body. The
1070 // caller RAII object will restore this.
1071 TileInfo.CurTileCount = std::nullopt;
1072 }
1073}
1074
1076 if (!getLangOpts().OpenACC)
1077 return;
1078
1079 if (!LoopInfo.TopLevelLoopSeen)
1080 return;
1081
1082 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1083 Diag(DoLoc, diag::err_acc_invalid_in_loop)
1084 << /*do loop*/ 2 << CollapseInfo.DirectiveKind
1086 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1087 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1088 diag::note_acc_active_clause_here)
1090
1091 // Remove the value so that we don't get cascading errors in the body. The
1092 // caller RAII object will restore this.
1093 CollapseInfo.CurCollapseCount = std::nullopt;
1094 }
1095
1096 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1097 Diag(DoLoc, diag::err_acc_invalid_in_loop)
1098 << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
1099 assert(TileInfo.ActiveTile && "tile count without object?");
1100 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
1102
1103 // Remove the value so that we don't get cascading errors in the body. The
1104 // caller RAII object will restore this.
1105 TileInfo.CurTileCount = std::nullopt;
1106 }
1107}
1108
1109void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
1110 ForStmtBeginChecker &C) {
1111 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
1112
1113 // Enable the while/do-while checking.
1114 LoopInfo.TopLevelLoopSeen = true;
1115
1116 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
1117 // Check the format of this loop if it is affected by the collapse.
1118 C.check();
1119
1120 // OpenACC 3.3 2.9.1:
1121 // Each associated loop, except the innermost, must contain exactly one loop
1122 // or loop nest.
1123 // This checks for more than 1 loop at the current level, the
1124 // 'depth'-satisifed checking manages the 'not zero' case.
1125 if (LoopInfo.CurLevelHasLoopAlready) {
1126 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
1127 << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
1128 assert(CollapseInfo.ActiveCollapse && "No collapse object?");
1129 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1130 diag::note_acc_active_clause_here)
1132 } else {
1133 --(*CollapseInfo.CurCollapseCount);
1134
1135 // Once we've hit zero here, we know we have deep enough 'for' loops to
1136 // get to the bottom.
1137 if (*CollapseInfo.CurCollapseCount == 0)
1138 CollapseInfo.CollapseDepthSatisfied = true;
1139 }
1140 }
1141
1142 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
1143 // Check the format of this loop if it is affected by the tile.
1144 C.check();
1145
1146 if (LoopInfo.CurLevelHasLoopAlready) {
1147 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
1148 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
1149 assert(TileInfo.ActiveTile && "No tile object?");
1150 Diag(TileInfo.ActiveTile->getBeginLoc(),
1151 diag::note_acc_active_clause_here)
1153 } else {
1154 TileInfo.CurTileCount = *TileInfo.CurTileCount - 1;
1155 // Once we've hit zero here, we know we have deep enough 'for' loops to
1156 // get to the bottom.
1157 if (*TileInfo.CurTileCount == 0)
1158 TileInfo.TileDepthSatisfied = true;
1159 }
1160 }
1161
1162 // Set this to 'false' for the body of this loop, so that the next level
1163 // checks independently.
1164 LoopInfo.CurLevelHasLoopAlready = false;
1165}
1166
1167namespace {
1168bool isValidLoopVariableType(QualType LoopVarTy) {
1169 // Just skip if it is dependent, it could be any of the below.
1170 if (LoopVarTy->isDependentType())
1171 return true;
1172
1173 // The loop variable must be of integer,
1174 if (LoopVarTy->isIntegerType())
1175 return true;
1176
1177 // C/C++ pointer,
1178 if (LoopVarTy->isPointerType())
1179 return true;
1180
1181 // or C++ random-access iterator type.
1182 if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
1183 // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
1184 // iterator type!
1185
1186 // We could either do a lot of work to see if this matches
1187 // random-access-iterator, but it seems that just checking that the
1188 // 'iterator_category' typedef is more than sufficient. If programmers are
1189 // willing to lie about this, we can let them.
1190
1191 for (const auto *TD :
1192 llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
1193 const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
1194
1195 if (TDND->getName() != "iterator_category")
1196 continue;
1197
1198 // If there is no type for this decl, return false.
1199 if (TDND->getUnderlyingType().isNull())
1200 return false;
1201
1202 const CXXRecordDecl *ItrCategoryDecl =
1203 TDND->getUnderlyingType()->getAsCXXRecordDecl();
1204
1205 // If the category isn't a record decl, it isn't the tag type.
1206 if (!ItrCategoryDecl)
1207 return false;
1208
1209 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
1210 if (RD->getName() != "random_access_iterator_tag")
1211 return false;
1212 // Checks just for std::random_access_iterator_tag.
1213 return RD->getEnclosingNamespaceContext()->isStdNamespace();
1214 };
1215
1216 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
1217 return true;
1218
1219 // We can also support tag-types inherited from the
1220 // random_access_iterator_tag.
1221 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases())
1222 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
1223 return true;
1224
1225 return false;
1226 }
1227 }
1228
1229 return false;
1230}
1231const ValueDecl *getDeclFromExpr(const Expr *E) {
1232 E = E->IgnoreParenImpCasts();
1233 if (const auto *FE = dyn_cast<FullExpr>(E))
1234 E = FE->getSubExpr();
1235
1236 E = E->IgnoreParenImpCasts();
1237
1238 if (!E)
1239 return nullptr;
1240 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
1241 return DRE->getDecl();
1242
1243 if (const auto *ME = dyn_cast<MemberExpr>(E))
1244 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1245 return ME->getMemberDecl();
1246
1247 return nullptr;
1248}
1249} // namespace
1250
1251void SemaOpenACC::ForStmtBeginChecker::checkRangeFor() {
1252 const RangeForInfo &RFI = std::get<RangeForInfo>(Info);
1253 // If this hasn't changed since last instantiated we're done.
1254 if (RFI.Uninstantiated == RFI.CurrentVersion)
1255 return;
1256
1257 const DeclStmt *UninstRangeStmt =
1258 IsInstantiation ? RFI.Uninstantiated->getBeginStmt() : nullptr;
1259 const DeclStmt *RangeStmt = RFI.CurrentVersion->getBeginStmt();
1260
1261 // If this isn't the first time we've checked this loop, suppress any cases
1262 // where we previously diagnosed.
1263 if (UninstRangeStmt) {
1264 const ValueDecl *InitVar =
1265 cast<ValueDecl>(UninstRangeStmt->getSingleDecl());
1266 QualType VarType = InitVar->getType().getNonReferenceType();
1267
1268 if (!isValidLoopVariableType(VarType))
1269 return;
1270 }
1271
1272 // In some dependent contexts, the autogenerated range statement doesn't get
1273 // included until instantiation, so skip for now.
1274 if (RangeStmt) {
1275 const ValueDecl *InitVar = cast<ValueDecl>(RangeStmt->getSingleDecl());
1276 QualType VarType = InitVar->getType().getNonReferenceType();
1277
1278 if (!isValidLoopVariableType(VarType)) {
1279 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1280 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1281 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1282 diag::note_acc_construct_here)
1283 << SemaRef.LoopWithoutSeqInfo.Kind;
1284 return;
1285 }
1286 }
1287}
1288bool SemaOpenACC::ForStmtBeginChecker::checkForInit(const Stmt *InitStmt,
1289 const ValueDecl *&InitVar,
1290 bool Diag) {
1291 // Init statement is required.
1292 if (!InitStmt) {
1293 if (Diag) {
1294 SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)
1295 << SemaRef.LoopWithoutSeqInfo.Kind;
1296 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1297 diag::note_acc_construct_here)
1298 << SemaRef.LoopWithoutSeqInfo.Kind;
1299 }
1300 return true;
1301 }
1302 auto DiagLoopVar = [this, Diag, InitStmt]() {
1303 if (Diag) {
1304 SemaRef.Diag(InitStmt->getBeginLoc(), diag::err_acc_loop_variable)
1305 << SemaRef.LoopWithoutSeqInfo.Kind;
1306 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1307 diag::note_acc_construct_here)
1308 << SemaRef.LoopWithoutSeqInfo.Kind;
1309 }
1310 return true;
1311 };
1312
1313 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(InitStmt))
1314 InitStmt = ExprTemp->getSubExpr();
1315 if (const auto *E = dyn_cast<Expr>(InitStmt))
1316 InitStmt = E->IgnoreParenImpCasts();
1317
1318 InitVar = nullptr;
1319 if (const auto *BO = dyn_cast<BinaryOperator>(InitStmt)) {
1320 // Allow assignment operator here.
1321
1322 if (!BO->isAssignmentOp())
1323 return DiagLoopVar();
1324
1325 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
1326 if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS))
1327 InitVar = DRE->getDecl();
1328 } else if (const auto *DS = dyn_cast<DeclStmt>(InitStmt)) {
1329 // Allow T t = <whatever>
1330 if (!DS->isSingleDecl())
1331 return DiagLoopVar();
1332 InitVar = dyn_cast<ValueDecl>(DS->getSingleDecl());
1333
1334 // Ensure we have an initializer, unless this is a record/dependent type.
1335 if (InitVar) {
1336 if (!isa<VarDecl>(InitVar))
1337 return DiagLoopVar();
1338
1339 if (!InitVar->getType()->isRecordType() &&
1340 !InitVar->getType()->isDependentType() &&
1341 !cast<VarDecl>(InitVar)->hasInit())
1342 return DiagLoopVar();
1343 }
1344 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(InitStmt)) {
1345 // Allow assignment operator call.
1346 if (CE->getOperator() != OO_Equal)
1347 return DiagLoopVar();
1348 if (CE->getNumArgs() < 1)
1349 return DiagLoopVar();
1350
1351 const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
1352 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1353 InitVar = DRE->getDecl();
1354 } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
1355 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1356 InitVar = ME->getMemberDecl();
1357 }
1358 }
1359
1360 // If after all of that, we haven't found a variable, give up.
1361 if (!InitVar)
1362 return DiagLoopVar();
1363
1364 InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
1365 QualType VarType = InitVar->getType().getNonReferenceType();
1366
1367 // Since we have one, all we need to do is ensure it is the right type.
1368 if (!isValidLoopVariableType(VarType)) {
1369 if (Diag) {
1370 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1371 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1372 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1373 diag::note_acc_construct_here)
1374 << SemaRef.LoopWithoutSeqInfo.Kind;
1375 }
1376 return true;
1377 }
1378
1379 return false;
1380}
1381
1382bool SemaOpenACC::ForStmtBeginChecker::checkForCond(const Stmt *CondStmt,
1383 const ValueDecl *InitVar,
1384 bool Diag) {
1385 // A condition statement is required.
1386 if (!CondStmt) {
1387 if (Diag) {
1388 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
1389 << SemaRef.LoopWithoutSeqInfo.Kind;
1390 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1391 diag::note_acc_construct_here)
1392 << SemaRef.LoopWithoutSeqInfo.Kind;
1393 }
1394
1395 return true;
1396 }
1397 auto DiagCondVar = [this, Diag, CondStmt] {
1398 if (Diag) {
1399 SemaRef.Diag(CondStmt->getBeginLoc(),
1400 diag::err_acc_loop_terminating_condition)
1401 << SemaRef.LoopWithoutSeqInfo.Kind;
1402 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1403 diag::note_acc_construct_here)
1404 << SemaRef.LoopWithoutSeqInfo.Kind;
1405 }
1406 return true;
1407 };
1408
1409 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(CondStmt))
1410 CondStmt = ExprTemp->getSubExpr();
1411 if (const auto *E = dyn_cast<Expr>(CondStmt))
1412 CondStmt = E->IgnoreParenImpCasts();
1413
1414 const ValueDecl *CondVar = nullptr;
1415 if (const auto *BO = dyn_cast<BinaryOperator>(CondStmt)) {
1416 switch (BO->getOpcode()) {
1417 default:
1418 return DiagCondVar();
1419 case BO_EQ:
1420 case BO_LT:
1421 case BO_GT:
1422 case BO_NE:
1423 case BO_LE:
1424 case BO_GE:
1425 break;
1426 }
1427
1428 // Assign the condition-var to the LHS. If it either comes back null, or
1429 // the LHS doesn't match the InitVar, assign it to the RHS so that 5 < N is
1430 // allowed.
1431 CondVar = getDeclFromExpr(BO->getLHS());
1432 if (!CondVar ||
1433 (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl()))
1434 CondVar = getDeclFromExpr(BO->getRHS());
1435
1436 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(CondStmt)) {
1437 // Any of the comparison ops should be ok here, but we don't know how to
1438 // handle spaceship, so disallow for now.
1439 if (!CE->isComparisonOp() || CE->getOperator() == OO_Spaceship)
1440 return DiagCondVar();
1441
1442 if (CE->getNumArgs() < 1)
1443 DiagCondVar();
1444
1445 // Same logic here: Assign it to the LHS, unless the LHS comes back null or
1446 // not equal to the init var.
1447 CondVar = getDeclFromExpr(CE->getArg(0));
1448 if (!CondVar ||
1449 (InitVar &&
1450 CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl() &&
1451 CE->getNumArgs() > 1))
1452 CondVar = getDeclFromExpr(CE->getArg(1));
1453 } else {
1454 return DiagCondVar();
1455 }
1456
1457 if (!CondVar)
1458 return DiagCondVar();
1459
1460 // Don't consider this an error unless the init variable was properly set,
1461 // else check to make sure they are the same variable.
1462 if (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1463 return DiagCondVar();
1464
1465 return false;
1466}
1467
1468namespace {
1469// Helper to check the RHS of an assignment during for's step. We can allow
1470// InitVar = InitVar + N, InitVar = N + InitVar, and Initvar = Initvar - N,
1471// where N is an integer.
1472bool isValidForIncRHSAssign(const ValueDecl *InitVar, const Expr *RHS) {
1473
1474 auto isValid = [](const ValueDecl *InitVar, const Expr *InnerLHS,
1475 const Expr *InnerRHS, bool IsAddition) {
1476 // ONE of the sides has to be an integer type.
1477 if (!InnerLHS->getType()->isIntegerType() &&
1478 !InnerRHS->getType()->isIntegerType())
1479 return false;
1480
1481 // If the init var is already an error, don't bother trying to check for
1482 // it.
1483 if (!InitVar)
1484 return true;
1485
1486 const ValueDecl *LHSDecl = getDeclFromExpr(InnerLHS);
1487 const ValueDecl *RHSDecl = getDeclFromExpr(InnerRHS);
1488 // If we can't get a declaration, this is probably an error, so give up.
1489 if (!LHSDecl || !RHSDecl)
1490 return true;
1491
1492 // If the LHS is the InitVar, the other must be int, so this is valid.
1493 if (LHSDecl->getCanonicalDecl() ==
1494 InitVar->getCanonicalDecl())
1495 return true;
1496
1497 // Subtraction doesn't allow the RHS to be init var, so this is invalid.
1498 if (!IsAddition)
1499 return false;
1500
1501 return RHSDecl->getCanonicalDecl() ==
1502 InitVar->getCanonicalDecl();
1503 };
1504
1505 if (const auto *BO = dyn_cast<BinaryOperator>(RHS)) {
1506 BinaryOperatorKind OpC = BO->getOpcode();
1507 if (OpC != BO_Add && OpC != BO_Sub)
1508 return false;
1509 return isValid(InitVar, BO->getLHS(), BO->getRHS(), OpC == BO_Add);
1510 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
1511 OverloadedOperatorKind Op = CE->getOperator();
1512 if (Op != OO_Plus && Op != OO_Minus)
1513 return false;
1514 // Despite Plus/Minus otherwise only being possible with 2 arguments, error
1515 // recovery will sometimes leave us with only 1 here, so fail out if we
1516 // don't have the correct number of args.
1517 if (CE->getNumArgs() != 2)
1518 return false;
1519 return isValid(InitVar, CE->getArg(0), CE->getArg(1), Op == OO_Plus);
1520 }
1521
1522 return false;
1523}
1524} // namespace
1525
1526bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,
1527 const ValueDecl *InitVar,
1528 bool Diag) {
1529 if (!IncStmt) {
1530 if (Diag) {
1531 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
1532 << SemaRef.LoopWithoutSeqInfo.Kind;
1533 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1534 diag::note_acc_construct_here)
1535 << SemaRef.LoopWithoutSeqInfo.Kind;
1536 }
1537 return true;
1538 }
1539 auto DiagIncVar = [this, Diag, IncStmt] {
1540 if (Diag) {
1541 SemaRef.Diag(IncStmt->getBeginLoc(), diag::err_acc_loop_not_monotonic)
1542 << SemaRef.LoopWithoutSeqInfo.Kind;
1543 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1544 diag::note_acc_construct_here)
1545 << SemaRef.LoopWithoutSeqInfo.Kind;
1546 }
1547 return true;
1548 };
1549
1550 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(IncStmt))
1551 IncStmt = ExprTemp->getSubExpr();
1552 if (const auto *E = dyn_cast<Expr>(IncStmt))
1553 IncStmt = E->IgnoreParenImpCasts();
1554
1555 const ValueDecl *IncVar = nullptr;
1556 // Here we enforce the monotonically increase/decrease:
1557 if (const auto *UO = dyn_cast<UnaryOperator>(IncStmt)) {
1558 // Allow increment/decrement ops.
1559 if (!UO->isIncrementDecrementOp())
1560 return DiagIncVar();
1561 IncVar = getDeclFromExpr(UO->getSubExpr());
1562 } else if (const auto *BO = dyn_cast<BinaryOperator>(IncStmt)) {
1563 switch (BO->getOpcode()) {
1564 default:
1565 return DiagIncVar();
1566 case BO_AddAssign:
1567 case BO_SubAssign:
1568 break;
1569 case BO_Assign:
1570 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1571 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1572 if (!isValidForIncRHSAssign(InitVar, BO->getRHS()))
1573 return DiagIncVar();
1574 break;
1575 }
1576 IncVar = getDeclFromExpr(BO->getLHS());
1577 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(IncStmt)) {
1578 if (CE->getNumArgs() < 1)
1579 return DiagIncVar();
1580
1581 switch (CE->getOperator()) {
1582 default:
1583 return DiagIncVar();
1584 case OO_PlusPlus:
1585 case OO_MinusMinus:
1586 case OO_PlusEqual:
1587 case OO_MinusEqual:
1588 break;
1589 case OO_Equal:
1590 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1591 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1592 if (CE->getNumArgs() != 2 ||
1593 !isValidForIncRHSAssign(InitVar, CE->getArg(1)))
1594 return DiagIncVar();
1595 break;
1596 }
1597
1598 IncVar = getDeclFromExpr(CE->getArg(0));
1599 } else {
1600 return DiagIncVar();
1601 }
1602
1603 if (!IncVar)
1604 return DiagIncVar();
1605
1606 // InitVar shouldn't be null unless there was an error, so don't diagnose if
1607 // that is the case. Else we should ensure that it refers to the loop
1608 // value.
1609 if (InitVar && IncVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1610 return DiagIncVar();
1611
1612 return false;
1613}
1614
1615void SemaOpenACC::ForStmtBeginChecker::checkFor() {
1616 const CheckForInfo &CFI = std::get<CheckForInfo>(Info);
1617
1618 if (!IsInstantiation) {
1619 // If this isn't an instantiation, we can just check all of these and
1620 // diagnose.
1621 const ValueDecl *CurInitVar = nullptr;
1622 checkForInit(CFI.Current.Init, CurInitVar, /*Diag=*/true);
1623 checkForCond(CFI.Current.Condition, CurInitVar, /*Diag=*/true);
1624 checkForInc(CFI.Current.Increment, CurInitVar, /*DIag=*/true);
1625 } else {
1626 const ValueDecl *UninstInitVar = nullptr;
1627 // Checking the 'init' section first. We have to always run both versions,
1628 // at minimum with the 'diag' off, so that we can ensure we get the correct
1629 // instantiation var for checking by later ones.
1630 bool UninstInitFailed =
1631 checkForInit(CFI.Uninst.Init, UninstInitVar, /*Diag=*/false);
1632
1633 // VarDecls are always rebuild because they are dependent, so we can do a
1634 // little work to suppress some of the double checking based on whether the
1635 // type is instantiation dependent. This is imperfect, but will get us most
1636 // cases suppressed. Currently this only handles the 'T t =' case.
1637 auto InitChanged = [=]() {
1638 if (CFI.Uninst.Init == CFI.Current.Init)
1639 return false;
1640
1641 QualType OldVDTy;
1642 QualType NewVDTy;
1643
1644 if (const auto *DS = dyn_cast<DeclStmt>(CFI.Uninst.Init))
1645 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1646 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1647 OldVDTy = VD->getType();
1648 if (const auto *DS = dyn_cast<DeclStmt>(CFI.Current.Init))
1649 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1650 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1651 NewVDTy = VD->getType();
1652
1653 if (OldVDTy.isNull() || NewVDTy.isNull())
1654 return true;
1655
1656 return OldVDTy->isInstantiationDependentType() !=
1658 };
1659
1660 // Only diagnose the new 'init' if the previous version didn't fail, AND the
1661 // current init changed meaningfully.
1662 bool ShouldDiagNewInit = !UninstInitFailed && InitChanged();
1663 const ValueDecl *CurInitVar = nullptr;
1664 checkForInit(CFI.Current.Init, CurInitVar, /*Diag=*/ShouldDiagNewInit);
1665
1666 // Check the condition and increment only if the previous version passed,
1667 // and this changed.
1668 if (CFI.Uninst.Condition != CFI.Current.Condition &&
1669 !checkForCond(CFI.Uninst.Condition, UninstInitVar, /*Diag=*/false))
1670 checkForCond(CFI.Current.Condition, CurInitVar, /*Diag=*/true);
1671 if (CFI.Uninst.Increment != CFI.Current.Increment &&
1672 !checkForInc(CFI.Uninst.Increment, UninstInitVar, /*Diag=*/false))
1673 checkForInc(CFI.Current.Increment, CurInitVar, /*Diag=*/true);
1674 }
1675}
1676
1677void SemaOpenACC::ForStmtBeginChecker::check() {
1678 // If this isn't an active loop without a seq, immediately return, nothing to
1679 // check.
1680 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
1681 return;
1682
1683 // If we've already checked, because this is a 'top level' one (and asking
1684 // again because 'tile' and 'collapse' might apply), just return, nothing to
1685 // do here.
1686 if (AlreadyChecked)
1687 return;
1688 AlreadyChecked = true;
1689
1690 // OpenACC3.3 2.1:
1691 // A loop associated with a loop construct that does not have a seq clause
1692 // must be written to meet all the following conditions:
1693 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
1694 // iterator type.
1695 // - The loop variable must monotonically increase or decrease in the
1696 // direction of its termination condition.
1697 // - The loop trip count must be computable in constant time when entering the
1698 // loop construct.
1699 //
1700 // For a C++ range-based for loop, the loop variable
1701 // identified by the above conditions is the internal iterator, such as a
1702 // pointer, that the compiler generates to iterate the range. it is not the
1703 // variable declared by the for loop.
1704
1705 if (std::holds_alternative<RangeForInfo>(Info))
1706 return checkRangeFor();
1707
1708 return checkFor();
1709}
1710
1712 const Stmt *First, const Stmt *OldSecond,
1713 const Stmt *Second, const Stmt *OldThird,
1714 const Stmt *Third) {
1715 if (!getLangOpts().OpenACC)
1716 return;
1717
1718 ForStmtBeginChecker FSBC{*this, ForLoc, OldFirst, OldSecond,
1719 OldThird, First, Second, Third};
1720 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1721 // as a part of the helper if a tile/collapse applies.
1722 if (!LoopInfo.TopLevelLoopSeen) {
1723 FSBC.check();
1724 }
1725
1726 ForStmtBeginHelper(ForLoc, FSBC);
1727}
1728
1730 const Stmt *Second, const Stmt *Third) {
1731 if (!getLangOpts().OpenACC)
1732 return;
1733
1734 ForStmtBeginChecker FSBC{*this, ForLoc, First, Second, Third};
1735
1736 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1737 // as a part of the helper if a tile/collapse applies.
1738 if (!LoopInfo.TopLevelLoopSeen)
1739 FSBC.check();
1740
1741 ForStmtBeginHelper(ForLoc, FSBC);
1742}
1743
1745 const Stmt *OldRangeFor,
1746 const Stmt *RangeFor) {
1747 if (!getLangOpts().OpenACC || OldRangeFor == nullptr || RangeFor == nullptr)
1748 return;
1749
1750 ForStmtBeginChecker FSBC{*this, ForLoc,
1751 cast_if_present<CXXForRangeStmt>(OldRangeFor),
1752 cast_if_present<CXXForRangeStmt>(RangeFor)};
1753 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1754 // as a part of the helper if a tile/collapse applies.
1755 if (!LoopInfo.TopLevelLoopSeen) {
1756 FSBC.check();
1757 }
1758 ForStmtBeginHelper(ForLoc, FSBC);
1759}
1760
1762 const Stmt *RangeFor) {
1763 if (!getLangOpts().OpenACC || RangeFor == nullptr)
1764 return;
1765
1766 ForStmtBeginChecker FSBC = {*this, ForLoc,
1767 cast_if_present<CXXForRangeStmt>(RangeFor)};
1768
1769 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1770 // as a part of the helper if a tile/collapse applies.
1771 if (!LoopInfo.TopLevelLoopSeen)
1772 FSBC.check();
1773
1774 ForStmtBeginHelper(ForLoc, FSBC);
1775}
1776
1777namespace {
1778SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
1779 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
1780 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
1781 // `DoStmt`, as those are caught as a violation elsewhere.
1782 // For `CompoundStmt` we need to search inside of it.
1783 if (!CurStmt ||
1785 CurStmt))
1786 return SourceLocation{};
1787
1788 // Any other construct is an error anyway, so it has already been diagnosed.
1789 if (isa<OpenACCConstructStmt>(CurStmt))
1790 return SourceLocation{};
1791
1792 // Search inside the compound statement, this allows for arbitrary nesting
1793 // of compound statements, as long as there isn't any code inside.
1794 if (const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
1795 for (const auto *ChildStmt : CS->children()) {
1796 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
1797 if (ChildStmtLoc.isValid())
1798 return ChildStmtLoc;
1799 }
1800 // Empty/not invalid compound statements are legal.
1801 return SourceLocation{};
1802 }
1803 return CurStmt->getBeginLoc();
1804}
1805} // namespace
1806
1808 if (!getLangOpts().OpenACC)
1809 return;
1810
1811 // Set this to 'true' so if we find another one at this level we can diagnose.
1812 LoopInfo.CurLevelHasLoopAlready = true;
1813
1814 if (!Body.isUsable())
1815 return;
1816
1817 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1818 *CollapseInfo.CurCollapseCount > 0 &&
1819 !CollapseInfo.ActiveCollapse->hasForce();
1820 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1821
1822 if (IsActiveCollapse || IsActiveTile) {
1823 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());
1824
1825 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
1826 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1827 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
1828 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1829 diag::note_acc_active_clause_here)
1831 }
1832
1833 if (OtherStmtLoc.isValid() && IsActiveTile) {
1834 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1835 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
1836 Diag(TileInfo.ActiveTile->getBeginLoc(),
1837 diag::note_acc_active_clause_here)
1839 }
1840 }
1841}
1842
1843namespace {
1844// Helper that should mirror ActOnRoutineName to get the FunctionDecl out for
1845// magic-static checking.
1846FunctionDecl *getFunctionFromRoutineName(Expr *RoutineName) {
1847 if (!RoutineName)
1848 return nullptr;
1849 RoutineName = RoutineName->IgnoreParenImpCasts();
1850 if (isa<RecoveryExpr>(RoutineName)) {
1851 // There is nothing we can do here, this isn't a function we can count on.
1852 return nullptr;
1854 RoutineName)) {
1855 // The lookup is dependent, so we'll have to figure this out later.
1856 return nullptr;
1857 } else if (auto *DRE = dyn_cast<DeclRefExpr>(RoutineName)) {
1858 ValueDecl *VD = DRE->getDecl();
1859
1860 if (auto *FD = dyn_cast<FunctionDecl>(VD))
1861 return FD;
1862
1863 // Allow lambdas.
1864 if (auto *VarD = dyn_cast<VarDecl>(VD)) {
1865 QualType VarDTy = VarD->getType();
1866 if (!VarDTy.isNull()) {
1867 if (auto *RD = VarDTy->getAsCXXRecordDecl()) {
1868 if (RD->isGenericLambda())
1869 return nullptr;
1870 if (RD->isLambda())
1871 return RD->getLambdaCallOperator();
1872 } else if (VarDTy->isDependentType()) {
1873 // We don't really know what this is going to be.
1874 return nullptr;
1875 }
1876 }
1877 return nullptr;
1878 } else if (isa<OverloadExpr>(RoutineName)) {
1879 return nullptr;
1880 }
1881 }
1882 return nullptr;
1883}
1884} // namespace
1885
1887 assert(RoutineName && "Routine name cannot be null here");
1888 RoutineName = RoutineName->IgnoreParenImpCasts();
1889
1890 if (isa<RecoveryExpr>(RoutineName)) {
1891 // This has already been diagnosed, so we can skip it.
1892 return ExprError();
1894 RoutineName)) {
1895 // These are dependent and we can't really check them, so delay until
1896 // instantiation.
1897 return RoutineName;
1898 } else if (const auto *DRE = dyn_cast<DeclRefExpr>(RoutineName)) {
1899 const ValueDecl *VD = DRE->getDecl();
1900
1901 if (isa<FunctionDecl>(VD))
1902 return RoutineName;
1903
1904 // Allow lambdas.
1905 if (const auto *VarD = dyn_cast<VarDecl>(VD)) {
1906 QualType VarDTy = VarD->getType();
1907 if (!VarDTy.isNull()) {
1908 if (const auto *RD = VarDTy->getAsCXXRecordDecl()) {
1909 if (RD->isGenericLambda()) {
1910 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1911 << RoutineName;
1912 return ExprError();
1913 }
1914 if (RD->isLambda())
1915 return RoutineName;
1916 } else if (VarDTy->isDependentType()) {
1917 // If this is a dependent variable, it might be a lambda. So we just
1918 // accept this and catch it next time.
1919 return RoutineName;
1920 }
1921 }
1922 }
1923
1924 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1925 << RoutineName;
1926 return ExprError();
1927 } else if (isa<OverloadExpr>(RoutineName)) {
1928 // This happens in function templates, even when the template arguments are
1929 // fully specified. We could possibly do some sort of matching to make sure
1930 // that this is looked up/deduced, but GCC does not do this, so there
1931 // doesn't seem to be a good reason for us to do it either.
1932 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1933 << RoutineName;
1934 return ExprError();
1935 }
1936
1937 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1938 << RoutineName;
1939 return ExprError();
1940}
1942 if (!getLangOpts().OpenACC || VD->isInvalidDecl() || !VD->isStaticLocal())
1943 return;
1944
1945 // This cast should be safe, since a static-local can only happen in a
1946 // function declaration. However, in error cases (or perhaps ObjC/C++?), this
1947 // could possibly be something like a 'block' decl, so if this is NOT a
1948 // function decl, just give up.
1949 auto *ContextDecl = dyn_cast<FunctionDecl>(getCurContext());
1950
1951 if (!ContextDecl)
1952 return;
1953
1954 // OpenACC 3.3 2.15:
1955 // In C and C++, function static variables are not supported in functions to
1956 // which a routine directive applies.
1957 for (const auto *A : ContextDecl->attrs()) {
1959 Diag(VD->getBeginLoc(), diag::err_acc_magic_static_in_routine);
1960 Diag(A->getLocation(), diag::note_acc_construct_here)
1962 return;
1963 }
1964 }
1965
1966 MagicStaticLocs.insert({ContextDecl->getCanonicalDecl(), VD->getBeginLoc()});
1967}
1968void SemaOpenACC::CheckLastRoutineDeclNameConflict(const NamedDecl *ND) {
1969 // OpenACC 3.3 A.3.4
1970 // When a procedure with that name is in scope and it is not the same
1971 // procedure as the immediately following procedure declaration or
1972 // definition, the resolution of the name can be confusing. Implementations
1973 // should then issue a compile-time warning diagnostic even though the
1974 // application is conforming.
1975
1976 // If we haven't created one, also can't diagnose.
1977 if (!LastRoutineDecl)
1978 return;
1979
1980 // If the currently created function doesn't have a name, we can't diagnose on
1981 // a match.
1982 if (!ND->getDeclName().isIdentifier())
1983 return;
1984
1985 // If the two are in different decl contexts, it doesn't make sense to
1986 // diagnose.
1987 if (LastRoutineDecl->getDeclContext() != ND->getLexicalDeclContext())
1988 return;
1989
1990 // If we don't have a referenced thing yet, we can't diagnose.
1991 FunctionDecl *RoutineTarget =
1992 getFunctionFromRoutineName(LastRoutineDecl->getFunctionReference());
1993 if (!RoutineTarget)
1994 return;
1995
1996 // If the Routine target doesn't have a name, we can't diagnose.
1997 if (!RoutineTarget->getDeclName().isIdentifier())
1998 return;
1999
2000 // Of course don't diagnose if the names don't match.
2001 if (ND->getName() != RoutineTarget->getName())
2002 return;
2003
2005 long LastLine =
2007
2008 // Do some line-number math to make sure they are within a line of eachother.
2009 // Comments or newlines can be inserted to clarify intent.
2010 if (NDLine - LastLine > 1)
2011 return;
2012
2013 // Don't warn if it actually DOES apply to this function via redecls.
2014 if (ND->getCanonicalDecl() == RoutineTarget->getCanonicalDecl())
2015 return;
2016
2017 Diag(LastRoutineDecl->getFunctionReference()->getBeginLoc(),
2018 diag::warn_acc_confusing_routine_name);
2019 Diag(RoutineTarget->getBeginLoc(), diag::note_previous_decl) << ND;
2020}
2021
2023 if (!VD || !getLangOpts().OpenACC || InitType.isNull())
2024 return;
2025
2026 // To avoid double-diagnostic, just diagnose this during instantiation. We'll
2027 // get 1 warning per instantiation, but this permits us to be more sensible
2028 // for cases where the lookup is confusing.
2030 return;
2031
2032 const auto *RD = InitType->getAsCXXRecordDecl();
2033 // If this isn't a lambda, no sense in diagnosing.
2034 if (!RD || !RD->isLambda())
2035 return;
2036
2037 CheckLastRoutineDeclNameConflict(VD);
2038}
2039
2041 if (!FD || !getLangOpts().OpenACC)
2042 return;
2043 CheckLastRoutineDeclNameConflict(FD);
2044}
2045
2049
2050 // Declaration directives an appear in a statement location, so call into that
2051 // function here.
2053 return ActOnStartDeclDirective(K, StartLoc, Clauses);
2054
2055 SemaRef.DiscardCleanupsInEvaluationContext();
2056 SemaRef.PopExpressionEvaluationContext();
2057
2058 // OpenACC 3.3 2.9.1:
2059 // Intervening code must not contain other OpenACC directives or calls to API
2060 // routines.
2061 //
2062 // ALL constructs are ill-formed if there is an active 'collapse'
2063 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
2064 Diag(StartLoc, diag::err_acc_invalid_in_loop)
2065 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
2067 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2068 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2069 diag::note_acc_active_clause_here)
2071 }
2072 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
2073 Diag(StartLoc, diag::err_acc_invalid_in_loop)
2074 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
2076 assert(TileInfo.ActiveTile && "Tile count without object?");
2077 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
2079 }
2080
2081 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
2082 return true;
2083 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
2084}
2085
2088 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
2089 OpenACCAtomicKind AtomicKind, SourceLocation RParenLoc,
2091 StmtResult AssocStmt) {
2092 switch (K) {
2094 return StmtError();
2098 return OpenACCComputeConstruct::Create(
2099 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
2100 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2101 }
2106 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
2107 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2108 }
2111 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
2112 EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2113 }
2116 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
2117 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2118 }
2120 return OpenACCEnterDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
2121 EndLoc, Clauses);
2122 }
2124 return OpenACCExitDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
2125 EndLoc, Clauses);
2126 }
2129 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
2130 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2131 }
2134 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
2135 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
2136 }
2138 return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc,
2139 EndLoc, Clauses);
2140 }
2142 return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
2143 EndLoc, Clauses);
2144 }
2146 return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
2147 EndLoc, Clauses);
2148 }
2150 return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
2151 EndLoc, Clauses);
2152 }
2155 getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc, Clauses,
2156 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2157 }
2159 assert(Clauses.empty() && "Cache doesn't allow clauses");
2160 return OpenACCCacheConstruct::Create(getASTContext(), StartLoc, DirLoc,
2161 LParenLoc, MiscLoc, Exprs, RParenLoc,
2162 EndLoc);
2163 }
2165 llvm_unreachable("routine shouldn't handled here");
2167 // Declare and routine arei declaration directives, but can be used here as
2168 // long as we wrap it in a DeclStmt. So make sure we do that here.
2169 DeclGroupRef DR = ActOnEndDeclDirective(K, StartLoc, DirLoc, LParenLoc,
2170 RParenLoc, EndLoc, Clauses);
2171
2172 return SemaRef.ActOnDeclStmt(DeclGroupPtrTy::make(DR), StartLoc, EndLoc);
2173 }
2174 }
2175 llvm_unreachable("Unhandled case in directive handling?");
2176}
2177
2179 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
2181 StmtResult AssocStmt) {
2182 switch (K) {
2183 default:
2184 llvm_unreachable("Unimplemented associated statement application");
2192 llvm_unreachable(
2193 "these don't have associated statements, so shouldn't get here");
2195 return CheckAtomicAssociatedStmt(DirectiveLoc, AtKind, AssocStmt);
2201 // There really isn't any checking here that could happen. As long as we
2202 // have a statement to associate, this should be fine.
2203 // OpenACC 3.3 Section 6:
2204 // Structured Block: in C or C++, an executable statement, possibly
2205 // compound, with a single entry at the top and a single exit at the
2206 // bottom.
2207 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
2208 // an interpretation of it is to allow this and treat the initializer as
2209 // the 'structured block'.
2210 return AssocStmt;
2215 if (!AssocStmt.isUsable())
2216 return StmtError();
2217
2218 if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
2219 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
2220 << K;
2221 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
2222 return StmtError();
2223 }
2224
2225 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
2226 if (!CollapseInfo.CollapseDepthSatisfied) {
2227 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2229 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2230 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2231 diag::note_acc_active_clause_here)
2233 }
2234
2235 if (!TileInfo.TileDepthSatisfied) {
2236 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2238 assert(TileInfo.ActiveTile && "Collapse count without object?");
2239 Diag(TileInfo.ActiveTile->getBeginLoc(),
2240 diag::note_acc_active_clause_here)
2242 }
2243 return StmtError();
2244 }
2245
2246 return AssocStmt.get();
2247 }
2248 llvm_unreachable("Invalid associated statement application");
2249}
2250
2251namespace {
2252
2253// Routine has some pretty complicated set of rules for how device_type
2254// interacts with 'gang', 'worker', 'vector', and 'seq'. Enforce part of it
2255// here.
2256bool CheckValidRoutineGangWorkerVectorSeqClauses(
2257 SemaOpenACC &SemaRef, SourceLocation DirectiveLoc,
2259 auto RequiredPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
2261 // The clause handling has assured us that there is no duplicates. That is,
2262 // if there is 1 before a device_type, there are none after a device_type.
2263 // If not, there is at most 1 applying to each device_type.
2264
2265 // What is left to legalize is that either:
2266 // 1- there is 1 before the first device_type.
2267 // 2- there is 1 AFTER each device_type.
2268 auto *FirstDeviceType =
2269 llvm::find_if(Clauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
2270
2271 // If there is 1 before the first device_type (or at all if no device_type),
2272 // we are legal.
2273 auto *ClauseItr =
2274 std::find_if(Clauses.begin(), FirstDeviceType, RequiredPred);
2275
2276 if (ClauseItr != FirstDeviceType)
2277 return false;
2278
2279 // If there IS no device_type, and no clause, diagnose.
2280 if (FirstDeviceType == Clauses.end())
2281 return SemaRef.Diag(DirectiveLoc, diag::err_acc_construct_one_clause_of)
2283 << "'gang', 'seq', 'vector', or 'worker'";
2284
2285 // Else, we have to check EACH device_type group. PrevDeviceType is the
2286 // device-type before the current group.
2287 auto *PrevDeviceType = FirstDeviceType;
2288
2289 while (PrevDeviceType != Clauses.end()) {
2290 auto *NextDeviceType =
2291 std::find_if(std::next(PrevDeviceType), Clauses.end(),
2292 llvm::IsaPred<OpenACCDeviceTypeClause>);
2293
2294 ClauseItr = std::find_if(PrevDeviceType, NextDeviceType, RequiredPred);
2295
2296 if (ClauseItr == NextDeviceType)
2297 return SemaRef.Diag((*PrevDeviceType)->getBeginLoc(),
2298 diag::err_acc_clause_routine_one_of_in_region);
2299
2300 PrevDeviceType = NextDeviceType;
2301 }
2302
2303 return false;
2304}
2305} // namespace
2306
2310 // OpenCC3.3 2.1 (line 889)
2311 // A program must not depend on the order of evaluation of expressions in
2312 // clause arguments or on any side effects of the evaluations.
2313 SemaRef.DiscardCleanupsInEvaluationContext();
2314 SemaRef.PopExpressionEvaluationContext();
2315
2316 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
2317 return true;
2319 CheckValidRoutineGangWorkerVectorSeqClauses(*this, StartLoc, Clauses))
2320 return true;
2321
2322 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
2323}
2324
2327 SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc,
2328 ArrayRef<OpenACCClause *> Clauses) {
2329 switch (K) {
2330 default:
2332 return DeclGroupRef{};
2334 // OpenACC3.3 2.13: At least one clause must appear on a declare directive.
2335 if (Clauses.empty()) {
2336 Diag(EndLoc, diag::err_acc_declare_required_clauses);
2337 // No reason to add this to the AST, as we would just end up trying to
2338 // instantiate this, which would double-diagnose here, which we wouldn't
2339 // want to do.
2340 return DeclGroupRef{};
2341 }
2342
2343 auto *DeclareDecl = OpenACCDeclareDecl::Create(
2344 getASTContext(), getCurContext(), StartLoc, DirLoc, EndLoc, Clauses);
2345 DeclareDecl->setAccess(AS_public);
2346 getCurContext()->addDecl(DeclareDecl);
2347 return DeclGroupRef{DeclareDecl};
2348 }
2350 llvm_unreachable("routine shouldn't be handled here");
2351 }
2352 llvm_unreachable("unhandled case in directive handling?");
2353}
2354
2355namespace {
2356// Given the decl on the next line, figure out if it is one that is acceptable
2357// to `routine`, or looks like the sort of decl we should be diagnosing against.
2358FunctionDecl *LegalizeNextParsedDecl(Decl *D) {
2359 if (!D)
2360 return nullptr;
2361
2362 // Functions are per-fact acceptable as-is.
2363 if (auto *FD = dyn_cast<FunctionDecl>(D))
2364 return FD;
2365
2366 // Function templates are functions, so attach to the templated decl.
2367 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
2368 return FTD->getTemplatedDecl();
2369
2370 if (auto *FD = dyn_cast<FieldDecl>(D)) {
2371 auto *RD =
2372 FD->getType().isNull() ? nullptr : FD->getType()->getAsCXXRecordDecl();
2373
2374 if (RD && RD->isGenericLambda())
2375 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2376 if (RD && RD->isLambda())
2377 return RD->getLambdaCallOperator();
2378 }
2379 // VarDecl we can look at the init instead of the type of the variable, this
2380 // makes us more tolerant of the 'auto' deduced type.
2381 if (auto *VD = dyn_cast<VarDecl>(D)) {
2382 Expr *Init = VD->getInit();
2383 if (!Init || Init->getType().isNull())
2384 return nullptr;
2385
2386 const auto *RD = Init->getType()->getAsCXXRecordDecl();
2387 if (RD && RD->isGenericLambda())
2388 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2389 if (RD && RD->isLambda())
2390 return RD->getLambdaCallOperator();
2391
2392 // FIXME: We could try harder in the case where this is a dependent thing
2393 // that ends up being a lambda (that is, the init is an unresolved lookup
2394 // expr), but we can't attach to the call/lookup expr. If we instead try to
2395 // attach to the VarDecl, when we go to instantiate it, attributes are
2396 // instantiated before the init, so we can't actually see the type at any
2397 // point where it would be relevant/able to be checked. We could perhaps do
2398 // some sort of 'after-init' instantiation/checking here, but that doesn't
2399 // seem valuable for a situation that other compilers don't handle.
2400 }
2401 return nullptr;
2402}
2403
2404void CreateRoutineDeclAttr(SemaOpenACC &SemaRef, SourceLocation DirLoc,
2405 ArrayRef<const OpenACCClause *> Clauses,
2406 ValueDecl *AddTo) {
2407 OpenACCRoutineDeclAttr *A =
2408 OpenACCRoutineDeclAttr::Create(SemaRef.getASTContext(), DirLoc);
2409 A->Clauses.assign(Clauses.begin(), Clauses.end());
2410 AddTo->addAttr(A);
2411}
2412} // namespace
2413
2414// Variant that adds attributes, because this is the unnamed case.
2417 Decl *NextParsedDecl) {
2418
2419 FunctionDecl *NextParsedFDecl = LegalizeNextParsedDecl(NextParsedDecl);
2420
2421 if (!NextParsedFDecl) {
2422 // If we don't have a valid 'next thing', just diagnose.
2423 SemaRef.Diag(DirLoc, diag::err_acc_decl_for_routine);
2424 return;
2425 }
2426
2427 // OpenACC 3.3 2.15:
2428 // In C and C++, function static variables are not supported in functions to
2429 // which a routine directive applies.
2430 if (auto Itr = MagicStaticLocs.find(NextParsedFDecl->getCanonicalDecl());
2431 Itr != MagicStaticLocs.end()) {
2432 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2433 Diag(DirLoc, diag::note_acc_construct_here)
2435
2436 return;
2437 }
2438
2439 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
2440 if (BindItr != Clauses.end()) {
2441 for (auto *A : NextParsedFDecl->attrs()) {
2442 // OpenACC 3.3 2.15:
2443 // If a procedure has a bind clause on both the declaration and definition
2444 // than they both must bind to the same name.
2445 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2446 auto OtherBindItr =
2447 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2448 if (OtherBindItr != RA->Clauses.end() &&
2449 (*cast<OpenACCBindClause>(*BindItr)) !=
2450 (*cast<OpenACCBindClause>(*OtherBindItr))) {
2451 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_unnamed_bind);
2452 Diag((*OtherBindItr)->getEndLoc(),
2453 diag::note_acc_previous_clause_here)
2454 << (*BindItr)->getClauseKind();
2455 return;
2456 }
2457 }
2458
2459 // OpenACC 3.3 2.15:
2460 // A bind clause may not bind to a routine name that has a visible bind
2461 // clause.
2462 // We take the combo of these two 2.15 restrictions to mean that the
2463 // 'declaration'/'definition' quote is an exception to this. So we're
2464 // going to disallow mixing of the two types entirely.
2465 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2466 RA && RA->getRange().getEnd().isValid()) {
2467 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2468 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2469 << "bind";
2470 return;
2471 }
2472 }
2473 }
2474
2475 CreateRoutineDeclAttr(*this, DirLoc, Clauses, NextParsedFDecl);
2476}
2477
2478// Variant that adds a decl, because this is the named case.
2480 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2481 Expr *FuncRef, SourceLocation RParenLoc,
2483 assert(LParenLoc.isValid());
2484
2485 FunctionDecl *FD = nullptr;
2486 if ((FD = getFunctionFromRoutineName(FuncRef))) {
2487 // OpenACC 3.3 2.15:
2488 // In C and C++, function static variables are not supported in functions to
2489 // which a routine directive applies.
2490 if (auto Itr = MagicStaticLocs.find(FD->getCanonicalDecl());
2491 Itr != MagicStaticLocs.end()) {
2492 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2493 Diag(DirLoc, diag::note_acc_construct_here)
2495
2496 return nullptr;
2497 }
2498
2499 // OpenACC 3.3 2.15:
2500 // A bind clause may not bind to a routine name that has a visible bind
2501 // clause.
2502 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
2503 SourceLocation BindLoc;
2504 if (BindItr != Clauses.end()) {
2505 BindLoc = (*BindItr)->getBeginLoc();
2506 // Since this is adding a 'named' routine, we aren't allowed to combine
2507 // with ANY other visible bind clause. Error if we see either.
2508
2509 for (auto *A : FD->attrs()) {
2510 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2511 auto OtherBindItr =
2512 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2513 if (OtherBindItr != RA->Clauses.end()) {
2514 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2515 Diag((*OtherBindItr)->getEndLoc(),
2516 diag::note_acc_previous_clause_here)
2517 << (*BindItr)->getClauseKind();
2518 return nullptr;
2519 }
2520 }
2521
2522 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2523 RA && RA->getRange().getEnd().isValid()) {
2524 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2525 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2526 << (*BindItr)->getClauseKind();
2527 return nullptr;
2528 }
2529 }
2530 }
2531
2532 // Set the end-range to the 'bind' clause here, so we can look it up
2533 // later.
2534 auto *RAA = OpenACCRoutineAnnotAttr::CreateImplicit(getASTContext(),
2535 {DirLoc, BindLoc});
2536 FD->addAttr(RAA);
2537 // In case we are referencing not the 'latest' version, make sure we add
2538 // the attribute to all declarations after the 'found' one.
2539 for (auto *CurFD : FD->redecls())
2540 CurFD->addAttr(RAA->clone(getASTContext()));
2541 }
2542
2543 LastRoutineDecl = OpenACCRoutineDecl::Create(
2544 getASTContext(), getCurContext(), StartLoc, DirLoc, LParenLoc, FuncRef,
2545 RParenLoc, EndLoc, Clauses);
2546 LastRoutineDecl->setAccess(AS_public);
2547 getCurContext()->addDecl(LastRoutineDecl);
2548
2549 if (FD) {
2550 // Add this attribute to the list of annotations so that codegen can visit
2551 // it later. FD doesn't necessarily exist, but that case should be
2552 // diagnosed.
2553 RoutineRefList.emplace_back(FD, LastRoutineDecl);
2554 }
2555 return LastRoutineDecl;
2556}
2557
2559 for (auto [FD, RoutineDecl] : RoutineRefList)
2560 SemaRef.Consumer.HandleOpenACCRoutineReference(FD, RoutineDecl);
2561}
2562
2564 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2565 Expr *ReferencedFunc, SourceLocation RParenLoc,
2567 DeclGroupPtrTy NextDecl) {
2568 assert((!ReferencedFunc || !NextDecl) &&
2569 "Only one of these should be filled");
2570
2571 if (LParenLoc.isInvalid()) {
2572 Decl *NextLineDecl = nullptr;
2573 if (NextDecl && NextDecl.get().isSingleDecl())
2574 NextLineDecl = NextDecl.get().getSingleDecl();
2575
2576 CheckRoutineDecl(DirLoc, Clauses, NextLineDecl);
2577
2578 return NextDecl.get();
2579 }
2580
2582 StartLoc, DirLoc, LParenLoc, ReferencedFunc, RParenLoc, Clauses, EndLoc)};
2583}
2584
2586 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2587 Expr *ReferencedFunc, SourceLocation RParenLoc,
2589 Stmt *NextStmt) {
2590 assert((!ReferencedFunc || !NextStmt) &&
2591 "Only one of these should be filled");
2592
2593 if (LParenLoc.isInvalid()) {
2594 Decl *NextLineDecl = nullptr;
2595 if (NextStmt)
2596 if (DeclStmt *DS = dyn_cast<DeclStmt>(NextStmt); DS && DS->isSingleDecl())
2597 NextLineDecl = DS->getSingleDecl();
2598
2599 CheckRoutineDecl(DirLoc, Clauses, NextLineDecl);
2600 return NextStmt;
2601 }
2602
2603 DeclGroupRef DR{CheckRoutineDecl(StartLoc, DirLoc, LParenLoc, ReferencedFunc,
2604 RParenLoc, Clauses, EndLoc)};
2605 return SemaRef.ActOnDeclStmt(DeclGroupPtrTy::make(DR), StartLoc, EndLoc);
2606}
2607
2608OpenACCRoutineDeclAttr *
2609SemaOpenACC::mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old) {
2610 OpenACCRoutineDeclAttr *New =
2611 OpenACCRoutineDeclAttr::Create(getASTContext(), Old.getLocation());
2612 // We should jsut be able to copy these, there isn't really any
2613 // merging/inheriting we have to do, so no worry about doing a deep copy.
2614 New->Clauses = Old.Clauses;
2615 return New;
2616}
2621
2626
2627namespace {
2628enum class InitKind { Invalid, Zero, One, AllOnes, Least, Largest };
2629llvm::APFloat getInitFloatValue(ASTContext &Context, InitKind IK, QualType Ty) {
2630 switch (IK) {
2631 case InitKind::Invalid:
2632 llvm_unreachable("invalid init kind");
2633 case InitKind::Zero:
2634 return llvm::APFloat::getZero(Context.getFloatTypeSemantics(Ty));
2635 case InitKind::One:
2636 return llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty));
2637 case InitKind::AllOnes:
2638 return llvm::APFloat::getAllOnesValue(Context.getFloatTypeSemantics(Ty));
2639 case InitKind::Least:
2640 return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty),
2641 /*Negative=*/true);
2642 case InitKind::Largest:
2643 return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty));
2644 }
2645 llvm_unreachable("unknown init kind");
2646}
2647
2648llvm::APInt getInitIntValue(ASTContext &Context, InitKind IK, QualType Ty) {
2649 switch (IK) {
2650 case InitKind::Invalid:
2651 llvm_unreachable("invalid init kind");
2652 case InitKind::Zero:
2653 return llvm::APInt(Context.getIntWidth(Ty), 0);
2654 case InitKind::One:
2655 return llvm::APInt(Context.getIntWidth(Ty), 1);
2656 case InitKind::AllOnes:
2657 return llvm::APInt::getAllOnes(Context.getIntWidth(Ty));
2658 case InitKind::Least:
2660 return llvm::APInt::getSignedMinValue(Context.getIntWidth(Ty));
2661 return llvm::APInt::getMinValue(Context.getIntWidth(Ty));
2662 case InitKind::Largest:
2664 return llvm::APInt::getSignedMaxValue(Context.getIntWidth(Ty));
2665 return llvm::APInt::getMaxValue(Context.getIntWidth(Ty));
2666 }
2667 llvm_unreachable("unknown init kind");
2668}
2669
2670/// Loops through a type and generates an appropriate InitListExpr to
2671/// generate type initialization.
2672Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
2673 SourceRange ExprRange, QualType Ty,
2674 InitKind IK) {
2675 if (IK == InitKind::Invalid)
2676 return nullptr;
2677
2678 if (IK == InitKind::Zero) {
2679 Expr *InitExpr =
2680 new (Context) InitListExpr(Context, ExprRange.getBegin(), {},
2681 ExprRange.getEnd(), /*isExplicit=*/false);
2682 InitExpr->setType(Context.VoidTy);
2683 return InitExpr;
2684 }
2685
2686 Ty = Ty.getCanonicalType();
2687 llvm::SmallVector<Expr *> Exprs;
2688
2689 if (const RecordDecl *RD = Ty->getAsRecordDecl()) {
2690 for (auto *F : RD->fields()) {
2691 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
2692 F->getType(), IK))
2693 Exprs.push_back(NewExpr);
2694 else
2695 return nullptr;
2696 }
2697 } else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
2698 for (uint64_t Idx = 0; Idx < AT->getZExtSize(); ++Idx) {
2699 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(
2700 Context, ExprRange, AT->getElementType(), IK))
2701 Exprs.push_back(NewExpr);
2702 else
2703 return nullptr;
2704 }
2705
2706 } else if (Ty->isPointerType()) {
2707 // For now, we are going to punt/not initialize pointer types, as
2708 // discussions/designs are ongoing on how to express this behavior,
2709 // particularly since they probably need the 'bounds' passed to them
2710 // correctly. A future patch/patch set will go through all of the pointer
2711 // values for all of the recipes to make sure we have a sane behavior.
2712
2713 // For now, this will result in a NYI during code generation for
2714 // no-initializer.
2715 return nullptr;
2716 } else {
2717 assert(Ty->isScalarType());
2718
2719 if (const auto *Cplx = Ty->getAs<ComplexType>()) {
2720 // we can get here in error cases, so make sure we generate something that
2721 // will work if we find ourselves wanting to enable this, so emit '0,0'
2722 // for both ints and floats.
2723
2724 QualType EltTy = Cplx->getElementType();
2725 if (EltTy->isFloatingType()) {
2726 Exprs.push_back(FloatingLiteral::Create(
2727 Context, getInitFloatValue(Context, InitKind::Zero, EltTy),
2728 /*isExact=*/true, EltTy, ExprRange.getBegin()));
2729 Exprs.push_back(FloatingLiteral::Create(
2730 Context, getInitFloatValue(Context, InitKind::Zero, EltTy),
2731 /*isExact=*/true, EltTy, ExprRange.getBegin()));
2732 } else {
2733 Exprs.push_back(IntegerLiteral::Create(
2734 Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,
2735 ExprRange.getBegin()));
2736 Exprs.push_back(IntegerLiteral::Create(
2737 Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,
2738 ExprRange.getBegin()));
2739 }
2740
2741 } else if (Ty->isFloatingType()) {
2742 Exprs.push_back(
2743 FloatingLiteral::Create(Context, getInitFloatValue(Context, IK, Ty),
2744 /*isExact=*/true, Ty, ExprRange.getBegin()));
2745 } else if (Ty->isBooleanType()) {
2746 Exprs.push_back(CXXBoolLiteralExpr::Create(Context,
2747 (IK == InitKind::One ||
2748 IK == InitKind::AllOnes ||
2749 IK == InitKind::Largest),
2750 Ty, ExprRange.getBegin()));
2751 } else if (Ty->isNullPtrType()) {
2752 Exprs.push_back(new (Context)
2753 CXXNullPtrLiteralExpr(Ty, ExprRange.getBegin()));
2754 } else {
2755 Exprs.push_back(IntegerLiteral::Create(
2756 Context, getInitIntValue(Context, IK, Ty), Ty, ExprRange.getBegin()));
2757 }
2758 }
2759
2760 Expr *InitExpr =
2761 new (Context) InitListExpr(Context, ExprRange.getBegin(), Exprs,
2762 ExprRange.getEnd(), /*isExplicit=*/false);
2763 InitExpr->setType(Ty);
2764 return InitExpr;
2765}
2766
2767VarDecl *CreateAllocaDecl(ASTContext &Ctx, DeclContext *DC,
2768 SourceLocation BeginLoc, IdentifierInfo *VarName,
2769 QualType VarTy) {
2770 auto *VD = VarDecl::Create(Ctx, DC, BeginLoc, BeginLoc, VarName, VarTy,
2771 Ctx.getTrivialTypeSourceInfo(VarTy), SC_Auto);
2772 VD->markUsed(Ctx);
2773 return VD;
2774}
2775
2776ExprResult FinishValueInit(Sema &S, InitializedEntity &Entity,
2777 SourceLocation Loc, QualType VarTy, Expr *InitExpr) {
2778 if (!InitExpr)
2779 return ExprEmpty();
2780
2781 InitializationKind Kind =
2782 InitializationKind::CreateForInit(Loc, /*DirectInit=*/true, InitExpr);
2783 InitializationSequence InitSeq(S, Entity, Kind, InitExpr,
2784 /*TopLevelOfInitList=*/false,
2785 /*TreatUnavailableAsInvalid=*/false);
2786
2787 return InitSeq.Perform(S, Entity, Kind, InitExpr, &VarTy);
2788}
2789
2790} // namespace
2791
2793 // We don't strip bounds here, so that we are doing our recipe init at the
2794 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2795 if (!VarExpr || VarExpr->getType()->isDependentType())
2797
2798 QualType VarTy =
2800
2801 // Array sections are special, and we have to treat them that way.
2802 if (const auto *ASE =
2803 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2804 VarTy = ASE->getElementType();
2805
2806 VarDecl *AllocaDecl = CreateAllocaDecl(
2807 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2808 &getASTContext().Idents.get("openacc.private.init"), VarTy);
2809
2812 InitializationKind Kind =
2814 InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
2815 ExprResult Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
2816
2817 // For 'no bounds' version, we can use this as a shortcut, so set the init
2818 // anyway.
2819 if (Init.isUsable()) {
2820 AllocaDecl->setInit(Init.get());
2821 AllocaDecl->setInitStyle(VarDecl::CallInit);
2822 }
2823
2824 return OpenACCPrivateRecipe(AllocaDecl);
2825}
2826
2829 // We don't strip bounds here, so that we are doing our recipe init at the
2830 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2831 if (!VarExpr || VarExpr->getType()->isDependentType())
2833
2834 QualType VarTy =
2836
2837 // Array sections are special, and we have to treat them that way.
2838 if (const auto *ASE =
2839 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2840 VarTy = ASE->getElementType();
2841
2842 VarDecl *AllocaDecl = CreateAllocaDecl(
2843 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2844 &getASTContext().Idents.get("openacc.firstprivate.init"), VarTy);
2845
2846 VarDecl *Temporary = CreateAllocaDecl(
2847 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2848 &getASTContext().Idents.get("openacc.temp"), VarTy);
2849
2850 auto *TemporaryDRE = DeclRefExpr::Create(
2852 /*ReferstoEnclosingVariableOrCapture=*/false,
2854 VarExpr->getBeginLoc()},
2855 VarTy, clang::VK_LValue, Temporary, nullptr, NOUR_None);
2856
2859
2860 const auto *ArrTy = getASTContext().getAsConstantArrayType(VarTy);
2861 if (!ArrTy) {
2862 ExprResult Init = FinishValueInit(
2863 SemaRef.SemaRef, Entity, VarExpr->getBeginLoc(), VarTy, TemporaryDRE);
2864
2865 // For 'no bounds' version, we can use this as a shortcut, so set the init
2866 // anyway.
2867 if (Init.isUsable()) {
2868 AllocaDecl->setInit(Init.get());
2869 AllocaDecl->setInitStyle(VarDecl::CallInit);
2870 }
2871 return OpenACCFirstPrivateRecipe(AllocaDecl, Temporary);
2872 }
2873
2874 // Arrays need to have each individual element initialized as there
2875 // isn't a normal 'equals' feature in C/C++. This section sets these up
2876 // as an init list after 'initializing' each individual element.
2878 // Decay to pointer for the array subscript expression.
2879 auto *CastToPtr = ImplicitCastExpr::Create(
2880 getASTContext(), getASTContext().getPointerType(ArrTy->getElementType()),
2881 CK_ArrayToPointerDecay, TemporaryDRE, /*BasePath=*/nullptr,
2883
2884 for (std::size_t I = 0; I < ArrTy->getLimitedSize(); ++I) {
2885 // Each element needs to be some sort of copy initialization from an
2886 // array-index of the original temporary (referenced via a
2887 // DeclRefExpr).
2888 auto *Idx = IntegerLiteral::Create(
2889 getASTContext(),
2890 llvm::APInt(getASTContext().getTypeSize(getASTContext().getSizeType()),
2891 I),
2892 getASTContext().getSizeType(), VarExpr->getBeginLoc());
2893
2894 Expr *Subscript = new (getASTContext()) ArraySubscriptExpr(
2895 CastToPtr, Idx, ArrTy->getElementType(), clang::VK_LValue, OK_Ordinary,
2896 VarExpr->getBeginLoc());
2897 // Generate a simple copy from the result of the subscript. This will
2898 // do a bitwise copy or a copy-constructor, as necessary.
2899 InitializedEntity CopyEntity =
2901 InitializationKind CopyKind =
2903 InitializationSequence CopySeq(SemaRef.SemaRef, CopyEntity, CopyKind,
2904 Subscript,
2905 /*TopLevelOfInitList=*/true);
2906 ExprResult ElemRes =
2907 CopySeq.Perform(SemaRef.SemaRef, CopyEntity, CopyKind, Subscript);
2908 Args.push_back(ElemRes.get());
2909 }
2910
2911 Expr *InitExpr = new (getASTContext())
2912 InitListExpr(getASTContext(), VarExpr->getBeginLoc(), Args,
2913 VarExpr->getEndLoc(), /*isExplicit=*/false);
2914 InitExpr->setType(VarTy);
2915
2916 ExprResult Init = FinishValueInit(SemaRef.SemaRef, Entity,
2917 VarExpr->getBeginLoc(), VarTy, InitExpr);
2918
2919 // For 'no bounds' version, we can use this as a shortcut, so set the init
2920 // anyway.
2921 if (Init.isUsable()) {
2922 AllocaDecl->setInit(Init.get());
2923 AllocaDecl->setInitStyle(VarDecl::CallInit);
2924 }
2925
2926 return OpenACCFirstPrivateRecipe(AllocaDecl, Temporary);
2927}
2928
2930 OpenACCReductionOperator ReductionOperator, const Expr *VarExpr) {
2931 // We don't strip bounds here, so that we are doing our recipe init at the
2932 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2933 if (!VarExpr || VarExpr->getType()->isDependentType())
2935
2936 QualType VarTy =
2938
2939 // Array sections are special, and we have to treat them that way.
2940 if (const auto *ASE =
2941 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2942 VarTy = ASE->getElementType();
2943
2945
2946 // We use the 'set-ness' of the alloca-decl to determine whether the combiner
2947 // is 'set' or not, so we can skip any attempts at it if we're going to fail
2948 // at any of the combiners.
2949 if (CreateReductionCombinerRecipe(VarExpr->getBeginLoc(), ReductionOperator,
2950 VarTy, CombinerRecipes))
2952
2953 VarDecl *AllocaDecl = CreateAllocaDecl(
2954 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2955 &getASTContext().Idents.get("openacc.reduction.init"), VarTy);
2956
2959
2960 InitKind IK = InitKind::Invalid;
2961 switch (ReductionOperator) {
2963 // This can only happen when there is an error, and since these inits
2964 // are used for code generation, we can just ignore/not bother doing any
2965 // initialization here.
2966 IK = InitKind::Invalid;
2967 break;
2969 IK = InitKind::Least;
2970 break;
2972 IK = InitKind::Largest;
2973 break;
2975 IK = InitKind::AllOnes;
2976 break;
2979 IK = InitKind::One;
2980 break;
2985 IK = InitKind::Zero;
2986 break;
2987 }
2988
2989 Expr *InitExpr = GenerateReductionInitRecipeExpr(
2990 getASTContext(), VarExpr->getSourceRange(), VarTy, IK);
2991
2992 ExprResult Init = FinishValueInit(SemaRef.SemaRef, Entity,
2993 VarExpr->getBeginLoc(), VarTy, InitExpr);
2994
2995 // For 'no bounds' version, we can use this as a shortcut, so set the init
2996 // anyway.
2997 if (Init.isUsable()) {
2998 AllocaDecl->setInit(Init.get());
2999 AllocaDecl->setInitStyle(VarDecl::CallInit);
3000 }
3001
3002 return OpenACCReductionRecipeWithStorage(AllocaDecl, CombinerRecipes);
3003}
3004
3005bool SemaOpenACC::CreateReductionCombinerRecipe(
3006 SourceLocation Loc, OpenACCReductionOperator ReductionOperator,
3007 QualType VarTy,
3009 &CombinerRecipes) {
3010 // Now we can try to generate the 'combiner' recipe. This is a little
3011 // complicated in that if the 'VarTy' is an array type, we want to take its
3012 // element type so we can generate that. Additionally, if this is a struct,
3013 // we have two options: If there is overloaded operators, we want to take
3014 // THOSE, else we want to do the individual elements.
3015
3016 BinaryOperatorKind BinOp;
3017 switch (ReductionOperator) {
3019 // This can only happen when there is an error, and since these inits
3020 // are used for code generation, we can just ignore/not bother doing any
3021 // initialization here.
3022 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3023 return false;
3025 BinOp = BinaryOperatorKind::BO_AddAssign;
3026 break;
3028 BinOp = BinaryOperatorKind::BO_MulAssign;
3029 break;
3031 BinOp = BinaryOperatorKind::BO_AndAssign;
3032 break;
3034 BinOp = BinaryOperatorKind::BO_OrAssign;
3035 break;
3037 BinOp = BinaryOperatorKind::BO_XorAssign;
3038 break;
3039
3042 BinOp = BinaryOperatorKind::BO_LT;
3043 break;
3045 BinOp = BinaryOperatorKind::BO_LAnd;
3046 break;
3048 BinOp = BinaryOperatorKind::BO_LOr;
3049 break;
3050 }
3051
3052 // If VarTy is an array type, at the top level only, we want to do our
3053 // compares/decomp/etc at the element level.
3054 if (auto *AT = getASTContext().getAsArrayType(VarTy))
3055 VarTy = AT->getElementType();
3056
3057 assert(!VarTy->isArrayType() && "Only 1 level of array allowed");
3058
3059 enum class CombinerFailureKind {
3060 None = 0,
3061 BinOp = 1,
3062 Conditional = 2,
3063 Assignment = 3,
3064 };
3065
3066 auto genCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE)
3067 -> std::pair<ExprResult, CombinerFailureKind> {
3068 ExprResult BinOpRes =
3069 SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc, BinOp, LHSDRE, RHSDRE,
3070 /*ForFoldExpr=*/false);
3071 switch (ReductionOperator) {
3077 // These 5 are simple and are being done as compound operators, so we can
3078 // immediately quit here.
3079 return {BinOpRes, BinOpRes.isUsable() ? CombinerFailureKind::None
3080 : CombinerFailureKind::BinOp};
3083 // These are done as:
3084 // LHS = (LHS < RHS) ? LHS : RHS; and LHS = (LHS < RHS) ? RHS : LHS;
3085 //
3086 // The BinOpRes should have been created with the less-than, so we just
3087 // have to build the conditional and assignment.
3088 if (!BinOpRes.isUsable())
3089 return {BinOpRes, CombinerFailureKind::BinOp};
3090
3091 // Create the correct conditional operator, swapping the results
3092 // (true/false value) depending on min/max.
3093 ExprResult CondRes;
3094 if (ReductionOperator == OpenACCReductionOperator::Min)
3095 CondRes = SemaRef.ActOnConditionalOp(Loc, Loc, BinOpRes.get(), LHSDRE,
3096 RHSDRE);
3097 else
3098 CondRes = SemaRef.ActOnConditionalOp(Loc, Loc, BinOpRes.get(), RHSDRE,
3099 LHSDRE);
3100
3101 if (!CondRes.isUsable())
3102 return {CondRes, CombinerFailureKind::Conditional};
3103
3104 // Build assignment.
3105 ExprResult Assignment = SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc,
3106 BinaryOperatorKind::BO_Assign,
3107 LHSDRE, CondRes.get(),
3108 /*ForFoldExpr=*/false);
3109 return {Assignment, Assignment.isUsable()
3110 ? CombinerFailureKind::None
3111 : CombinerFailureKind::Assignment};
3112 }
3115 // These are done as LHS = LHS && RHS (or LHS = LHS || RHS). So after the
3116 // binop, all we have to do is the assignment.
3117 if (!BinOpRes.isUsable())
3118 return {BinOpRes, CombinerFailureKind::BinOp};
3119
3120 // Build assignment.
3121 ExprResult Assignment = SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc,
3122 BinaryOperatorKind::BO_Assign,
3123 LHSDRE, BinOpRes.get(),
3124 /*ForFoldExpr=*/false);
3125 return {Assignment, Assignment.isUsable()
3126 ? CombinerFailureKind::None
3127 : CombinerFailureKind::Assignment};
3128 }
3130 llvm_unreachable("Invalid should have been caught above");
3131 }
3132 llvm_unreachable("Unhandled case");
3133 };
3134
3135 auto tryCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE,
3136 bool IncludeTrap) {
3137 if (IncludeTrap) {
3138 // Trap all of the errors here, we'll emit our own at the end.
3139 Sema::TentativeAnalysisScope Trap{SemaRef};
3140 return genCombiner(LHSDRE, RHSDRE);
3141 }
3142 return genCombiner(LHSDRE, RHSDRE);
3143 };
3144
3145 struct CombinerAttemptTy {
3146 CombinerFailureKind FailKind;
3147 VarDecl *LHS;
3148 DeclRefExpr *LHSDRE;
3149 VarDecl *RHS;
3150 DeclRefExpr *RHSDRE;
3151 Expr *Op;
3152 };
3153
3154 auto formCombiner = [&, this](QualType Ty) -> CombinerAttemptTy {
3155 VarDecl *LHSDecl = CreateAllocaDecl(
3156 getASTContext(), SemaRef.getCurContext(), Loc,
3157 &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty);
3158 auto *LHSDRE = DeclRefExpr::Create(
3159 getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, LHSDecl,
3160 /*ReferstoEnclosingVariableOrCapture=*/false,
3161 DeclarationNameInfo{DeclarationName{LHSDecl->getDeclName()},
3162 LHSDecl->getBeginLoc()},
3163 Ty, clang::VK_LValue, LHSDecl, nullptr, NOUR_None);
3164 VarDecl *RHSDecl = CreateAllocaDecl(
3165 getASTContext(), SemaRef.getCurContext(), Loc,
3166 &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty);
3167 auto *RHSDRE = DeclRefExpr::Create(
3168 getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, RHSDecl,
3169 /*ReferstoEnclosingVariableOrCapture=*/false,
3170 DeclarationNameInfo{DeclarationName{RHSDecl->getDeclName()},
3171 RHSDecl->getBeginLoc()},
3172 Ty, clang::VK_LValue, RHSDecl, nullptr, NOUR_None);
3173
3174 std::pair<ExprResult, CombinerFailureKind> BinOpResult =
3175 tryCombiner(LHSDRE, RHSDRE, /*IncludeTrap=*/true);
3176
3177 return {BinOpResult.second, LHSDecl, LHSDRE, RHSDecl, RHSDRE,
3178 BinOpResult.first.get()};
3179 };
3180
3181 CombinerAttemptTy TopLevelCombinerInfo = formCombiner(VarTy);
3182
3183 if (TopLevelCombinerInfo.Op) {
3184 if (!TopLevelCombinerInfo.Op->containsErrors() &&
3185 TopLevelCombinerInfo.Op->isInstantiationDependent()) {
3186 // If this is instantiation dependent, we're just going to 'give up' here
3187 // and count on us to get it right during instantaition.
3188 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3189 return false;
3190 } else if (!TopLevelCombinerInfo.Op->containsErrors()) {
3191 // Else, we succeeded, we can just return this combiner.
3192 CombinerRecipes.push_back({TopLevelCombinerInfo.LHS,
3193 TopLevelCombinerInfo.RHS,
3194 TopLevelCombinerInfo.Op});
3195 return false;
3196 }
3197 }
3198
3199 auto EmitFailureNote = [&](CombinerFailureKind CFK) {
3200 if (CFK == CombinerFailureKind::BinOp)
3201 return Diag(Loc, diag::note_acc_reduction_combiner_forming)
3202 << CFK << BinaryOperator::getOpcodeStr(BinOp);
3203 return Diag(Loc, diag::note_acc_reduction_combiner_forming) << CFK;
3204 };
3205
3206 // Since the 'root' level didn't fail, the only thing that could be successful
3207 // is a struct that we decompose on its individual fields.
3208
3209 RecordDecl *RD = VarTy->getAsRecordDecl();
3210 if (!RD) {
3211 Diag(Loc, diag::err_acc_reduction_recipe_no_op) << VarTy;
3212 EmitFailureNote(TopLevelCombinerInfo.FailKind);
3213 tryCombiner(TopLevelCombinerInfo.LHSDRE, TopLevelCombinerInfo.RHSDRE,
3214 /*IncludeTrap=*/false);
3215 return true;
3216 }
3217
3218 for (const FieldDecl *FD : RD->fields()) {
3219 CombinerAttemptTy FieldCombinerInfo = formCombiner(FD->getType());
3220
3221 if (!FieldCombinerInfo.Op || FieldCombinerInfo.Op->containsErrors()) {
3222 Diag(Loc, diag::err_acc_reduction_recipe_no_op) << FD->getType();
3223 Diag(FD->getBeginLoc(), diag::note_acc_reduction_recipe_noop_field) << RD;
3224 EmitFailureNote(FieldCombinerInfo.FailKind);
3225 tryCombiner(FieldCombinerInfo.LHSDRE, FieldCombinerInfo.RHSDRE,
3226 /*IncludeTrap=*/false);
3227 return true;
3228 }
3229
3230 if (FieldCombinerInfo.Op->isInstantiationDependent()) {
3231 // If this is instantiation dependent, we're just going to 'give up' here
3232 // and count on us to get it right during instantaition.
3233 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3234 } else {
3235 CombinerRecipes.push_back(
3236 {FieldCombinerInfo.LHS, FieldCombinerInfo.RHS, FieldCombinerInfo.Op});
3237 }
3238 }
3239
3240 return false;
3241}
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:511
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
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:7231
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5405
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2727
QualType getElementType() const
Definition TypeBase.h:3833
StringRef getOpcodeStr() const
Definition Expr.h:4110
static CXXBoolLiteralExpr * Create(const ASTContext &C, bool Val, QualType Ty, SourceLocation Loc)
Definition ExprCXX.h:738
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2968
base_class_range bases()
Definition DeclCXX.h:608
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:494
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1640
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition Stmt.h:1653
const Decl * getSingleDecl() const
Definition Stmt.h:1655
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:831
This represents one expression.
Definition Expr.h:112
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:145
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:194
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3101
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition Expr.h:246
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:223
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:144
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Definition Expr.h:526
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:1082
Represents a function declaration or definition.
Definition Decl.h:2029
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:3727
bool isDeleted() const
Whether this function has been deleted.
Definition Decl.h:2576
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:2081
Describes an C or C++ initializer list.
Definition Expr.h:5314
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:981
This represents a decl that may have a name.
Definition Decl.h:274
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
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:5677
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:8674
QualType getCanonicalType() const
Definition TypeBase.h:8541
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8583
field_range fields() const
Definition Decl.h:4572
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3672
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:9390
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12644
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
@ Normal
Apply the normal rules for complete types.
Definition Sema.h:15229
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
Definition Sema.h:6833
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
SourceManager & SourceMgr
Definition Sema.h:1312
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:105
bool isDependentSizedArrayType() const
Definition TypeBase.h:8845
bool isBooleanType() const
Definition TypeBase.h:9229
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2293
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:8829
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArrayType() const
Definition TypeBase.h:8825
bool isPointerType() const
Definition TypeBase.h:8726
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9136
bool isEnumeralType() const
Definition TypeBase.h:8857
bool isScalarType() const
Definition TypeBase.h:9198
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:9086
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2855
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2847
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9372
bool isFunctionType() const
Definition TypeBase.h:8722
bool isFloatingType() const
Definition Type.cpp:2393
bool isAnyPointerType() const
Definition TypeBase.h:8734
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9319
bool isNullPtrType() const
Definition TypeBase.h:9129
bool isRecordType() const
Definition TypeBase.h:8853
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2132
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1476
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:940
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1214
void setInit(Expr *I)
Definition Decl.cpp:2458
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
The JSON file list parser is used to communicate input to InstallAPI.
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:668
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:152
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:125
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ SC_Auto
Definition Specifiers.h:257
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:140
U cast(CodeGen::Address addr)
Definition Address.h:327
@ None
The alignment was not explicit in code.
Definition ASTContext.h:176
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
@ NOUR_None
This is an odr-use.
Definition Specifiers.h:176
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:652
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:654
static OpenACCFirstPrivateRecipe Empty()
static OpenACCPrivateRecipe Empty()
static OpenACCReductionRecipeWithStorage Empty()