brintos

brintos / llvm-project-archived public Read only

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