clang 23.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
1349 const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
1350 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1351 InitVar = DRE->getDecl();
1352 } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
1353 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1354 InitVar = ME->getMemberDecl();
1355 }
1356 }
1357
1358 // If after all of that, we haven't found a variable, give up.
1359 if (!InitVar)
1360 return DiagLoopVar();
1361
1362 InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
1363 QualType VarType = InitVar->getType().getNonReferenceType();
1364
1365 // Since we have one, all we need to do is ensure it is the right type.
1366 if (!isValidLoopVariableType(VarType)) {
1367 if (Diag) {
1368 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
1369 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
1370 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1371 diag::note_acc_construct_here)
1372 << SemaRef.LoopWithoutSeqInfo.Kind;
1373 }
1374 return true;
1375 }
1376
1377 return false;
1378}
1379
1380bool SemaOpenACC::ForStmtBeginChecker::checkForCond(const Stmt *CondStmt,
1381 const ValueDecl *InitVar,
1382 bool Diag) {
1383 // A condition statement is required.
1384 if (!CondStmt) {
1385 if (Diag) {
1386 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
1387 << SemaRef.LoopWithoutSeqInfo.Kind;
1388 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1389 diag::note_acc_construct_here)
1390 << SemaRef.LoopWithoutSeqInfo.Kind;
1391 }
1392
1393 return true;
1394 }
1395 auto DiagCondVar = [this, Diag, CondStmt] {
1396 if (Diag) {
1397 SemaRef.Diag(CondStmt->getBeginLoc(),
1398 diag::err_acc_loop_terminating_condition)
1399 << SemaRef.LoopWithoutSeqInfo.Kind;
1400 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1401 diag::note_acc_construct_here)
1402 << SemaRef.LoopWithoutSeqInfo.Kind;
1403 }
1404 return true;
1405 };
1406
1407 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(CondStmt))
1408 CondStmt = ExprTemp->getSubExpr();
1409 if (const auto *E = dyn_cast<Expr>(CondStmt))
1410 CondStmt = E->IgnoreParenImpCasts();
1411
1412 const ValueDecl *CondVar = nullptr;
1413 if (const auto *BO = dyn_cast<BinaryOperator>(CondStmt)) {
1414 switch (BO->getOpcode()) {
1415 default:
1416 return DiagCondVar();
1417 case BO_EQ:
1418 case BO_LT:
1419 case BO_GT:
1420 case BO_NE:
1421 case BO_LE:
1422 case BO_GE:
1423 break;
1424 }
1425
1426 // Assign the condition-var to the LHS. If it either comes back null, or
1427 // the LHS doesn't match the InitVar, assign it to the RHS so that 5 < N is
1428 // allowed.
1429 CondVar = getDeclFromExpr(BO->getLHS());
1430 if (!CondVar ||
1431 (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl()))
1432 CondVar = getDeclFromExpr(BO->getRHS());
1433
1434 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(CondStmt)) {
1435 // Any of the comparison ops should be ok here, but we don't know how to
1436 // handle spaceship, so disallow for now.
1437 if (!CE->isComparisonOp() || CE->getOperator() == OO_Spaceship)
1438 return DiagCondVar();
1439
1440 // Same logic here: Assign it to the LHS, unless the LHS comes back null or
1441 // not equal to the init var.
1442 CondVar = getDeclFromExpr(CE->getArg(0));
1443 if (!CondVar ||
1444 (InitVar &&
1445 CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl() &&
1446 CE->getNumArgs() > 1))
1447 CondVar = getDeclFromExpr(CE->getArg(1));
1448 } else {
1449 return DiagCondVar();
1450 }
1451
1452 if (!CondVar)
1453 return DiagCondVar();
1454
1455 // Don't consider this an error unless the init variable was properly set,
1456 // else check to make sure they are the same variable.
1457 if (InitVar && CondVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1458 return DiagCondVar();
1459
1460 return false;
1461}
1462
1463namespace {
1464// Helper to check the RHS of an assignment during for's step. We can allow
1465// InitVar = InitVar + N, InitVar = N + InitVar, and Initvar = Initvar - N,
1466// where N is an integer.
1467bool isValidForIncRHSAssign(const ValueDecl *InitVar, const Expr *RHS) {
1468
1469 auto isValid = [](const ValueDecl *InitVar, const Expr *InnerLHS,
1470 const Expr *InnerRHS, bool IsAddition) {
1471 // ONE of the sides has to be an integer type.
1472 if (!InnerLHS->getType()->isIntegerType() &&
1473 !InnerRHS->getType()->isIntegerType())
1474 return false;
1475
1476 // If the init var is already an error, don't bother trying to check for
1477 // it.
1478 if (!InitVar)
1479 return true;
1480
1481 const ValueDecl *LHSDecl = getDeclFromExpr(InnerLHS);
1482 const ValueDecl *RHSDecl = getDeclFromExpr(InnerRHS);
1483 // If we can't get a declaration, this is probably an error, so give up.
1484 if (!LHSDecl || !RHSDecl)
1485 return true;
1486
1487 // If the LHS is the InitVar, the other must be int, so this is valid.
1488 if (LHSDecl->getCanonicalDecl() ==
1489 InitVar->getCanonicalDecl())
1490 return true;
1491
1492 // Subtraction doesn't allow the RHS to be init var, so this is invalid.
1493 if (!IsAddition)
1494 return false;
1495
1496 return RHSDecl->getCanonicalDecl() ==
1497 InitVar->getCanonicalDecl();
1498 };
1499
1500 if (const auto *BO = dyn_cast<BinaryOperator>(RHS)) {
1501 BinaryOperatorKind OpC = BO->getOpcode();
1502 if (OpC != BO_Add && OpC != BO_Sub)
1503 return false;
1504 return isValid(InitVar, BO->getLHS(), BO->getRHS(), OpC == BO_Add);
1505 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
1506 OverloadedOperatorKind Op = CE->getOperator();
1507 if (Op != OO_Plus && Op != OO_Minus)
1508 return false;
1509 return isValid(InitVar, CE->getArg(0), CE->getArg(1), Op == OO_Plus);
1510 }
1511
1512 return false;
1513}
1514} // namespace
1515
1516bool SemaOpenACC::ForStmtBeginChecker::checkForInc(const Stmt *IncStmt,
1517 const ValueDecl *InitVar,
1518 bool Diag) {
1519 if (!IncStmt) {
1520 if (Diag) {
1521 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
1522 << SemaRef.LoopWithoutSeqInfo.Kind;
1523 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
1524 diag::note_acc_construct_here)
1525 << SemaRef.LoopWithoutSeqInfo.Kind;
1526 }
1527 return true;
1528 }
1529 auto DiagIncVar = [this, Diag, IncStmt] {
1530 if (Diag) {
1531 SemaRef.Diag(IncStmt->getBeginLoc(), 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
1540 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(IncStmt))
1541 IncStmt = ExprTemp->getSubExpr();
1542 if (const auto *E = dyn_cast<Expr>(IncStmt))
1543 IncStmt = E->IgnoreParenImpCasts();
1544
1545 const ValueDecl *IncVar = nullptr;
1546 // Here we enforce the monotonically increase/decrease:
1547 if (const auto *UO = dyn_cast<UnaryOperator>(IncStmt)) {
1548 // Allow increment/decrement ops.
1549 if (!UO->isIncrementDecrementOp())
1550 return DiagIncVar();
1551 IncVar = getDeclFromExpr(UO->getSubExpr());
1552 } else if (const auto *BO = dyn_cast<BinaryOperator>(IncStmt)) {
1553 switch (BO->getOpcode()) {
1554 default:
1555 return DiagIncVar();
1556 case BO_AddAssign:
1557 case BO_SubAssign:
1558 break;
1559 case BO_Assign:
1560 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1561 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1562 if (!isValidForIncRHSAssign(InitVar, BO->getRHS()))
1563 return DiagIncVar();
1564 break;
1565 }
1566 IncVar = getDeclFromExpr(BO->getLHS());
1567 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(IncStmt)) {
1568 switch (CE->getOperator()) {
1569 default:
1570 return DiagIncVar();
1571 case OO_PlusPlus:
1572 case OO_MinusMinus:
1573 case OO_PlusEqual:
1574 case OO_MinusEqual:
1575 break;
1576 case OO_Equal:
1577 // For assignment we also allow InitVar = InitVar + N, InitVar = N +
1578 // InitVar, and InitVar = InitVar - N; BUT only if 'N' is integral.
1579 if (!isValidForIncRHSAssign(InitVar, CE->getArg(1)))
1580 return DiagIncVar();
1581 break;
1582 }
1583
1584 IncVar = getDeclFromExpr(CE->getArg(0));
1585 } else {
1586 return DiagIncVar();
1587 }
1588
1589 if (!IncVar)
1590 return DiagIncVar();
1591
1592 // InitVar shouldn't be null unless there was an error, so don't diagnose if
1593 // that is the case. Else we should ensure that it refers to the loop
1594 // value.
1595 if (InitVar && IncVar->getCanonicalDecl() != InitVar->getCanonicalDecl())
1596 return DiagIncVar();
1597
1598 return false;
1599}
1600
1601void SemaOpenACC::ForStmtBeginChecker::checkFor() {
1602 const CheckForInfo &CFI = std::get<CheckForInfo>(Info);
1603
1604 if (!IsInstantiation) {
1605 // If this isn't an instantiation, we can just check all of these and
1606 // diagnose.
1607 const ValueDecl *CurInitVar = nullptr;
1608 checkForInit(CFI.Current.Init, CurInitVar, /*Diag=*/true);
1609 checkForCond(CFI.Current.Condition, CurInitVar, /*Diag=*/true);
1610 checkForInc(CFI.Current.Increment, CurInitVar, /*DIag=*/true);
1611 } else {
1612 const ValueDecl *UninstInitVar = nullptr;
1613 // Checking the 'init' section first. We have to always run both versions,
1614 // at minimum with the 'diag' off, so that we can ensure we get the correct
1615 // instantiation var for checking by later ones.
1616 bool UninstInitFailed =
1617 checkForInit(CFI.Uninst.Init, UninstInitVar, /*Diag=*/false);
1618
1619 // VarDecls are always rebuild because they are dependent, so we can do a
1620 // little work to suppress some of the double checking based on whether the
1621 // type is instantiation dependent. This is imperfect, but will get us most
1622 // cases suppressed. Currently this only handles the 'T t =' case.
1623 auto InitChanged = [=]() {
1624 if (CFI.Uninst.Init == CFI.Current.Init)
1625 return false;
1626
1627 QualType OldVDTy;
1628 QualType NewVDTy;
1629
1630 if (const auto *DS = dyn_cast<DeclStmt>(CFI.Uninst.Init))
1631 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1632 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1633 OldVDTy = VD->getType();
1634 if (const auto *DS = dyn_cast<DeclStmt>(CFI.Current.Init))
1635 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1636 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1637 NewVDTy = VD->getType();
1638
1639 if (OldVDTy.isNull() || NewVDTy.isNull())
1640 return true;
1641
1642 return OldVDTy->isInstantiationDependentType() !=
1644 };
1645
1646 // Only diagnose the new 'init' if the previous version didn't fail, AND the
1647 // current init changed meaningfully.
1648 bool ShouldDiagNewInit = !UninstInitFailed && InitChanged();
1649 const ValueDecl *CurInitVar = nullptr;
1650 checkForInit(CFI.Current.Init, CurInitVar, /*Diag=*/ShouldDiagNewInit);
1651
1652 // Check the condition and increment only if the previous version passed,
1653 // and this changed.
1654 if (CFI.Uninst.Condition != CFI.Current.Condition &&
1655 !checkForCond(CFI.Uninst.Condition, UninstInitVar, /*Diag=*/false))
1656 checkForCond(CFI.Current.Condition, CurInitVar, /*Diag=*/true);
1657 if (CFI.Uninst.Increment != CFI.Current.Increment &&
1658 !checkForInc(CFI.Uninst.Increment, UninstInitVar, /*Diag=*/false))
1659 checkForInc(CFI.Current.Increment, CurInitVar, /*Diag=*/true);
1660 }
1661}
1662
1663void SemaOpenACC::ForStmtBeginChecker::check() {
1664 // If this isn't an active loop without a seq, immediately return, nothing to
1665 // check.
1666 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
1667 return;
1668
1669 // If we've already checked, because this is a 'top level' one (and asking
1670 // again because 'tile' and 'collapse' might apply), just return, nothing to
1671 // do here.
1672 if (AlreadyChecked)
1673 return;
1674 AlreadyChecked = true;
1675
1676 // OpenACC3.3 2.1:
1677 // A loop associated with a loop construct that does not have a seq clause
1678 // must be written to meet all the following conditions:
1679 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
1680 // iterator type.
1681 // - The loop variable must monotonically increase or decrease in the
1682 // direction of its termination condition.
1683 // - The loop trip count must be computable in constant time when entering the
1684 // loop construct.
1685 //
1686 // For a C++ range-based for loop, the loop variable
1687 // identified by the above conditions is the internal iterator, such as a
1688 // pointer, that the compiler generates to iterate the range. it is not the
1689 // variable declared by the for loop.
1690
1691 if (std::holds_alternative<RangeForInfo>(Info))
1692 return checkRangeFor();
1693
1694 return checkFor();
1695}
1696
1698 const Stmt *First, const Stmt *OldSecond,
1699 const Stmt *Second, const Stmt *OldThird,
1700 const Stmt *Third) {
1701 if (!getLangOpts().OpenACC)
1702 return;
1703
1704 ForStmtBeginChecker FSBC{*this, ForLoc, OldFirst, OldSecond,
1705 OldThird, First, Second, Third};
1706 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1707 // as a part of the helper if a tile/collapse applies.
1708 if (!LoopInfo.TopLevelLoopSeen) {
1709 FSBC.check();
1710 }
1711
1712 ForStmtBeginHelper(ForLoc, FSBC);
1713}
1714
1716 const Stmt *Second, const Stmt *Third) {
1717 if (!getLangOpts().OpenACC)
1718 return;
1719
1720 ForStmtBeginChecker FSBC{*this, ForLoc, First, Second, Third};
1721
1722 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1723 // as a part of the helper if a tile/collapse applies.
1724 if (!LoopInfo.TopLevelLoopSeen)
1725 FSBC.check();
1726
1727 ForStmtBeginHelper(ForLoc, FSBC);
1728}
1729
1731 const Stmt *OldRangeFor,
1732 const Stmt *RangeFor) {
1733 if (!getLangOpts().OpenACC || OldRangeFor == nullptr || RangeFor == nullptr)
1734 return;
1735
1736 ForStmtBeginChecker FSBC{*this, ForLoc,
1737 cast_if_present<CXXForRangeStmt>(OldRangeFor),
1738 cast_if_present<CXXForRangeStmt>(RangeFor)};
1739 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1740 // as a part of the helper if a tile/collapse applies.
1741 if (!LoopInfo.TopLevelLoopSeen) {
1742 FSBC.check();
1743 }
1744 ForStmtBeginHelper(ForLoc, FSBC);
1745}
1746
1748 const Stmt *RangeFor) {
1749 if (!getLangOpts().OpenACC || RangeFor == nullptr)
1750 return;
1751
1752 ForStmtBeginChecker FSBC = {*this, ForLoc,
1753 cast_if_present<CXXForRangeStmt>(RangeFor)};
1754
1755 // Check if this is the top-level 'for' for a 'loop'. Else it will be checked
1756 // as a part of the helper if a tile/collapse applies.
1757 if (!LoopInfo.TopLevelLoopSeen)
1758 FSBC.check();
1759
1760 ForStmtBeginHelper(ForLoc, FSBC);
1761}
1762
1763namespace {
1764SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
1765 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
1766 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
1767 // `DoStmt`, as those are caught as a violation elsewhere.
1768 // For `CompoundStmt` we need to search inside of it.
1769 if (!CurStmt ||
1771 CurStmt))
1772 return SourceLocation{};
1773
1774 // Any other construct is an error anyway, so it has already been diagnosed.
1775 if (isa<OpenACCConstructStmt>(CurStmt))
1776 return SourceLocation{};
1777
1778 // Search inside the compound statement, this allows for arbitrary nesting
1779 // of compound statements, as long as there isn't any code inside.
1780 if (const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
1781 for (const auto *ChildStmt : CS->children()) {
1782 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
1783 if (ChildStmtLoc.isValid())
1784 return ChildStmtLoc;
1785 }
1786 // Empty/not invalid compound statements are legal.
1787 return SourceLocation{};
1788 }
1789 return CurStmt->getBeginLoc();
1790}
1791} // namespace
1792
1794 if (!getLangOpts().OpenACC)
1795 return;
1796
1797 // Set this to 'true' so if we find another one at this level we can diagnose.
1798 LoopInfo.CurLevelHasLoopAlready = true;
1799
1800 if (!Body.isUsable())
1801 return;
1802
1803 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
1804 *CollapseInfo.CurCollapseCount > 0 &&
1805 !CollapseInfo.ActiveCollapse->hasForce();
1806 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
1807
1808 if (IsActiveCollapse || IsActiveTile) {
1809 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());
1810
1811 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
1812 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1813 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
1814 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
1815 diag::note_acc_active_clause_here)
1817 }
1818
1819 if (OtherStmtLoc.isValid() && IsActiveTile) {
1820 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
1821 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
1822 Diag(TileInfo.ActiveTile->getBeginLoc(),
1823 diag::note_acc_active_clause_here)
1825 }
1826 }
1827}
1828
1829namespace {
1830// Helper that should mirror ActOnRoutineName to get the FunctionDecl out for
1831// magic-static checking.
1832FunctionDecl *getFunctionFromRoutineName(Expr *RoutineName) {
1833 if (!RoutineName)
1834 return nullptr;
1835 RoutineName = RoutineName->IgnoreParenImpCasts();
1836 if (isa<RecoveryExpr>(RoutineName)) {
1837 // There is nothing we can do here, this isn't a function we can count on.
1838 return nullptr;
1840 RoutineName)) {
1841 // The lookup is dependent, so we'll have to figure this out later.
1842 return nullptr;
1843 } else if (auto *DRE = dyn_cast<DeclRefExpr>(RoutineName)) {
1844 ValueDecl *VD = DRE->getDecl();
1845
1846 if (auto *FD = dyn_cast<FunctionDecl>(VD))
1847 return FD;
1848
1849 // Allow lambdas.
1850 if (auto *VarD = dyn_cast<VarDecl>(VD)) {
1851 QualType VarDTy = VarD->getType();
1852 if (!VarDTy.isNull()) {
1853 if (auto *RD = VarDTy->getAsCXXRecordDecl()) {
1854 if (RD->isGenericLambda())
1855 return nullptr;
1856 if (RD->isLambda())
1857 return RD->getLambdaCallOperator();
1858 } else if (VarDTy->isDependentType()) {
1859 // We don't really know what this is going to be.
1860 return nullptr;
1861 }
1862 }
1863 return nullptr;
1864 } else if (isa<OverloadExpr>(RoutineName)) {
1865 return nullptr;
1866 }
1867 }
1868 return nullptr;
1869}
1870} // namespace
1871
1873 assert(RoutineName && "Routine name cannot be null here");
1874 RoutineName = RoutineName->IgnoreParenImpCasts();
1875
1876 if (isa<RecoveryExpr>(RoutineName)) {
1877 // This has already been diagnosed, so we can skip it.
1878 return ExprError();
1880 RoutineName)) {
1881 // These are dependent and we can't really check them, so delay until
1882 // instantiation.
1883 return RoutineName;
1884 } else if (const auto *DRE = dyn_cast<DeclRefExpr>(RoutineName)) {
1885 const ValueDecl *VD = DRE->getDecl();
1886
1887 if (isa<FunctionDecl>(VD))
1888 return RoutineName;
1889
1890 // Allow lambdas.
1891 if (const auto *VarD = dyn_cast<VarDecl>(VD)) {
1892 QualType VarDTy = VarD->getType();
1893 if (!VarDTy.isNull()) {
1894 if (const auto *RD = VarDTy->getAsCXXRecordDecl()) {
1895 if (RD->isGenericLambda()) {
1896 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1897 << RoutineName;
1898 return ExprError();
1899 }
1900 if (RD->isLambda())
1901 return RoutineName;
1902 } else if (VarDTy->isDependentType()) {
1903 // If this is a dependent variable, it might be a lambda. So we just
1904 // accept this and catch it next time.
1905 return RoutineName;
1906 }
1907 }
1908 }
1909
1910 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1911 << RoutineName;
1912 return ExprError();
1913 } else if (isa<OverloadExpr>(RoutineName)) {
1914 // This happens in function templates, even when the template arguments are
1915 // fully specified. We could possibly do some sort of matching to make sure
1916 // that this is looked up/deduced, but GCC does not do this, so there
1917 // doesn't seem to be a good reason for us to do it either.
1918 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_overload_set)
1919 << RoutineName;
1920 return ExprError();
1921 }
1922
1923 Diag(RoutineName->getBeginLoc(), diag::err_acc_routine_not_func)
1924 << RoutineName;
1925 return ExprError();
1926}
1928 if (!getLangOpts().OpenACC || VD->isInvalidDecl() || !VD->isStaticLocal())
1929 return;
1930
1931 // This cast should be safe, since a static-local can only happen in a
1932 // function declaration. However, in error cases (or perhaps ObjC/C++?), this
1933 // could possibly be something like a 'block' decl, so if this is NOT a
1934 // function decl, just give up.
1935 auto *ContextDecl = dyn_cast<FunctionDecl>(getCurContext());
1936
1937 if (!ContextDecl)
1938 return;
1939
1940 // OpenACC 3.3 2.15:
1941 // In C and C++, function static variables are not supported in functions to
1942 // which a routine directive applies.
1943 for (const auto *A : ContextDecl->attrs()) {
1945 Diag(VD->getBeginLoc(), diag::err_acc_magic_static_in_routine);
1946 Diag(A->getLocation(), diag::note_acc_construct_here)
1948 return;
1949 }
1950 }
1951
1952 MagicStaticLocs.insert({ContextDecl->getCanonicalDecl(), VD->getBeginLoc()});
1953}
1954void SemaOpenACC::CheckLastRoutineDeclNameConflict(const NamedDecl *ND) {
1955 // OpenACC 3.3 A.3.4
1956 // When a procedure with that name is in scope and it is not the same
1957 // procedure as the immediately following procedure declaration or
1958 // definition, the resolution of the name can be confusing. Implementations
1959 // should then issue a compile-time warning diagnostic even though the
1960 // application is conforming.
1961
1962 // If we haven't created one, also can't diagnose.
1963 if (!LastRoutineDecl)
1964 return;
1965
1966 // If the currently created function doesn't have a name, we can't diagnose on
1967 // a match.
1968 if (!ND->getDeclName().isIdentifier())
1969 return;
1970
1971 // If the two are in different decl contexts, it doesn't make sense to
1972 // diagnose.
1973 if (LastRoutineDecl->getDeclContext() != ND->getLexicalDeclContext())
1974 return;
1975
1976 // If we don't have a referenced thing yet, we can't diagnose.
1977 FunctionDecl *RoutineTarget =
1978 getFunctionFromRoutineName(LastRoutineDecl->getFunctionReference());
1979 if (!RoutineTarget)
1980 return;
1981
1982 // If the Routine target doesn't have a name, we can't diagnose.
1983 if (!RoutineTarget->getDeclName().isIdentifier())
1984 return;
1985
1986 // Of course don't diagnose if the names don't match.
1987 if (ND->getName() != RoutineTarget->getName())
1988 return;
1989
1991 long LastLine =
1993
1994 // Do some line-number math to make sure they are within a line of eachother.
1995 // Comments or newlines can be inserted to clarify intent.
1996 if (NDLine - LastLine > 1)
1997 return;
1998
1999 // Don't warn if it actually DOES apply to this function via redecls.
2000 if (ND->getCanonicalDecl() == RoutineTarget->getCanonicalDecl())
2001 return;
2002
2003 Diag(LastRoutineDecl->getFunctionReference()->getBeginLoc(),
2004 diag::warn_acc_confusing_routine_name);
2005 Diag(RoutineTarget->getBeginLoc(), diag::note_previous_decl) << ND;
2006}
2007
2009 if (!VD || !getLangOpts().OpenACC || InitType.isNull())
2010 return;
2011
2012 // To avoid double-diagnostic, just diagnose this during instantiation. We'll
2013 // get 1 warning per instantiation, but this permits us to be more sensible
2014 // for cases where the lookup is confusing.
2016 return;
2017
2018 const auto *RD = InitType->getAsCXXRecordDecl();
2019 // If this isn't a lambda, no sense in diagnosing.
2020 if (!RD || !RD->isLambda())
2021 return;
2022
2023 CheckLastRoutineDeclNameConflict(VD);
2024}
2025
2027 if (!FD || !getLangOpts().OpenACC)
2028 return;
2029 CheckLastRoutineDeclNameConflict(FD);
2030}
2031
2035
2036 // Declaration directives an appear in a statement location, so call into that
2037 // function here.
2039 return ActOnStartDeclDirective(K, StartLoc, Clauses);
2040
2041 SemaRef.DiscardCleanupsInEvaluationContext();
2042 SemaRef.PopExpressionEvaluationContext();
2043
2044 // OpenACC 3.3 2.9.1:
2045 // Intervening code must not contain other OpenACC directives or calls to API
2046 // routines.
2047 //
2048 // ALL constructs are ill-formed if there is an active 'collapse'
2049 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
2050 Diag(StartLoc, diag::err_acc_invalid_in_loop)
2051 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
2053 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2054 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2055 diag::note_acc_active_clause_here)
2057 }
2058 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
2059 Diag(StartLoc, diag::err_acc_invalid_in_loop)
2060 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
2062 assert(TileInfo.ActiveTile && "Tile count without object?");
2063 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
2065 }
2066
2067 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
2068 return true;
2069 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
2070}
2071
2074 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
2075 OpenACCAtomicKind AtomicKind, SourceLocation RParenLoc,
2077 StmtResult AssocStmt) {
2078 switch (K) {
2080 return StmtError();
2084 return OpenACCComputeConstruct::Create(
2085 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
2086 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2087 }
2092 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
2093 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2094 }
2097 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
2098 EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2099 }
2102 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
2103 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2104 }
2106 return OpenACCEnterDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
2107 EndLoc, Clauses);
2108 }
2110 return OpenACCExitDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
2111 EndLoc, Clauses);
2112 }
2115 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
2116 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2117 }
2120 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
2121 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
2122 }
2124 return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc,
2125 EndLoc, Clauses);
2126 }
2128 return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
2129 EndLoc, Clauses);
2130 }
2132 return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
2133 EndLoc, Clauses);
2134 }
2136 return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
2137 EndLoc, Clauses);
2138 }
2141 getASTContext(), StartLoc, DirLoc, AtomicKind, EndLoc, Clauses,
2142 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
2143 }
2145 assert(Clauses.empty() && "Cache doesn't allow clauses");
2146 return OpenACCCacheConstruct::Create(getASTContext(), StartLoc, DirLoc,
2147 LParenLoc, MiscLoc, Exprs, RParenLoc,
2148 EndLoc);
2149 }
2151 llvm_unreachable("routine shouldn't handled here");
2153 // Declare and routine arei declaration directives, but can be used here as
2154 // long as we wrap it in a DeclStmt. So make sure we do that here.
2155 DeclGroupRef DR = ActOnEndDeclDirective(K, StartLoc, DirLoc, LParenLoc,
2156 RParenLoc, EndLoc, Clauses);
2157
2158 return SemaRef.ActOnDeclStmt(DeclGroupPtrTy::make(DR), StartLoc, EndLoc);
2159 }
2160 }
2161 llvm_unreachable("Unhandled case in directive handling?");
2162}
2163
2165 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
2167 StmtResult AssocStmt) {
2168 switch (K) {
2169 default:
2170 llvm_unreachable("Unimplemented associated statement application");
2178 llvm_unreachable(
2179 "these don't have associated statements, so shouldn't get here");
2181 return CheckAtomicAssociatedStmt(DirectiveLoc, AtKind, AssocStmt);
2187 // There really isn't any checking here that could happen. As long as we
2188 // have a statement to associate, this should be fine.
2189 // OpenACC 3.3 Section 6:
2190 // Structured Block: in C or C++, an executable statement, possibly
2191 // compound, with a single entry at the top and a single exit at the
2192 // bottom.
2193 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
2194 // an interpretation of it is to allow this and treat the initializer as
2195 // the 'structured block'.
2196 return AssocStmt;
2201 if (!AssocStmt.isUsable())
2202 return StmtError();
2203
2204 if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
2205 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
2206 << K;
2207 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
2208 return StmtError();
2209 }
2210
2211 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
2212 if (!CollapseInfo.CollapseDepthSatisfied) {
2213 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2215 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2216 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2217 diag::note_acc_active_clause_here)
2219 }
2220
2221 if (!TileInfo.TileDepthSatisfied) {
2222 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
2224 assert(TileInfo.ActiveTile && "Collapse count without object?");
2225 Diag(TileInfo.ActiveTile->getBeginLoc(),
2226 diag::note_acc_active_clause_here)
2228 }
2229 return StmtError();
2230 }
2231
2232 return AssocStmt.get();
2233 }
2234 llvm_unreachable("Invalid associated statement application");
2235}
2236
2237namespace {
2238
2239// Routine has some pretty complicated set of rules for how device_type
2240// interacts with 'gang', 'worker', 'vector', and 'seq'. Enforce part of it
2241// here.
2242bool CheckValidRoutineGangWorkerVectorSeqClauses(
2243 SemaOpenACC &SemaRef, SourceLocation DirectiveLoc,
2245 auto RequiredPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
2247 // The clause handling has assured us that there is no duplicates. That is,
2248 // if there is 1 before a device_type, there are none after a device_type.
2249 // If not, there is at most 1 applying to each device_type.
2250
2251 // What is left to legalize is that either:
2252 // 1- there is 1 before the first device_type.
2253 // 2- there is 1 AFTER each device_type.
2254 auto *FirstDeviceType =
2255 llvm::find_if(Clauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
2256
2257 // If there is 1 before the first device_type (or at all if no device_type),
2258 // we are legal.
2259 auto *ClauseItr =
2260 std::find_if(Clauses.begin(), FirstDeviceType, RequiredPred);
2261
2262 if (ClauseItr != FirstDeviceType)
2263 return false;
2264
2265 // If there IS no device_type, and no clause, diagnose.
2266 if (FirstDeviceType == Clauses.end())
2267 return SemaRef.Diag(DirectiveLoc, diag::err_acc_construct_one_clause_of)
2269 << "'gang', 'seq', 'vector', or 'worker'";
2270
2271 // Else, we have to check EACH device_type group. PrevDeviceType is the
2272 // device-type before the current group.
2273 auto *PrevDeviceType = FirstDeviceType;
2274
2275 while (PrevDeviceType != Clauses.end()) {
2276 auto *NextDeviceType =
2277 std::find_if(std::next(PrevDeviceType), Clauses.end(),
2278 llvm::IsaPred<OpenACCDeviceTypeClause>);
2279
2280 ClauseItr = std::find_if(PrevDeviceType, NextDeviceType, RequiredPred);
2281
2282 if (ClauseItr == NextDeviceType)
2283 return SemaRef.Diag((*PrevDeviceType)->getBeginLoc(),
2284 diag::err_acc_clause_routine_one_of_in_region);
2285
2286 PrevDeviceType = NextDeviceType;
2287 }
2288
2289 return false;
2290}
2291} // namespace
2292
2296 // OpenCC3.3 2.1 (line 889)
2297 // A program must not depend on the order of evaluation of expressions in
2298 // clause arguments or on any side effects of the evaluations.
2299 SemaRef.DiscardCleanupsInEvaluationContext();
2300 SemaRef.PopExpressionEvaluationContext();
2301
2302 if (DiagnoseRequiredClauses(K, StartLoc, Clauses))
2303 return true;
2305 CheckValidRoutineGangWorkerVectorSeqClauses(*this, StartLoc, Clauses))
2306 return true;
2307
2308 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
2309}
2310
2313 SourceLocation LParenLoc, SourceLocation RParenLoc, SourceLocation EndLoc,
2314 ArrayRef<OpenACCClause *> Clauses) {
2315 switch (K) {
2316 default:
2318 return DeclGroupRef{};
2320 // OpenACC3.3 2.13: At least one clause must appear on a declare directive.
2321 if (Clauses.empty()) {
2322 Diag(EndLoc, diag::err_acc_declare_required_clauses);
2323 // No reason to add this to the AST, as we would just end up trying to
2324 // instantiate this, which would double-diagnose here, which we wouldn't
2325 // want to do.
2326 return DeclGroupRef{};
2327 }
2328
2329 auto *DeclareDecl = OpenACCDeclareDecl::Create(
2330 getASTContext(), getCurContext(), StartLoc, DirLoc, EndLoc, Clauses);
2331 DeclareDecl->setAccess(AS_public);
2332 getCurContext()->addDecl(DeclareDecl);
2333 return DeclGroupRef{DeclareDecl};
2334 }
2336 llvm_unreachable("routine shouldn't be handled here");
2337 }
2338 llvm_unreachable("unhandled case in directive handling?");
2339}
2340
2341namespace {
2342// Given the decl on the next line, figure out if it is one that is acceptable
2343// to `routine`, or looks like the sort of decl we should be diagnosing against.
2344FunctionDecl *LegalizeNextParsedDecl(Decl *D) {
2345 if (!D)
2346 return nullptr;
2347
2348 // Functions are per-fact acceptable as-is.
2349 if (auto *FD = dyn_cast<FunctionDecl>(D))
2350 return FD;
2351
2352 // Function templates are functions, so attach to the templated decl.
2353 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
2354 return FTD->getTemplatedDecl();
2355
2356 if (auto *FD = dyn_cast<FieldDecl>(D)) {
2357 auto *RD =
2358 FD->getType().isNull() ? nullptr : FD->getType()->getAsCXXRecordDecl();
2359
2360 if (RD && RD->isGenericLambda())
2361 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2362 if (RD && RD->isLambda())
2363 return RD->getLambdaCallOperator();
2364 }
2365 // VarDecl we can look at the init instead of the type of the variable, this
2366 // makes us more tolerant of the 'auto' deduced type.
2367 if (auto *VD = dyn_cast<VarDecl>(D)) {
2368 Expr *Init = VD->getInit();
2369 if (!Init || Init->getType().isNull())
2370 return nullptr;
2371
2372 const auto *RD = Init->getType()->getAsCXXRecordDecl();
2373 if (RD && RD->isGenericLambda())
2374 return RD->getDependentLambdaCallOperator()->getTemplatedDecl();
2375 if (RD && RD->isLambda())
2376 return RD->getLambdaCallOperator();
2377
2378 // FIXME: We could try harder in the case where this is a dependent thing
2379 // that ends up being a lambda (that is, the init is an unresolved lookup
2380 // expr), but we can't attach to the call/lookup expr. If we instead try to
2381 // attach to the VarDecl, when we go to instantiate it, attributes are
2382 // instantiated before the init, so we can't actually see the type at any
2383 // point where it would be relevant/able to be checked. We could perhaps do
2384 // some sort of 'after-init' instantiation/checking here, but that doesn't
2385 // seem valuable for a situation that other compilers don't handle.
2386 }
2387 return nullptr;
2388}
2389
2390void CreateRoutineDeclAttr(SemaOpenACC &SemaRef, SourceLocation DirLoc,
2391 ArrayRef<const OpenACCClause *> Clauses,
2392 ValueDecl *AddTo) {
2393 OpenACCRoutineDeclAttr *A =
2394 OpenACCRoutineDeclAttr::Create(SemaRef.getASTContext(), DirLoc);
2395 A->Clauses.assign(Clauses.begin(), Clauses.end());
2396 AddTo->addAttr(A);
2397}
2398} // namespace
2399
2400// Variant that adds attributes, because this is the unnamed case.
2403 Decl *NextParsedDecl) {
2404
2405 FunctionDecl *NextParsedFDecl = LegalizeNextParsedDecl(NextParsedDecl);
2406
2407 if (!NextParsedFDecl) {
2408 // If we don't have a valid 'next thing', just diagnose.
2409 SemaRef.Diag(DirLoc, diag::err_acc_decl_for_routine);
2410 return;
2411 }
2412
2413 // OpenACC 3.3 2.15:
2414 // In C and C++, function static variables are not supported in functions to
2415 // which a routine directive applies.
2416 if (auto Itr = MagicStaticLocs.find(NextParsedFDecl->getCanonicalDecl());
2417 Itr != MagicStaticLocs.end()) {
2418 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2419 Diag(DirLoc, diag::note_acc_construct_here)
2421
2422 return;
2423 }
2424
2425 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
2426 if (BindItr != Clauses.end()) {
2427 for (auto *A : NextParsedFDecl->attrs()) {
2428 // OpenACC 3.3 2.15:
2429 // If a procedure has a bind clause on both the declaration and definition
2430 // than they both must bind to the same name.
2431 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2432 auto OtherBindItr =
2433 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2434 if (OtherBindItr != RA->Clauses.end() &&
2435 (*cast<OpenACCBindClause>(*BindItr)) !=
2436 (*cast<OpenACCBindClause>(*OtherBindItr))) {
2437 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_unnamed_bind);
2438 Diag((*OtherBindItr)->getEndLoc(),
2439 diag::note_acc_previous_clause_here)
2440 << (*BindItr)->getClauseKind();
2441 return;
2442 }
2443 }
2444
2445 // OpenACC 3.3 2.15:
2446 // A bind clause may not bind to a routine name that has a visible bind
2447 // clause.
2448 // We take the combo of these two 2.15 restrictions to mean that the
2449 // 'declaration'/'definition' quote is an exception to this. So we're
2450 // going to disallow mixing of the two types entirely.
2451 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2452 RA && RA->getRange().getEnd().isValid()) {
2453 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2454 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2455 << "bind";
2456 return;
2457 }
2458 }
2459 }
2460
2461 CreateRoutineDeclAttr(*this, DirLoc, Clauses, NextParsedFDecl);
2462}
2463
2464// Variant that adds a decl, because this is the named case.
2466 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2467 Expr *FuncRef, SourceLocation RParenLoc,
2469 assert(LParenLoc.isValid());
2470
2471 FunctionDecl *FD = nullptr;
2472 if ((FD = getFunctionFromRoutineName(FuncRef))) {
2473 // OpenACC 3.3 2.15:
2474 // In C and C++, function static variables are not supported in functions to
2475 // which a routine directive applies.
2476 if (auto Itr = MagicStaticLocs.find(FD->getCanonicalDecl());
2477 Itr != MagicStaticLocs.end()) {
2478 Diag(Itr->second, diag::err_acc_magic_static_in_routine);
2479 Diag(DirLoc, diag::note_acc_construct_here)
2481
2482 return nullptr;
2483 }
2484
2485 // OpenACC 3.3 2.15:
2486 // A bind clause may not bind to a routine name that has a visible bind
2487 // clause.
2488 auto BindItr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCBindClause>);
2489 SourceLocation BindLoc;
2490 if (BindItr != Clauses.end()) {
2491 BindLoc = (*BindItr)->getBeginLoc();
2492 // Since this is adding a 'named' routine, we aren't allowed to combine
2493 // with ANY other visible bind clause. Error if we see either.
2494
2495 for (auto *A : FD->attrs()) {
2496 if (auto *RA = dyn_cast<OpenACCRoutineDeclAttr>(A)) {
2497 auto OtherBindItr =
2498 llvm::find_if(RA->Clauses, llvm::IsaPred<OpenACCBindClause>);
2499 if (OtherBindItr != RA->Clauses.end()) {
2500 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2501 Diag((*OtherBindItr)->getEndLoc(),
2502 diag::note_acc_previous_clause_here)
2503 << (*BindItr)->getClauseKind();
2504 return nullptr;
2505 }
2506 }
2507
2508 if (auto *RA = dyn_cast<OpenACCRoutineAnnotAttr>(A);
2509 RA && RA->getRange().getEnd().isValid()) {
2510 Diag((*BindItr)->getBeginLoc(), diag::err_acc_duplicate_bind);
2511 Diag(RA->getRange().getEnd(), diag::note_acc_previous_clause_here)
2512 << (*BindItr)->getClauseKind();
2513 return nullptr;
2514 }
2515 }
2516 }
2517
2518 // Set the end-range to the 'bind' clause here, so we can look it up
2519 // later.
2520 auto *RAA = OpenACCRoutineAnnotAttr::CreateImplicit(getASTContext(),
2521 {DirLoc, BindLoc});
2522 FD->addAttr(RAA);
2523 // In case we are referencing not the 'latest' version, make sure we add
2524 // the attribute to all declarations after the 'found' one.
2525 for (auto *CurFD : FD->redecls())
2526 CurFD->addAttr(RAA->clone(getASTContext()));
2527 }
2528
2529 LastRoutineDecl = OpenACCRoutineDecl::Create(
2530 getASTContext(), getCurContext(), StartLoc, DirLoc, LParenLoc, FuncRef,
2531 RParenLoc, EndLoc, Clauses);
2532 LastRoutineDecl->setAccess(AS_public);
2533 getCurContext()->addDecl(LastRoutineDecl);
2534
2535 if (FD) {
2536 // Add this attribute to the list of annotations so that codegen can visit
2537 // it later. FD doesn't necessarily exist, but that case should be
2538 // diagnosed.
2539 RoutineRefList.emplace_back(FD, LastRoutineDecl);
2540 }
2541 return LastRoutineDecl;
2542}
2543
2545 for (auto [FD, RoutineDecl] : RoutineRefList)
2546 SemaRef.Consumer.HandleOpenACCRoutineReference(FD, RoutineDecl);
2547}
2548
2550 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2551 Expr *ReferencedFunc, SourceLocation RParenLoc,
2553 DeclGroupPtrTy NextDecl) {
2554 assert((!ReferencedFunc || !NextDecl) &&
2555 "Only one of these should be filled");
2556
2557 if (LParenLoc.isInvalid()) {
2558 Decl *NextLineDecl = nullptr;
2559 if (NextDecl && NextDecl.get().isSingleDecl())
2560 NextLineDecl = NextDecl.get().getSingleDecl();
2561
2562 CheckRoutineDecl(DirLoc, Clauses, NextLineDecl);
2563
2564 return NextDecl.get();
2565 }
2566
2568 StartLoc, DirLoc, LParenLoc, ReferencedFunc, RParenLoc, Clauses, EndLoc)};
2569}
2570
2572 SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc,
2573 Expr *ReferencedFunc, SourceLocation RParenLoc,
2575 Stmt *NextStmt) {
2576 assert((!ReferencedFunc || !NextStmt) &&
2577 "Only one of these should be filled");
2578
2579 if (LParenLoc.isInvalid()) {
2580 Decl *NextLineDecl = nullptr;
2581 if (NextStmt)
2582 if (DeclStmt *DS = dyn_cast<DeclStmt>(NextStmt); DS && DS->isSingleDecl())
2583 NextLineDecl = DS->getSingleDecl();
2584
2585 CheckRoutineDecl(DirLoc, Clauses, NextLineDecl);
2586 return NextStmt;
2587 }
2588
2589 DeclGroupRef DR{CheckRoutineDecl(StartLoc, DirLoc, LParenLoc, ReferencedFunc,
2590 RParenLoc, Clauses, EndLoc)};
2591 return SemaRef.ActOnDeclStmt(DeclGroupPtrTy::make(DR), StartLoc, EndLoc);
2592}
2593
2594OpenACCRoutineDeclAttr *
2595SemaOpenACC::mergeRoutineDeclAttr(const OpenACCRoutineDeclAttr &Old) {
2596 OpenACCRoutineDeclAttr *New =
2597 OpenACCRoutineDeclAttr::Create(getASTContext(), Old.getLocation());
2598 // We should jsut be able to copy these, there isn't really any
2599 // merging/inheriting we have to do, so no worry about doing a deep copy.
2600 New->Clauses = Old.Clauses;
2601 return New;
2602}
2607
2612
2613namespace {
2614enum class InitKind { Invalid, Zero, One, AllOnes, Least, Largest };
2615llvm::APFloat getInitFloatValue(ASTContext &Context, InitKind IK, QualType Ty) {
2616 switch (IK) {
2617 case InitKind::Invalid:
2618 llvm_unreachable("invalid init kind");
2619 case InitKind::Zero:
2620 return llvm::APFloat::getZero(Context.getFloatTypeSemantics(Ty));
2621 case InitKind::One:
2622 return llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty));
2623 case InitKind::AllOnes:
2624 return llvm::APFloat::getAllOnesValue(Context.getFloatTypeSemantics(Ty));
2625 case InitKind::Least:
2626 return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty),
2627 /*Negative=*/true);
2628 case InitKind::Largest:
2629 return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty));
2630 }
2631 llvm_unreachable("unknown init kind");
2632}
2633
2634llvm::APInt getInitIntValue(ASTContext &Context, InitKind IK, QualType Ty) {
2635 switch (IK) {
2636 case InitKind::Invalid:
2637 llvm_unreachable("invalid init kind");
2638 case InitKind::Zero:
2639 return llvm::APInt(Context.getIntWidth(Ty), 0);
2640 case InitKind::One:
2641 return llvm::APInt(Context.getIntWidth(Ty), 1);
2642 case InitKind::AllOnes:
2643 return llvm::APInt::getAllOnes(Context.getIntWidth(Ty));
2644 case InitKind::Least:
2646 return llvm::APInt::getSignedMinValue(Context.getIntWidth(Ty));
2647 return llvm::APInt::getMinValue(Context.getIntWidth(Ty));
2648 case InitKind::Largest:
2650 return llvm::APInt::getSignedMaxValue(Context.getIntWidth(Ty));
2651 return llvm::APInt::getMaxValue(Context.getIntWidth(Ty));
2652 }
2653 llvm_unreachable("unknown init kind");
2654}
2655
2656/// Loops through a type and generates an appropriate InitListExpr to
2657/// generate type initialization.
2658Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
2659 SourceRange ExprRange, QualType Ty,
2660 InitKind IK) {
2661 if (IK == InitKind::Invalid)
2662 return nullptr;
2663
2664 if (IK == InitKind::Zero) {
2665 Expr *InitExpr = new (Context)
2666 InitListExpr(Context, ExprRange.getBegin(), {}, ExprRange.getEnd());
2667 InitExpr->setType(Context.VoidTy);
2668 return InitExpr;
2669 }
2670
2671 Ty = Ty.getCanonicalType();
2672 llvm::SmallVector<Expr *> Exprs;
2673
2674 if (const RecordDecl *RD = Ty->getAsRecordDecl()) {
2675 for (auto *F : RD->fields()) {
2676 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
2677 F->getType(), IK))
2678 Exprs.push_back(NewExpr);
2679 else
2680 return nullptr;
2681 }
2682 } else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
2683 for (uint64_t Idx = 0; Idx < AT->getZExtSize(); ++Idx) {
2684 if (Expr *NewExpr = GenerateReductionInitRecipeExpr(
2685 Context, ExprRange, AT->getElementType(), IK))
2686 Exprs.push_back(NewExpr);
2687 else
2688 return nullptr;
2689 }
2690
2691 } else if (Ty->isPointerType()) {
2692 // For now, we are going to punt/not initialize pointer types, as
2693 // discussions/designs are ongoing on how to express this behavior,
2694 // particularly since they probably need the 'bounds' passed to them
2695 // correctly. A future patch/patch set will go through all of the pointer
2696 // values for all of the recipes to make sure we have a sane behavior.
2697
2698 // For now, this will result in a NYI during code generation for
2699 // no-initializer.
2700 return nullptr;
2701 } else {
2702 assert(Ty->isScalarType());
2703
2704 if (const auto *Cplx = Ty->getAs<ComplexType>()) {
2705 // we can get here in error cases, so make sure we generate something that
2706 // will work if we find ourselves wanting to enable this, so emit '0,0'
2707 // for both ints and floats.
2708
2709 QualType EltTy = Cplx->getElementType();
2710 if (EltTy->isFloatingType()) {
2711 Exprs.push_back(FloatingLiteral::Create(
2712 Context, getInitFloatValue(Context, InitKind::Zero, EltTy),
2713 /*isExact=*/true, EltTy, ExprRange.getBegin()));
2714 Exprs.push_back(FloatingLiteral::Create(
2715 Context, getInitFloatValue(Context, InitKind::Zero, EltTy),
2716 /*isExact=*/true, EltTy, ExprRange.getBegin()));
2717 } else {
2718 Exprs.push_back(IntegerLiteral::Create(
2719 Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,
2720 ExprRange.getBegin()));
2721 Exprs.push_back(IntegerLiteral::Create(
2722 Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,
2723 ExprRange.getBegin()));
2724 }
2725
2726 } else if (Ty->isFloatingType()) {
2727 Exprs.push_back(
2728 FloatingLiteral::Create(Context, getInitFloatValue(Context, IK, Ty),
2729 /*isExact=*/true, Ty, ExprRange.getBegin()));
2730 } else if (Ty->isBooleanType()) {
2731 Exprs.push_back(CXXBoolLiteralExpr::Create(Context,
2732 (IK == InitKind::One ||
2733 IK == InitKind::AllOnes ||
2734 IK == InitKind::Largest),
2735 Ty, ExprRange.getBegin()));
2736 } else {
2737 Exprs.push_back(IntegerLiteral::Create(
2738 Context, getInitIntValue(Context, IK, Ty), Ty, ExprRange.getBegin()));
2739 }
2740 }
2741
2742 Expr *InitExpr = new (Context)
2743 InitListExpr(Context, ExprRange.getBegin(), Exprs, ExprRange.getEnd());
2744 InitExpr->setType(Ty);
2745 return InitExpr;
2746}
2747
2748VarDecl *CreateAllocaDecl(ASTContext &Ctx, DeclContext *DC,
2749 SourceLocation BeginLoc, IdentifierInfo *VarName,
2750 QualType VarTy) {
2751 auto *VD = VarDecl::Create(Ctx, DC, BeginLoc, BeginLoc, VarName, VarTy,
2752 Ctx.getTrivialTypeSourceInfo(VarTy), SC_Auto);
2753 VD->markUsed(Ctx);
2754 return VD;
2755}
2756
2757ExprResult FinishValueInit(Sema &S, InitializedEntity &Entity,
2758 SourceLocation Loc, QualType VarTy, Expr *InitExpr) {
2759 if (!InitExpr)
2760 return ExprEmpty();
2761
2762 InitializationKind Kind =
2763 InitializationKind::CreateForInit(Loc, /*DirectInit=*/true, InitExpr);
2764 InitializationSequence InitSeq(S, Entity, Kind, InitExpr,
2765 /*TopLevelOfInitList=*/false,
2766 /*TreatUnavailableAsInvalid=*/false);
2767
2768 return InitSeq.Perform(S, Entity, Kind, InitExpr, &VarTy);
2769}
2770
2771} // namespace
2772
2774 // We don't strip bounds here, so that we are doing our recipe init at the
2775 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2776 if (!VarExpr || VarExpr->getType()->isDependentType())
2778
2779 QualType VarTy =
2781
2782 // Array sections are special, and we have to treat them that way.
2783 if (const auto *ASE =
2784 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2785 VarTy = ASE->getElementType();
2786
2787 VarDecl *AllocaDecl = CreateAllocaDecl(
2788 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2789 &getASTContext().Idents.get("openacc.private.init"), VarTy);
2790
2793 InitializationKind Kind =
2795 InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
2796 ExprResult Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
2797
2798 // For 'no bounds' version, we can use this as a shortcut, so set the init
2799 // anyway.
2800 if (Init.isUsable()) {
2801 AllocaDecl->setInit(Init.get());
2802 AllocaDecl->setInitStyle(VarDecl::CallInit);
2803 }
2804
2805 return OpenACCPrivateRecipe(AllocaDecl);
2806}
2807
2810 // We don't strip bounds here, so that we are doing our recipe init at the
2811 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2812 if (!VarExpr || VarExpr->getType()->isDependentType())
2814
2815 QualType VarTy =
2817
2818 // Array sections are special, and we have to treat them that way.
2819 if (const auto *ASE =
2820 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2821 VarTy = ASE->getElementType();
2822
2823 VarDecl *AllocaDecl = CreateAllocaDecl(
2824 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2825 &getASTContext().Idents.get("openacc.firstprivate.init"), VarTy);
2826
2827 VarDecl *Temporary = CreateAllocaDecl(
2828 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2829 &getASTContext().Idents.get("openacc.temp"), VarTy);
2830
2831 auto *TemporaryDRE = DeclRefExpr::Create(
2833 /*ReferstoEnclosingVariableOrCapture=*/false,
2835 VarExpr->getBeginLoc()},
2836 VarTy, clang::VK_LValue, Temporary, nullptr, NOUR_None);
2837
2840
2841 const auto *ArrTy = getASTContext().getAsConstantArrayType(VarTy);
2842 if (!ArrTy) {
2843 ExprResult Init = FinishValueInit(
2844 SemaRef.SemaRef, Entity, VarExpr->getBeginLoc(), VarTy, TemporaryDRE);
2845
2846 // For 'no bounds' version, we can use this as a shortcut, so set the init
2847 // anyway.
2848 if (Init.isUsable()) {
2849 AllocaDecl->setInit(Init.get());
2850 AllocaDecl->setInitStyle(VarDecl::CallInit);
2851 }
2852 return OpenACCFirstPrivateRecipe(AllocaDecl, Temporary);
2853 }
2854
2855 // Arrays need to have each individual element initialized as there
2856 // isn't a normal 'equals' feature in C/C++. This section sets these up
2857 // as an init list after 'initializing' each individual element.
2859 // Decay to pointer for the array subscript expression.
2860 auto *CastToPtr = ImplicitCastExpr::Create(
2861 getASTContext(), getASTContext().getPointerType(ArrTy->getElementType()),
2862 CK_ArrayToPointerDecay, TemporaryDRE, /*BasePath=*/nullptr,
2864
2865 for (std::size_t I = 0; I < ArrTy->getLimitedSize(); ++I) {
2866 // Each element needs to be some sort of copy initialization from an
2867 // array-index of the original temporary (referenced via a
2868 // DeclRefExpr).
2869 auto *Idx = IntegerLiteral::Create(
2870 getASTContext(),
2871 llvm::APInt(getASTContext().getTypeSize(getASTContext().getSizeType()),
2872 I),
2873 getASTContext().getSizeType(), VarExpr->getBeginLoc());
2874
2875 Expr *Subscript = new (getASTContext()) ArraySubscriptExpr(
2876 CastToPtr, Idx, ArrTy->getElementType(), clang::VK_LValue, OK_Ordinary,
2877 VarExpr->getBeginLoc());
2878 // Generate a simple copy from the result of the subscript. This will
2879 // do a bitwise copy or a copy-constructor, as necessary.
2880 InitializedEntity CopyEntity =
2882 InitializationKind CopyKind =
2884 InitializationSequence CopySeq(SemaRef.SemaRef, CopyEntity, CopyKind,
2885 Subscript,
2886 /*TopLevelOfInitList=*/true);
2887 ExprResult ElemRes =
2888 CopySeq.Perform(SemaRef.SemaRef, CopyEntity, CopyKind, Subscript);
2889 Args.push_back(ElemRes.get());
2890 }
2891
2892 Expr *InitExpr = new (getASTContext()) InitListExpr(
2893 getASTContext(), VarExpr->getBeginLoc(), Args, VarExpr->getEndLoc());
2894 InitExpr->setType(VarTy);
2895
2896 ExprResult Init = FinishValueInit(SemaRef.SemaRef, Entity,
2897 VarExpr->getBeginLoc(), VarTy, InitExpr);
2898
2899 // For 'no bounds' version, we can use this as a shortcut, so set the init
2900 // anyway.
2901 if (Init.isUsable()) {
2902 AllocaDecl->setInit(Init.get());
2903 AllocaDecl->setInitStyle(VarDecl::CallInit);
2904 }
2905
2906 return OpenACCFirstPrivateRecipe(AllocaDecl, Temporary);
2907}
2908
2910 OpenACCReductionOperator ReductionOperator, const Expr *VarExpr) {
2911 // We don't strip bounds here, so that we are doing our recipe init at the
2912 // 'lowest' possible level. Codegen is going to have to do its own 'looping'.
2913 if (!VarExpr || VarExpr->getType()->isDependentType())
2915
2916 QualType VarTy =
2918
2919 // Array sections are special, and we have to treat them that way.
2920 if (const auto *ASE =
2921 dyn_cast<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()))
2922 VarTy = ASE->getElementType();
2923
2925
2926 // We use the 'set-ness' of the alloca-decl to determine whether the combiner
2927 // is 'set' or not, so we can skip any attempts at it if we're going to fail
2928 // at any of the combiners.
2929 if (CreateReductionCombinerRecipe(VarExpr->getBeginLoc(), ReductionOperator,
2930 VarTy, CombinerRecipes))
2932
2933 VarDecl *AllocaDecl = CreateAllocaDecl(
2934 getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2935 &getASTContext().Idents.get("openacc.reduction.init"), VarTy);
2936
2939
2940 InitKind IK = InitKind::Invalid;
2941 switch (ReductionOperator) {
2943 // This can only happen when there is an error, and since these inits
2944 // are used for code generation, we can just ignore/not bother doing any
2945 // initialization here.
2946 IK = InitKind::Invalid;
2947 break;
2949 IK = InitKind::Least;
2950 break;
2952 IK = InitKind::Largest;
2953 break;
2955 IK = InitKind::AllOnes;
2956 break;
2959 IK = InitKind::One;
2960 break;
2965 IK = InitKind::Zero;
2966 break;
2967 }
2968
2969 Expr *InitExpr = GenerateReductionInitRecipeExpr(
2970 getASTContext(), VarExpr->getSourceRange(), VarTy, IK);
2971
2972 ExprResult Init = FinishValueInit(SemaRef.SemaRef, Entity,
2973 VarExpr->getBeginLoc(), VarTy, InitExpr);
2974
2975 // For 'no bounds' version, we can use this as a shortcut, so set the init
2976 // anyway.
2977 if (Init.isUsable()) {
2978 AllocaDecl->setInit(Init.get());
2979 AllocaDecl->setInitStyle(VarDecl::CallInit);
2980 }
2981
2982 return OpenACCReductionRecipeWithStorage(AllocaDecl, CombinerRecipes);
2983}
2984
2985bool SemaOpenACC::CreateReductionCombinerRecipe(
2986 SourceLocation Loc, OpenACCReductionOperator ReductionOperator,
2987 QualType VarTy,
2989 &CombinerRecipes) {
2990 // Now we can try to generate the 'combiner' recipe. This is a little
2991 // complicated in that if the 'VarTy' is an array type, we want to take its
2992 // element type so we can generate that. Additionally, if this is a struct,
2993 // we have two options: If there is overloaded operators, we want to take
2994 // THOSE, else we want to do the individual elements.
2995
2996 BinaryOperatorKind BinOp;
2997 switch (ReductionOperator) {
2999 // This can only happen when there is an error, and since these inits
3000 // are used for code generation, we can just ignore/not bother doing any
3001 // initialization here.
3002 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3003 return false;
3005 BinOp = BinaryOperatorKind::BO_AddAssign;
3006 break;
3008 BinOp = BinaryOperatorKind::BO_MulAssign;
3009 break;
3011 BinOp = BinaryOperatorKind::BO_AndAssign;
3012 break;
3014 BinOp = BinaryOperatorKind::BO_OrAssign;
3015 break;
3017 BinOp = BinaryOperatorKind::BO_XorAssign;
3018 break;
3019
3022 BinOp = BinaryOperatorKind::BO_LT;
3023 break;
3025 BinOp = BinaryOperatorKind::BO_LAnd;
3026 break;
3028 BinOp = BinaryOperatorKind::BO_LOr;
3029 break;
3030 }
3031
3032 // If VarTy is an array type, at the top level only, we want to do our
3033 // compares/decomp/etc at the element level.
3034 if (auto *AT = getASTContext().getAsArrayType(VarTy))
3035 VarTy = AT->getElementType();
3036
3037 assert(!VarTy->isArrayType() && "Only 1 level of array allowed");
3038
3039 enum class CombinerFailureKind {
3040 None = 0,
3041 BinOp = 1,
3042 Conditional = 2,
3043 Assignment = 3,
3044 };
3045
3046 auto genCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE)
3047 -> std::pair<ExprResult, CombinerFailureKind> {
3048 ExprResult BinOpRes =
3049 SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc, BinOp, LHSDRE, RHSDRE,
3050 /*ForFoldExpr=*/false);
3051 switch (ReductionOperator) {
3057 // These 5 are simple and are being done as compound operators, so we can
3058 // immediately quit here.
3059 return {BinOpRes, BinOpRes.isUsable() ? CombinerFailureKind::None
3060 : CombinerFailureKind::BinOp};
3063 // These are done as:
3064 // LHS = (LHS < RHS) ? LHS : RHS; and LHS = (LHS < RHS) ? RHS : LHS;
3065 //
3066 // The BinOpRes should have been created with the less-than, so we just
3067 // have to build the conditional and assignment.
3068 if (!BinOpRes.isUsable())
3069 return {BinOpRes, CombinerFailureKind::BinOp};
3070
3071 // Create the correct conditional operator, swapping the results
3072 // (true/false value) depending on min/max.
3073 ExprResult CondRes;
3074 if (ReductionOperator == OpenACCReductionOperator::Min)
3075 CondRes = SemaRef.ActOnConditionalOp(Loc, Loc, BinOpRes.get(), LHSDRE,
3076 RHSDRE);
3077 else
3078 CondRes = SemaRef.ActOnConditionalOp(Loc, Loc, BinOpRes.get(), RHSDRE,
3079 LHSDRE);
3080
3081 if (!CondRes.isUsable())
3082 return {CondRes, CombinerFailureKind::Conditional};
3083
3084 // Build assignment.
3085 ExprResult Assignment = SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc,
3086 BinaryOperatorKind::BO_Assign,
3087 LHSDRE, CondRes.get(),
3088 /*ForFoldExpr=*/false);
3089 return {Assignment, Assignment.isUsable()
3090 ? CombinerFailureKind::None
3091 : CombinerFailureKind::Assignment};
3092 }
3095 // These are done as LHS = LHS && RHS (or LHS = LHS || RHS). So after the
3096 // binop, all we have to do is the assignment.
3097 if (!BinOpRes.isUsable())
3098 return {BinOpRes, CombinerFailureKind::BinOp};
3099
3100 // Build assignment.
3101 ExprResult Assignment = SemaRef.BuildBinOp(SemaRef.getCurScope(), Loc,
3102 BinaryOperatorKind::BO_Assign,
3103 LHSDRE, BinOpRes.get(),
3104 /*ForFoldExpr=*/false);
3105 return {Assignment, Assignment.isUsable()
3106 ? CombinerFailureKind::None
3107 : CombinerFailureKind::Assignment};
3108 }
3110 llvm_unreachable("Invalid should have been caught above");
3111 }
3112 llvm_unreachable("Unhandled case");
3113 };
3114
3115 auto tryCombiner = [&, this](DeclRefExpr *LHSDRE, DeclRefExpr *RHSDRE,
3116 bool IncludeTrap) {
3117 if (IncludeTrap) {
3118 // Trap all of the errors here, we'll emit our own at the end.
3119 Sema::TentativeAnalysisScope Trap{SemaRef};
3120 return genCombiner(LHSDRE, RHSDRE);
3121 }
3122 return genCombiner(LHSDRE, RHSDRE);
3123 };
3124
3125 struct CombinerAttemptTy {
3126 CombinerFailureKind FailKind;
3127 VarDecl *LHS;
3128 DeclRefExpr *LHSDRE;
3129 VarDecl *RHS;
3130 DeclRefExpr *RHSDRE;
3131 Expr *Op;
3132 };
3133
3134 auto formCombiner = [&, this](QualType Ty) -> CombinerAttemptTy {
3135 VarDecl *LHSDecl = CreateAllocaDecl(
3136 getASTContext(), SemaRef.getCurContext(), Loc,
3137 &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty);
3138 auto *LHSDRE = DeclRefExpr::Create(
3139 getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, LHSDecl,
3140 /*ReferstoEnclosingVariableOrCapture=*/false,
3141 DeclarationNameInfo{DeclarationName{LHSDecl->getDeclName()},
3142 LHSDecl->getBeginLoc()},
3143 Ty, clang::VK_LValue, LHSDecl, nullptr, NOUR_None);
3144 VarDecl *RHSDecl = CreateAllocaDecl(
3145 getASTContext(), SemaRef.getCurContext(), Loc,
3146 &getASTContext().Idents.get("openacc.reduction.combiner.lhs"), Ty);
3147 auto *RHSDRE = DeclRefExpr::Create(
3148 getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{}, RHSDecl,
3149 /*ReferstoEnclosingVariableOrCapture=*/false,
3150 DeclarationNameInfo{DeclarationName{RHSDecl->getDeclName()},
3151 RHSDecl->getBeginLoc()},
3152 Ty, clang::VK_LValue, RHSDecl, nullptr, NOUR_None);
3153
3154 std::pair<ExprResult, CombinerFailureKind> BinOpResult =
3155 tryCombiner(LHSDRE, RHSDRE, /*IncludeTrap=*/true);
3156
3157 return {BinOpResult.second, LHSDecl, LHSDRE, RHSDecl, RHSDRE,
3158 BinOpResult.first.get()};
3159 };
3160
3161 CombinerAttemptTy TopLevelCombinerInfo = formCombiner(VarTy);
3162
3163 if (TopLevelCombinerInfo.Op) {
3164 if (!TopLevelCombinerInfo.Op->containsErrors() &&
3165 TopLevelCombinerInfo.Op->isInstantiationDependent()) {
3166 // If this is instantiation dependent, we're just going to 'give up' here
3167 // and count on us to get it right during instantaition.
3168 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3169 return false;
3170 } else if (!TopLevelCombinerInfo.Op->containsErrors()) {
3171 // Else, we succeeded, we can just return this combiner.
3172 CombinerRecipes.push_back({TopLevelCombinerInfo.LHS,
3173 TopLevelCombinerInfo.RHS,
3174 TopLevelCombinerInfo.Op});
3175 return false;
3176 }
3177 }
3178
3179 auto EmitFailureNote = [&](CombinerFailureKind CFK) {
3180 if (CFK == CombinerFailureKind::BinOp)
3181 return Diag(Loc, diag::note_acc_reduction_combiner_forming)
3182 << CFK << BinaryOperator::getOpcodeStr(BinOp);
3183 return Diag(Loc, diag::note_acc_reduction_combiner_forming) << CFK;
3184 };
3185
3186 // Since the 'root' level didn't fail, the only thing that could be successful
3187 // is a struct that we decompose on its individual fields.
3188
3189 RecordDecl *RD = VarTy->getAsRecordDecl();
3190 if (!RD) {
3191 Diag(Loc, diag::err_acc_reduction_recipe_no_op) << VarTy;
3192 EmitFailureNote(TopLevelCombinerInfo.FailKind);
3193 tryCombiner(TopLevelCombinerInfo.LHSDRE, TopLevelCombinerInfo.RHSDRE,
3194 /*IncludeTrap=*/false);
3195 return true;
3196 }
3197
3198 for (const FieldDecl *FD : RD->fields()) {
3199 CombinerAttemptTy FieldCombinerInfo = formCombiner(FD->getType());
3200
3201 if (!FieldCombinerInfo.Op || FieldCombinerInfo.Op->containsErrors()) {
3202 Diag(Loc, diag::err_acc_reduction_recipe_no_op) << FD->getType();
3203 Diag(FD->getBeginLoc(), diag::note_acc_reduction_recipe_noop_field) << RD;
3204 EmitFailureNote(FieldCombinerInfo.FailKind);
3205 tryCombiner(FieldCombinerInfo.LHSDRE, FieldCombinerInfo.RHSDRE,
3206 /*IncludeTrap=*/false);
3207 return true;
3208 }
3209
3210 if (FieldCombinerInfo.Op->isInstantiationDependent()) {
3211 // If this is instantiation dependent, we're just going to 'give up' here
3212 // and count on us to get it right during instantaition.
3213 CombinerRecipes.push_back({nullptr, nullptr, nullptr});
3214 } else {
3215 CombinerRecipes.push_back(
3216 {FieldCombinerInfo.LHS, FieldCombinerInfo.RHS, FieldCombinerInfo.Op});
3217 }
3218 }
3219
3220 return false;
3221}
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:508
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:227
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:7220
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5384
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition Expr.h:2724
QualType getElementType() const
Definition TypeBase.h:3789
StringRef getOpcodeStr() const
Definition Expr.h:4107
static CXXBoolLiteralExpr * Create(const ASTContext &C, bool Val, QualType Ty, SourceLocation Loc)
Definition ExprCXX.h:739
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2952
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:488
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1637
bool isSingleDecl() const
isSingleDecl - This method returns true if this DeclStmt refers to a single Decl.
Definition Stmt.h:1650
const Decl * getSingleDecl() const
Definition Stmt.h:1652
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:591
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:931
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:991
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:3090
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:277
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:1076
Represents a function declaration or definition.
Definition Decl.h:2018
FunctionDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:3742
bool isDeleted() const
Whether this function has been deleted.
Definition Decl.h:2558
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:2073
Describes an C or C++ initializer list.
Definition Expr.h:5302
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:975
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:5656
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:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
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:8621
QualType getCanonicalType() const
Definition TypeBase.h:8488
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8530
field_range fields() const
Definition Decl.h:4546
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3628
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:339
bool isOpenACCLoopConstructScope() const
Definition Scope.h:568
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition Scope.h:398
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:287
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:9385
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12595
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:15207
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
Definition Sema.h:6821
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
SourceManager & SourceMgr
Definition Sema.h:1311
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:86
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:8792
bool isBooleanType() const
Definition TypeBase.h:9176
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2289
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:8776
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArrayType() const
Definition TypeBase.h:8772
bool isPointerType() const
Definition TypeBase.h:8673
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9083
bool isEnumeralType() const
Definition TypeBase.h:8804
bool isScalarType() const
Definition TypeBase.h:9145
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:9033
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2845
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2837
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9319
bool isFunctionType() const
Definition TypeBase.h:8669
bool isFloatingType() const
Definition Type.cpp:2389
bool isAnyPointerType() const
Definition TypeBase.h:8681
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9266
bool isRecordType() const
Definition TypeBase.h:8800
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:924
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2130
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1465
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:932
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1206
void setInit(Expr *I)
Definition Decl.cpp:2456
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:669
@ 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:905
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:180
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:648
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:650
static OpenACCFirstPrivateRecipe Empty()
static OpenACCPrivateRecipe Empty()
static OpenACCReductionRecipeWithStorage Empty()