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