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