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