xref: /llvm-project/clang/lib/Sema/SemaOpenACC.cpp (revision 2c75bda42605b620f8450e44a7b6f2db3adc21cb)
124144d72SErich Keane //===--- SemaOpenACC.cpp - Semantic Analysis for OpenACC constructs -------===//
224144d72SErich Keane //
324144d72SErich Keane // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
424144d72SErich Keane // See https://llvm.org/LICENSE.txt for license information.
524144d72SErich Keane // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
624144d72SErich Keane //
724144d72SErich Keane //===----------------------------------------------------------------------===//
824144d72SErich Keane /// \file
9*2c75bda4Serichkeane /// This file implements semantic analysis for OpenACC constructs, and things
10*2c75bda4Serichkeane /// that are not clause specific.
1124144d72SErich Keane ///
1224144d72SErich Keane //===----------------------------------------------------------------------===//
1324144d72SErich Keane 
14d2884444SVlad Serebrennikov #include "clang/AST/StmtOpenACC.h"
15db4ea21dSerichkeane #include "clang/Basic/DiagnosticSema.h"
1676600aeeSErich Keane #include "clang/Basic/OpenACCKinds.h"
1724144d72SErich Keane #include "clang/Sema/Sema.h"
18*2c75bda4Serichkeane #include "clang/Sema/SemaOpenACC.h"
19c1298878SErich Keane #include "llvm/ADT/StringExtras.h"
2061338782SErich Keane #include "llvm/Support/Casting.h"
2124144d72SErich Keane 
2224144d72SErich Keane using namespace clang;
23cb891127SErich Keane 
24cb891127SErich Keane namespace {
25e45f6e56SVlad Serebrennikov bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K,
26cb891127SErich Keane                                     SourceLocation StartLoc, bool IsStmt) {
27cb891127SErich Keane   switch (K) {
28cb891127SErich Keane   default:
29cb891127SErich Keane   case OpenACCDirectiveKind::Invalid:
30cb891127SErich Keane     // Nothing to do here, both invalid and unimplemented don't really need to
31cb891127SErich Keane     // do anything.
32cb891127SErich Keane     break;
3339351f8eSerichkeane   case OpenACCDirectiveKind::ParallelLoop:
3439351f8eSerichkeane   case OpenACCDirectiveKind::SerialLoop:
3539351f8eSerichkeane   case OpenACCDirectiveKind::KernelsLoop:
36cb891127SErich Keane   case OpenACCDirectiveKind::Parallel:
37bb97c992Serichkeane   case OpenACCDirectiveKind::Serial:
38bb97c992Serichkeane   case OpenACCDirectiveKind::Kernels:
3942f4e505SErich Keane   case OpenACCDirectiveKind::Loop:
40010d0115Serichkeane   case OpenACCDirectiveKind::Data:
41010d0115Serichkeane   case OpenACCDirectiveKind::EnterData:
42010d0115Serichkeane   case OpenACCDirectiveKind::ExitData:
43010d0115Serichkeane   case OpenACCDirectiveKind::HostData:
44e34cc7c9Serichkeane   case OpenACCDirectiveKind::Wait:
45cb891127SErich Keane     if (!IsStmt)
46d2884444SVlad Serebrennikov       return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
47cb891127SErich Keane     break;
48cb891127SErich Keane   }
49cb891127SErich Keane   return false;
50cb891127SErich Keane }
5126fee0ffSErich Keane 
520b0b1530Serichkeane void CollectActiveReductionClauses(
530b0b1530Serichkeane     llvm::SmallVector<OpenACCReductionClause *> &ActiveClauses,
540b0b1530Serichkeane     ArrayRef<OpenACCClause *> CurClauses) {
550b0b1530Serichkeane   for (auto *CurClause : CurClauses) {
560b0b1530Serichkeane     if (auto *RedClause = dyn_cast<OpenACCReductionClause>(CurClause);
570b0b1530Serichkeane         RedClause && !RedClause->getVarList().empty())
580b0b1530Serichkeane       ActiveClauses.push_back(RedClause);
590b0b1530Serichkeane   }
600b0b1530Serichkeane }
610b0b1530Serichkeane 
62010d0115Serichkeane // Depth needs to be preserved for all associated statements that aren't
63010d0115Serichkeane // supposed to modify the compute/combined/loop construct information.
64010d0115Serichkeane bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
65010d0115Serichkeane   switch (DK) {
66010d0115Serichkeane   case OpenACCDirectiveKind::Parallel:
67010d0115Serichkeane   case OpenACCDirectiveKind::ParallelLoop:
68010d0115Serichkeane   case OpenACCDirectiveKind::Serial:
69010d0115Serichkeane   case OpenACCDirectiveKind::SerialLoop:
70010d0115Serichkeane   case OpenACCDirectiveKind::Kernels:
71010d0115Serichkeane   case OpenACCDirectiveKind::KernelsLoop:
72010d0115Serichkeane   case OpenACCDirectiveKind::Loop:
73010d0115Serichkeane     return false;
74010d0115Serichkeane   case OpenACCDirectiveKind::Data:
75010d0115Serichkeane   case OpenACCDirectiveKind::HostData:
76010d0115Serichkeane     return true;
77010d0115Serichkeane   case OpenACCDirectiveKind::EnterData:
78010d0115Serichkeane   case OpenACCDirectiveKind::ExitData:
79e34cc7c9Serichkeane   case OpenACCDirectiveKind::Wait:
804bbdb018Serichkeane   case OpenACCDirectiveKind::Init:
814bbdb018Serichkeane   case OpenACCDirectiveKind::Shutdown:
8221c785d7Serichkeane   case OpenACCDirectiveKind::Set:
83db81e8c4Serichkeane   case OpenACCDirectiveKind::Update:
84010d0115Serichkeane     llvm_unreachable("Doesn't have an associated stmt");
85010d0115Serichkeane   default:
86010d0115Serichkeane   case OpenACCDirectiveKind::Invalid:
87010d0115Serichkeane     llvm_unreachable("Unhandled directive kind?");
88010d0115Serichkeane   }
89010d0115Serichkeane   llvm_unreachable("Unhandled directive kind?");
90010d0115Serichkeane }
91010d0115Serichkeane 
92cb891127SErich Keane } // namespace
93cb891127SErich Keane 
94d2884444SVlad Serebrennikov SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
95e45f6e56SVlad Serebrennikov 
96da4b972eSErich Keane SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
97b0cfbfd7SErich Keane     SemaOpenACC &S, OpenACCDirectiveKind DK, SourceLocation DirLoc,
98da4b972eSErich Keane     ArrayRef<const OpenACCClause *> UnInstClauses,
99da4b972eSErich Keane     ArrayRef<OpenACCClause *> Clauses)
1005b25c313SErich Keane     : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
1013a4b9f38Serichkeane       DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel),
102cf456ed2SErich Keane       OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
103c8cbdc65SErich Keane       OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
10439351f8eSerichkeane       OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo),
1050b0b1530Serichkeane       ActiveReductionClauses(S.ActiveReductionClauses),
106010d0115Serichkeane       LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DirKind)) {
1070b0b1530Serichkeane 
10842f4e505SErich Keane   // Compute constructs end up taking their 'loop'.
10942f4e505SErich Keane   if (DirKind == OpenACCDirectiveKind::Parallel ||
11042f4e505SErich Keane       DirKind == OpenACCDirectiveKind::Serial ||
11142f4e505SErich Keane       DirKind == OpenACCDirectiveKind::Kernels) {
1120b0b1530Serichkeane     CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
1135b25c313SErich Keane     SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
1145b25c313SErich Keane     SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
1155b25c313SErich Keane 
1165b25c313SErich Keane     // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1175b25c313SErich Keane     // construct, the gang clause behaves as follows. ... The region of a loop
1185b25c313SErich Keane     // with a gang clause may not contain another loop with a gang clause unless
1195b25c313SErich Keane     // within a nested compute region.
1205b25c313SErich Keane     //
1215b25c313SErich Keane     // Implement the 'unless within a nested compute region' part.
1223a4b9f38Serichkeane     SemaRef.LoopGangClauseOnKernel = {};
123cf456ed2SErich Keane     SemaRef.LoopWorkerClauseLoc = {};
124c8cbdc65SErich Keane     SemaRef.LoopVectorClauseLoc = {};
12539351f8eSerichkeane     SemaRef.LoopWithoutSeqInfo = {};
12639351f8eSerichkeane   } else if (DirKind == OpenACCDirectiveKind::ParallelLoop ||
12739351f8eSerichkeane              DirKind == OpenACCDirectiveKind::SerialLoop ||
12839351f8eSerichkeane              DirKind == OpenACCDirectiveKind::KernelsLoop) {
12939351f8eSerichkeane     SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
13039351f8eSerichkeane     SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
13139351f8eSerichkeane 
13239351f8eSerichkeane     CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
13339351f8eSerichkeane     SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
13439351f8eSerichkeane     SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
13539351f8eSerichkeane 
1363a4b9f38Serichkeane     SemaRef.LoopGangClauseOnKernel = {};
13739351f8eSerichkeane     SemaRef.LoopWorkerClauseLoc = {};
13839351f8eSerichkeane     SemaRef.LoopVectorClauseLoc = {};
13939351f8eSerichkeane 
14039351f8eSerichkeane     // Set the active 'loop' location if there isn't a 'seq' on it, so we can
14139351f8eSerichkeane     // diagnose the for loops.
14239351f8eSerichkeane     SemaRef.LoopWithoutSeqInfo = {};
14339351f8eSerichkeane     if (Clauses.end() ==
14439351f8eSerichkeane         llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
14539351f8eSerichkeane       SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
14639351f8eSerichkeane 
14739351f8eSerichkeane     // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
14839351f8eSerichkeane     // construct, the gang clause behaves as follows. ... The region of a loop
14939351f8eSerichkeane     // with a gang clause may not contain another loop with a gang clause unless
15039351f8eSerichkeane     // within a nested compute region.
15139351f8eSerichkeane     //
15239351f8eSerichkeane     // We don't bother doing this when this is a template instantiation, as
15339351f8eSerichkeane     // there is no reason to do these checks: the existance of a
15439351f8eSerichkeane     // gang/kernels/etc cannot be dependent.
15539351f8eSerichkeane     if (DirKind == OpenACCDirectiveKind::KernelsLoop && UnInstClauses.empty()) {
15639351f8eSerichkeane       // This handles the 'outer loop' part of this.
15739351f8eSerichkeane       auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
15839351f8eSerichkeane       if (Itr != Clauses.end())
1593a4b9f38Serichkeane         SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), DirKind};
16039351f8eSerichkeane     }
16139351f8eSerichkeane 
16239351f8eSerichkeane     if (UnInstClauses.empty()) {
16339351f8eSerichkeane       auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
16439351f8eSerichkeane       if (Itr != Clauses.end())
16539351f8eSerichkeane         SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
16639351f8eSerichkeane 
16739351f8eSerichkeane       auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
16839351f8eSerichkeane       if (Itr2 != Clauses.end())
16939351f8eSerichkeane         SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
17039351f8eSerichkeane     }
171da4b972eSErich Keane   } else if (DirKind == OpenACCDirectiveKind::Loop) {
1720b0b1530Serichkeane     CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
173da4b972eSErich Keane     SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
1743c98d8c1SErich Keane     SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
1755b25c313SErich Keane 
176b0cfbfd7SErich Keane     // Set the active 'loop' location if there isn't a 'seq' on it, so we can
177b0cfbfd7SErich Keane     // diagnose the for loops.
17839351f8eSerichkeane     SemaRef.LoopWithoutSeqInfo = {};
179b0cfbfd7SErich Keane     if (Clauses.end() ==
180b0cfbfd7SErich Keane         llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
18139351f8eSerichkeane       SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
182b0cfbfd7SErich Keane 
1835b25c313SErich Keane     // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1845b25c313SErich Keane     // construct, the gang clause behaves as follows. ... The region of a loop
1855b25c313SErich Keane     // with a gang clause may not contain another loop with a gang clause unless
1865b25c313SErich Keane     // within a nested compute region.
1875b25c313SErich Keane     //
1885b25c313SErich Keane     // We don't bother doing this when this is a template instantiation, as
1895b25c313SErich Keane     // there is no reason to do these checks: the existance of a
1905b25c313SErich Keane     // gang/kernels/etc cannot be dependent.
1915b25c313SErich Keane     if (SemaRef.getActiveComputeConstructInfo().Kind ==
1925b25c313SErich Keane             OpenACCDirectiveKind::Kernels &&
1935b25c313SErich Keane         UnInstClauses.empty()) {
1945b25c313SErich Keane       // This handles the 'outer loop' part of this.
1955b25c313SErich Keane       auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
1965b25c313SErich Keane       if (Itr != Clauses.end())
1973a4b9f38Serichkeane         SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(),
1983a4b9f38Serichkeane                                           OpenACCDirectiveKind::Kernels};
1995b25c313SErich Keane     }
200cf456ed2SErich Keane 
201cf456ed2SErich Keane     if (UnInstClauses.empty()) {
202cf456ed2SErich Keane       auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
203cf456ed2SErich Keane       if (Itr != Clauses.end())
204cf456ed2SErich Keane         SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
205c8cbdc65SErich Keane 
206c8cbdc65SErich Keane       auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
207c8cbdc65SErich Keane       if (Itr2 != Clauses.end())
208c8cbdc65SErich Keane         SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
209cf456ed2SErich Keane     }
21042f4e505SErich Keane   }
21142f4e505SErich Keane }
21242f4e505SErich Keane 
213da4b972eSErich Keane void SemaOpenACC::AssociatedStmtRAII::SetCollapseInfoBeforeAssociatedStmt(
214da4b972eSErich Keane     ArrayRef<const OpenACCClause *> UnInstClauses,
215da4b972eSErich Keane     ArrayRef<OpenACCClause *> Clauses) {
2165e92bfe9SErich Keane 
2175e92bfe9SErich Keane   // Reset this checking for loops that aren't covered in a RAII object.
2183c98d8c1SErich Keane   SemaRef.LoopInfo.CurLevelHasLoopAlready = false;
2195e92bfe9SErich Keane   SemaRef.CollapseInfo.CollapseDepthSatisfied = true;
2203c98d8c1SErich Keane   SemaRef.TileInfo.TileDepthSatisfied = true;
2215e92bfe9SErich Keane 
222da4b972eSErich Keane   // We make sure to take an optional list of uninstantiated clauses, so that
223da4b972eSErich Keane   // we can check to make sure we don't 'double diagnose' in the event that
224da4b972eSErich Keane   // the value of 'N' was not dependent in a template. We also ensure during
225da4b972eSErich Keane   // Sema that there is only 1 collapse on each construct, so we can count on
226da4b972eSErich Keane   // the fact that if both find a 'collapse', that they are the same one.
227da4b972eSErich Keane   auto *CollapseClauseItr =
228da4b972eSErich Keane       llvm::find_if(Clauses, llvm::IsaPred<OpenACCCollapseClause>);
229da4b972eSErich Keane   auto *UnInstCollapseClauseItr =
230da4b972eSErich Keane       llvm::find_if(UnInstClauses, llvm::IsaPred<OpenACCCollapseClause>);
231da4b972eSErich Keane 
232da4b972eSErich Keane   if (Clauses.end() == CollapseClauseItr)
233da4b972eSErich Keane     return;
234da4b972eSErich Keane 
235da4b972eSErich Keane   OpenACCCollapseClause *CollapseClause =
236da4b972eSErich Keane       cast<OpenACCCollapseClause>(*CollapseClauseItr);
237da4b972eSErich Keane 
238da4b972eSErich Keane   SemaRef.CollapseInfo.ActiveCollapse = CollapseClause;
239da4b972eSErich Keane   Expr *LoopCount = CollapseClause->getLoopCount();
240da4b972eSErich Keane 
241da4b972eSErich Keane   // If the loop count is still instantiation dependent, setting the depth
242da4b972eSErich Keane   // counter isn't necessary, so return here.
243da4b972eSErich Keane   if (!LoopCount || LoopCount->isInstantiationDependent())
244da4b972eSErich Keane     return;
245da4b972eSErich Keane 
246da4b972eSErich Keane   // Suppress diagnostics if we've done a 'transform' where the previous version
247da4b972eSErich Keane   // wasn't dependent, meaning we already diagnosed it.
248da4b972eSErich Keane   if (UnInstCollapseClauseItr != UnInstClauses.end() &&
249da4b972eSErich Keane       !cast<OpenACCCollapseClause>(*UnInstCollapseClauseItr)
250da4b972eSErich Keane            ->getLoopCount()
251da4b972eSErich Keane            ->isInstantiationDependent())
252da4b972eSErich Keane     return;
253da4b972eSErich Keane 
2545e92bfe9SErich Keane   SemaRef.CollapseInfo.CollapseDepthSatisfied = false;
255da4b972eSErich Keane   SemaRef.CollapseInfo.CurCollapseCount =
256da4b972eSErich Keane       cast<ConstantExpr>(LoopCount)->getResultAsAPSInt();
2570aef005cSerichkeane   SemaRef.CollapseInfo.DirectiveKind = DirKind;
258da4b972eSErich Keane }
259da4b972eSErich Keane 
2603c98d8c1SErich Keane void SemaOpenACC::AssociatedStmtRAII::SetTileInfoBeforeAssociatedStmt(
2613c98d8c1SErich Keane     ArrayRef<const OpenACCClause *> UnInstClauses,
2623c98d8c1SErich Keane     ArrayRef<OpenACCClause *> Clauses) {
2633c98d8c1SErich Keane   // We don't diagnose if this is during instantiation, since the only thing we
2643c98d8c1SErich Keane   // care about is the number of arguments, which we can figure out without
2653c98d8c1SErich Keane   // instantiation, so we don't want to double-diagnose.
2663c98d8c1SErich Keane   if (UnInstClauses.size() > 0)
2673c98d8c1SErich Keane     return;
2683c98d8c1SErich Keane   auto *TileClauseItr =
2693c98d8c1SErich Keane       llvm::find_if(Clauses, llvm::IsaPred<OpenACCTileClause>);
2703c98d8c1SErich Keane 
2713c98d8c1SErich Keane   if (Clauses.end() == TileClauseItr)
2723c98d8c1SErich Keane     return;
2733c98d8c1SErich Keane 
2743c98d8c1SErich Keane   OpenACCTileClause *TileClause = cast<OpenACCTileClause>(*TileClauseItr);
2753c98d8c1SErich Keane   SemaRef.TileInfo.ActiveTile = TileClause;
2763c98d8c1SErich Keane   SemaRef.TileInfo.TileDepthSatisfied = false;
2773c98d8c1SErich Keane   SemaRef.TileInfo.CurTileCount = TileClause->getSizeExprs().size();
2780aa78927Serichkeane   SemaRef.TileInfo.DirectiveKind = DirKind;
2793c98d8c1SErich Keane }
2803c98d8c1SErich Keane 
28142f4e505SErich Keane SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
282010d0115Serichkeane   if (DirKind == OpenACCDirectiveKind::Parallel ||
283010d0115Serichkeane       DirKind == OpenACCDirectiveKind::Serial ||
284010d0115Serichkeane       DirKind == OpenACCDirectiveKind::Kernels ||
285010d0115Serichkeane       DirKind == OpenACCDirectiveKind::Loop ||
286010d0115Serichkeane       DirKind == OpenACCDirectiveKind::ParallelLoop ||
287010d0115Serichkeane       DirKind == OpenACCDirectiveKind::SerialLoop ||
288010d0115Serichkeane       DirKind == OpenACCDirectiveKind::KernelsLoop) {
2895b25c313SErich Keane     SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
2903a4b9f38Serichkeane     SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;
291cf456ed2SErich Keane     SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
292c8cbdc65SErich Keane     SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
29339351f8eSerichkeane     SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;
2940b0b1530Serichkeane     SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);
295010d0115Serichkeane   } else if (DirKind == OpenACCDirectiveKind::Data ||
296010d0115Serichkeane              DirKind == OpenACCDirectiveKind::HostData) {
297010d0115Serichkeane     // Intentionally doesn't reset the Loop, Compute Construct, or reduction
298010d0115Serichkeane     // effects.
29942f4e505SErich Keane   }
30042f4e505SErich Keane }
30142f4e505SErich Keane 
302e45f6e56SVlad Serebrennikov void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K,
303193e9007Serichkeane                                  SourceLocation DirLoc) {
3046dacc382Serichkeane   // Start an evaluation context to parse the clause arguments on.
3056dacc382Serichkeane   SemaRef.PushExpressionEvaluationContext(
3066dacc382Serichkeane       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
3076dacc382Serichkeane 
308db4ea21dSerichkeane   switch (K) {
309db4ea21dSerichkeane   case OpenACCDirectiveKind::Invalid:
310db4ea21dSerichkeane     // Nothing to do here, an invalid kind has nothing we can check here.  We
311db4ea21dSerichkeane     // want to continue parsing clauses as far as we can, so we will just
312db4ea21dSerichkeane     // ensure that we can still work and don't check any construct-specific
313db4ea21dSerichkeane     // rules anywhere.
314db4ea21dSerichkeane     break;
315cb891127SErich Keane   case OpenACCDirectiveKind::Parallel:
316bb97c992Serichkeane   case OpenACCDirectiveKind::Serial:
317bb97c992Serichkeane   case OpenACCDirectiveKind::Kernels:
31839351f8eSerichkeane   case OpenACCDirectiveKind::ParallelLoop:
31939351f8eSerichkeane   case OpenACCDirectiveKind::SerialLoop:
32039351f8eSerichkeane   case OpenACCDirectiveKind::KernelsLoop:
32142f4e505SErich Keane   case OpenACCDirectiveKind::Loop:
322010d0115Serichkeane   case OpenACCDirectiveKind::Data:
323010d0115Serichkeane   case OpenACCDirectiveKind::EnterData:
324010d0115Serichkeane   case OpenACCDirectiveKind::ExitData:
325010d0115Serichkeane   case OpenACCDirectiveKind::HostData:
3264bbdb018Serichkeane   case OpenACCDirectiveKind::Init:
3274bbdb018Serichkeane   case OpenACCDirectiveKind::Shutdown:
32821c785d7Serichkeane   case OpenACCDirectiveKind::Set:
329db81e8c4Serichkeane   case OpenACCDirectiveKind::Update:
330cb891127SErich Keane     // Nothing to do here, there is no real legalization that needs to happen
331cb891127SErich Keane     // here as these constructs do not take any arguments.
332cb891127SErich Keane     break;
333e34cc7c9Serichkeane   case OpenACCDirectiveKind::Wait:
334e34cc7c9Serichkeane     // Nothing really to do here, the arguments to the 'wait' should have
335e34cc7c9Serichkeane     // already been handled by the time we get here.
336e34cc7c9Serichkeane     break;
337db4ea21dSerichkeane   default:
338193e9007Serichkeane     Diag(DirLoc, diag::warn_acc_construct_unimplemented) << K;
339db4ea21dSerichkeane     break;
340db4ea21dSerichkeane   }
341db4ea21dSerichkeane }
34224144d72SErich Keane 
34376600aeeSErich Keane ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind DK,
34476600aeeSErich Keane                                      OpenACCClauseKind CK, SourceLocation Loc,
34576600aeeSErich Keane                                      Expr *IntExpr) {
34676600aeeSErich Keane 
34776600aeeSErich Keane   assert(((DK != OpenACCDirectiveKind::Invalid &&
34876600aeeSErich Keane            CK == OpenACCClauseKind::Invalid) ||
34976600aeeSErich Keane           (DK == OpenACCDirectiveKind::Invalid &&
350c1298878SErich Keane            CK != OpenACCClauseKind::Invalid) ||
351c1298878SErich Keane           (DK == OpenACCDirectiveKind::Invalid &&
352c1298878SErich Keane            CK == OpenACCClauseKind::Invalid)) &&
35376600aeeSErich Keane          "Only one of directive or clause kind should be provided");
35476600aeeSErich Keane 
35576600aeeSErich Keane   class IntExprConverter : public Sema::ICEConvertDiagnoser {
35676600aeeSErich Keane     OpenACCDirectiveKind DirectiveKind;
35776600aeeSErich Keane     OpenACCClauseKind ClauseKind;
35876600aeeSErich Keane     Expr *IntExpr;
35976600aeeSErich Keane 
360c1298878SErich Keane     // gets the index into the diagnostics so we can use this for clauses,
361c1298878SErich Keane     // directives, and sub array.s
362c1298878SErich Keane     unsigned getDiagKind() const {
363c1298878SErich Keane       if (ClauseKind != OpenACCClauseKind::Invalid)
364c1298878SErich Keane         return 0;
365c1298878SErich Keane       if (DirectiveKind != OpenACCDirectiveKind::Invalid)
366c1298878SErich Keane         return 1;
367c1298878SErich Keane       return 2;
368c1298878SErich Keane     }
369c1298878SErich Keane 
37076600aeeSErich Keane   public:
37176600aeeSErich Keane     IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
37276600aeeSErich Keane                      Expr *IntExpr)
37376600aeeSErich Keane         : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false,
37476600aeeSErich Keane                               /*Suppress=*/false,
37576600aeeSErich Keane                               /*SuppressConversion=*/true),
37676600aeeSErich Keane           DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
37776600aeeSErich Keane 
37876600aeeSErich Keane     bool match(QualType T) override {
37976600aeeSErich Keane       // OpenACC spec just calls this 'integer expression' as having an
38076600aeeSErich Keane       // 'integer type', so fall back on C99's 'integer type'.
38176600aeeSErich Keane       return T->isIntegerType();
38276600aeeSErich Keane     }
38376600aeeSErich Keane     SemaBase::SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
38476600aeeSErich Keane                                                    QualType T) override {
385c1298878SErich Keane       return S.Diag(Loc, diag::err_acc_int_expr_requires_integer)
386c1298878SErich Keane              << getDiagKind() << ClauseKind << DirectiveKind << T;
38776600aeeSErich Keane     }
38876600aeeSErich Keane 
38976600aeeSErich Keane     SemaBase::SemaDiagnosticBuilder
39076600aeeSErich Keane     diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override {
39176600aeeSErich Keane       return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type)
39276600aeeSErich Keane              << T << IntExpr->getSourceRange();
39376600aeeSErich Keane     }
39476600aeeSErich Keane 
39576600aeeSErich Keane     SemaBase::SemaDiagnosticBuilder
39676600aeeSErich Keane     diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T,
39776600aeeSErich Keane                          QualType ConvTy) override {
39876600aeeSErich Keane       return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion)
39976600aeeSErich Keane              << T << ConvTy;
40076600aeeSErich Keane     }
40176600aeeSErich Keane 
40276600aeeSErich Keane     SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
40376600aeeSErich Keane                                                      CXXConversionDecl *Conv,
40476600aeeSErich Keane                                                      QualType ConvTy) override {
40576600aeeSErich Keane       return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
40676600aeeSErich Keane              << ConvTy->isEnumeralType() << ConvTy;
40776600aeeSErich Keane     }
40876600aeeSErich Keane 
40976600aeeSErich Keane     SemaBase::SemaDiagnosticBuilder
41076600aeeSErich Keane     diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override {
41176600aeeSErich Keane       return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T;
41276600aeeSErich Keane     }
41376600aeeSErich Keane 
41476600aeeSErich Keane     SemaBase::SemaDiagnosticBuilder
41576600aeeSErich Keane     noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
41676600aeeSErich Keane       return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
41776600aeeSErich Keane              << ConvTy->isEnumeralType() << ConvTy;
41876600aeeSErich Keane     }
41976600aeeSErich Keane 
42076600aeeSErich Keane     SemaBase::SemaDiagnosticBuilder
42176600aeeSErich Keane     diagnoseConversion(Sema &S, SourceLocation Loc, QualType T,
42276600aeeSErich Keane                        QualType ConvTy) override {
42376600aeeSErich Keane       llvm_unreachable("conversion functions are permitted");
42476600aeeSErich Keane     }
42576600aeeSErich Keane   } IntExprDiagnoser(DK, CK, IntExpr);
42676600aeeSErich Keane 
42797da34e0SErich Keane   if (!IntExpr)
42897da34e0SErich Keane     return ExprError();
42997da34e0SErich Keane 
43076600aeeSErich Keane   ExprResult IntExprResult = SemaRef.PerformContextualImplicitConversion(
43176600aeeSErich Keane       Loc, IntExpr, IntExprDiagnoser);
43276600aeeSErich Keane   if (IntExprResult.isInvalid())
43376600aeeSErich Keane     return ExprError();
43476600aeeSErich Keane 
43576600aeeSErich Keane   IntExpr = IntExprResult.get();
43676600aeeSErich Keane   if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType())
43776600aeeSErich Keane     return ExprError();
43876600aeeSErich Keane 
43976600aeeSErich Keane   // TODO OpenACC: Do we want to perform usual unary conversions here? When
44076600aeeSErich Keane   // doing codegen we might find that is necessary, but skip it for now.
44176600aeeSErich Keane   return IntExpr;
44276600aeeSErich Keane }
44376600aeeSErich Keane 
44448c8a579Serichkeane bool SemaOpenACC::CheckVarIsPointerType(OpenACCClauseKind ClauseKind,
44548c8a579Serichkeane                                         Expr *VarExpr) {
44648c8a579Serichkeane   // We already know that VarExpr is a proper reference to a variable, so we
44748c8a579Serichkeane   // should be able to just take the type of the expression to get the type of
44848c8a579Serichkeane   // the referenced variable.
44948c8a579Serichkeane 
45048c8a579Serichkeane   // We've already seen an error, don't diagnose anything else.
45148c8a579Serichkeane   if (!VarExpr || VarExpr->containsErrors())
45248c8a579Serichkeane     return false;
45348c8a579Serichkeane 
45448c8a579Serichkeane   if (isa<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()) ||
45548c8a579Serichkeane       VarExpr->hasPlaceholderType(BuiltinType::ArraySection)) {
45648c8a579Serichkeane     Diag(VarExpr->getExprLoc(), diag::err_array_section_use) << /*OpenACC=*/0;
45748c8a579Serichkeane     Diag(VarExpr->getExprLoc(), diag::note_acc_expected_pointer_var);
45848c8a579Serichkeane     return true;
45948c8a579Serichkeane   }
46048c8a579Serichkeane 
46148c8a579Serichkeane   QualType Ty = VarExpr->getType();
46248c8a579Serichkeane   Ty = Ty.getNonReferenceType().getUnqualifiedType();
46348c8a579Serichkeane 
46448c8a579Serichkeane   // Nothing we can do if this is a dependent type.
46548c8a579Serichkeane   if (Ty->isDependentType())
46648c8a579Serichkeane     return false;
46748c8a579Serichkeane 
46848c8a579Serichkeane   if (!Ty->isPointerType())
46948c8a579Serichkeane     return Diag(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)
47048c8a579Serichkeane            << ClauseKind << Ty;
47148c8a579Serichkeane   return false;
47248c8a579Serichkeane }
47348c8a579Serichkeane 
474a15b685cSErich Keane ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKind CK, Expr *VarExpr) {
475fa67986dSErich Keane   Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
476fa67986dSErich Keane 
477fbb14dd9Serichkeane   // 'use_device' doesn't allow array subscript or array sections.
478fbb14dd9Serichkeane   // OpenACC3.3 2.8:
479fbb14dd9Serichkeane   // A 'var' in a 'use_device' clause must be the name of a variable or array.
480fbb14dd9Serichkeane   if (CK == OpenACCClauseKind::UseDevice &&
481fbb14dd9Serichkeane       isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
482fbb14dd9Serichkeane     Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
483fbb14dd9Serichkeane     return ExprError();
484fbb14dd9Serichkeane   }
485fbb14dd9Serichkeane 
486fa67986dSErich Keane   // Sub-arrays/subscript-exprs are fine as long as the base is a
487fa67986dSErich Keane   // VarExpr/MemberExpr. So strip all of those off.
488fa67986dSErich Keane   while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
489fa67986dSErich Keane     if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
490fa67986dSErich Keane       CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
491fa67986dSErich Keane     else
492fa67986dSErich Keane       CurVarExpr =
493fa67986dSErich Keane           cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
494fa67986dSErich Keane   }
495fa67986dSErich Keane 
496fa67986dSErich Keane   // References to a VarDecl are fine.
497fa67986dSErich Keane   if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
498fa67986dSErich Keane     if (isa<VarDecl, NonTypeTemplateParmDecl>(
499a15b685cSErich Keane             DRE->getFoundDecl()->getCanonicalDecl()))
500fa67986dSErich Keane       return VarExpr;
501fa67986dSErich Keane   }
502fa67986dSErich Keane 
503a15b685cSErich Keane   // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
504a15b685cSErich Keane   // reduction clause must be a scalar variable name, an aggregate variable
505a15b685cSErich Keane   // name, an array element, or a subarray.
506fbb14dd9Serichkeane   // If CK is a 'use_device', this also isn't valid, as it isn' the name of a
507fbb14dd9Serichkeane   // variable or array.
508fbb14dd9Serichkeane   // A MemberExpr that references a Field is valid for other clauses.
509fbb14dd9Serichkeane   if (CK != OpenACCClauseKind::Reduction &&
510fbb14dd9Serichkeane       CK != OpenACCClauseKind::UseDevice) {
511fa67986dSErich Keane     if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
512fa67986dSErich Keane       if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl()))
513fa67986dSErich Keane         return VarExpr;
514fa67986dSErich Keane     }
515a15b685cSErich Keane   }
516fa67986dSErich Keane 
517fbb14dd9Serichkeane   // Referring to 'this' is ok for the most part, but for 'use_device' doesn't
518fbb14dd9Serichkeane   // fall into 'variable or array name'
519fbb14dd9Serichkeane   if (CK != OpenACCClauseKind::UseDevice && isa<CXXThisExpr>(CurVarExpr))
520fa67986dSErich Keane     return VarExpr;
521fa67986dSErich Keane 
522fa67986dSErich Keane   // Nothing really we can do here, as these are dependent.  So just return they
523fa67986dSErich Keane   // are valid.
524a15b685cSErich Keane   if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
525a15b685cSErich Keane       (CK != OpenACCClauseKind::Reduction &&
526a15b685cSErich Keane        isa<CXXDependentScopeMemberExpr>(CurVarExpr)))
527fa67986dSErich Keane     return VarExpr;
528fa67986dSErich Keane 
529fa67986dSErich Keane   // There isn't really anything we can do in the case of a recovery expr, so
530fa67986dSErich Keane   // skip the diagnostic rather than produce a confusing diagnostic.
531fa67986dSErich Keane   if (isa<RecoveryExpr>(CurVarExpr))
532fa67986dSErich Keane     return ExprError();
533fa67986dSErich Keane 
534fbb14dd9Serichkeane   if (CK == OpenACCClauseKind::UseDevice)
535fbb14dd9Serichkeane     Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
536fbb14dd9Serichkeane   else
537a15b685cSErich Keane     Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
538a15b685cSErich Keane         << (CK != OpenACCClauseKind::Reduction);
539fa67986dSErich Keane   return ExprError();
540fa67986dSErich Keane }
541fa67986dSErich Keane 
54239adc8f4SErich Keane ExprResult SemaOpenACC::ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
54339adc8f4SErich Keane                                               Expr *LowerBound,
54439adc8f4SErich Keane                                               SourceLocation ColonLoc,
54539adc8f4SErich Keane                                               Expr *Length,
54639adc8f4SErich Keane                                               SourceLocation RBLoc) {
54739adc8f4SErich Keane   ASTContext &Context = getASTContext();
54839adc8f4SErich Keane 
549c1298878SErich Keane   // Handle placeholders.
550c1298878SErich Keane   if (Base->hasPlaceholderType() &&
551c1298878SErich Keane       !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
552c1298878SErich Keane     ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
553c1298878SErich Keane     if (Result.isInvalid())
554c1298878SErich Keane       return ExprError();
555c1298878SErich Keane     Base = Result.get();
556c1298878SErich Keane   }
557c1298878SErich Keane   if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
558c1298878SErich Keane     ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
559c1298878SErich Keane     if (Result.isInvalid())
560c1298878SErich Keane       return ExprError();
561c1298878SErich Keane     Result = SemaRef.DefaultLvalueConversion(Result.get());
562c1298878SErich Keane     if (Result.isInvalid())
563c1298878SErich Keane       return ExprError();
564c1298878SErich Keane     LowerBound = Result.get();
565c1298878SErich Keane   }
566c1298878SErich Keane   if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
567c1298878SErich Keane     ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
568c1298878SErich Keane     if (Result.isInvalid())
569c1298878SErich Keane       return ExprError();
570c1298878SErich Keane     Result = SemaRef.DefaultLvalueConversion(Result.get());
571c1298878SErich Keane     if (Result.isInvalid())
572c1298878SErich Keane       return ExprError();
573c1298878SErich Keane     Length = Result.get();
574c1298878SErich Keane   }
575c1298878SErich Keane 
576c1298878SErich Keane   // Check the 'base' value, it must be an array or pointer type, and not to/of
577c1298878SErich Keane   // a function type.
578c1298878SErich Keane   QualType OriginalBaseTy = ArraySectionExpr::getBaseOriginalType(Base);
579c1298878SErich Keane   QualType ResultTy;
580c1298878SErich Keane   if (!Base->isTypeDependent()) {
581c1298878SErich Keane     if (OriginalBaseTy->isAnyPointerType()) {
582c1298878SErich Keane       ResultTy = OriginalBaseTy->getPointeeType();
583c1298878SErich Keane     } else if (OriginalBaseTy->isArrayType()) {
584c1298878SErich Keane       ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
585c1298878SErich Keane     } else {
586c1298878SErich Keane       return ExprError(
587c1298878SErich Keane           Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
588c1298878SErich Keane           << Base->getSourceRange());
589c1298878SErich Keane     }
590c1298878SErich Keane 
591c1298878SErich Keane     if (ResultTy->isFunctionType()) {
592c1298878SErich Keane       Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
593c1298878SErich Keane           << ResultTy << Base->getSourceRange();
594c1298878SErich Keane       return ExprError();
595c1298878SErich Keane     }
596c1298878SErich Keane 
597c1298878SErich Keane     if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
598c1298878SErich Keane                                     diag::err_acc_subarray_incomplete_type,
599c1298878SErich Keane                                     Base))
600c1298878SErich Keane       return ExprError();
601c1298878SErich Keane 
602c1298878SErich Keane     if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
603c1298878SErich Keane       ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
604c1298878SErich Keane       if (Result.isInvalid())
605c1298878SErich Keane         return ExprError();
606c1298878SErich Keane       Base = Result.get();
607c1298878SErich Keane     }
608c1298878SErich Keane   }
609c1298878SErich Keane 
610c1298878SErich Keane   auto GetRecovery = [&](Expr *E, QualType Ty) {
611c1298878SErich Keane     ExprResult Recovery =
612c1298878SErich Keane         SemaRef.CreateRecoveryExpr(E->getBeginLoc(), E->getEndLoc(), E, Ty);
613c1298878SErich Keane     return Recovery.isUsable() ? Recovery.get() : nullptr;
614c1298878SErich Keane   };
615c1298878SErich Keane 
616c1298878SErich Keane   // Ensure both of the expressions are int-exprs.
617c1298878SErich Keane   if (LowerBound && !LowerBound->isTypeDependent()) {
618c1298878SErich Keane     ExprResult LBRes =
619c1298878SErich Keane         ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Invalid,
620c1298878SErich Keane                      LowerBound->getExprLoc(), LowerBound);
621c1298878SErich Keane 
622c1298878SErich Keane     if (LBRes.isUsable())
623c1298878SErich Keane       LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
624c1298878SErich Keane     LowerBound =
625c1298878SErich Keane         LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
626c1298878SErich Keane   }
627c1298878SErich Keane 
628c1298878SErich Keane   if (Length && !Length->isTypeDependent()) {
629c1298878SErich Keane     ExprResult LenRes =
630c1298878SErich Keane         ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Invalid,
631c1298878SErich Keane                      Length->getExprLoc(), Length);
632c1298878SErich Keane 
633c1298878SErich Keane     if (LenRes.isUsable())
634c1298878SErich Keane       LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
635c1298878SErich Keane     Length =
636c1298878SErich Keane         LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
637c1298878SErich Keane   }
638c1298878SErich Keane 
639c1298878SErich Keane   // Length is required if the base type is not an array of known bounds.
640c1298878SErich Keane   if (!Length && (OriginalBaseTy.isNull() ||
641c1298878SErich Keane                   (!OriginalBaseTy->isDependentType() &&
642c1298878SErich Keane                    !OriginalBaseTy->isConstantArrayType() &&
643c1298878SErich Keane                    !OriginalBaseTy->isDependentSizedArrayType()))) {
644c1298878SErich Keane     bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
645c1298878SErich Keane     Diag(ColonLoc, diag::err_acc_subarray_no_length) << IsArray;
646c1298878SErich Keane     // Fill in a dummy 'length' so that when we instantiate this we don't
647c1298878SErich Keane     // double-diagnose here.
648c1298878SErich Keane     ExprResult Recovery = SemaRef.CreateRecoveryExpr(
6494dd55c56SJay Foad         ColonLoc, SourceLocation(), ArrayRef<Expr *>(), Context.IntTy);
650c1298878SErich Keane     Length = Recovery.isUsable() ? Recovery.get() : nullptr;
651c1298878SErich Keane   }
652c1298878SErich Keane 
653c1298878SErich Keane   // Check the values of each of the arguments, they cannot be negative(we
654c1298878SErich Keane   // assume), and if the array bound is known, must be within range. As we do
655c1298878SErich Keane   // so, do our best to continue with evaluation, we can set the
656c1298878SErich Keane   // value/expression to nullptr/nullopt if they are invalid, and treat them as
657c1298878SErich Keane   // not present for the rest of evaluation.
658c1298878SErich Keane 
659c1298878SErich Keane   // We don't have to check for dependence, because the dependent size is
660c1298878SErich Keane   // represented as a different AST node.
661c1298878SErich Keane   std::optional<llvm::APSInt> BaseSize;
662c1298878SErich Keane   if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
663c1298878SErich Keane     const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);
664c1298878SErich Keane     BaseSize = ArrayTy->getSize();
665c1298878SErich Keane   }
666c1298878SErich Keane 
667c1298878SErich Keane   auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
668c1298878SErich Keane     if (!E || E->isInstantiationDependent())
669c1298878SErich Keane       return std::nullopt;
670c1298878SErich Keane 
671c1298878SErich Keane     Expr::EvalResult Res;
672c1298878SErich Keane     if (!E->EvaluateAsInt(Res, Context))
673c1298878SErich Keane       return std::nullopt;
674c1298878SErich Keane     return Res.Val.getInt();
675c1298878SErich Keane   };
676c1298878SErich Keane 
677c1298878SErich Keane   std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
678c1298878SErich Keane   std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
679c1298878SErich Keane 
680c1298878SErich Keane   // Check lower bound for negative or out of range.
681c1298878SErich Keane   if (LowerBoundValue.has_value()) {
682c1298878SErich Keane     if (LowerBoundValue->isNegative()) {
683c1298878SErich Keane       Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
684c1298878SErich Keane           << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
685c1298878SErich Keane       LowerBoundValue.reset();
686c1298878SErich Keane       LowerBound = GetRecovery(LowerBound, LowerBound->getType());
687c1298878SErich Keane     } else if (BaseSize.has_value() &&
688c1298878SErich Keane                llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
689c1298878SErich Keane       // Lower bound (start index) must be less than the size of the array.
690c1298878SErich Keane       Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
691c1298878SErich Keane           << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
692c1298878SErich Keane           << toString(*BaseSize, /*Radix=*/10);
693c1298878SErich Keane       LowerBoundValue.reset();
694c1298878SErich Keane       LowerBound = GetRecovery(LowerBound, LowerBound->getType());
695c1298878SErich Keane     }
696c1298878SErich Keane   }
697c1298878SErich Keane 
698c1298878SErich Keane   // Check length for negative or out of range.
699c1298878SErich Keane   if (LengthValue.has_value()) {
700c1298878SErich Keane     if (LengthValue->isNegative()) {
701c1298878SErich Keane       Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
702c1298878SErich Keane           << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
703c1298878SErich Keane       LengthValue.reset();
704c1298878SErich Keane       Length = GetRecovery(Length, Length->getType());
705c1298878SErich Keane     } else if (BaseSize.has_value() &&
706c1298878SErich Keane                llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
707c1298878SErich Keane       // Length must be lessthan or EQUAL to the size of the array.
708c1298878SErich Keane       Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
709c1298878SErich Keane           << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
710c1298878SErich Keane           << toString(*BaseSize, /*Radix=*/10);
711c1298878SErich Keane       LengthValue.reset();
712c1298878SErich Keane       Length = GetRecovery(Length, Length->getType());
713c1298878SErich Keane     }
714c1298878SErich Keane   }
715c1298878SErich Keane 
716c1298878SErich Keane   // Adding two APSInts requires matching sign, so extract that here.
717c1298878SErich Keane   auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
718c1298878SErich Keane     if (LHS.isSigned() == RHS.isSigned())
719c1298878SErich Keane       return LHS + RHS;
720c1298878SErich Keane 
721c1298878SErich Keane     unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
722c1298878SErich Keane     return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), /*Signed=*/true);
723c1298878SErich Keane   };
724c1298878SErich Keane 
725c1298878SErich Keane   // If we know all 3 values, we can diagnose that the total value would be out
726c1298878SErich Keane   // of range.
727c1298878SErich Keane   if (BaseSize.has_value() && LowerBoundValue.has_value() &&
728c1298878SErich Keane       LengthValue.has_value() &&
729c1298878SErich Keane       llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
730c1298878SErich Keane                                   *BaseSize) > 0) {
731c1298878SErich Keane     Diag(Base->getExprLoc(),
732c1298878SErich Keane          diag::err_acc_subarray_base_plus_length_out_of_range)
733c1298878SErich Keane         << toString(*LowerBoundValue, /*Radix=*/10)
734c1298878SErich Keane         << toString(*LengthValue, /*Radix=*/10)
735c1298878SErich Keane         << toString(*BaseSize, /*Radix=*/10);
736c1298878SErich Keane 
737c1298878SErich Keane     LowerBoundValue.reset();
738c1298878SErich Keane     LowerBound = GetRecovery(LowerBound, LowerBound->getType());
739c1298878SErich Keane     LengthValue.reset();
740c1298878SErich Keane     Length = GetRecovery(Length, Length->getType());
741c1298878SErich Keane   }
742c1298878SErich Keane 
743c1298878SErich Keane   // If any part of the expression is dependent, return a dependent sub-array.
744c1298878SErich Keane   QualType ArrayExprTy = Context.ArraySectionTy;
745c1298878SErich Keane   if (Base->isTypeDependent() ||
746c1298878SErich Keane       (LowerBound && LowerBound->isInstantiationDependent()) ||
747c1298878SErich Keane       (Length && Length->isInstantiationDependent()))
748c1298878SErich Keane     ArrayExprTy = Context.DependentTy;
749c1298878SErich Keane 
75039adc8f4SErich Keane   return new (Context)
751c1298878SErich Keane       ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
752c1298878SErich Keane                        OK_Ordinary, ColonLoc, RBLoc);
75339adc8f4SErich Keane }
75439adc8f4SErich Keane 
755da4b972eSErich Keane void SemaOpenACC::ActOnWhileStmt(SourceLocation WhileLoc) {
756da4b972eSErich Keane   if (!getLangOpts().OpenACC)
757da4b972eSErich Keane     return;
758da4b972eSErich Keane 
7593c98d8c1SErich Keane   if (!LoopInfo.TopLevelLoopSeen)
760da4b972eSErich Keane     return;
761da4b972eSErich Keane 
762da4b972eSErich Keane   if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
7633c98d8c1SErich Keane     Diag(WhileLoc, diag::err_acc_invalid_in_loop)
7640aef005cSerichkeane         << /*while loop*/ 1 << CollapseInfo.DirectiveKind
7650aef005cSerichkeane         << OpenACCClauseKind::Collapse;
766da4b972eSErich Keane     assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
767da4b972eSErich Keane     Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
7683c98d8c1SErich Keane          diag::note_acc_active_clause_here)
7693c98d8c1SErich Keane         << OpenACCClauseKind::Collapse;
770da4b972eSErich Keane 
771da4b972eSErich Keane     // Remove the value so that we don't get cascading errors in the body. The
772da4b972eSErich Keane     // caller RAII object will restore this.
773da4b972eSErich Keane     CollapseInfo.CurCollapseCount = std::nullopt;
774da4b972eSErich Keane   }
7753c98d8c1SErich Keane 
7763c98d8c1SErich Keane   if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
7773c98d8c1SErich Keane     Diag(WhileLoc, diag::err_acc_invalid_in_loop)
7780aa78927Serichkeane         << /*while loop*/ 1 << TileInfo.DirectiveKind
7790aef005cSerichkeane         << OpenACCClauseKind::Tile;
7803c98d8c1SErich Keane     assert(TileInfo.ActiveTile && "tile count without object?");
7813c98d8c1SErich Keane     Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
7823c98d8c1SErich Keane         << OpenACCClauseKind::Tile;
7833c98d8c1SErich Keane 
7843c98d8c1SErich Keane     // Remove the value so that we don't get cascading errors in the body. The
7853c98d8c1SErich Keane     // caller RAII object will restore this.
7863c98d8c1SErich Keane     TileInfo.CurTileCount = std::nullopt;
7873c98d8c1SErich Keane   }
788da4b972eSErich Keane }
789da4b972eSErich Keane 
790da4b972eSErich Keane void SemaOpenACC::ActOnDoStmt(SourceLocation DoLoc) {
791da4b972eSErich Keane   if (!getLangOpts().OpenACC)
792da4b972eSErich Keane     return;
793da4b972eSErich Keane 
7943c98d8c1SErich Keane   if (!LoopInfo.TopLevelLoopSeen)
795da4b972eSErich Keane     return;
796da4b972eSErich Keane 
797da4b972eSErich Keane   if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
7983c98d8c1SErich Keane     Diag(DoLoc, diag::err_acc_invalid_in_loop)
7990aef005cSerichkeane         << /*do loop*/ 2 << CollapseInfo.DirectiveKind
8000aef005cSerichkeane         << OpenACCClauseKind::Collapse;
801da4b972eSErich Keane     assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
802da4b972eSErich Keane     Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
8033c98d8c1SErich Keane          diag::note_acc_active_clause_here)
8043c98d8c1SErich Keane         << OpenACCClauseKind::Collapse;
805da4b972eSErich Keane 
806da4b972eSErich Keane     // Remove the value so that we don't get cascading errors in the body. The
807da4b972eSErich Keane     // caller RAII object will restore this.
808da4b972eSErich Keane     CollapseInfo.CurCollapseCount = std::nullopt;
809da4b972eSErich Keane   }
8103c98d8c1SErich Keane 
8113c98d8c1SErich Keane   if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
8123c98d8c1SErich Keane     Diag(DoLoc, diag::err_acc_invalid_in_loop)
8130aa78927Serichkeane         << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
8143c98d8c1SErich Keane     assert(TileInfo.ActiveTile && "tile count without object?");
8153c98d8c1SErich Keane     Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
8163c98d8c1SErich Keane         << OpenACCClauseKind::Tile;
8173c98d8c1SErich Keane 
8183c98d8c1SErich Keane     // Remove the value so that we don't get cascading errors in the body. The
8193c98d8c1SErich Keane     // caller RAII object will restore this.
8203c98d8c1SErich Keane     TileInfo.CurTileCount = std::nullopt;
8213c98d8c1SErich Keane   }
822da4b972eSErich Keane }
823da4b972eSErich Keane 
824b0cfbfd7SErich Keane void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
825b0cfbfd7SErich Keane                                      ForStmtBeginChecker &C) {
826b0cfbfd7SErich Keane   assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
827da4b972eSErich Keane 
828da4b972eSErich Keane   // Enable the while/do-while checking.
8293c98d8c1SErich Keane   LoopInfo.TopLevelLoopSeen = true;
830da4b972eSErich Keane 
8315e92bfe9SErich Keane   if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
832b0cfbfd7SErich Keane     C.check();
8335e92bfe9SErich Keane 
8345e92bfe9SErich Keane     // OpenACC 3.3 2.9.1:
8355e92bfe9SErich Keane     // Each associated loop, except the innermost, must contain exactly one loop
8365e92bfe9SErich Keane     // or loop nest.
8375e92bfe9SErich Keane     // This checks for more than 1 loop at the current level, the
8385e92bfe9SErich Keane     // 'depth'-satisifed checking manages the 'not zero' case.
8393c98d8c1SErich Keane     if (LoopInfo.CurLevelHasLoopAlready) {
8400aef005cSerichkeane       Diag(ForLoc, diag::err_acc_clause_multiple_loops)
8410aef005cSerichkeane           << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
8425e92bfe9SErich Keane       assert(CollapseInfo.ActiveCollapse && "No collapse object?");
8435e92bfe9SErich Keane       Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
8443c98d8c1SErich Keane            diag::note_acc_active_clause_here)
8453c98d8c1SErich Keane           << OpenACCClauseKind::Collapse;
8465e92bfe9SErich Keane     } else {
847da4b972eSErich Keane       --(*CollapseInfo.CurCollapseCount);
8485e92bfe9SErich Keane 
8495e92bfe9SErich Keane       // Once we've hit zero here, we know we have deep enough 'for' loops to
8505e92bfe9SErich Keane       // get to the bottom.
8515e92bfe9SErich Keane       if (*CollapseInfo.CurCollapseCount == 0)
8525e92bfe9SErich Keane         CollapseInfo.CollapseDepthSatisfied = true;
8535e92bfe9SErich Keane     }
8545e92bfe9SErich Keane   }
8555e92bfe9SErich Keane 
8563c98d8c1SErich Keane   if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
857b0cfbfd7SErich Keane     C.check();
858b0cfbfd7SErich Keane 
8593c98d8c1SErich Keane     if (LoopInfo.CurLevelHasLoopAlready) {
8600aef005cSerichkeane       Diag(ForLoc, diag::err_acc_clause_multiple_loops)
8610aa78927Serichkeane           << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
8623c98d8c1SErich Keane       assert(TileInfo.ActiveTile && "No tile object?");
8633c98d8c1SErich Keane       Diag(TileInfo.ActiveTile->getBeginLoc(),
8643c98d8c1SErich Keane            diag::note_acc_active_clause_here)
8653c98d8c1SErich Keane           << OpenACCClauseKind::Tile;
8663c98d8c1SErich Keane     } else {
8673c98d8c1SErich Keane       --(*TileInfo.CurTileCount);
8683c98d8c1SErich Keane       // Once we've hit zero here, we know we have deep enough 'for' loops to
8693c98d8c1SErich Keane       // get to the bottom.
8703c98d8c1SErich Keane       if (*TileInfo.CurTileCount == 0)
8713c98d8c1SErich Keane         TileInfo.TileDepthSatisfied = true;
8723c98d8c1SErich Keane     }
8733c98d8c1SErich Keane   }
8743c98d8c1SErich Keane 
8755e92bfe9SErich Keane   // Set this to 'false' for the body of this loop, so that the next level
8765e92bfe9SErich Keane   // checks independently.
8773c98d8c1SErich Keane   LoopInfo.CurLevelHasLoopAlready = false;
878da4b972eSErich Keane }
879da4b972eSErich Keane 
8804f82f27cSErich Keane namespace {
881b0cfbfd7SErich Keane bool isValidLoopVariableType(QualType LoopVarTy) {
882b0cfbfd7SErich Keane   // Just skip if it is dependent, it could be any of the below.
883b0cfbfd7SErich Keane   if (LoopVarTy->isDependentType())
884b0cfbfd7SErich Keane     return true;
885b0cfbfd7SErich Keane 
886b0cfbfd7SErich Keane   // The loop variable must be of integer,
887b0cfbfd7SErich Keane   if (LoopVarTy->isIntegerType())
888b0cfbfd7SErich Keane     return true;
889b0cfbfd7SErich Keane 
890b0cfbfd7SErich Keane   // C/C++ pointer,
891b0cfbfd7SErich Keane   if (LoopVarTy->isPointerType())
892b0cfbfd7SErich Keane     return true;
893b0cfbfd7SErich Keane 
894b0cfbfd7SErich Keane   // or C++ random-access iterator type.
895b0cfbfd7SErich Keane   if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
896b0cfbfd7SErich Keane     // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
897b0cfbfd7SErich Keane     // iterator type!
898b0cfbfd7SErich Keane 
899b0cfbfd7SErich Keane     // We could either do a lot of work to see if this matches
900b0cfbfd7SErich Keane     // random-access-iterator, but it seems that just checking that the
901b0cfbfd7SErich Keane     // 'iterator_category' typedef is more than sufficient. If programmers are
902b0cfbfd7SErich Keane     // willing to lie about this, we can let them.
903b0cfbfd7SErich Keane 
904b0cfbfd7SErich Keane     for (const auto *TD :
905b0cfbfd7SErich Keane          llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
906b0cfbfd7SErich Keane       const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
907b0cfbfd7SErich Keane 
908b0cfbfd7SErich Keane       if (TDND->getName() != "iterator_category")
909b0cfbfd7SErich Keane         continue;
910b0cfbfd7SErich Keane 
911b0cfbfd7SErich Keane       // If there is no type for this decl, return false.
912b0cfbfd7SErich Keane       if (TDND->getUnderlyingType().isNull())
913b0cfbfd7SErich Keane         return false;
914b0cfbfd7SErich Keane 
915b0cfbfd7SErich Keane       const CXXRecordDecl *ItrCategoryDecl =
916b0cfbfd7SErich Keane           TDND->getUnderlyingType()->getAsCXXRecordDecl();
917b0cfbfd7SErich Keane 
918b0cfbfd7SErich Keane       // If the category isn't a record decl, it isn't the tag type.
919b0cfbfd7SErich Keane       if (!ItrCategoryDecl)
920b0cfbfd7SErich Keane         return false;
921b0cfbfd7SErich Keane 
922b0cfbfd7SErich Keane       auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
923b0cfbfd7SErich Keane         if (RD->getName() != "random_access_iterator_tag")
924b0cfbfd7SErich Keane           return false;
925b0cfbfd7SErich Keane         // Checks just for std::random_access_iterator_tag.
926b0cfbfd7SErich Keane         return RD->getEnclosingNamespaceContext()->isStdNamespace();
927b0cfbfd7SErich Keane       };
928b0cfbfd7SErich Keane 
929b0cfbfd7SErich Keane       if (IsRandomAccessIteratorTag(ItrCategoryDecl))
930b0cfbfd7SErich Keane         return true;
931b0cfbfd7SErich Keane 
932b0cfbfd7SErich Keane       // We can also support types inherited from the
933b0cfbfd7SErich Keane       // random_access_iterator_tag.
934b0cfbfd7SErich Keane       for (CXXBaseSpecifier BS : ItrCategoryDecl->bases()) {
935b0cfbfd7SErich Keane 
936b0cfbfd7SErich Keane         if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
937b0cfbfd7SErich Keane           return true;
938b0cfbfd7SErich Keane       }
939b0cfbfd7SErich Keane 
940b0cfbfd7SErich Keane       return false;
941b0cfbfd7SErich Keane     }
942b0cfbfd7SErich Keane   }
943b0cfbfd7SErich Keane 
944b0cfbfd7SErich Keane   return false;
945b0cfbfd7SErich Keane }
946b0cfbfd7SErich Keane 
947b0cfbfd7SErich Keane } // namespace
948b0cfbfd7SErich Keane 
949b0cfbfd7SErich Keane void SemaOpenACC::ForStmtBeginChecker::check() {
95039351f8eSerichkeane   if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
951b0cfbfd7SErich Keane     return;
952b0cfbfd7SErich Keane 
953b0cfbfd7SErich Keane   if (AlreadyChecked)
954b0cfbfd7SErich Keane     return;
955b0cfbfd7SErich Keane   AlreadyChecked = true;
956b0cfbfd7SErich Keane 
957b0cfbfd7SErich Keane   // OpenACC3.3 2.1:
958b0cfbfd7SErich Keane   // A loop associated with a loop construct that does not have a seq clause
959b0cfbfd7SErich Keane   // must be written to meet all the following conditions:
960b0cfbfd7SErich Keane   // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
961b0cfbfd7SErich Keane   // iterator type.
962b0cfbfd7SErich Keane   // - The loop variable must monotonically increase or decrease in the
963b0cfbfd7SErich Keane   // direction of its termination condition.
964b0cfbfd7SErich Keane   // - The loop trip count must be computable in constant time when entering the
965b0cfbfd7SErich Keane   // loop construct.
966b0cfbfd7SErich Keane   //
967b0cfbfd7SErich Keane   // For a C++ range-based for loop, the loop variable
968b0cfbfd7SErich Keane   // identified by the above conditions is the internal iterator, such as a
969b0cfbfd7SErich Keane   // pointer, that the compiler generates to iterate the range.  it is not the
970b0cfbfd7SErich Keane   // variable declared by the for loop.
971b0cfbfd7SErich Keane 
972b0cfbfd7SErich Keane   if (IsRangeFor) {
973b0cfbfd7SErich Keane     // If the range-for is being instantiated and didn't change, don't
974b0cfbfd7SErich Keane     // re-diagnose.
975b0cfbfd7SErich Keane     if (!RangeFor.has_value())
976b0cfbfd7SErich Keane       return;
977b0cfbfd7SErich Keane     // For a range-for, we can assume everything is 'corect' other than the type
978b0cfbfd7SErich Keane     // of the iterator, so check that.
979b0cfbfd7SErich Keane     const DeclStmt *RangeStmt = (*RangeFor)->getBeginStmt();
980b0cfbfd7SErich Keane 
981b0cfbfd7SErich Keane     // In some dependent contexts, the autogenerated range statement doesn't get
982b0cfbfd7SErich Keane     // included until instantiation, so skip for now.
983b0cfbfd7SErich Keane     if (!RangeStmt)
984b0cfbfd7SErich Keane       return;
985b0cfbfd7SErich Keane 
986b0cfbfd7SErich Keane     const ValueDecl *InitVar = cast<ValueDecl>(RangeStmt->getSingleDecl());
987b0cfbfd7SErich Keane     QualType VarType = InitVar->getType().getNonReferenceType();
988b0cfbfd7SErich Keane     if (!isValidLoopVariableType(VarType)) {
989b0cfbfd7SErich Keane       SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
99039351f8eSerichkeane           << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
99139351f8eSerichkeane       SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
99239351f8eSerichkeane                    diag::note_acc_construct_here)
99339351f8eSerichkeane           << SemaRef.LoopWithoutSeqInfo.Kind;
994b0cfbfd7SErich Keane     }
995b0cfbfd7SErich Keane     return;
996b0cfbfd7SErich Keane   }
997b0cfbfd7SErich Keane 
998b0cfbfd7SErich Keane   // Else we are in normal 'ForStmt', so we can diagnose everything.
999b0cfbfd7SErich Keane   // We only have to check cond/inc if they have changed, but 'init' needs to
1000b0cfbfd7SErich Keane   // just suppress its diagnostics if it hasn't changed.
1001b0cfbfd7SErich Keane   const ValueDecl *InitVar = checkInit();
1002b0cfbfd7SErich Keane   if (Cond.has_value())
1003b0cfbfd7SErich Keane     checkCond();
1004b0cfbfd7SErich Keane   if (Inc.has_value())
1005b0cfbfd7SErich Keane     checkInc(InitVar);
1006b0cfbfd7SErich Keane }
1007b0cfbfd7SErich Keane const ValueDecl *SemaOpenACC::ForStmtBeginChecker::checkInit() {
1008b0cfbfd7SErich Keane   if (!Init) {
1009b0cfbfd7SErich Keane     if (InitChanged) {
101039351f8eSerichkeane       SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)
101139351f8eSerichkeane           << SemaRef.LoopWithoutSeqInfo.Kind;
101239351f8eSerichkeane       SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
101339351f8eSerichkeane                    diag::note_acc_construct_here)
101439351f8eSerichkeane           << SemaRef.LoopWithoutSeqInfo.Kind;
1015b0cfbfd7SErich Keane     }
1016b0cfbfd7SErich Keane     return nullptr;
1017b0cfbfd7SErich Keane   }
1018b0cfbfd7SErich Keane 
1019b0cfbfd7SErich Keane   auto DiagLoopVar = [&]() {
1020b0cfbfd7SErich Keane     if (InitChanged) {
102139351f8eSerichkeane       SemaRef.Diag(Init->getBeginLoc(), diag::err_acc_loop_variable)
102239351f8eSerichkeane           << SemaRef.LoopWithoutSeqInfo.Kind;
102339351f8eSerichkeane       SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
102439351f8eSerichkeane                    diag::note_acc_construct_here)
102539351f8eSerichkeane           << SemaRef.LoopWithoutSeqInfo.Kind;
1026b0cfbfd7SErich Keane     }
1027b0cfbfd7SErich Keane     return nullptr;
1028b0cfbfd7SErich Keane   };
1029b0cfbfd7SErich Keane 
1030b0cfbfd7SErich Keane   if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
1031b0cfbfd7SErich Keane     Init = ExprTemp->getSubExpr();
1032b0cfbfd7SErich Keane   if (const auto *E = dyn_cast<Expr>(Init))
1033b0cfbfd7SErich Keane     Init = E->IgnoreParenImpCasts();
1034b0cfbfd7SErich Keane 
1035b0cfbfd7SErich Keane   const ValueDecl *InitVar = nullptr;
1036b0cfbfd7SErich Keane 
1037b0cfbfd7SErich Keane   if (const auto *BO = dyn_cast<BinaryOperator>(Init)) {
1038b0cfbfd7SErich Keane     // Allow assignment operator here.
1039b0cfbfd7SErich Keane 
1040b0cfbfd7SErich Keane     if (!BO->isAssignmentOp())
1041b0cfbfd7SErich Keane       return DiagLoopVar();
1042b0cfbfd7SErich Keane 
1043b0cfbfd7SErich Keane     const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
1044b0cfbfd7SErich Keane 
1045b0cfbfd7SErich Keane     if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS))
1046b0cfbfd7SErich Keane       InitVar = DRE->getDecl();
1047b0cfbfd7SErich Keane   } else if (const auto *DS = dyn_cast<DeclStmt>(Init)) {
1048b0cfbfd7SErich Keane     // Allow T t = <whatever>
1049b0cfbfd7SErich Keane     if (!DS->isSingleDecl())
1050b0cfbfd7SErich Keane       return DiagLoopVar();
1051b0cfbfd7SErich Keane 
1052b0cfbfd7SErich Keane     InitVar = dyn_cast<ValueDecl>(DS->getSingleDecl());
1053b0cfbfd7SErich Keane 
1054b0cfbfd7SErich Keane     // Ensure we have an initializer, unless this is a record/dependent type.
1055b0cfbfd7SErich Keane 
1056b0cfbfd7SErich Keane     if (InitVar) {
1057b0cfbfd7SErich Keane       if (!isa<VarDecl>(InitVar))
1058b0cfbfd7SErich Keane         return DiagLoopVar();
1059b0cfbfd7SErich Keane 
1060b0cfbfd7SErich Keane       if (!InitVar->getType()->isRecordType() &&
1061b0cfbfd7SErich Keane           !InitVar->getType()->isDependentType() &&
1062b0cfbfd7SErich Keane           !cast<VarDecl>(InitVar)->hasInit())
1063b0cfbfd7SErich Keane         return DiagLoopVar();
1064b0cfbfd7SErich Keane     }
1065b0cfbfd7SErich Keane   } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Init)) {
1066b0cfbfd7SErich Keane     // Allow assignment operator call.
1067b0cfbfd7SErich Keane     if (CE->getOperator() != OO_Equal)
1068b0cfbfd7SErich Keane       return DiagLoopVar();
1069b0cfbfd7SErich Keane 
1070b0cfbfd7SErich Keane     const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
1071b0cfbfd7SErich Keane 
1072b0cfbfd7SErich Keane     if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
1073b0cfbfd7SErich Keane       InitVar = DRE->getDecl();
1074b0cfbfd7SErich Keane     } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
1075b0cfbfd7SErich Keane       if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1076b0cfbfd7SErich Keane         InitVar = ME->getMemberDecl();
1077b0cfbfd7SErich Keane     }
1078b0cfbfd7SErich Keane   }
1079b0cfbfd7SErich Keane 
1080b0cfbfd7SErich Keane   if (!InitVar)
1081b0cfbfd7SErich Keane     return DiagLoopVar();
1082b0cfbfd7SErich Keane 
1083b0cfbfd7SErich Keane   InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
1084b0cfbfd7SErich Keane   QualType VarType = InitVar->getType().getNonReferenceType();
1085b0cfbfd7SErich Keane 
1086b0cfbfd7SErich Keane   // Since we have one, all we need to do is ensure it is the right type.
1087b0cfbfd7SErich Keane   if (!isValidLoopVariableType(VarType)) {
1088b0cfbfd7SErich Keane     if (InitChanged) {
1089b0cfbfd7SErich Keane       SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
109039351f8eSerichkeane           << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
109139351f8eSerichkeane       SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
109239351f8eSerichkeane                    diag::note_acc_construct_here)
109339351f8eSerichkeane           << SemaRef.LoopWithoutSeqInfo.Kind;
1094b0cfbfd7SErich Keane     }
1095b0cfbfd7SErich Keane     return nullptr;
1096b0cfbfd7SErich Keane   }
1097b0cfbfd7SErich Keane 
1098b0cfbfd7SErich Keane   return InitVar;
1099b0cfbfd7SErich Keane }
1100b0cfbfd7SErich Keane void SemaOpenACC::ForStmtBeginChecker::checkCond() {
1101b0cfbfd7SErich Keane   if (!*Cond) {
110239351f8eSerichkeane     SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
110339351f8eSerichkeane         << SemaRef.LoopWithoutSeqInfo.Kind;
110439351f8eSerichkeane     SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
110539351f8eSerichkeane         << SemaRef.LoopWithoutSeqInfo.Kind;
1106b0cfbfd7SErich Keane   }
1107b0cfbfd7SErich Keane   // Nothing else to do here.  we could probably do some additional work to look
1108b0cfbfd7SErich Keane   // into the termination condition, but that error-prone.  For now, we don't
1109b0cfbfd7SErich Keane   // implement anything other than 'there is a termination condition', and if
1110b0cfbfd7SErich Keane   // codegen/MLIR comes up with some necessary restrictions, we can implement
1111b0cfbfd7SErich Keane   // them here.
1112b0cfbfd7SErich Keane }
1113b0cfbfd7SErich Keane 
1114b0cfbfd7SErich Keane void SemaOpenACC::ForStmtBeginChecker::checkInc(const ValueDecl *Init) {
1115b0cfbfd7SErich Keane 
1116b0cfbfd7SErich Keane   if (!*Inc) {
111739351f8eSerichkeane     SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
111839351f8eSerichkeane         << SemaRef.LoopWithoutSeqInfo.Kind;
111939351f8eSerichkeane     SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
112039351f8eSerichkeane         << SemaRef.LoopWithoutSeqInfo.Kind;
1121b0cfbfd7SErich Keane     return;
1122b0cfbfd7SErich Keane   }
1123b0cfbfd7SErich Keane   auto DiagIncVar = [this] {
112439351f8eSerichkeane     SemaRef.Diag((*Inc)->getBeginLoc(), diag::err_acc_loop_not_monotonic)
112539351f8eSerichkeane         << SemaRef.LoopWithoutSeqInfo.Kind;
112639351f8eSerichkeane     SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
112739351f8eSerichkeane         << SemaRef.LoopWithoutSeqInfo.Kind;
1128b0cfbfd7SErich Keane     return;
1129b0cfbfd7SErich Keane   };
1130b0cfbfd7SErich Keane 
1131b0cfbfd7SErich Keane   if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(*Inc))
1132b0cfbfd7SErich Keane     Inc = ExprTemp->getSubExpr();
1133b0cfbfd7SErich Keane   if (const auto *E = dyn_cast<Expr>(*Inc))
1134b0cfbfd7SErich Keane     Inc = E->IgnoreParenImpCasts();
1135b0cfbfd7SErich Keane 
1136b0cfbfd7SErich Keane   auto getDeclFromExpr = [](const Expr *E) -> const ValueDecl * {
1137b0cfbfd7SErich Keane     E = E->IgnoreParenImpCasts();
1138b0cfbfd7SErich Keane     if (const auto *FE = dyn_cast<FullExpr>(E))
1139b0cfbfd7SErich Keane       E = FE->getSubExpr();
1140b0cfbfd7SErich Keane 
1141b0cfbfd7SErich Keane     E = E->IgnoreParenImpCasts();
1142b0cfbfd7SErich Keane 
1143b0cfbfd7SErich Keane     if (!E)
1144b0cfbfd7SErich Keane       return nullptr;
1145b0cfbfd7SErich Keane     if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
1146b0cfbfd7SErich Keane       return dyn_cast<ValueDecl>(DRE->getDecl());
1147b0cfbfd7SErich Keane 
1148b0cfbfd7SErich Keane     if (const auto *ME = dyn_cast<MemberExpr>(E))
1149b0cfbfd7SErich Keane       if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
1150b0cfbfd7SErich Keane         return ME->getMemberDecl();
1151b0cfbfd7SErich Keane 
1152b0cfbfd7SErich Keane     return nullptr;
1153b0cfbfd7SErich Keane   };
1154b0cfbfd7SErich Keane 
1155b0cfbfd7SErich Keane   const ValueDecl *IncVar = nullptr;
1156b0cfbfd7SErich Keane 
1157b0cfbfd7SErich Keane   // Here we enforce the monotonically increase/decrease:
1158b0cfbfd7SErich Keane   if (const auto *UO = dyn_cast<UnaryOperator>(*Inc)) {
1159b0cfbfd7SErich Keane     // Allow increment/decrement ops.
1160b0cfbfd7SErich Keane     if (!UO->isIncrementDecrementOp())
1161b0cfbfd7SErich Keane       return DiagIncVar();
1162b0cfbfd7SErich Keane     IncVar = getDeclFromExpr(UO->getSubExpr());
1163b0cfbfd7SErich Keane   } else if (const auto *BO = dyn_cast<BinaryOperator>(*Inc)) {
1164b0cfbfd7SErich Keane     switch (BO->getOpcode()) {
1165b0cfbfd7SErich Keane     default:
1166b0cfbfd7SErich Keane       return DiagIncVar();
1167b0cfbfd7SErich Keane     case BO_AddAssign:
1168b0cfbfd7SErich Keane     case BO_SubAssign:
1169b0cfbfd7SErich Keane     case BO_MulAssign:
1170b0cfbfd7SErich Keane     case BO_DivAssign:
1171b0cfbfd7SErich Keane     case BO_Assign:
1172b0cfbfd7SErich Keane       // += -= *= /= should all be fine here, this should be all of the
1173b0cfbfd7SErich Keane       // 'monotonical' compound-assign ops.
1174b0cfbfd7SErich Keane       // Assignment we just give up on, we could do better, and ensure that it
1175b0cfbfd7SErich Keane       // is a binary/operator expr doing more work, but that seems like a lot
1176b0cfbfd7SErich Keane       // of work for an error prone check.
1177b0cfbfd7SErich Keane       break;
1178b0cfbfd7SErich Keane     }
1179b0cfbfd7SErich Keane     IncVar = getDeclFromExpr(BO->getLHS());
1180b0cfbfd7SErich Keane   } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(*Inc)) {
1181b0cfbfd7SErich Keane     switch (CE->getOperator()) {
1182b0cfbfd7SErich Keane     default:
1183b0cfbfd7SErich Keane       return DiagIncVar();
1184b0cfbfd7SErich Keane     case OO_PlusPlus:
1185b0cfbfd7SErich Keane     case OO_MinusMinus:
1186b0cfbfd7SErich Keane     case OO_PlusEqual:
1187b0cfbfd7SErich Keane     case OO_MinusEqual:
1188b0cfbfd7SErich Keane     case OO_StarEqual:
1189b0cfbfd7SErich Keane     case OO_SlashEqual:
1190b0cfbfd7SErich Keane     case OO_Equal:
1191b0cfbfd7SErich Keane       // += -= *= /= should all be fine here, this should be all of the
1192b0cfbfd7SErich Keane       // 'monotonical' compound-assign ops.
1193b0cfbfd7SErich Keane       // Assignment we just give up on, we could do better, and ensure that it
1194b0cfbfd7SErich Keane       // is a binary/operator expr doing more work, but that seems like a lot
1195b0cfbfd7SErich Keane       // of work for an error prone check.
1196b0cfbfd7SErich Keane       break;
1197b0cfbfd7SErich Keane     }
1198b0cfbfd7SErich Keane 
1199b0cfbfd7SErich Keane     IncVar = getDeclFromExpr(CE->getArg(0));
1200b0cfbfd7SErich Keane 
1201b0cfbfd7SErich Keane   } else if (const auto *ME = dyn_cast<CXXMemberCallExpr>(*Inc)) {
1202b0cfbfd7SErich Keane     IncVar = getDeclFromExpr(ME->getImplicitObjectArgument());
1203b0cfbfd7SErich Keane     // We can't really do much for member expressions, other than hope they are
1204b0cfbfd7SErich Keane     // doing the right thing, so give up here.
1205b0cfbfd7SErich Keane   }
1206b0cfbfd7SErich Keane 
1207b0cfbfd7SErich Keane   if (!IncVar)
1208b0cfbfd7SErich Keane     return DiagIncVar();
1209b0cfbfd7SErich Keane 
1210b0cfbfd7SErich Keane   // InitVar shouldn't be null unless there was an error, so don't diagnose if
1211b0cfbfd7SErich Keane   // that is the case. Else we should ensure that it refers to the  loop
1212b0cfbfd7SErich Keane   // value.
1213b0cfbfd7SErich Keane   if (Init && IncVar->getCanonicalDecl() != Init->getCanonicalDecl())
1214b0cfbfd7SErich Keane     return DiagIncVar();
1215b0cfbfd7SErich Keane 
1216b0cfbfd7SErich Keane   return;
1217b0cfbfd7SErich Keane }
1218b0cfbfd7SErich Keane 
1219b0cfbfd7SErich Keane void SemaOpenACC::ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *OldFirst,
1220b0cfbfd7SErich Keane                                     const Stmt *First, const Stmt *OldSecond,
1221b0cfbfd7SErich Keane                                     const Stmt *Second, const Stmt *OldThird,
1222b0cfbfd7SErich Keane                                     const Stmt *Third) {
1223b0cfbfd7SErich Keane   if (!getLangOpts().OpenACC)
1224b0cfbfd7SErich Keane     return;
1225b0cfbfd7SErich Keane 
1226b0cfbfd7SErich Keane   std::optional<const Stmt *> S;
1227b0cfbfd7SErich Keane   if (OldSecond == Second)
1228b0cfbfd7SErich Keane     S = std::nullopt;
1229b0cfbfd7SErich Keane   else
1230b0cfbfd7SErich Keane     S = Second;
1231b0cfbfd7SErich Keane   std::optional<const Stmt *> T;
1232b0cfbfd7SErich Keane   if (OldThird == Third)
1233b0cfbfd7SErich Keane     S = std::nullopt;
1234b0cfbfd7SErich Keane   else
1235b0cfbfd7SErich Keane     S = Third;
1236b0cfbfd7SErich Keane 
1237b0cfbfd7SErich Keane   bool InitChanged = false;
1238b0cfbfd7SErich Keane   if (OldFirst != First) {
1239b0cfbfd7SErich Keane     InitChanged = true;
1240b0cfbfd7SErich Keane 
1241b0cfbfd7SErich Keane     // VarDecls are always rebuild because they are dependent, so we can do a
1242b0cfbfd7SErich Keane     // little work to suppress some of the double checking based on whether the
1243b0cfbfd7SErich Keane     // type is instantiation dependent.
1244b0cfbfd7SErich Keane     QualType OldVDTy;
1245b0cfbfd7SErich Keane     QualType NewVDTy;
1246b0cfbfd7SErich Keane     if (const auto *DS = dyn_cast<DeclStmt>(OldFirst))
1247b0cfbfd7SErich Keane       if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1248b0cfbfd7SErich Keane               DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1249b0cfbfd7SErich Keane         OldVDTy = VD->getType();
1250b0cfbfd7SErich Keane     if (const auto *DS = dyn_cast<DeclStmt>(First))
1251b0cfbfd7SErich Keane       if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
1252b0cfbfd7SErich Keane               DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
1253b0cfbfd7SErich Keane         NewVDTy = VD->getType();
1254b0cfbfd7SErich Keane 
1255b0cfbfd7SErich Keane     if (!OldVDTy.isNull() && !NewVDTy.isNull())
1256b0cfbfd7SErich Keane       InitChanged = OldVDTy->isInstantiationDependentType() !=
1257b0cfbfd7SErich Keane                     NewVDTy->isInstantiationDependentType();
1258b0cfbfd7SErich Keane   }
1259b0cfbfd7SErich Keane 
1260b0cfbfd7SErich Keane   ForStmtBeginChecker FSBC{*this, ForLoc, First, InitChanged, S, T};
1261b0cfbfd7SErich Keane   if (!LoopInfo.TopLevelLoopSeen) {
1262b0cfbfd7SErich Keane     FSBC.check();
1263b0cfbfd7SErich Keane   }
1264b0cfbfd7SErich Keane 
1265b0cfbfd7SErich Keane   ForStmtBeginHelper(ForLoc, FSBC);
1266b0cfbfd7SErich Keane }
1267b0cfbfd7SErich Keane 
1268b0cfbfd7SErich Keane void SemaOpenACC::ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First,
1269b0cfbfd7SErich Keane                                     const Stmt *Second, const Stmt *Third) {
1270b0cfbfd7SErich Keane   if (!getLangOpts().OpenACC)
1271b0cfbfd7SErich Keane     return;
1272b0cfbfd7SErich Keane 
1273b0cfbfd7SErich Keane   ForStmtBeginChecker FSBC{*this,  ForLoc, First, /*InitChanged=*/true,
1274b0cfbfd7SErich Keane                            Second, Third};
1275b0cfbfd7SErich Keane   if (!LoopInfo.TopLevelLoopSeen) {
1276b0cfbfd7SErich Keane     FSBC.check();
1277b0cfbfd7SErich Keane   }
1278b0cfbfd7SErich Keane 
1279b0cfbfd7SErich Keane   ForStmtBeginHelper(ForLoc, FSBC);
1280b0cfbfd7SErich Keane }
1281b0cfbfd7SErich Keane 
1282b0cfbfd7SErich Keane void SemaOpenACC::ActOnRangeForStmtBegin(SourceLocation ForLoc,
1283b0cfbfd7SErich Keane                                          const Stmt *OldRangeFor,
1284b0cfbfd7SErich Keane                                          const Stmt *RangeFor) {
1285b0cfbfd7SErich Keane   if (!getLangOpts().OpenACC)
1286b0cfbfd7SErich Keane     return;
1287b0cfbfd7SErich Keane 
1288b0cfbfd7SErich Keane   std::optional<const CXXForRangeStmt *> RF;
1289b0cfbfd7SErich Keane 
1290b0cfbfd7SErich Keane   if (OldRangeFor == RangeFor)
1291b0cfbfd7SErich Keane     RF = std::nullopt;
1292b0cfbfd7SErich Keane   else
1293b0cfbfd7SErich Keane     RF = cast<CXXForRangeStmt>(RangeFor);
1294b0cfbfd7SErich Keane 
1295b0cfbfd7SErich Keane   ForStmtBeginChecker FSBC{*this, ForLoc, RF};
1296b0cfbfd7SErich Keane   if (!LoopInfo.TopLevelLoopSeen) {
1297b0cfbfd7SErich Keane     FSBC.check();
1298b0cfbfd7SErich Keane   }
1299b0cfbfd7SErich Keane   ForStmtBeginHelper(ForLoc, FSBC);
1300b0cfbfd7SErich Keane }
1301b0cfbfd7SErich Keane 
1302b0cfbfd7SErich Keane void SemaOpenACC::ActOnRangeForStmtBegin(SourceLocation ForLoc,
1303b0cfbfd7SErich Keane                                          const Stmt *RangeFor) {
1304b0cfbfd7SErich Keane   if (!getLangOpts().OpenACC)
1305b0cfbfd7SErich Keane     return;
1306b0cfbfd7SErich Keane 
1307b0cfbfd7SErich Keane   ForStmtBeginChecker FSBC{*this, ForLoc, cast<CXXForRangeStmt>(RangeFor)};
1308b0cfbfd7SErich Keane   if (!LoopInfo.TopLevelLoopSeen) {
1309b0cfbfd7SErich Keane     FSBC.check();
1310b0cfbfd7SErich Keane   }
1311b0cfbfd7SErich Keane   ForStmtBeginHelper(ForLoc, FSBC);
1312b0cfbfd7SErich Keane }
1313b0cfbfd7SErich Keane 
1314b0cfbfd7SErich Keane namespace {
13153c98d8c1SErich Keane SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
13164f82f27cSErich Keane   // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
13174f82f27cSErich Keane   // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
13184f82f27cSErich Keane   // `DoStmt`, as those are caught as a violation elsewhere.
13194f82f27cSErich Keane   // For `CompoundStmt` we need to search inside of it.
13204f82f27cSErich Keane   if (!CurStmt ||
13214f82f27cSErich Keane       isa<ForStmt, NullStmt, ForStmt, CXXForRangeStmt, WhileStmt, DoStmt>(
13224f82f27cSErich Keane           CurStmt))
13234f82f27cSErich Keane     return SourceLocation{};
13244f82f27cSErich Keane 
13254f82f27cSErich Keane   // Any other construct is an error anyway, so it has already been diagnosed.
13264f82f27cSErich Keane   if (isa<OpenACCConstructStmt>(CurStmt))
13274f82f27cSErich Keane     return SourceLocation{};
13284f82f27cSErich Keane 
13294f82f27cSErich Keane   // Search inside the compound statement, this allows for arbitrary nesting
13304f82f27cSErich Keane   // of compound statements, as long as there isn't any code inside.
13314f82f27cSErich Keane   if (const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
13324f82f27cSErich Keane     for (const auto *ChildStmt : CS->children()) {
13333c98d8c1SErich Keane       SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
13344f82f27cSErich Keane       if (ChildStmtLoc.isValid())
13354f82f27cSErich Keane         return ChildStmtLoc;
13364f82f27cSErich Keane     }
13374f82f27cSErich Keane     // Empty/not invalid compound statements are legal.
13384f82f27cSErich Keane     return SourceLocation{};
13394f82f27cSErich Keane   }
13404f82f27cSErich Keane   return CurStmt->getBeginLoc();
13414f82f27cSErich Keane }
13424f82f27cSErich Keane } // namespace
13434f82f27cSErich Keane 
1344da4b972eSErich Keane void SemaOpenACC::ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body) {
1345da4b972eSErich Keane   if (!getLangOpts().OpenACC)
1346da4b972eSErich Keane     return;
1347b0cfbfd7SErich Keane 
13485e92bfe9SErich Keane   // Set this to 'true' so if we find another one at this level we can diagnose.
13493c98d8c1SErich Keane   LoopInfo.CurLevelHasLoopAlready = true;
13504f82f27cSErich Keane 
13514f82f27cSErich Keane   if (!Body.isUsable())
13524f82f27cSErich Keane     return;
13534f82f27cSErich Keane 
13543c98d8c1SErich Keane   bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
13553c98d8c1SErich Keane                           *CollapseInfo.CurCollapseCount > 0 &&
13563c98d8c1SErich Keane                           !CollapseInfo.ActiveCollapse->hasForce();
13573c98d8c1SErich Keane   bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
13584f82f27cSErich Keane 
13593c98d8c1SErich Keane   if (IsActiveCollapse || IsActiveTile) {
13603c98d8c1SErich Keane     SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());
13614f82f27cSErich Keane 
13623c98d8c1SErich Keane     if (OtherStmtLoc.isValid() && IsActiveCollapse) {
13633c98d8c1SErich Keane       Diag(OtherStmtLoc, diag::err_acc_intervening_code)
13640aef005cSerichkeane           << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
13654f82f27cSErich Keane       Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
13663c98d8c1SErich Keane            diag::note_acc_active_clause_here)
13673c98d8c1SErich Keane           << OpenACCClauseKind::Collapse;
13683c98d8c1SErich Keane     }
13693c98d8c1SErich Keane 
13703c98d8c1SErich Keane     if (OtherStmtLoc.isValid() && IsActiveTile) {
13713c98d8c1SErich Keane       Diag(OtherStmtLoc, diag::err_acc_intervening_code)
13720aa78927Serichkeane           << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
13733c98d8c1SErich Keane       Diag(TileInfo.ActiveTile->getBeginLoc(),
13743c98d8c1SErich Keane            diag::note_acc_active_clause_here)
13753c98d8c1SErich Keane           << OpenACCClauseKind::Tile;
13764f82f27cSErich Keane     }
13774f82f27cSErich Keane   }
1378da4b972eSErich Keane }
1379da4b972eSErich Keane 
1380bfc2dbe0Serichkeane namespace {
1381bfc2dbe0Serichkeane // Get a list of clause Kinds for diagnosing a list, joined by a commas and an
1382bfc2dbe0Serichkeane // 'or'.
1383bfc2dbe0Serichkeane std::string GetListOfClauses(llvm::ArrayRef<OpenACCClauseKind> Clauses) {
1384bfc2dbe0Serichkeane   assert(!Clauses.empty() && "empty clause list not supported");
1385bfc2dbe0Serichkeane 
1386bfc2dbe0Serichkeane   std::string Output;
1387bfc2dbe0Serichkeane   llvm::raw_string_ostream OS{Output};
1388bfc2dbe0Serichkeane 
1389bfc2dbe0Serichkeane   if (Clauses.size() == 1) {
1390bfc2dbe0Serichkeane     OS << '\'' << Clauses[0] << '\'';
1391bfc2dbe0Serichkeane     return Output;
1392bfc2dbe0Serichkeane   }
1393bfc2dbe0Serichkeane 
1394bfc2dbe0Serichkeane   llvm::ArrayRef<OpenACCClauseKind> AllButLast{Clauses.begin(),
1395bfc2dbe0Serichkeane                                                Clauses.end() - 1};
1396bfc2dbe0Serichkeane 
1397bfc2dbe0Serichkeane   llvm::interleave(
1398bfc2dbe0Serichkeane       AllButLast, [&](OpenACCClauseKind K) { OS << '\'' << K << '\''; },
1399bfc2dbe0Serichkeane       [&] { OS << ", "; });
1400bfc2dbe0Serichkeane 
1401bfc2dbe0Serichkeane   OS << " or \'" << Clauses.back() << '\'';
1402bfc2dbe0Serichkeane   return Output;
1403bfc2dbe0Serichkeane }
1404bfc2dbe0Serichkeane } // namespace
1405bfc2dbe0Serichkeane 
1406bfc2dbe0Serichkeane bool SemaOpenACC::ActOnStartStmtDirective(
1407bfc2dbe0Serichkeane     OpenACCDirectiveKind K, SourceLocation StartLoc,
1408bfc2dbe0Serichkeane     ArrayRef<const OpenACCClause *> Clauses) {
14096dacc382Serichkeane   SemaRef.DiscardCleanupsInEvaluationContext();
14106dacc382Serichkeane   SemaRef.PopExpressionEvaluationContext();
1411da4b972eSErich Keane 
1412da4b972eSErich Keane   // OpenACC 3.3 2.9.1:
1413da4b972eSErich Keane   // Intervening code must not contain other OpenACC directives or calls to API
1414da4b972eSErich Keane   // routines.
1415da4b972eSErich Keane   //
1416da4b972eSErich Keane   // ALL constructs are ill-formed if there is an active 'collapse'
1417da4b972eSErich Keane   if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
14183c98d8c1SErich Keane     Diag(StartLoc, diag::err_acc_invalid_in_loop)
14190aef005cSerichkeane         << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
14200aef005cSerichkeane         << OpenACCClauseKind::Collapse << K;
1421da4b972eSErich Keane     assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
1422da4b972eSErich Keane     Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
14233c98d8c1SErich Keane          diag::note_acc_active_clause_here)
14243c98d8c1SErich Keane         << OpenACCClauseKind::Collapse;
14253c98d8c1SErich Keane   }
14263c98d8c1SErich Keane   if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
14273c98d8c1SErich Keane     Diag(StartLoc, diag::err_acc_invalid_in_loop)
14280aa78927Serichkeane         << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
14290aef005cSerichkeane         << OpenACCClauseKind::Tile << K;
14303c98d8c1SErich Keane     assert(TileInfo.ActiveTile && "Tile count without object?");
14313c98d8c1SErich Keane     Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
14323c98d8c1SErich Keane         << OpenACCClauseKind::Tile;
1433da4b972eSErich Keane   }
1434da4b972eSErich Keane 
1435bfc2dbe0Serichkeane   // OpenACC3.3 2.6.5: At least one copy, copyin, copyout, create, no_create,
1436bfc2dbe0Serichkeane   // present, deviceptr, attach, or default clause must appear on a 'data'
1437bfc2dbe0Serichkeane   // construct.
1438bfc2dbe0Serichkeane   if (K == OpenACCDirectiveKind::Data &&
1439bfc2dbe0Serichkeane       llvm::find_if(Clauses,
1440bfc2dbe0Serichkeane                     llvm::IsaPred<OpenACCCopyClause, OpenACCCopyInClause,
1441bfc2dbe0Serichkeane                                   OpenACCCopyOutClause, OpenACCCreateClause,
1442bfc2dbe0Serichkeane                                   OpenACCNoCreateClause, OpenACCPresentClause,
1443bfc2dbe0Serichkeane                                   OpenACCDevicePtrClause, OpenACCAttachClause,
1444bfc2dbe0Serichkeane                                   OpenACCDefaultClause>) == Clauses.end())
1445bfc2dbe0Serichkeane     return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1446bfc2dbe0Serichkeane            << K
1447bfc2dbe0Serichkeane            << GetListOfClauses(
1448bfc2dbe0Serichkeane                   {OpenACCClauseKind::Copy, OpenACCClauseKind::CopyIn,
1449bfc2dbe0Serichkeane                    OpenACCClauseKind::CopyOut, OpenACCClauseKind::Create,
1450bfc2dbe0Serichkeane                    OpenACCClauseKind::NoCreate, OpenACCClauseKind::Present,
1451bfc2dbe0Serichkeane                    OpenACCClauseKind::DevicePtr, OpenACCClauseKind::Attach,
1452bfc2dbe0Serichkeane                    OpenACCClauseKind::Default});
1453bfc2dbe0Serichkeane 
1454bfc2dbe0Serichkeane   // OpenACC3.3 2.6.6: At least one copyin, create, or attach clause must appear
1455bfc2dbe0Serichkeane   // on an enter data directive.
1456bfc2dbe0Serichkeane   if (K == OpenACCDirectiveKind::EnterData &&
1457bfc2dbe0Serichkeane       llvm::find_if(Clauses,
1458bfc2dbe0Serichkeane                     llvm::IsaPred<OpenACCCopyInClause, OpenACCCreateClause,
1459bfc2dbe0Serichkeane                                   OpenACCAttachClause>) == Clauses.end())
1460bfc2dbe0Serichkeane     return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1461bfc2dbe0Serichkeane            << K
1462bfc2dbe0Serichkeane            << GetListOfClauses({
1463bfc2dbe0Serichkeane                   OpenACCClauseKind::CopyIn,
1464bfc2dbe0Serichkeane                   OpenACCClauseKind::Create,
1465bfc2dbe0Serichkeane                   OpenACCClauseKind::Attach,
1466bfc2dbe0Serichkeane               });
1467bfc2dbe0Serichkeane   // OpenACC3.3 2.6.6: At least one copyout, delete, or detach clause must
1468bfc2dbe0Serichkeane   // appear on an exit data directive.
1469bfc2dbe0Serichkeane   if (K == OpenACCDirectiveKind::ExitData &&
1470bfc2dbe0Serichkeane       llvm::find_if(Clauses,
1471bfc2dbe0Serichkeane                     llvm::IsaPred<OpenACCCopyOutClause, OpenACCDeleteClause,
1472bfc2dbe0Serichkeane                                   OpenACCDetachClause>) == Clauses.end())
1473bfc2dbe0Serichkeane     return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1474bfc2dbe0Serichkeane            << K
1475bfc2dbe0Serichkeane            << GetListOfClauses({
1476bfc2dbe0Serichkeane                   OpenACCClauseKind::CopyOut,
1477bfc2dbe0Serichkeane                   OpenACCClauseKind::Delete,
1478bfc2dbe0Serichkeane                   OpenACCClauseKind::Detach,
1479bfc2dbe0Serichkeane               });
1480bfc2dbe0Serichkeane 
1481bfc2dbe0Serichkeane   // OpenACC3.3 2.8: At least 'one use_device' clause must appear.
1482bfc2dbe0Serichkeane   if (K == OpenACCDirectiveKind::HostData &&
1483bfc2dbe0Serichkeane       llvm::find_if(Clauses, llvm::IsaPred<OpenACCUseDeviceClause>) ==
1484bfc2dbe0Serichkeane           Clauses.end())
1485bfc2dbe0Serichkeane     return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1486bfc2dbe0Serichkeane            << K << GetListOfClauses({OpenACCClauseKind::UseDevice});
1487bfc2dbe0Serichkeane 
148821c785d7Serichkeane   // OpenACC3.3 2.14.3: At least one default_async, device_num, or device_type
148921c785d7Serichkeane   // clause must appear.
149021c785d7Serichkeane   if (K == OpenACCDirectiveKind::Set &&
149121c785d7Serichkeane       llvm::find_if(
149221c785d7Serichkeane           Clauses,
1493ff24e9a1Serichkeane           llvm::IsaPred<OpenACCDefaultAsyncClause, OpenACCDeviceNumClause,
1494ff24e9a1Serichkeane                         OpenACCDeviceTypeClause, OpenACCIfClause>) ==
1495ff24e9a1Serichkeane           Clauses.end())
149621c785d7Serichkeane     return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
149721c785d7Serichkeane            << K
149821c785d7Serichkeane            << GetListOfClauses({OpenACCClauseKind::DefaultAsync,
149921c785d7Serichkeane                                 OpenACCClauseKind::DeviceNum,
150021c785d7Serichkeane                                 OpenACCClauseKind::DeviceType,
150121c785d7Serichkeane                                 OpenACCClauseKind::If});
150221c785d7Serichkeane 
1503553fa204Serichkeane   // OpenACC3.3 2.14.4: At least one self, host, or device clause must appear on
1504553fa204Serichkeane   // an update directive.
1505553fa204Serichkeane   if (K == OpenACCDirectiveKind::Update &&
1506553fa204Serichkeane       llvm::find_if(Clauses, llvm::IsaPred<OpenACCSelfClause, OpenACCHostClause,
1507553fa204Serichkeane                                            OpenACCDeviceClause>) ==
1508553fa204Serichkeane           Clauses.end())
1509553fa204Serichkeane     return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
1510553fa204Serichkeane            << K
1511553fa204Serichkeane            << GetListOfClauses({OpenACCClauseKind::Self,
1512553fa204Serichkeane                                 OpenACCClauseKind::Host,
1513553fa204Serichkeane                                 OpenACCClauseKind::Device});
1514db81e8c4Serichkeane 
1515cb891127SErich Keane   return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
151624144d72SErich Keane }
151724144d72SErich Keane 
1518e34cc7c9Serichkeane StmtResult SemaOpenACC::ActOnEndStmtDirective(
1519e34cc7c9Serichkeane     OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
1520e34cc7c9Serichkeane     SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
1521e34cc7c9Serichkeane     SourceLocation RParenLoc, SourceLocation EndLoc,
1522e34cc7c9Serichkeane     ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt) {
1523cb891127SErich Keane   switch (K) {
1524cb891127SErich Keane   default:
152524144d72SErich Keane     return StmtEmpty();
1526cb891127SErich Keane   case OpenACCDirectiveKind::Invalid:
1527cb891127SErich Keane     return StmtError();
1528cb891127SErich Keane   case OpenACCDirectiveKind::Parallel:
1529bb97c992Serichkeane   case OpenACCDirectiveKind::Serial:
153042f4e505SErich Keane   case OpenACCDirectiveKind::Kernels: {
1531e4d57d6aSerichkeane     return OpenACCComputeConstruct::Create(
1532193e9007Serichkeane         getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
1533e4d57d6aSerichkeane         AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
153442f4e505SErich Keane   }
153539351f8eSerichkeane   case OpenACCDirectiveKind::ParallelLoop:
153639351f8eSerichkeane   case OpenACCDirectiveKind::SerialLoop:
153739351f8eSerichkeane   case OpenACCDirectiveKind::KernelsLoop: {
153839351f8eSerichkeane     return OpenACCCombinedConstruct::Create(
153939351f8eSerichkeane         getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
154039351f8eSerichkeane         AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
154139351f8eSerichkeane   }
154242f4e505SErich Keane   case OpenACCDirectiveKind::Loop: {
1543e4d57d6aSerichkeane     return OpenACCLoopConstruct::Create(
1544e4d57d6aSerichkeane         getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
1545e4d57d6aSerichkeane         EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
154642f4e505SErich Keane   }
1547010d0115Serichkeane   case OpenACCDirectiveKind::Data: {
1548010d0115Serichkeane     return OpenACCDataConstruct::Create(
1549010d0115Serichkeane         getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
1550010d0115Serichkeane         AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1551010d0115Serichkeane   }
1552010d0115Serichkeane   case OpenACCDirectiveKind::EnterData: {
1553010d0115Serichkeane     return OpenACCEnterDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
1554010d0115Serichkeane                                              EndLoc, Clauses);
1555010d0115Serichkeane   }
1556010d0115Serichkeane   case OpenACCDirectiveKind::ExitData: {
1557010d0115Serichkeane     return OpenACCExitDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
1558010d0115Serichkeane                                             EndLoc, Clauses);
1559010d0115Serichkeane   }
1560010d0115Serichkeane   case OpenACCDirectiveKind::HostData: {
1561010d0115Serichkeane     return OpenACCHostDataConstruct::Create(
1562010d0115Serichkeane         getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
1563010d0115Serichkeane         AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
1564010d0115Serichkeane   }
1565e34cc7c9Serichkeane   case OpenACCDirectiveKind::Wait: {
1566e34cc7c9Serichkeane     return OpenACCWaitConstruct::Create(
1567e34cc7c9Serichkeane         getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
1568e34cc7c9Serichkeane         Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
1569e34cc7c9Serichkeane   }
15704bbdb018Serichkeane   case OpenACCDirectiveKind::Init: {
15714bbdb018Serichkeane     return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc,
15724bbdb018Serichkeane                                         EndLoc, Clauses);
15734bbdb018Serichkeane   }
15744bbdb018Serichkeane   case OpenACCDirectiveKind::Shutdown: {
15754bbdb018Serichkeane     return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
15764bbdb018Serichkeane                                             EndLoc, Clauses);
15774bbdb018Serichkeane   }
157821c785d7Serichkeane   case OpenACCDirectiveKind::Set: {
157921c785d7Serichkeane     return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
158021c785d7Serichkeane                                        EndLoc, Clauses);
158121c785d7Serichkeane   }
1582db81e8c4Serichkeane   case OpenACCDirectiveKind::Update: {
1583db81e8c4Serichkeane     return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
1584db81e8c4Serichkeane                                           EndLoc, Clauses);
1585db81e8c4Serichkeane   }
1586cb891127SErich Keane   }
1587cb891127SErich Keane   llvm_unreachable("Unhandled case in directive handling?");
158824144d72SErich Keane }
158924144d72SErich Keane 
1590b0cfbfd7SErich Keane StmtResult SemaOpenACC::ActOnAssociatedStmt(
1591b0cfbfd7SErich Keane     SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
1592b0cfbfd7SErich Keane     ArrayRef<const OpenACCClause *> Clauses, StmtResult AssocStmt) {
1593cb891127SErich Keane   switch (K) {
1594cb891127SErich Keane   default:
1595cb891127SErich Keane     llvm_unreachable("Unimplemented associated statement application");
1596010d0115Serichkeane   case OpenACCDirectiveKind::EnterData:
1597010d0115Serichkeane   case OpenACCDirectiveKind::ExitData:
1598e34cc7c9Serichkeane   case OpenACCDirectiveKind::Wait:
15994bbdb018Serichkeane   case OpenACCDirectiveKind::Init:
16004bbdb018Serichkeane   case OpenACCDirectiveKind::Shutdown:
160121c785d7Serichkeane   case OpenACCDirectiveKind::Set:
1602010d0115Serichkeane     llvm_unreachable(
1603010d0115Serichkeane         "these don't have associated statements, so shouldn't get here");
1604cb891127SErich Keane   case OpenACCDirectiveKind::Parallel:
1605bb97c992Serichkeane   case OpenACCDirectiveKind::Serial:
1606bb97c992Serichkeane   case OpenACCDirectiveKind::Kernels:
1607010d0115Serichkeane   case OpenACCDirectiveKind::Data:
1608010d0115Serichkeane   case OpenACCDirectiveKind::HostData:
1609cb891127SErich Keane     // There really isn't any checking here that could happen. As long as we
1610cb891127SErich Keane     // have a statement to associate, this should be fine.
1611cb891127SErich Keane     // OpenACC 3.3 Section 6:
1612cb891127SErich Keane     // Structured Block: in C or C++, an executable statement, possibly
1613cb891127SErich Keane     // compound, with a single entry at the top and a single exit at the
1614cb891127SErich Keane     // bottom.
1615cb891127SErich Keane     // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
1616cb891127SErich Keane     // an interpretation of it is to allow this and treat the initializer as
1617cb891127SErich Keane     // the 'structured block'.
161824144d72SErich Keane     return AssocStmt;
161942f4e505SErich Keane   case OpenACCDirectiveKind::Loop:
162039351f8eSerichkeane   case OpenACCDirectiveKind::ParallelLoop:
162139351f8eSerichkeane   case OpenACCDirectiveKind::SerialLoop:
162239351f8eSerichkeane   case OpenACCDirectiveKind::KernelsLoop:
16235e92bfe9SErich Keane     if (!AssocStmt.isUsable())
16245e92bfe9SErich Keane       return StmtError();
16255e92bfe9SErich Keane 
16265e92bfe9SErich Keane     if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
162739351f8eSerichkeane       Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
162839351f8eSerichkeane           << K;
162942f4e505SErich Keane       Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
163042f4e505SErich Keane       return StmtError();
163142f4e505SErich Keane     }
16325e92bfe9SErich Keane 
16333c98d8c1SErich Keane     if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
16345e92bfe9SErich Keane       if (!CollapseInfo.CollapseDepthSatisfied) {
16353c98d8c1SErich Keane         Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
16363c98d8c1SErich Keane             << OpenACCClauseKind::Collapse;
16375e92bfe9SErich Keane         assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
16385e92bfe9SErich Keane         Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
16393c98d8c1SErich Keane              diag::note_acc_active_clause_here)
16403c98d8c1SErich Keane             << OpenACCClauseKind::Collapse;
16413c98d8c1SErich Keane       }
16423c98d8c1SErich Keane 
16433c98d8c1SErich Keane       if (!TileInfo.TileDepthSatisfied) {
16443c98d8c1SErich Keane         Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
16453c98d8c1SErich Keane             << OpenACCClauseKind::Tile;
16463c98d8c1SErich Keane         assert(TileInfo.ActiveTile && "Collapse count without object?");
16473c98d8c1SErich Keane         Diag(TileInfo.ActiveTile->getBeginLoc(),
16483c98d8c1SErich Keane              diag::note_acc_active_clause_here)
16493c98d8c1SErich Keane             << OpenACCClauseKind::Tile;
16503c98d8c1SErich Keane       }
16515e92bfe9SErich Keane       return StmtError();
16525e92bfe9SErich Keane     }
16535e92bfe9SErich Keane 
1654b0cfbfd7SErich Keane     return AssocStmt.get();
165524144d72SErich Keane   }
1656cb891127SErich Keane   llvm_unreachable("Invalid associated statement application");
1657cb891127SErich Keane }
165824144d72SErich Keane 
1659e45f6e56SVlad Serebrennikov bool SemaOpenACC::ActOnStartDeclDirective(OpenACCDirectiveKind K,
166024144d72SErich Keane                                           SourceLocation StartLoc) {
16616dacc382Serichkeane   // OpenCC3.3 2.1 (line 889)
16626dacc382Serichkeane   // A program must not depend on the order of evaluation of expressions in
16636dacc382Serichkeane   // clause arguments or on any side effects of the evaluations.
16646dacc382Serichkeane   SemaRef.DiscardCleanupsInEvaluationContext();
16656dacc382Serichkeane   SemaRef.PopExpressionEvaluationContext();
1666cb891127SErich Keane   return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
166724144d72SErich Keane }
166824144d72SErich Keane 
1669e45f6e56SVlad Serebrennikov DeclGroupRef SemaOpenACC::ActOnEndDeclDirective() { return DeclGroupRef{}; }
1670d412cea8SErich Keane 
1671d412cea8SErich Keane ExprResult
1672d412cea8SErich Keane SemaOpenACC::BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
1673d412cea8SErich Keane   return OpenACCAsteriskSizeExpr::Create(getASTContext(), AsteriskLoc);
1674d412cea8SErich Keane }
1675d412cea8SErich Keane 
1676d412cea8SErich Keane ExprResult
1677d412cea8SErich Keane SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
1678d412cea8SErich Keane   return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
1679d412cea8SErich Keane }
1680