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