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