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