brintos

brintos / llvm-project-archived public Read only

0
0
Text · 96.5 KiB · 8091d91 Raw
2373 lines · cpp
1//===--- SemaOpenACCClause.cpp - Semantic Analysis for OpenACC clause -----===//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 clauses.10///11//===----------------------------------------------------------------------===//12 13#include "clang/AST/DeclCXX.h"14#include "clang/AST/ExprCXX.h"15#include "clang/AST/OpenACCClause.h"16#include "clang/Basic/DiagnosticSema.h"17#include "clang/Basic/OpenACCKinds.h"18#include "clang/Sema/SemaOpenACC.h"19 20using namespace clang;21 22namespace {23bool checkValidAfterDeviceType(24    SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause,25    const SemaOpenACC::OpenACCParsedClause &NewClause) {26  // OpenACC3.3: Section 2.4: Clauses that precede any device_type clause are27  // default clauses.  Clauses that follow a device_type clause up to the end of28  // the directive or up to the next device_type clause are device-specific29  // clauses for the device types specified in the device_type argument.30  //31  // The above implies that despite what the individual text says, these are32  // valid.33  if (NewClause.getClauseKind() == OpenACCClauseKind::DType ||34      NewClause.getClauseKind() == OpenACCClauseKind::DeviceType)35    return false;36 37  // Implement check from OpenACC3.3: section 2.5.4:38  // Only the async, wait, num_gangs, num_workers, and vector_length clauses may39  // follow a device_type clause.40  if (isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind())) {41    switch (NewClause.getClauseKind()) {42    case OpenACCClauseKind::Async:43    case OpenACCClauseKind::Wait:44    case OpenACCClauseKind::NumGangs:45    case OpenACCClauseKind::NumWorkers:46    case OpenACCClauseKind::VectorLength:47      return false;48    default:49      break;50    }51  } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {52    // Implement check from OpenACC3.3: section 2.9:53    // Only the collapse, gang, worker, vector, seq, independent, auto, and tile54    // clauses may follow a device_type clause.55    switch (NewClause.getClauseKind()) {56    case OpenACCClauseKind::Collapse:57    case OpenACCClauseKind::Gang:58    case OpenACCClauseKind::Worker:59    case OpenACCClauseKind::Vector:60    case OpenACCClauseKind::Seq:61    case OpenACCClauseKind::Independent:62    case OpenACCClauseKind::Auto:63    case OpenACCClauseKind::Tile:64      return false;65    default:66      break;67    }68  } else if (isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind())) {69    // This seems like it should be the union of 2.9 and 2.5.4 from above.70    switch (NewClause.getClauseKind()) {71    case OpenACCClauseKind::Async:72    case OpenACCClauseKind::Wait:73    case OpenACCClauseKind::NumGangs:74    case OpenACCClauseKind::NumWorkers:75    case OpenACCClauseKind::VectorLength:76    case OpenACCClauseKind::Collapse:77    case OpenACCClauseKind::Gang:78    case OpenACCClauseKind::Worker:79    case OpenACCClauseKind::Vector:80    case OpenACCClauseKind::Seq:81    case OpenACCClauseKind::Independent:82    case OpenACCClauseKind::Auto:83    case OpenACCClauseKind::Tile:84      return false;85    default:86      break;87    }88  } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Data) {89    // OpenACC3.3 section 2.6.5: Only the async and wait clauses may follow a90    // device_type clause.91    switch (NewClause.getClauseKind()) {92    case OpenACCClauseKind::Async:93    case OpenACCClauseKind::Wait:94      return false;95    default:96      break;97    }98  } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Set ||99             NewClause.getDirectiveKind() == OpenACCDirectiveKind::Init ||100             NewClause.getDirectiveKind() == OpenACCDirectiveKind::Shutdown) {101    // There are no restrictions on 'set', 'init', or 'shutdown'.102    return false;103  } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Update) {104    // OpenACC3.3 section 2.14.4: Only the async and wait clauses may follow a105    // device_type clause.106    switch (NewClause.getClauseKind()) {107    case OpenACCClauseKind::Async:108    case OpenACCClauseKind::Wait:109      return false;110    default:111      break;112    }113  } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Routine) {114    // OpenACC 3.3 section 2.15: Only the 'gang', 'worker', 'vector', 'seq', and115    // 'bind' clauses may follow a device_type clause.116    switch (NewClause.getClauseKind()) {117    case OpenACCClauseKind::Gang:118    case OpenACCClauseKind::Worker:119    case OpenACCClauseKind::Vector:120    case OpenACCClauseKind::Seq:121    case OpenACCClauseKind::Bind:122      return false;123    default:124      break;125    }126  }127  S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type)128      << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind()129      << NewClause.getDirectiveKind();130  S.Diag(DeviceTypeClause.getBeginLoc(),131         diag::note_acc_active_applies_clause_here)132      << diag::ACCDeviceTypeApp::Active << DeviceTypeClause.getClauseKind();133  return true;134}135 136// GCC looks through linkage specs, but not the other transparent declaration137// contexts for 'declare' restrictions, so this helper function helps get us138// through that.139const DeclContext *removeLinkageSpecDC(const DeclContext *DC) {140  while (isa<LinkageSpecDecl>(DC))141    DC = DC->getParent();142 143  return DC;144}145 146class SemaOpenACCClauseVisitor {147  SemaOpenACC &SemaRef;148  ASTContext &Ctx;149  ArrayRef<const OpenACCClause *> ExistingClauses;150 151  // OpenACC 3.3 2.9:152  //  A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause153  //  appears.154  bool155  DiagGangWorkerVectorSeqConflict(SemaOpenACC::OpenACCParsedClause &Clause) {156    if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop &&157        !isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind()))158      return false;159    assert(Clause.getClauseKind() == OpenACCClauseKind::Gang ||160           Clause.getClauseKind() == OpenACCClauseKind::Worker ||161           Clause.getClauseKind() == OpenACCClauseKind::Vector);162    const auto *Itr =163        llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);164 165    if (Itr != ExistingClauses.end()) {166      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)167          << Clause.getClauseKind() << (*Itr)->getClauseKind()168          << Clause.getDirectiveKind();169      SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)170          << (*Itr)->getClauseKind();171 172      return true;173    }174    return false;175  }176 177  OpenACCModifierKind178  CheckModifierList(SemaOpenACC::OpenACCParsedClause &Clause,179                    OpenACCModifierKind Mods) {180    auto CheckSingle = [=](OpenACCModifierKind CurMods,181                           OpenACCModifierKind ValidKinds,182                           OpenACCModifierKind Bit) {183      if (!isOpenACCModifierBitSet(CurMods, Bit) ||184          isOpenACCModifierBitSet(ValidKinds, Bit))185        return CurMods;186 187      SemaRef.Diag(Clause.getLParenLoc(), diag::err_acc_invalid_modifier)188          << Bit << Clause.getClauseKind();189 190      return CurMods ^ Bit;191    };192    auto Check = [&](OpenACCModifierKind ValidKinds) {193      if ((Mods | ValidKinds) == ValidKinds)194        return Mods;195 196      Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Always);197      Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::AlwaysIn);198      Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::AlwaysOut);199      Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Readonly);200      Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Zero);201      Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Capture);202      return Mods;203    };204 205    // The 'capture' modifier is only valid on copyin, copyout, and create on206    // structured data or compute constructs (which also includes combined).207    bool IsStructuredDataOrCompute =208        Clause.getDirectiveKind() == OpenACCDirectiveKind::Data ||209        isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) ||210        isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind());211 212    switch (Clause.getClauseKind()) {213    default:214      llvm_unreachable("Only for copy, copyin, copyout, create");215    case OpenACCClauseKind::Copy:216    case OpenACCClauseKind::PCopy:217    case OpenACCClauseKind::PresentOrCopy:218      // COPY: Capture always219      return Check(OpenACCModifierKind::Always | OpenACCModifierKind::AlwaysIn |220                   OpenACCModifierKind::AlwaysOut |221                   OpenACCModifierKind::Capture);222    case OpenACCClauseKind::CopyIn:223    case OpenACCClauseKind::PCopyIn:224    case OpenACCClauseKind::PresentOrCopyIn:225      // COPYIN: Capture only struct.data & compute226      return Check(OpenACCModifierKind::Always | OpenACCModifierKind::AlwaysIn |227                   OpenACCModifierKind::Readonly |228                   (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture229                                              : OpenACCModifierKind::Invalid));230    case OpenACCClauseKind::CopyOut:231    case OpenACCClauseKind::PCopyOut:232    case OpenACCClauseKind::PresentOrCopyOut:233      // COPYOUT: Capture only struct.data & compute234      return Check(OpenACCModifierKind::Always |235                   OpenACCModifierKind::AlwaysOut | OpenACCModifierKind::Zero |236                   (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture237                                              : OpenACCModifierKind::Invalid));238    case OpenACCClauseKind::Create:239    case OpenACCClauseKind::PCreate:240    case OpenACCClauseKind::PresentOrCreate:241      // CREATE: Capture only struct.data & compute242      return Check(OpenACCModifierKind::Zero |243                   (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture244                                              : OpenACCModifierKind::Invalid));245    }246    llvm_unreachable("didn't return from switch above?");247  }248 249  // Helper for the 'routine' checks during 'new' clause addition. Precondition250  // is that we already know the new clause is one of the prohbiited ones.251  template <typename Pred>252  bool253  CheckValidRoutineNewClauseHelper(Pred HasPredicate,254                                   SemaOpenACC::OpenACCParsedClause &Clause) {255    if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Routine)256      return false;257 258    auto *FirstDeviceType =259        llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCDeviceTypeClause>);260 261    if (FirstDeviceType == ExistingClauses.end()) {262      // If there isn't a device type yet, ANY duplicate is wrong.263 264      auto *ExistingProhibitedClause =265          llvm::find_if(ExistingClauses, HasPredicate);266 267      if (ExistingProhibitedClause == ExistingClauses.end())268        return false;269 270      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)271          << Clause.getClauseKind()272          << (*ExistingProhibitedClause)->getClauseKind()273          << Clause.getDirectiveKind();274      SemaRef.Diag((*ExistingProhibitedClause)->getBeginLoc(),275                   diag::note_acc_previous_clause_here)276          << (*ExistingProhibitedClause)->getClauseKind();277      return true;278    }279 280    // At this point we know that this is 'after' a device type. So this is an281    // error if: 1- there is one BEFORE the 'device_type' 2- there is one282    // between this and the previous 'device_type'.283 284    auto *BeforeDeviceType =285        std::find_if(ExistingClauses.begin(), FirstDeviceType, HasPredicate);286    // If there is one before the device_type (and we know we are after a287    // device_type), than this is ill-formed.288    if (BeforeDeviceType != FirstDeviceType) {289      SemaRef.Diag(290          Clause.getBeginLoc(),291          diag::err_acc_clause_routine_cannot_combine_before_device_type)292          << Clause.getClauseKind() << (*BeforeDeviceType)->getClauseKind();293      SemaRef.Diag((*BeforeDeviceType)->getBeginLoc(),294                   diag::note_acc_previous_clause_here)295          << (*BeforeDeviceType)->getClauseKind();296      SemaRef.Diag((*FirstDeviceType)->getBeginLoc(),297                   diag::note_acc_active_applies_clause_here)298          << diag::ACCDeviceTypeApp::Active299          << (*FirstDeviceType)->getClauseKind();300      return true;301    }302 303    auto LastDeviceTypeItr =304        std::find_if(ExistingClauses.rbegin(), ExistingClauses.rend(),305                     llvm::IsaPred<OpenACCDeviceTypeClause>);306 307    // We already know there is one in the list, so it is nonsensical to not308    // have one.309    assert(LastDeviceTypeItr != ExistingClauses.rend());310 311    // Get the device-type from-the-front (not reverse) iterator from the312    // reverse iterator.313    auto *LastDeviceType = LastDeviceTypeItr.base() - 1;314 315    auto *ExistingProhibitedSinceLastDevice =316        std::find_if(LastDeviceType, ExistingClauses.end(), HasPredicate);317 318    // No prohibited ones since the last device-type.319    if (ExistingProhibitedSinceLastDevice == ExistingClauses.end())320      return false;321 322    SemaRef.Diag(Clause.getBeginLoc(),323                 diag::err_acc_clause_routine_cannot_combine_same_device_type)324        << Clause.getClauseKind()325        << (*ExistingProhibitedSinceLastDevice)->getClauseKind();326    SemaRef.Diag((*ExistingProhibitedSinceLastDevice)->getBeginLoc(),327                 diag::note_acc_previous_clause_here)328        << (*ExistingProhibitedSinceLastDevice)->getClauseKind();329    SemaRef.Diag((*LastDeviceType)->getBeginLoc(),330                 diag::note_acc_active_applies_clause_here)331        << diag::ACCDeviceTypeApp::Active << (*LastDeviceType)->getClauseKind();332    return true;333  }334 335  // Routine has a pretty complicated set of rules for how device_type and the336  // gang, worker, vector, and seq clauses work.  So diagnose some of it here.337  bool CheckValidRoutineGangWorkerVectorSeqNewClause(338      SemaOpenACC::OpenACCParsedClause &Clause) {339 340    if (Clause.getClauseKind() != OpenACCClauseKind::Gang &&341        Clause.getClauseKind() != OpenACCClauseKind::Vector &&342        Clause.getClauseKind() != OpenACCClauseKind::Worker &&343        Clause.getClauseKind() != OpenACCClauseKind::Seq)344      return false;345    auto ProhibitedPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,346                                        OpenACCVectorClause, OpenACCSeqClause>;347 348    return CheckValidRoutineNewClauseHelper(ProhibitedPred, Clause);349  }350 351  // Bind should have similar rules on a routine as gang/worker/vector/seq,352  // except there is no 'must have 1' rule, so we can get all the checking done353  // here.354  bool355  CheckValidRoutineBindNewClause(SemaOpenACC::OpenACCParsedClause &Clause) {356 357    if (Clause.getClauseKind() != OpenACCClauseKind::Bind)358      return false;359 360    auto HasBindPred = llvm::IsaPred<OpenACCBindClause>;361    return CheckValidRoutineNewClauseHelper(HasBindPred, Clause);362  }363 364  // For 'tile' and 'collapse', only allow 1 per 'device_type'.365  // Also applies to num_worker, num_gangs, vector_length, and async.366  // This does introspection into the actual device-types to prevent duplicates367  // across device types as well.368  template <typename TheClauseTy>369  bool DisallowSinceLastDeviceType(SemaOpenACC::OpenACCParsedClause &Clause) {370    auto LastDeviceTypeItr =371        std::find_if(ExistingClauses.rbegin(), ExistingClauses.rend(),372                     llvm::IsaPred<OpenACCDeviceTypeClause>);373 374    auto LastSinceDevTy =375        std::find_if(ExistingClauses.rbegin(), LastDeviceTypeItr,376                     llvm::IsaPred<TheClauseTy>);377 378    // In this case there is a duplicate since the last device_type/lack of a379    // device_type.  Diagnose these as duplicates.380    if (LastSinceDevTy != LastDeviceTypeItr) {381      SemaRef.Diag(Clause.getBeginLoc(),382                   diag::err_acc_clause_since_last_device_type)383          << Clause.getClauseKind() << Clause.getDirectiveKind()384          << (LastDeviceTypeItr != ExistingClauses.rend());385 386      SemaRef.Diag((*LastSinceDevTy)->getBeginLoc(),387                   diag::note_acc_previous_clause_here)388          << (*LastSinceDevTy)->getClauseKind();389 390      // Mention the last device_type as well.391      if (LastDeviceTypeItr != ExistingClauses.rend())392        SemaRef.Diag((*LastDeviceTypeItr)->getBeginLoc(),393                     diag::note_acc_active_applies_clause_here)394            << diag::ACCDeviceTypeApp::Active395            << (*LastDeviceTypeItr)->getClauseKind();396      return true;397    }398 399    // If this isn't in a device_type, and we didn't diagnose that there are400    // dupes above, just give up, no sense in searching for previous device_type401    // regions as they don't exist.402    if (LastDeviceTypeItr == ExistingClauses.rend())403      return false;404 405    // The device-type that is active for us, so we can compare to the previous406    // ones.407    const auto &ActiveDeviceTypeClause =408        cast<OpenACCDeviceTypeClause>(**LastDeviceTypeItr);409 410    auto PrevDeviceTypeItr = LastDeviceTypeItr;411    auto CurDevTypeItr = LastDeviceTypeItr;412 413    while ((CurDevTypeItr = std::find_if(414                std::next(PrevDeviceTypeItr), ExistingClauses.rend(),415                llvm::IsaPred<OpenACCDeviceTypeClause>)) !=416           ExistingClauses.rend()) {417      // At this point, we know that we have a region between two device_types,418      // as specified by CurDevTypeItr and PrevDeviceTypeItr.419 420      auto CurClauseKindItr = std::find_if(PrevDeviceTypeItr, CurDevTypeItr,421                                           llvm::IsaPred<TheClauseTy>);422 423      // There are no clauses of the current kind between these device_types, so424      // continue.425      if (CurClauseKindItr == CurDevTypeItr) {426        PrevDeviceTypeItr = CurDevTypeItr;427        continue;428      }429 430      // At this point, we know that this device_type region has a collapse.  So431      // diagnose if the two device_types have any overlap in their432      // architectures.433      const auto &CurDeviceTypeClause =434          cast<OpenACCDeviceTypeClause>(**CurDevTypeItr);435 436      for (const DeviceTypeArgument &arg :437           ActiveDeviceTypeClause.getArchitectures()) {438        for (const DeviceTypeArgument &prevArg :439             CurDeviceTypeClause.getArchitectures()) {440 441          // This should catch duplicates * regions, duplicate same-text (thanks442          // to identifier equiv.) and case insensitive dupes.443          if (arg.getIdentifierInfo() == prevArg.getIdentifierInfo() ||444              (arg.getIdentifierInfo() && prevArg.getIdentifierInfo() &&445               StringRef{arg.getIdentifierInfo()->getName()}.equals_insensitive(446                   prevArg.getIdentifierInfo()->getName()))) {447            SemaRef.Diag(Clause.getBeginLoc(),448                         diag::err_acc_clause_conflicts_prev_dev_type)449                << Clause.getClauseKind()450                << (arg.getIdentifierInfo() ? arg.getIdentifierInfo()->getName()451                                            : "*");452            // mention the active device type.453            SemaRef.Diag(ActiveDeviceTypeClause.getBeginLoc(),454                         diag::note_acc_active_applies_clause_here)455                << diag::ACCDeviceTypeApp::Active456                << ActiveDeviceTypeClause.getClauseKind();457            // mention the previous clause.458            SemaRef.Diag((*CurClauseKindItr)->getBeginLoc(),459                         diag::note_acc_previous_clause_here)460                << (*CurClauseKindItr)->getClauseKind();461            // mention the previous device type.462            SemaRef.Diag(CurDeviceTypeClause.getBeginLoc(),463                         diag::note_acc_active_applies_clause_here)464                << diag::ACCDeviceTypeApp::Applies465                << CurDeviceTypeClause.getClauseKind();466            return true;467          }468        }469      }470 471      PrevDeviceTypeItr = CurDevTypeItr;472    }473    return false;474  }475 476public:477  SemaOpenACCClauseVisitor(SemaOpenACC &S,478                           ArrayRef<const OpenACCClause *> ExistingClauses)479      : SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {}480 481  OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {482 483    if (SemaRef.DiagnoseAllowedOnceClauses(484            Clause.getDirectiveKind(), Clause.getClauseKind(),485            Clause.getBeginLoc(), ExistingClauses) ||486        SemaRef.DiagnoseExclusiveClauses(Clause.getDirectiveKind(),487                                         Clause.getClauseKind(),488                                         Clause.getBeginLoc(), ExistingClauses))489      return nullptr;490    if (CheckValidRoutineGangWorkerVectorSeqNewClause(Clause) ||491        CheckValidRoutineBindNewClause(Clause))492      return nullptr;493 494    switch (Clause.getClauseKind()) {495    case OpenACCClauseKind::Shortloop:496      llvm_unreachable("Shortloop shouldn't be generated in clang");497    case OpenACCClauseKind::Invalid:498      return nullptr;499#define VISIT_CLAUSE(CLAUSE_NAME)                                              \500  case OpenACCClauseKind::CLAUSE_NAME:                                         \501    return Visit##CLAUSE_NAME##Clause(Clause);502#define CLAUSE_ALIAS(ALIAS, CLAUSE_NAME, DEPRECATED)                           \503  case OpenACCClauseKind::ALIAS:                                               \504  if (DEPRECATED)                                                              \505    SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name)   \506        << Clause.getClauseKind() << OpenACCClauseKind::CLAUSE_NAME;           \507  return Visit##CLAUSE_NAME##Clause(Clause);508#include "clang/Basic/OpenACCClauses.def"509    }510    llvm_unreachable("Invalid clause kind");511  }512 513#define VISIT_CLAUSE(CLAUSE_NAME)                                              \514  OpenACCClause *Visit##CLAUSE_NAME##Clause(                                   \515      SemaOpenACC::OpenACCParsedClause &Clause);516#include "clang/Basic/OpenACCClauses.def"517};518 519OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause(520    SemaOpenACC::OpenACCParsedClause &Clause) {521  // Don't add an invalid clause to the AST.522  if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)523    return nullptr;524 525  return OpenACCDefaultClause::Create(526      Ctx, Clause.getDefaultClauseKind(), Clause.getBeginLoc(),527      Clause.getLParenLoc(), Clause.getEndLoc());528}529 530OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause(531    SemaOpenACC::OpenACCParsedClause &Clause) {532 533  if (DisallowSinceLastDeviceType<OpenACCTileClause>(Clause))534    return nullptr;535 536  llvm::SmallVector<Expr *> NewSizeExprs;537 538  // Make sure these are all positive constant expressions or *.539  for (Expr *E : Clause.getIntExprs()) {540    ExprResult Res = SemaRef.CheckTileSizeExpr(E);541 542    if (!Res.isUsable())543      return nullptr;544 545    NewSizeExprs.push_back(Res.get());546  }547 548  return OpenACCTileClause::Create(Ctx, Clause.getBeginLoc(),549                                   Clause.getLParenLoc(), NewSizeExprs,550                                   Clause.getEndLoc());551}552 553OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(554    SemaOpenACC::OpenACCParsedClause &Clause) {555 556  // The parser has ensured that we have a proper condition expr, so there557  // isn't really much to do here.558 559  // If the 'if' clause is true, it makes the 'self' clause have no effect,560  // diagnose that here.  This only applies on compute/combined constructs.561  if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Update) {562    const auto *Itr =563        llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);564    if (Itr != ExistingClauses.end()) {565      SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);566      SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)567          << (*Itr)->getClauseKind();568    }569  }570 571  return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(),572                                 Clause.getLParenLoc(),573                                 Clause.getConditionExpr(), Clause.getEndLoc());574}575 576OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(577    SemaOpenACC::OpenACCParsedClause &Clause) {578 579  // If the 'if' clause is true, it makes the 'self' clause have no effect,580  // diagnose that here.  This only applies on compute/combined constructs.581  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Update)582    return OpenACCSelfClause::Create(Ctx, Clause.getBeginLoc(),583                                     Clause.getLParenLoc(), Clause.getVarList(),584                                     Clause.getEndLoc());585 586  const auto *Itr =587      llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>);588  if (Itr != ExistingClauses.end()) {589    SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);590    SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)591        << (*Itr)->getClauseKind();592  }593  return OpenACCSelfClause::Create(594      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),595      Clause.getConditionExpr(), Clause.getEndLoc());596}597 598OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(599    SemaOpenACC::OpenACCParsedClause &Clause) {600 601  if (DisallowSinceLastDeviceType<OpenACCNumGangsClause>(Clause))602    return nullptr;603 604  // num_gangs requires at least 1 int expr in all forms.  Diagnose here, but605  // allow us to continue, an empty clause might be useful for future606  // diagnostics.607  if (Clause.getIntExprs().empty())608    SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)609        << /*NoArgs=*/0;610 611  unsigned MaxArgs =612      (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||613       Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)614          ? 3615          : 1;616  // The max number of args differs between parallel and other constructs.617  // Again, allow us to continue for the purposes of future diagnostics.618  if (Clause.getIntExprs().size() > MaxArgs)619    SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)620        << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs621        << Clause.getIntExprs().size();622 623  // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop624  // directive that has a gang clause and is within a compute construct that has625  // a num_gangs clause with more than one explicit argument.626  if (Clause.getIntExprs().size() > 1 &&627      isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) {628    auto *GangClauseItr =629        llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);630    auto *ReductionClauseItr =631        llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);632 633    if (GangClauseItr != ExistingClauses.end() &&634        ReductionClauseItr != ExistingClauses.end()) {635      SemaRef.Diag(Clause.getBeginLoc(),636                   diag::err_acc_gang_reduction_numgangs_conflict)637          << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang638          << Clause.getDirectiveKind() << /*is on combined directive=*/1;639      SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),640                   diag::note_acc_previous_clause_here)641          << (*ReductionClauseItr)->getClauseKind();642      SemaRef.Diag((*GangClauseItr)->getBeginLoc(),643                   diag::note_acc_previous_clause_here)644          << (*GangClauseItr)->getClauseKind();645      return nullptr;646    }647  }648 649  // OpenACC 3.3 Section 2.5.4:650  // A reduction clause may not appear on a parallel construct with a651  // num_gangs clause that has more than one argument.652  if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||653       Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) &&654      Clause.getIntExprs().size() > 1) {655    auto *Parallel =656        llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);657 658    if (Parallel != ExistingClauses.end()) {659      SemaRef.Diag(Clause.getBeginLoc(),660                   diag::err_acc_reduction_num_gangs_conflict)661          << /*>1 arg in first loc=*/1 << Clause.getClauseKind()662          << Clause.getDirectiveKind() << OpenACCClauseKind::Reduction;663      SemaRef.Diag((*Parallel)->getBeginLoc(),664                   diag::note_acc_previous_clause_here)665          << (*Parallel)->getClauseKind();666      return nullptr;667    }668  }669 670  // OpenACC 3.3 Section 2.9.2:671  // An argument with no keyword or with the 'num' keyword is allowed only when672  // the 'num_gangs' does not appear on the 'kernel' construct.673  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {674    auto GangClauses = llvm::make_filter_range(675        ExistingClauses, llvm::IsaPred<OpenACCGangClause>);676 677    for (auto *GC : GangClauses) {678      if (cast<OpenACCGangClause>(GC)->hasExprOfKind(OpenACCGangKind::Num)) {679        SemaRef.Diag(Clause.getBeginLoc(),680                     diag::err_acc_num_arg_conflict_reverse)681            << OpenACCClauseKind::NumGangs << OpenACCClauseKind::Gang682            << /*Num argument*/ 1;683        SemaRef.Diag(GC->getBeginLoc(), diag::note_acc_previous_clause_here)684            << GC->getClauseKind();685        return nullptr;686      }687    }688  }689 690  return OpenACCNumGangsClause::Create(691      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs(),692      Clause.getEndLoc());693}694 695OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(696    SemaOpenACC::OpenACCParsedClause &Clause) {697 698  if (DisallowSinceLastDeviceType<OpenACCNumWorkersClause>(Clause))699    return nullptr;700 701  // OpenACC 3.3 Section 2.9.2:702  // An argument is allowed only when the 'num_workers' does not appear on the703  // kernels construct.704  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {705    auto WorkerClauses = llvm::make_filter_range(706        ExistingClauses, llvm::IsaPred<OpenACCWorkerClause>);707 708    for (auto *WC : WorkerClauses) {709      if (cast<OpenACCWorkerClause>(WC)->hasIntExpr()) {710        SemaRef.Diag(Clause.getBeginLoc(),711                     diag::err_acc_num_arg_conflict_reverse)712            << OpenACCClauseKind::NumWorkers << OpenACCClauseKind::Worker713            << /*num argument*/ 0;714        SemaRef.Diag(WC->getBeginLoc(), diag::note_acc_previous_clause_here)715            << WC->getClauseKind();716        return nullptr;717      }718    }719  }720 721  assert(Clause.getIntExprs().size() == 1 &&722         "Invalid number of expressions for NumWorkers");723  return OpenACCNumWorkersClause::Create(724      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],725      Clause.getEndLoc());726}727 728OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause(729    SemaOpenACC::OpenACCParsedClause &Clause) {730 731  if (DisallowSinceLastDeviceType<OpenACCVectorLengthClause>(Clause))732    return nullptr;733 734  // OpenACC 3.3 Section 2.9.4:735  // An argument is allowed only when the 'vector_length' does not appear on the736  // 'kernels' construct.737  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {738    auto VectorClauses = llvm::make_filter_range(739        ExistingClauses, llvm::IsaPred<OpenACCVectorClause>);740 741    for (auto *VC : VectorClauses) {742      if (cast<OpenACCVectorClause>(VC)->hasIntExpr()) {743        SemaRef.Diag(Clause.getBeginLoc(),744                     diag::err_acc_num_arg_conflict_reverse)745            << OpenACCClauseKind::VectorLength << OpenACCClauseKind::Vector746            << /*num argument*/ 0;747        SemaRef.Diag(VC->getBeginLoc(), diag::note_acc_previous_clause_here)748            << VC->getClauseKind();749        return nullptr;750      }751    }752  }753 754  assert(Clause.getIntExprs().size() == 1 &&755         "Invalid number of expressions for NumWorkers");756  return OpenACCVectorLengthClause::Create(757      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],758      Clause.getEndLoc());759}760 761OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(762    SemaOpenACC::OpenACCParsedClause &Clause) {763  if (DisallowSinceLastDeviceType<OpenACCAsyncClause>(Clause))764    return nullptr;765 766  assert(Clause.getNumIntExprs() < 2 &&767         "Invalid number of expressions for Async");768  return OpenACCAsyncClause::Create(769      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),770      Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr,771      Clause.getEndLoc());772}773 774OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause(775    SemaOpenACC::OpenACCParsedClause &Clause) {776  assert(Clause.getNumIntExprs() == 1 &&777         "Invalid number of expressions for device_num");778  return OpenACCDeviceNumClause::Create(779      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],780      Clause.getEndLoc());781}782 783OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultAsyncClause(784    SemaOpenACC::OpenACCParsedClause &Clause) {785  assert(Clause.getNumIntExprs() == 1 &&786         "Invalid number of expressions for default_async");787  return OpenACCDefaultAsyncClause::Create(788      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],789      Clause.getEndLoc());790}791 792OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(793    SemaOpenACC::OpenACCParsedClause &Clause) {794  // ActOnVar ensured that everything is a valid variable reference, so there795  // really isn't anything to do here. GCC does some duplicate-finding, though796  // it isn't apparent in the standard where this is justified.797 798  llvm::SmallVector<OpenACCPrivateRecipe> InitRecipes;799 800  // Assemble the recipes list.801  for (const Expr *VarExpr : Clause.getVarList())802    InitRecipes.push_back(SemaRef.CreatePrivateInitRecipe(VarExpr));803 804  return OpenACCPrivateClause::Create(805      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),806      InitRecipes, Clause.getEndLoc());807}808 809OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(810    SemaOpenACC::OpenACCParsedClause &Clause) {811  // ActOnVar ensured that everything is a valid variable reference, so there812  // really isn't anything to do here. GCC does some duplicate-finding, though813  // it isn't apparent in the standard where this is justified.814 815  llvm::SmallVector<OpenACCFirstPrivateRecipe> InitRecipes;816 817  // Assemble the recipes list.818  for (const Expr *VarExpr : Clause.getVarList())819    InitRecipes.push_back(SemaRef.CreateFirstPrivateInitRecipe(VarExpr));820 821  return OpenACCFirstPrivateClause::Create(822      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),823      InitRecipes, Clause.getEndLoc());824}825 826OpenACCClause *SemaOpenACCClauseVisitor::VisitNoCreateClause(827    SemaOpenACC::OpenACCParsedClause &Clause) {828  // ActOnVar ensured that everything is a valid variable reference, so there829  // really isn't anything to do here. GCC does some duplicate-finding, though830  // it isn't apparent in the standard where this is justified.831 832  return OpenACCNoCreateClause::Create(Ctx, Clause.getBeginLoc(),833                                       Clause.getLParenLoc(),834                                       Clause.getVarList(), Clause.getEndLoc());835}836 837OpenACCClause *SemaOpenACCClauseVisitor::VisitPresentClause(838    SemaOpenACC::OpenACCParsedClause &Clause) {839  // ActOnVar ensured that everything is a valid variable reference, so there840  // really isn't anything to do here. GCC does some duplicate-finding, though841  // it isn't apparent in the standard where this is justified.842 843  // 'declare' has some restrictions that need to be enforced separately, so844  // check it here.845  if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))846    return nullptr;847 848  return OpenACCPresentClause::Create(Ctx, Clause.getBeginLoc(),849                                      Clause.getLParenLoc(),850                                      Clause.getVarList(), Clause.getEndLoc());851}852 853OpenACCClause *SemaOpenACCClauseVisitor::VisitHostClause(854    SemaOpenACC::OpenACCParsedClause &Clause) {855  // ActOnVar ensured that everything is a valid variable reference, so there856  // really isn't anything to do here. GCC does some duplicate-finding, though857  // it isn't apparent in the standard where this is justified.858 859  return OpenACCHostClause::Create(Ctx, Clause.getBeginLoc(),860                                   Clause.getLParenLoc(), Clause.getVarList(),861                                   Clause.getEndLoc());862}863 864OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceClause(865    SemaOpenACC::OpenACCParsedClause &Clause) {866  // ActOnVar ensured that everything is a valid variable reference, so there867  // really isn't anything to do here. GCC does some duplicate-finding, though868  // it isn't apparent in the standard where this is justified.869 870  return OpenACCDeviceClause::Create(Ctx, Clause.getBeginLoc(),871                                     Clause.getLParenLoc(), Clause.getVarList(),872                                     Clause.getEndLoc());873}874 875OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyClause(876    SemaOpenACC::OpenACCParsedClause &Clause) {877  // ActOnVar ensured that everything is a valid variable reference, so there878  // really isn't anything to do here. GCC does some duplicate-finding, though879  // it isn't apparent in the standard where this is justified.880 881  OpenACCModifierKind NewMods =882      CheckModifierList(Clause, Clause.getModifierList());883 884  // 'declare' has some restrictions that need to be enforced separately, so885  // check it here.886  if (SemaRef.CheckDeclareClause(Clause, NewMods))887    return nullptr;888 889  return OpenACCCopyClause::Create(890      Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),891      Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());892}893 894OpenACCClause *SemaOpenACCClauseVisitor::VisitLinkClause(895    SemaOpenACC::OpenACCParsedClause &Clause) {896  // 'declare' has some restrictions that need to be enforced separately, so897  // check it here.898  if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))899    return nullptr;900 901  Clause.setVarListDetails(SemaRef.CheckLinkClauseVarList(Clause.getVarList()),902                           OpenACCModifierKind::Invalid);903 904  return OpenACCLinkClause::Create(Ctx, Clause.getBeginLoc(),905                                   Clause.getLParenLoc(), Clause.getVarList(),906                                   Clause.getEndLoc());907}908 909OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceResidentClause(910    SemaOpenACC::OpenACCParsedClause &Clause) {911  // 'declare' has some restrictions that need to be enforced separately, so912  // check it here.913  if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))914    return nullptr;915 916  return OpenACCDeviceResidentClause::Create(917      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),918      Clause.getEndLoc());919}920 921OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyInClause(922    SemaOpenACC::OpenACCParsedClause &Clause) {923  // ActOnVar ensured that everything is a valid variable reference, so there924  // really isn't anything to do here. GCC does some duplicate-finding, though925  // it isn't apparent in the standard where this is justified.926 927  OpenACCModifierKind NewMods =928      CheckModifierList(Clause, Clause.getModifierList());929 930  // 'declare' has some restrictions that need to be enforced separately, so931  // check it here.932  if (SemaRef.CheckDeclareClause(Clause, NewMods))933    return nullptr;934 935  return OpenACCCopyInClause::Create(936      Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),937      Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());938}939 940OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyOutClause(941    SemaOpenACC::OpenACCParsedClause &Clause) {942  // ActOnVar ensured that everything is a valid variable reference, so there943  // really isn't anything to do here. GCC does some duplicate-finding, though944  // it isn't apparent in the standard where this is justified.945 946  OpenACCModifierKind NewMods =947      CheckModifierList(Clause, Clause.getModifierList());948 949  // 'declare' has some restrictions that need to be enforced separately, so950  // check it here.951  if (SemaRef.CheckDeclareClause(Clause, NewMods))952    return nullptr;953 954  return OpenACCCopyOutClause::Create(955      Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),956      Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());957}958 959OpenACCClause *SemaOpenACCClauseVisitor::VisitCreateClause(960    SemaOpenACC::OpenACCParsedClause &Clause) {961  // ActOnVar ensured that everything is a valid variable reference, so there962  // really isn't anything to do here. GCC does some duplicate-finding, though963  // it isn't apparent in the standard where this is justified.964 965  OpenACCModifierKind NewMods =966      CheckModifierList(Clause, Clause.getModifierList());967 968  // 'declare' has some restrictions that need to be enforced separately, so969  // check it here.970  if (SemaRef.CheckDeclareClause(Clause, NewMods))971    return nullptr;972 973  return OpenACCCreateClause::Create(974      Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),975      Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());976}977 978OpenACCClause *SemaOpenACCClauseVisitor::VisitAttachClause(979    SemaOpenACC::OpenACCParsedClause &Clause) {980  // ActOnVar ensured that everything is a valid variable reference, but we981  // still have to make sure it is a pointer type.982  llvm::SmallVector<Expr *> VarList{Clause.getVarList()};983  llvm::erase_if(VarList, [&](Expr *E) {984    return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Attach, E);985  });986  Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);987  return OpenACCAttachClause::Create(Ctx, Clause.getBeginLoc(),988                                     Clause.getLParenLoc(), Clause.getVarList(),989                                     Clause.getEndLoc());990}991 992OpenACCClause *SemaOpenACCClauseVisitor::VisitDetachClause(993    SemaOpenACC::OpenACCParsedClause &Clause) {994  // ActOnVar ensured that everything is a valid variable reference, but we995  // still have to make sure it is a pointer type.996  llvm::SmallVector<Expr *> VarList{Clause.getVarList()};997  llvm::erase_if(VarList, [&](Expr *E) {998    return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Detach, E);999  });1000  Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);1001  return OpenACCDetachClause::Create(Ctx, Clause.getBeginLoc(),1002                                     Clause.getLParenLoc(), Clause.getVarList(),1003                                     Clause.getEndLoc());1004}1005 1006OpenACCClause *SemaOpenACCClauseVisitor::VisitDeleteClause(1007    SemaOpenACC::OpenACCParsedClause &Clause) {1008  // ActOnVar ensured that everything is a valid variable reference, so there1009  // really isn't anything to do here. GCC does some duplicate-finding, though1010  // it isn't apparent in the standard where this is justified.1011  return OpenACCDeleteClause::Create(Ctx, Clause.getBeginLoc(),1012                                     Clause.getLParenLoc(), Clause.getVarList(),1013                                     Clause.getEndLoc());1014}1015 1016OpenACCClause *SemaOpenACCClauseVisitor::VisitUseDeviceClause(1017    SemaOpenACC::OpenACCParsedClause &Clause) {1018  // ActOnVar ensured that everything is a valid variable or array, so nothing1019  // left to do here.1020  return OpenACCUseDeviceClause::Create(1021      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),1022      Clause.getEndLoc());1023}1024 1025OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause(1026    SemaOpenACC::OpenACCParsedClause &Clause) {1027  // ActOnVar ensured that everything is a valid variable reference, but we1028  // still have to make sure it is a pointer type.1029  llvm::SmallVector<Expr *> VarList{Clause.getVarList()};1030  llvm::erase_if(VarList, [&](Expr *E) {1031    return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::DevicePtr, E);1032  });1033  Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);1034 1035  // 'declare' has some restrictions that need to be enforced separately, so1036  // check it here.1037  if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))1038    return nullptr;1039 1040  return OpenACCDevicePtrClause::Create(1041      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),1042      Clause.getEndLoc());1043}1044 1045OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause(1046    SemaOpenACC::OpenACCParsedClause &Clause) {1047  return OpenACCWaitClause::Create(1048      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getDevNumExpr(),1049      Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc());1050}1051 1052OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(1053    SemaOpenACC::OpenACCParsedClause &Clause) {1054 1055  // OpenACC Pull #550 (https://github.com/OpenACC/openacc-spec/pull/550)1056  // clarified that Init, Shutdown, and Set only support a single architecture.1057  // Though the dialect only requires it for 'set' as far as we know, we'll just1058  // implement all 3 here.1059  if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Init ||1060       Clause.getDirectiveKind() == OpenACCDirectiveKind::Shutdown ||1061       Clause.getDirectiveKind() == OpenACCDirectiveKind::Set) &&1062      Clause.getDeviceTypeArchitectures().size() > 1) {1063    SemaRef.Diag(Clause.getDeviceTypeArchitectures()[1].getLoc(),1064                 diag::err_acc_device_type_multiple_archs)1065        << Clause.getDirectiveKind();1066    return nullptr;1067  }1068 1069  // The list of valid device_type values. Flang also has these hardcoded in1070  // openacc_parsers.cpp, as there does not seem to be a reliable backend1071  // source. The list below is sourced from Flang, though NVC++ supports only1072  // 'nvidia', 'host', 'multicore', and 'default'.1073  const std::array<llvm::StringLiteral, 6> ValidValues{1074      "default", "nvidia", "acc_device_nvidia", "radeon", "host", "multicore"};1075  // As an optimization, we have a manually maintained list of valid values1076  // below, rather than trying to calculate from above. These should be kept in1077  // sync if/when the above list ever changes.1078  std::string ValidValuesString =1079      "'default', 'nvidia', 'acc_device_nvidia', 'radeon', 'host', 'multicore'";1080 1081  llvm::SmallVector<DeviceTypeArgument> Architectures{1082      Clause.getDeviceTypeArchitectures()};1083 1084  // The parser has ensured that we either have a single entry of just '*'1085  // (represented by a nullptr IdentifierInfo), or a list.1086 1087  bool Diagnosed = false;1088  auto FilterPred = [&](const DeviceTypeArgument &Arch) {1089    // The '*' case.1090    if (!Arch.getIdentifierInfo())1091      return false;1092    return llvm::find_if(ValidValues, [&](StringRef RHS) {1093             return Arch.getIdentifierInfo()->getName().equals_insensitive(RHS);1094           }) == ValidValues.end();1095  };1096 1097  auto Diagnose = [&](const DeviceTypeArgument &Arch) {1098    Diagnosed = SemaRef.Diag(Arch.getLoc(), diag::err_acc_invalid_default_type)1099                << Arch.getIdentifierInfo() << Clause.getClauseKind()1100                << ValidValuesString;1101  };1102 1103  // There aren't stable enumertor versions of 'for-each-then-erase', so do it1104  // here.  We DO keep track of whether we diagnosed something to make sure we1105  // don't do the 'erase_if' in the event that the first list didn't find1106  // anything.1107  llvm::for_each(llvm::make_filter_range(Architectures, FilterPred), Diagnose);1108  if (Diagnosed)1109    llvm::erase_if(Architectures, FilterPred);1110 1111  return OpenACCDeviceTypeClause::Create(1112      Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),1113      Architectures, Clause.getEndLoc());1114}1115 1116OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(1117    SemaOpenACC::OpenACCParsedClause &Clause) {1118 1119  return OpenACCAutoClause::Create(Ctx, Clause.getBeginLoc(),1120                                   Clause.getEndLoc());1121}1122 1123OpenACCClause *SemaOpenACCClauseVisitor::VisitNoHostClause(1124    SemaOpenACC::OpenACCParsedClause &Clause) {1125  return OpenACCNoHostClause::Create(Ctx, Clause.getBeginLoc(),1126                                     Clause.getEndLoc());1127}1128 1129OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(1130    SemaOpenACC::OpenACCParsedClause &Clause) {1131 1132  return OpenACCIndependentClause::Create(Ctx, Clause.getBeginLoc(),1133                                          Clause.getEndLoc());1134}1135 1136ExprResult CheckGangStaticExpr(SemaOpenACC &S, Expr *E) {1137  if (isa<OpenACCAsteriskSizeExpr>(E))1138    return E;1139  return S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang,1140                        E->getBeginLoc(), E);1141}1142 1143bool IsOrphanLoop(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {1144  return DK == OpenACCDirectiveKind::Loop &&1145         AssocKind == OpenACCDirectiveKind::Invalid;1146}1147 1148bool HasAssocKind(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {1149  return DK == OpenACCDirectiveKind::Loop &&1150         AssocKind != OpenACCDirectiveKind::Invalid;1151}1152 1153ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, OpenACCGangKind GK,1154                             OpenACCClauseKind CK, OpenACCDirectiveKind DK,1155                             OpenACCDirectiveKind AssocKind) {1156  S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)1157      << GK << CK << IsOrphanLoop(DK, AssocKind) << DK1158      << HasAssocKind(DK, AssocKind) << AssocKind;1159  return ExprError();1160}1161ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, StringRef TagKind,1162                             OpenACCClauseKind CK, OpenACCDirectiveKind DK,1163                             OpenACCDirectiveKind AssocKind) {1164  S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)1165      << TagKind << CK << IsOrphanLoop(DK, AssocKind) << DK1166      << HasAssocKind(DK, AssocKind) << AssocKind;1167  return ExprError();1168}1169 1170ExprResult CheckGangDimExpr(SemaOpenACC &S, Expr *E) {1171  // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel1172  // construct, or an orphaned loop construct, the gang clause behaves as1173  // follows. ... The dim argument must be a constant positive integer value1174  // 1, 2, or 3.1175  // -also-1176  // OpenACC 3.3 2.15: The 'dim' argument must be a constant positive integer1177  // with value 1, 2, or 3.1178  if (!E)1179    return ExprError();1180  ExprResult Res = S.ActOnIntExpr(OpenACCDirectiveKind::Invalid,1181                                  OpenACCClauseKind::Gang, E->getBeginLoc(), E);1182 1183  if (!Res.isUsable())1184    return Res;1185 1186  if (Res.get()->isInstantiationDependent())1187    return Res;1188 1189  std::optional<llvm::APSInt> ICE =1190      Res.get()->getIntegerConstantExpr(S.getASTContext());1191 1192  if (!ICE || *ICE <= 0 || ICE > 3) {1193    S.Diag(Res.get()->getBeginLoc(), diag::err_acc_gang_dim_value)1194        << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();1195    return ExprError();1196  }1197 1198  return ExprResult{1199      ConstantExpr::Create(S.getASTContext(), Res.get(), APValue{*ICE})};1200}1201 1202ExprResult CheckGangParallelExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,1203                                 OpenACCDirectiveKind AssocKind,1204                                 OpenACCGangKind GK, Expr *E) {1205  switch (GK) {1206  case OpenACCGangKind::Static:1207    return CheckGangStaticExpr(S, E);1208  case OpenACCGangKind::Num:1209    // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel1210    // construct, or an orphaned loop construct, the gang clause behaves as1211    // follows. ... The num argument is not allowed.1212    return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);1213  case OpenACCGangKind::Dim:1214    return CheckGangDimExpr(S, E);1215  }1216  llvm_unreachable("Unknown gang kind in gang parallel check");1217}1218 1219ExprResult CheckGangKernelsExpr(SemaOpenACC &S,1220                                ArrayRef<const OpenACCClause *> ExistingClauses,1221                                OpenACCDirectiveKind DK,1222                                OpenACCDirectiveKind AssocKind,1223                                OpenACCGangKind GK, Expr *E) {1224  switch (GK) {1225  // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels1226  // construct, the gang clause behaves as follows. ... The dim argument is1227  // not allowed.1228  case OpenACCGangKind::Dim:1229    return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);1230  case OpenACCGangKind::Num: {1231    // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels1232    // construct, the gang clause behaves as follows. ... An argument with no1233    // keyword or with num keyword is only allowed when num_gangs does not1234    // appear on the kernels construct. ... The region of a loop with the gang1235    // clause may not contain another loop with a gang clause unless within a1236    // nested compute region.1237 1238    // If this is a 'combined' construct, search the list of existing clauses.1239    // Else we need to search the containing 'kernel'.1240    auto Collection = isOpenACCCombinedDirectiveKind(DK)1241                          ? ExistingClauses1242                          : S.getActiveComputeConstructInfo().Clauses;1243 1244    const auto *Itr =1245        llvm::find_if(Collection, llvm::IsaPred<OpenACCNumGangsClause>);1246 1247    if (Itr != Collection.end()) {1248      S.Diag(E->getBeginLoc(), diag::err_acc_num_arg_conflict)1249          << "num" << OpenACCClauseKind::Gang << DK1250          << HasAssocKind(DK, AssocKind) << AssocKind1251          << OpenACCClauseKind::NumGangs;1252 1253      S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)1254          << (*Itr)->getClauseKind();1255      return ExprError();1256    }1257    return ExprResult{E};1258  }1259  case OpenACCGangKind::Static:1260    return CheckGangStaticExpr(S, E);1261  }1262  llvm_unreachable("Unknown gang kind in gang kernels check");1263}1264 1265ExprResult CheckGangSerialExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,1266                               OpenACCDirectiveKind AssocKind,1267                               OpenACCGangKind GK, Expr *E) {1268  switch (GK) {1269  // 'dim' and 'num' don't really make sense on serial, and GCC rejects them1270  // too, so we disallow them too.1271  case OpenACCGangKind::Dim:1272  case OpenACCGangKind::Num:1273    return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);1274  case OpenACCGangKind::Static:1275    return CheckGangStaticExpr(S, E);1276  }1277  llvm_unreachable("Unknown gang kind in gang serial check");1278}1279 1280ExprResult CheckGangRoutineExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,1281                                OpenACCDirectiveKind AssocKind,1282                                OpenACCGangKind GK, Expr *E) {1283  switch (GK) {1284    // Only 'dim' is allowed on a routine, so diallow num and static.1285  case OpenACCGangKind::Num:1286  case OpenACCGangKind::Static:1287    return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);1288  case OpenACCGangKind::Dim:1289    return CheckGangDimExpr(S, E);1290  }1291  llvm_unreachable("Unknown gang kind in gang serial check");1292}1293 1294OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(1295    SemaOpenACC::OpenACCParsedClause &Clause) {1296  if (DiagGangWorkerVectorSeqConflict(Clause))1297    return nullptr;1298 1299  Expr *IntExpr =1300      Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;1301  if (IntExpr) {1302    switch (Clause.getDirectiveKind()) {1303    default:1304      llvm_unreachable("Invalid directive kind for this clause");1305    case OpenACCDirectiveKind::Loop:1306      switch (SemaRef.getActiveComputeConstructInfo().Kind) {1307      case OpenACCDirectiveKind::Invalid:1308      case OpenACCDirectiveKind::Parallel:1309      case OpenACCDirectiveKind::ParallelLoop:1310        // No restriction on when 'parallel' can contain an argument.1311        break;1312      case OpenACCDirectiveKind::Serial:1313      case OpenACCDirectiveKind::SerialLoop:1314        // GCC disallows this, and there is no real good reason for us to permit1315        // it, so disallow until we come up with a use case that makes sense.1316        DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector,1317                          Clause.getDirectiveKind(),1318                          SemaRef.getActiveComputeConstructInfo().Kind);1319        IntExpr = nullptr;1320        break;1321      case OpenACCDirectiveKind::Kernels:1322      case OpenACCDirectiveKind::KernelsLoop: {1323        const auto *Itr =1324            llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,1325                          llvm::IsaPred<OpenACCVectorLengthClause>);1326        if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {1327          SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)1328              << "length" << OpenACCClauseKind::Vector1329              << Clause.getDirectiveKind()1330              << HasAssocKind(Clause.getDirectiveKind(),1331                              SemaRef.getActiveComputeConstructInfo().Kind)1332              << SemaRef.getActiveComputeConstructInfo().Kind1333              << OpenACCClauseKind::VectorLength;1334          SemaRef.Diag((*Itr)->getBeginLoc(),1335                       diag::note_acc_previous_clause_here)1336              << (*Itr)->getClauseKind();1337 1338          IntExpr = nullptr;1339        }1340        break;1341      }1342      default:1343        llvm_unreachable("Non compute construct in active compute construct");1344      }1345      break;1346    case OpenACCDirectiveKind::KernelsLoop: {1347      const auto *Itr = llvm::find_if(ExistingClauses,1348                                      llvm::IsaPred<OpenACCVectorLengthClause>);1349      if (Itr != ExistingClauses.end()) {1350        SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)1351            << "length" << OpenACCClauseKind::Vector1352            << Clause.getDirectiveKind()1353            << HasAssocKind(Clause.getDirectiveKind(),1354                            SemaRef.getActiveComputeConstructInfo().Kind)1355            << SemaRef.getActiveComputeConstructInfo().Kind1356            << OpenACCClauseKind::VectorLength;1357        SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)1358            << (*Itr)->getClauseKind();1359 1360        IntExpr = nullptr;1361      }1362      break;1363    }1364    case OpenACCDirectiveKind::SerialLoop:1365    case OpenACCDirectiveKind::Routine:1366      DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector,1367                        Clause.getDirectiveKind(),1368                        SemaRef.getActiveComputeConstructInfo().Kind);1369      IntExpr = nullptr;1370      break;1371    case OpenACCDirectiveKind::ParallelLoop:1372      break;1373    case OpenACCDirectiveKind::Invalid:1374      // This can happen when the directive was not recognized, but we continued1375      // anyway.  Since there is a lot of stuff that can happen (including1376      // 'allow anything' in the parallel loop case), just skip all checking and1377      // continue.1378      break;1379    }1380  }1381 1382  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {1383    // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not1384    // contain a loop with a gang, worker, or vector clause unless within a1385    // nested compute region.1386    if (SemaRef.LoopVectorClauseLoc.isValid()) {1387      // This handles the 'inner loop' diagnostic, but we cannot set that we're1388      // on one of these until we get to the end of the construct.1389      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)1390          << OpenACCClauseKind::Vector << OpenACCClauseKind::Vector1391          << /*skip kernels construct info*/ 0;1392      SemaRef.Diag(SemaRef.LoopVectorClauseLoc,1393                   diag::note_acc_previous_clause_here)1394          << "vector";1395      return nullptr;1396    }1397  }1398 1399  return OpenACCVectorClause::Create(Ctx, Clause.getBeginLoc(),1400                                     Clause.getLParenLoc(), IntExpr,1401                                     Clause.getEndLoc());1402}1403 1404OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(1405    SemaOpenACC::OpenACCParsedClause &Clause) {1406  if (DiagGangWorkerVectorSeqConflict(Clause))1407    return nullptr;1408 1409  Expr *IntExpr =1410      Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;1411 1412  if (IntExpr) {1413    switch (Clause.getDirectiveKind()) {1414    default:1415      llvm_unreachable("Invalid directive kind for this clause");1416    case OpenACCDirectiveKind::Invalid:1417      // This can happen in cases where the directive was not recognized but we1418      // continued anyway.  Kernels allows kind of any integer argument, so we1419      // can assume it is that (rather than marking the argument invalid like1420      // with parallel/serial/routine), and just continue as if nothing1421      // happened.  We'll skip the 'kernels' checking vs num-workers, since this1422      // MIGHT be something else.1423      break;1424    case OpenACCDirectiveKind::Loop:1425      switch (SemaRef.getActiveComputeConstructInfo().Kind) {1426      case OpenACCDirectiveKind::Invalid:1427      case OpenACCDirectiveKind::ParallelLoop:1428      case OpenACCDirectiveKind::SerialLoop:1429      case OpenACCDirectiveKind::Parallel:1430      case OpenACCDirectiveKind::Serial:1431        DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num,1432                          OpenACCClauseKind::Worker, Clause.getDirectiveKind(),1433                          SemaRef.getActiveComputeConstructInfo().Kind);1434        IntExpr = nullptr;1435        break;1436      case OpenACCDirectiveKind::KernelsLoop:1437      case OpenACCDirectiveKind::Kernels: {1438        const auto *Itr =1439            llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,1440                          llvm::IsaPred<OpenACCNumWorkersClause>);1441        if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {1442          SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)1443              << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()1444              << HasAssocKind(Clause.getDirectiveKind(),1445                              SemaRef.getActiveComputeConstructInfo().Kind)1446              << SemaRef.getActiveComputeConstructInfo().Kind1447              << OpenACCClauseKind::NumWorkers;1448          SemaRef.Diag((*Itr)->getBeginLoc(),1449                       diag::note_acc_previous_clause_here)1450              << (*Itr)->getClauseKind();1451 1452          IntExpr = nullptr;1453        }1454        break;1455      }1456      default:1457        llvm_unreachable("Non compute construct in active compute construct");1458      }1459      break;1460    case OpenACCDirectiveKind::ParallelLoop:1461    case OpenACCDirectiveKind::SerialLoop:1462    case OpenACCDirectiveKind::Routine:1463      DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num,1464                        OpenACCClauseKind::Worker, Clause.getDirectiveKind(),1465                        SemaRef.getActiveComputeConstructInfo().Kind);1466      IntExpr = nullptr;1467      break;1468    case OpenACCDirectiveKind::KernelsLoop: {1469      const auto *Itr = llvm::find_if(ExistingClauses,1470                                      llvm::IsaPred<OpenACCNumWorkersClause>);1471      if (Itr != ExistingClauses.end()) {1472        SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)1473            << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()1474            << HasAssocKind(Clause.getDirectiveKind(),1475                            SemaRef.getActiveComputeConstructInfo().Kind)1476            << SemaRef.getActiveComputeConstructInfo().Kind1477            << OpenACCClauseKind::NumWorkers;1478        SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)1479            << (*Itr)->getClauseKind();1480 1481        IntExpr = nullptr;1482      }1483    }1484    }1485  }1486 1487  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {1488    // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not1489    // contain a loop with a gang or worker clause unless within a nested1490    // compute region.1491    if (SemaRef.LoopWorkerClauseLoc.isValid()) {1492      // This handles the 'inner loop' diagnostic, but we cannot set that we're1493      // on one of these until we get to the end of the construct.1494      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)1495          << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker1496          << /*skip kernels construct info*/ 0;1497      SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,1498                   diag::note_acc_previous_clause_here)1499          << "worker";1500      return nullptr;1501    }1502 1503    // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not1504    // contain a loop with a gang, worker, or vector clause unless within a1505    // nested compute region.1506    if (SemaRef.LoopVectorClauseLoc.isValid()) {1507      // This handles the 'inner loop' diagnostic, but we cannot set that we're1508      // on one of these until we get to the end of the construct.1509      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)1510          << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector1511          << /*skip kernels construct info*/ 0;1512      SemaRef.Diag(SemaRef.LoopVectorClauseLoc,1513                   diag::note_acc_previous_clause_here)1514          << "vector";1515      return nullptr;1516    }1517  }1518 1519  return OpenACCWorkerClause::Create(Ctx, Clause.getBeginLoc(),1520                                     Clause.getLParenLoc(), IntExpr,1521                                     Clause.getEndLoc());1522}1523 1524OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(1525    SemaOpenACC::OpenACCParsedClause &Clause) {1526 1527  if (DiagGangWorkerVectorSeqConflict(Clause))1528    return nullptr;1529 1530  // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop1531  // directive that has a gang clause and is within a compute construct that has1532  // a num_gangs clause with more than one explicit argument.1533  if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&1534       SemaRef.getActiveComputeConstructInfo().Kind !=1535           OpenACCDirectiveKind::Invalid) ||1536      isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) {1537    // num_gangs clause on the active compute construct.1538    auto ActiveComputeConstructContainer =1539        isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())1540            ? ExistingClauses1541            : SemaRef.getActiveComputeConstructInfo().Clauses;1542    auto *NumGangsClauseItr = llvm::find_if(1543        ActiveComputeConstructContainer, llvm::IsaPred<OpenACCNumGangsClause>);1544 1545    if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&1546        cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >1547            1) {1548      auto *ReductionClauseItr =1549          llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);1550 1551      if (ReductionClauseItr != ExistingClauses.end()) {1552        SemaRef.Diag(Clause.getBeginLoc(),1553                     diag::err_acc_gang_reduction_numgangs_conflict)1554            << OpenACCClauseKind::Gang << OpenACCClauseKind::Reduction1555            << Clause.getDirectiveKind()1556            << isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind());1557        SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),1558                     diag::note_acc_previous_clause_here)1559            << (*ReductionClauseItr)->getClauseKind();1560        SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),1561                     diag::note_acc_previous_clause_here)1562            << (*NumGangsClauseItr)->getClauseKind();1563        return nullptr;1564      }1565    }1566  }1567 1568  llvm::SmallVector<OpenACCGangKind> GangKinds;1569  llvm::SmallVector<Expr *> IntExprs;1570 1571  // Store the existing locations, so we can do duplicate checking.  Index is1572  // the int-value of the OpenACCGangKind enum.1573  SourceLocation ExistingElemLoc[3];1574 1575  for (unsigned I = 0; I < Clause.getIntExprs().size(); ++I) {1576    OpenACCGangKind GK = Clause.getGangKinds()[I];1577    ExprResult ER =1578        SemaRef.CheckGangExpr(ExistingClauses, Clause.getDirectiveKind(), GK,1579                              Clause.getIntExprs()[I]);1580 1581    if (!ER.isUsable())1582      continue;1583 1584    // OpenACC 3.3 2.9: 'gang-arg-list' may have at most one num, one dim, and1585    // one static argument.1586    if (ExistingElemLoc[static_cast<unsigned>(GK)].isValid()) {1587      SemaRef.Diag(ER.get()->getBeginLoc(), diag::err_acc_gang_multiple_elt)1588          << static_cast<unsigned>(GK);1589      SemaRef.Diag(ExistingElemLoc[static_cast<unsigned>(GK)],1590                   diag::note_acc_previous_expr_here);1591      continue;1592    }1593 1594    ExistingElemLoc[static_cast<unsigned>(GK)] = ER.get()->getBeginLoc();1595    GangKinds.push_back(GK);1596    IntExprs.push_back(ER.get());1597  }1598 1599  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {1600    // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels1601    // construct, the gang clause behaves as follows. ... The region of a loop1602    // with a gang clause may not contain another loop with a gang clause unless1603    // within a nested compute region.1604    if (SemaRef.LoopGangClauseOnKernel.Loc.isValid()) {1605      // This handles the 'inner loop' diagnostic, but we cannot set that we're1606      // on one of these until we get to the end of the construct.1607      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)1608          << OpenACCClauseKind::Gang << OpenACCClauseKind::Gang1609          << /*kernels construct info*/ 11610          << SemaRef.LoopGangClauseOnKernel.DirKind;1611      SemaRef.Diag(SemaRef.LoopGangClauseOnKernel.Loc,1612                   diag::note_acc_previous_clause_here)1613          << "gang";1614      return nullptr;1615    }1616 1617    // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not1618    // contain a loop with a gang or worker clause unless within a nested1619    // compute region.1620    if (SemaRef.LoopWorkerClauseLoc.isValid()) {1621      // This handles the 'inner loop' diagnostic, but we cannot set that we're1622      // on one of these until we get to the end of the construct.1623      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)1624          << OpenACCClauseKind::Gang << OpenACCClauseKind::Worker1625          << /*!kernels construct info*/ 0;1626      SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,1627                   diag::note_acc_previous_clause_here)1628          << "worker";1629      return nullptr;1630    }1631 1632    // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not1633    // contain a loop with a gang, worker, or vector clause unless within a1634    // nested compute region.1635    if (SemaRef.LoopVectorClauseLoc.isValid()) {1636      // This handles the 'inner loop' diagnostic, but we cannot set that we're1637      // on one of these until we get to the end of the construct.1638      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)1639          << OpenACCClauseKind::Gang << OpenACCClauseKind::Vector1640          << /*!kernels construct info*/ 0;1641      SemaRef.Diag(SemaRef.LoopVectorClauseLoc,1642                   diag::note_acc_previous_clause_here)1643          << "vector";1644      return nullptr;1645    }1646  }1647 1648  return SemaRef.CheckGangClause(Clause.getDirectiveKind(), ExistingClauses,1649                                 Clause.getBeginLoc(), Clause.getLParenLoc(),1650                                 GangKinds, IntExprs, Clause.getEndLoc());1651}1652 1653OpenACCClause *SemaOpenACCClauseVisitor::VisitFinalizeClause(1654    SemaOpenACC::OpenACCParsedClause &Clause) {1655  // There isn't anything to do here, this is only valid on one construct, and1656  // has no associated rules.1657  return OpenACCFinalizeClause::Create(Ctx, Clause.getBeginLoc(),1658                                       Clause.getEndLoc());1659}1660 1661OpenACCClause *SemaOpenACCClauseVisitor::VisitIfPresentClause(1662    SemaOpenACC::OpenACCParsedClause &Clause) {1663  // There isn't anything to do here, this is only valid on one construct, and1664  // has no associated rules.1665  return OpenACCIfPresentClause::Create(Ctx, Clause.getBeginLoc(),1666                                        Clause.getEndLoc());1667}1668 1669OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(1670    SemaOpenACC::OpenACCParsedClause &Clause) {1671  // OpenACC 3.3 2.9:1672  //  A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause1673  //  appears.1674  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop ||1675      isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) {1676    const auto *Itr = llvm::find_if(1677        ExistingClauses, llvm::IsaPred<OpenACCGangClause, OpenACCVectorClause,1678                                       OpenACCWorkerClause>);1679    if (Itr != ExistingClauses.end()) {1680      SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)1681          << Clause.getClauseKind() << (*Itr)->getClauseKind()1682          << Clause.getDirectiveKind();1683      SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)1684          << (*Itr)->getClauseKind();1685      return nullptr;1686    }1687  }1688 1689  return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(),1690                                  Clause.getEndLoc());1691}1692 1693OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(1694    SemaOpenACC::OpenACCParsedClause &Clause) {1695  // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop1696  // directive that has a gang clause and is within a compute construct that has1697  // a num_gangs clause with more than one explicit argument.1698  if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&1699       SemaRef.getActiveComputeConstructInfo().Kind !=1700           OpenACCDirectiveKind::Invalid) ||1701      isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())) {1702    // num_gangs clause on the active compute construct.1703    auto ActiveComputeConstructContainer =1704        isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind())1705            ? ExistingClauses1706            : SemaRef.getActiveComputeConstructInfo().Clauses;1707    auto *NumGangsClauseItr = llvm::find_if(1708        ActiveComputeConstructContainer, llvm::IsaPred<OpenACCNumGangsClause>);1709 1710    if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&1711        cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >1712            1) {1713      auto *GangClauseItr =1714          llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);1715 1716      if (GangClauseItr != ExistingClauses.end()) {1717        SemaRef.Diag(Clause.getBeginLoc(),1718                     diag::err_acc_gang_reduction_numgangs_conflict)1719            << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang1720            << Clause.getDirectiveKind()1721            << isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind());1722        SemaRef.Diag((*GangClauseItr)->getBeginLoc(),1723                     diag::note_acc_previous_clause_here)1724            << (*GangClauseItr)->getClauseKind();1725        SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),1726                     diag::note_acc_previous_clause_here)1727            << (*NumGangsClauseItr)->getClauseKind();1728        return nullptr;1729      }1730    }1731  }1732 1733  // OpenACC3.3 Section 2.9.11: If a variable is involved in a reduction that1734  // spans multiple nested loops where two or more of those loops have1735  // associated loop directives, a reduction clause containing that variable1736  // must appear on each of those loop directives.1737  //1738  // This can't really be implemented in the CFE, as this requires a level of1739  // rechability/useage analysis that we're not really wanting to get into.1740  // Additionally, I'm alerted that this restriction is one that the middle-end1741  // can just 'figure out' as an extension and isn't really necessary.1742  //1743  // OpenACC3.3 Section 2.9.11: Every 'var' in a reduction clause appearing on1744  // an orphaned loop construct must be private.1745  //1746  // This again is something we cannot really diagnose, as it requires we see1747  // all the uses/scopes of all variables referenced.  The middle end/MLIR might1748  // be able to diagnose this.1749 1750  // OpenACC 3.3 Section 2.5.4:1751  // A reduction clause may not appear on a parallel construct with a1752  // num_gangs clause that has more than one argument.1753  if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||1754      Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) {1755    auto NumGangsClauses = llvm::make_filter_range(1756        ExistingClauses, llvm::IsaPred<OpenACCNumGangsClause>);1757 1758    for (auto *NGC : NumGangsClauses) {1759      unsigned NumExprs =1760          cast<OpenACCNumGangsClause>(NGC)->getIntExprs().size();1761 1762      if (NumExprs > 1) {1763        SemaRef.Diag(Clause.getBeginLoc(),1764                     diag::err_acc_reduction_num_gangs_conflict)1765            << /*>1 arg in first loc=*/0 << Clause.getClauseKind()1766            << Clause.getDirectiveKind() << OpenACCClauseKind::NumGangs;1767        SemaRef.Diag(NGC->getBeginLoc(), diag::note_acc_previous_clause_here)1768            << NGC->getClauseKind();1769        return nullptr;1770      }1771    }1772  }1773 1774  SmallVector<Expr *> ValidVars;1775  SmallVector<OpenACCReductionRecipeWithStorage> Recipes;1776 1777  for (Expr *Var : Clause.getVarList()) {1778    ExprResult Res = SemaRef.CheckReductionVar(Clause.getDirectiveKind(),1779                                               Clause.getReductionOp(), Var);1780 1781    if (Res.isUsable()) {1782      ValidVars.push_back(Res.get());1783 1784      Recipes.push_back(SemaRef.CreateReductionInitRecipe(1785          Clause.getReductionOp(), Res.get()));1786    }1787  }1788 1789  return SemaRef.CheckReductionClause(1790      ExistingClauses, Clause.getDirectiveKind(), Clause.getBeginLoc(),1791      Clause.getLParenLoc(), Clause.getReductionOp(), ValidVars,1792      Recipes,1793      Clause.getEndLoc());1794}1795 1796OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(1797    SemaOpenACC::OpenACCParsedClause &Clause) {1798 1799  if (DisallowSinceLastDeviceType<OpenACCCollapseClause>(Clause))1800    return nullptr;1801 1802  ExprResult LoopCount = SemaRef.CheckCollapseLoopCount(Clause.getLoopCount());1803 1804  if (!LoopCount.isUsable())1805    return nullptr;1806 1807  return OpenACCCollapseClause::Create(Ctx, Clause.getBeginLoc(),1808                                       Clause.getLParenLoc(), Clause.isForce(),1809                                       LoopCount.get(), Clause.getEndLoc());1810}1811 1812OpenACCClause *SemaOpenACCClauseVisitor::VisitBindClause(1813    SemaOpenACC::OpenACCParsedClause &Clause) {1814 1815  if (std::holds_alternative<StringLiteral *>(Clause.getBindDetails()))1816    return OpenACCBindClause::Create(1817        Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),1818        std::get<StringLiteral *>(Clause.getBindDetails()), Clause.getEndLoc());1819  return OpenACCBindClause::Create(1820      Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),1821      std::get<IdentifierInfo *>(Clause.getBindDetails()), Clause.getEndLoc());1822}1823 1824// Return true if the two vars refer to the same variable, for the purposes of1825// equality checking.1826bool areVarsEqual(Expr *VarExpr1, Expr *VarExpr2) {1827  if (VarExpr1->isInstantiationDependent() ||1828      VarExpr2->isInstantiationDependent())1829    return false;1830 1831  VarExpr1 = VarExpr1->IgnoreParenCasts();1832  VarExpr2 = VarExpr2->IgnoreParenCasts();1833 1834  // Legal expressions can be: Scalar variable reference, sub-array, array1835  // element, or composite variable member.1836 1837  // Sub-array.1838  if (isa<ArraySectionExpr>(VarExpr1)) {1839    auto *Expr2AS = dyn_cast<ArraySectionExpr>(VarExpr2);1840    if (!Expr2AS)1841      return false;1842 1843    auto *Expr1AS = cast<ArraySectionExpr>(VarExpr1);1844 1845    if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))1846      return false;1847    // We could possibly check to see if the ranges aren't overlapping, but it1848    // isn't clear that the rules allow this.1849    return true;1850  }1851 1852  // Array-element.1853  if (isa<ArraySubscriptExpr>(VarExpr1)) {1854    auto *Expr2AS = dyn_cast<ArraySubscriptExpr>(VarExpr2);1855    if (!Expr2AS)1856      return false;1857 1858    auto *Expr1AS = cast<ArraySubscriptExpr>(VarExpr1);1859 1860    if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))1861      return false;1862 1863    // We could possibly check to see if the elements referenced aren't the1864    // same, but it isn't clear by reading of the standard that this is allowed1865    // (and that the 'var' refered to isn't the array).1866    return true;1867  }1868 1869  // Scalar variable reference, or composite variable.1870  if (isa<DeclRefExpr>(VarExpr1)) {1871    auto *Expr2DRE = dyn_cast<DeclRefExpr>(VarExpr2);1872    if (!Expr2DRE)1873      return false;1874 1875    auto *Expr1DRE = cast<DeclRefExpr>(VarExpr1);1876 1877    return Expr1DRE->getDecl()->getMostRecentDecl() ==1878           Expr2DRE->getDecl()->getMostRecentDecl();1879  }1880 1881  llvm_unreachable("Unknown variable type encountered");1882}1883} // namespace1884 1885OpenACCClause *1886SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,1887                         OpenACCParsedClause &Clause) {1888  if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)1889    return nullptr;1890 1891  if (DiagnoseAllowedClauses(Clause.getDirectiveKind(), Clause.getClauseKind(),1892                             Clause.getBeginLoc()))1893    return nullptr;1894 1895  if (const auto *DevTypeClause = llvm::find_if(1896          ExistingClauses, llvm::IsaPred<OpenACCDeviceTypeClause>);1897      DevTypeClause != ExistingClauses.end()) {1898    if (checkValidAfterDeviceType(1899            *this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))1900      return nullptr;1901  }1902 1903  SemaOpenACCClauseVisitor Visitor{*this, ExistingClauses};1904  OpenACCClause *Result = Visitor.Visit(Clause);1905  assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) &&1906         "Created wrong clause?");1907 1908  return Result;1909}1910 1911bool SemaOpenACC::CheckReductionVarType(Expr *VarExpr) {1912  SourceLocation VarLoc = VarExpr->getBeginLoc();1913 1914  SmallVector<PartialDiagnosticAt> Notes;1915  // The standard isn't clear how many levels of 'array element' or 'subarray'1916  // are permitted, but we can handle as many as we need, so we'll strip them1917  // off here. This will result in CurType being the actual 'type' of the1918  // expression, which is what we are looking to check.1919  QualType CurType = isa<ArraySectionExpr>(VarExpr)1920                         ? cast<ArraySectionExpr>(VarExpr)->getElementType()1921                         : VarExpr->getType();1922 1923  // This can happen when we have a dependent type in an array element that the1924  // above function has tried to 'unwrap'. Since this can only happen with1925  // dependence, just let it go.1926  if (CurType.isNull())1927    return false;1928 1929  // If we are still an array type, we allow 1 level of 'unpeeling' of the1930  // array.  The standard isn't clear here whether this is allowed, but1931  // array-of-valid-things makes sense.1932  if (auto *AT = getASTContext().getAsArrayType(CurType)) {1933    // If we're already the array type, peel off the array and leave the element1934    // type.1935    PartialDiagnostic PD = PDiag(diag::note_acc_reduction_array)1936                           << diag::OACCReductionArray::ArrayTy << CurType;1937    Notes.push_back({VarLoc, PD});1938    CurType = AT->getElementType();1939  }1940 1941  auto IsValidMemberOfComposite = [](QualType Ty) {1942    return !Ty->isAnyComplexType() &&1943           (Ty->isDependentType() ||1944            (Ty->isScalarType() && !Ty->isPointerType()));1945  };1946 1947  auto EmitDiags = [&](SourceLocation Loc, PartialDiagnostic PD) {1948    Diag(Loc, PD);1949 1950    for (auto [Loc, PD] : Notes)1951      Diag(Loc, PD);1952 1953    return Diag(VarLoc, diag::note_acc_reduction_type_summary);1954  };1955 1956  // If the type is already scalar, or is dependent, just give up.1957  if (IsValidMemberOfComposite(CurType)) {1958    // Nothing to do here, is valid.1959  } else if (auto *RD = CurType->getAsRecordDecl()) {1960    if (!RD->isStruct() && !RD->isClass())1961      return EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)1962                                   << RD1963                                   << diag::OACCReductionTy::NotClassStruct);1964 1965    if (!RD->isCompleteDefinition())1966      return EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)1967                                   << RD << diag::OACCReductionTy::NotComplete);1968 1969    if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);1970        CXXRD && !CXXRD->isAggregate())1971      return EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)1972                                   << CXXRD << diag::OACCReductionTy::NotAgg);1973 1974    for (FieldDecl *FD : RD->fields()) {1975      if (!IsValidMemberOfComposite(FD->getType())) {1976        PartialDiagnostic PD =1977            PDiag(diag::note_acc_reduction_member_of_composite)1978            << FD->getName() << RD->getName();1979        Notes.push_back({FD->getBeginLoc(), PD});1980        // TODO: member here.note_acc_reduction_member_of_composite1981        return EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)1982                                     << FD->getType()1983                                     << diag::OACCReductionTy::MemberNotScalar);1984      }1985    }1986  } else {1987    return EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)1988                                 << CurType1989                                 << diag::OACCReductionTy::NotScalar);1990  }1991 1992  return false;1993}1994 1995/// OpenACC 3.3 section 2.5.15:1996/// At a mininmum, the supported data types include ... the numerical data types1997/// in C, C++, and Fortran.1998///1999/// If the reduction var is a composite variable, each2000/// member of the composite variable must be a supported datatype for the2001/// reduction operation.2002ExprResult SemaOpenACC::CheckReductionVar(OpenACCDirectiveKind DirectiveKind,2003                                          OpenACCReductionOperator ReductionOp,2004                                          Expr *VarExpr) {2005  // For now, we only support 'scalar' types, or composites/arrays of scalar2006  // types.2007  VarExpr = VarExpr->IgnoreParenCasts();2008 2009  if (CheckReductionVarType(VarExpr))2010    return ExprError();2011 2012  // OpenACC3.3: 2.9.11: Reduction clauses on nested constructs for the same2013  // reduction 'var' must have the same reduction operator.2014  if (!VarExpr->isInstantiationDependent()) {2015 2016    for (const OpenACCReductionClause *RClause : ActiveReductionClauses) {2017      if (RClause->getReductionOp() == ReductionOp)2018        break;2019 2020      for (Expr *OldVarExpr : RClause->getVarList()) {2021        if (OldVarExpr->isInstantiationDependent())2022          continue;2023 2024        if (areVarsEqual(VarExpr, OldVarExpr)) {2025          Diag(VarExpr->getExprLoc(), diag::err_reduction_op_mismatch)2026              << ReductionOp << RClause->getReductionOp();2027          Diag(OldVarExpr->getExprLoc(), diag::note_acc_previous_clause_here)2028              << RClause->getClauseKind();2029          return ExprError();2030        }2031      }2032    }2033  }2034 2035  return VarExpr;2036}2037 2038ExprResult SemaOpenACC::CheckTileSizeExpr(Expr *SizeExpr) {2039  if (!SizeExpr)2040    return ExprError();2041 2042  assert((SizeExpr->isInstantiationDependent() ||2043          SizeExpr->getType()->isIntegerType()) &&2044         "size argument non integer?");2045 2046  // If dependent, or an asterisk, the expression is fine.2047  if (SizeExpr->isInstantiationDependent() ||2048      isa<OpenACCAsteriskSizeExpr>(SizeExpr))2049    return ExprResult{SizeExpr};2050 2051  std::optional<llvm::APSInt> ICE =2052      SizeExpr->getIntegerConstantExpr(getASTContext());2053 2054  // OpenACC 3.3 2.9.82055  // where each tile size is a constant positive integer expression or asterisk.2056  if (!ICE || *ICE <= 0) {2057    Diag(SizeExpr->getBeginLoc(), diag::err_acc_size_expr_value)2058        << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();2059    return ExprError();2060  }2061 2062  return ExprResult{2063      ConstantExpr::Create(getASTContext(), SizeExpr, APValue{*ICE})};2064}2065 2066ExprResult SemaOpenACC::CheckCollapseLoopCount(Expr *LoopCount) {2067  if (!LoopCount)2068    return ExprError();2069 2070  assert((LoopCount->isInstantiationDependent() ||2071          LoopCount->getType()->isIntegerType()) &&2072         "Loop argument non integer?");2073 2074  // If this is dependent, there really isn't anything we can check.2075  if (LoopCount->isInstantiationDependent())2076    return ExprResult{LoopCount};2077 2078  std::optional<llvm::APSInt> ICE =2079      LoopCount->getIntegerConstantExpr(getASTContext());2080 2081  // OpenACC 3.3: 2.9.12082  // The argument to the collapse clause must be a constant positive integer2083  // expression.2084  if (!ICE || *ICE <= 0) {2085    Diag(LoopCount->getBeginLoc(), diag::err_acc_collapse_loop_count)2086        << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();2087    return ExprError();2088  }2089 2090  return ExprResult{2091      ConstantExpr::Create(getASTContext(), LoopCount, APValue{*ICE})};2092}2093 2094ExprResult2095SemaOpenACC::CheckGangExpr(ArrayRef<const OpenACCClause *> ExistingClauses,2096                           OpenACCDirectiveKind DK, OpenACCGangKind GK,2097                           Expr *E) {2098  // There are two cases for the enforcement here: the 'current' directive is a2099  // 'loop', where we need to check the active compute construct kind, or the2100  // current directive is a 'combined' construct, where we have to check the2101  // current one.2102  switch (DK) {2103  case OpenACCDirectiveKind::ParallelLoop:2104    return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,2105                                 E);2106  case OpenACCDirectiveKind::SerialLoop:2107    return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,2108                               E);2109  case OpenACCDirectiveKind::KernelsLoop:2110    return CheckGangKernelsExpr(*this, ExistingClauses, DK,2111                                ActiveComputeConstructInfo.Kind, GK, E);2112  case OpenACCDirectiveKind::Routine:2113    return CheckGangRoutineExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,2114                                E);2115  case OpenACCDirectiveKind::Loop:2116    switch (ActiveComputeConstructInfo.Kind) {2117    case OpenACCDirectiveKind::Invalid:2118    case OpenACCDirectiveKind::Parallel:2119    case OpenACCDirectiveKind::ParallelLoop:2120      return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind,2121                                   GK, E);2122    case OpenACCDirectiveKind::SerialLoop:2123    case OpenACCDirectiveKind::Serial:2124      return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,2125                                 E);2126    case OpenACCDirectiveKind::KernelsLoop:2127    case OpenACCDirectiveKind::Kernels:2128      return CheckGangKernelsExpr(*this, ExistingClauses, DK,2129                                  ActiveComputeConstructInfo.Kind, GK, E);2130    default:2131      llvm_unreachable("Non compute construct in active compute construct?");2132    }2133  case OpenACCDirectiveKind::Invalid:2134    // This can happen in cases where the the directive was not recognized but2135    // we continued anyway. Since the validity checking is all-over the place2136    // (it can be a star/integer, or a constant expr depending on the tag), we2137    // just give up and return an ExprError here.2138    return ExprError();2139  default:2140    llvm_unreachable("Invalid directive kind for a Gang clause");2141  }2142  llvm_unreachable("Compute construct directive not handled?");2143}2144 2145OpenACCClause *2146SemaOpenACC::CheckGangClause(OpenACCDirectiveKind DirKind,2147                             ArrayRef<const OpenACCClause *> ExistingClauses,2148                             SourceLocation BeginLoc, SourceLocation LParenLoc,2149                             ArrayRef<OpenACCGangKind> GangKinds,2150                             ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) {2151  // Reduction isn't possible on 'routine' so we don't bother checking it here.2152  if (DirKind != OpenACCDirectiveKind::Routine) {2153    // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive2154    // that has a gang clause with a dim: argument whose value is greater2155    // than 1.2156    const auto *ReductionItr =2157        llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);2158 2159    if (ReductionItr != ExistingClauses.end()) {2160      const auto GangZip = llvm::zip_equal(GangKinds, IntExprs);2161      const auto GangItr = llvm::find_if(GangZip, [](const auto &Tuple) {2162        return std::get<0>(Tuple) == OpenACCGangKind::Dim;2163      });2164 2165      if (GangItr != GangZip.end()) {2166        const Expr *DimExpr = std::get<1>(*GangItr);2167 2168        assert((DimExpr->isInstantiationDependent() ||2169                isa<ConstantExpr>(DimExpr)) &&2170               "Improperly formed gang argument");2171        if (const auto *DimVal = dyn_cast<ConstantExpr>(DimExpr);2172            DimVal && DimVal->getResultAsAPSInt() > 1) {2173          Diag(DimVal->getBeginLoc(), diag::err_acc_gang_reduction_conflict)2174              << /*gang/reduction=*/0 << DirKind;2175          Diag((*ReductionItr)->getBeginLoc(),2176               diag::note_acc_previous_clause_here)2177              << (*ReductionItr)->getClauseKind();2178          return nullptr;2179        }2180      }2181    }2182  }2183 2184  return OpenACCGangClause::Create(getASTContext(), BeginLoc, LParenLoc,2185                                   GangKinds, IntExprs, EndLoc);2186}2187 2188OpenACCClause *SemaOpenACC::CheckReductionClause(2189    ArrayRef<const OpenACCClause *> ExistingClauses,2190    OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc,2191    SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp,2192    ArrayRef<Expr *> Vars, ArrayRef<OpenACCReductionRecipeWithStorage> Recipes,2193    SourceLocation EndLoc) {2194  if (DirectiveKind == OpenACCDirectiveKind::Loop ||2195      isOpenACCCombinedDirectiveKind(DirectiveKind)) {2196    // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive2197    // that has a gang clause with a dim: argument whose value is greater2198    // than 1.2199    const auto GangClauses = llvm::make_filter_range(2200        ExistingClauses, llvm::IsaPred<OpenACCGangClause>);2201 2202    for (auto *GC : GangClauses) {2203      const auto *GangClause = cast<OpenACCGangClause>(GC);2204      for (unsigned I = 0; I < GangClause->getNumExprs(); ++I) {2205        std::pair<OpenACCGangKind, const Expr *> EPair = GangClause->getExpr(I);2206        if (EPair.first != OpenACCGangKind::Dim)2207          continue;2208 2209        if (const auto *DimVal = dyn_cast<ConstantExpr>(EPair.second);2210            DimVal && DimVal->getResultAsAPSInt() > 1) {2211          Diag(BeginLoc, diag::err_acc_gang_reduction_conflict)2212              << /*reduction/gang=*/1 << DirectiveKind;2213          Diag(GangClause->getBeginLoc(), diag::note_acc_previous_clause_here)2214              << GangClause->getClauseKind();2215          return nullptr;2216        }2217      }2218    }2219  }2220 2221  auto *Ret = OpenACCReductionClause::Create(2222      getASTContext(), BeginLoc, LParenLoc, ReductionOp, Vars, Recipes, EndLoc);2223  return Ret;2224}2225 2226llvm::SmallVector<Expr *>2227SemaOpenACC::CheckLinkClauseVarList(ArrayRef<Expr *> VarExprs) {2228  const DeclContext *DC = removeLinkageSpecDC(getCurContext());2229 2230  // Link has no special restrictions on its var list unless it is not at NS/TU2231  // scope.2232  if (isa<NamespaceDecl, TranslationUnitDecl>(DC))2233    return llvm::SmallVector<Expr *>(VarExprs);2234 2235  llvm::SmallVector<Expr *> NewVarList;2236 2237  for (Expr *VarExpr : VarExprs) {2238    if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(VarExpr)) {2239      NewVarList.push_back(VarExpr);2240      continue;2241    }2242 2243    // Field decls can't be global, nor extern, and declare can't refer to2244    // non-static fields in class-scope, so this always fails the scope check.2245    // BUT for now we add this so it gets diagnosed by the general 'declare'2246    // rules.2247    if (isa<MemberExpr>(VarExpr)) {2248      NewVarList.push_back(VarExpr);2249      continue;2250    }2251 2252    Expr *OrigExpr = VarExpr;2253 2254    while (isa<ArraySectionExpr, ArraySubscriptExpr>(VarExpr)) {2255      if (auto *ASE = dyn_cast<ArraySectionExpr>(VarExpr))2256        VarExpr = ASE->getBase()->IgnoreParenImpCasts();2257      else2258        VarExpr =2259            cast<ArraySubscriptExpr>(VarExpr)->getBase()->IgnoreParenImpCasts();2260    }2261 2262    const auto *DRE = cast<DeclRefExpr>(VarExpr);2263    const VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl());2264 2265    if (!Var || !Var->hasExternalStorage())2266      Diag(VarExpr->getBeginLoc(), diag::err_acc_link_not_extern);2267    else2268      NewVarList.push_back(OrigExpr);2269  }2270 2271  return NewVarList;2272}2273bool SemaOpenACC::CheckDeclareClause(SemaOpenACC::OpenACCParsedClause &Clause,2274                                     OpenACCModifierKind Mods) {2275 2276  if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Declare)2277    return false;2278 2279  const DeclContext *DC = removeLinkageSpecDC(getCurContext());2280 2281  // Whether this is 'create', 'copyin', 'deviceptr', 'device_resident', or2282  // 'link', which have 2 special rules.2283  bool IsSpecialClause =2284      Clause.getClauseKind() == OpenACCClauseKind::Create ||2285      Clause.getClauseKind() == OpenACCClauseKind::CopyIn ||2286      Clause.getClauseKind() == OpenACCClauseKind::DevicePtr ||2287      Clause.getClauseKind() == OpenACCClauseKind::DeviceResident ||2288      Clause.getClauseKind() == OpenACCClauseKind::Link;2289 2290  // OpenACC 3.3 2.13:2291  // In C or C++ global or namespace scope, only 'create',2292  // 'copyin', 'deviceptr', 'device_resident', or 'link' clauses are2293  // allowed.2294  if (!IsSpecialClause && isa<NamespaceDecl, TranslationUnitDecl>(DC)) {2295    return Diag(Clause.getBeginLoc(), diag::err_acc_declare_clause_at_global)2296           << Clause.getClauseKind();2297  }2298 2299  llvm::SmallVector<Expr *> FilteredVarList;2300  const DeclaratorDecl *CurDecl = nullptr;2301  for (Expr *VarExpr : Clause.getVarList()) {2302    if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(VarExpr)) {2303      // There isn't really anything we can do here, so we add them anyway and2304      // we can check them again when we instantiate this.2305    } else if (const auto *MemExpr = dyn_cast<MemberExpr>(VarExpr)) {2306      FieldDecl *FD =2307          cast<FieldDecl>(MemExpr->getMemberDecl()->getCanonicalDecl());2308      CurDecl = FD;2309 2310      if (removeLinkageSpecDC(2311              FD->getLexicalDeclContext()->getPrimaryContext()) != DC) {2312        Diag(MemExpr->getBeginLoc(), diag::err_acc_declare_same_scope)2313            << Clause.getClauseKind();2314        continue;2315      }2316    } else {2317 2318      const Expr *VarExprTemp = VarExpr;2319 2320      while (const auto *ASE = dyn_cast<ArraySectionExpr>(VarExprTemp))2321        VarExprTemp = ASE->getBase()->IgnoreParenImpCasts();2322 2323      const auto *DRE = cast<DeclRefExpr>(VarExprTemp);2324      if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {2325        CurDecl = Var->getCanonicalDecl();2326 2327        // OpenACC3.3 2.13:2328        // A 'declare' directive must be in the same scope as the declaration of2329        // any var that appears in the clauses of the directive or any scope2330        // within a C/C++ function.2331        // We can't really check 'scope' here, so we check declaration context,2332        // which is a reasonable approximation, but misses scopes inside of2333        // functions.2334        if (removeLinkageSpecDC(2335                Var->getLexicalDeclContext()->getPrimaryContext()) != DC) {2336          Diag(VarExpr->getBeginLoc(), diag::err_acc_declare_same_scope)2337              << Clause.getClauseKind();2338          continue;2339        }2340        // OpenACC3.3 2.13:2341        // C and C++ extern variables may only appear in 'create',2342        // 'copyin', 'deviceptr', 'device_resident', or 'link' clauses on a2343        // 'declare' directive.2344        if (!IsSpecialClause && Var->hasExternalStorage()) {2345          Diag(VarExpr->getBeginLoc(), diag::err_acc_declare_extern)2346              << Clause.getClauseKind();2347          continue;2348        }2349      }2350 2351      // OpenACC3.3 2.13:2352      // A var may appear at most once in all the clauses of declare2353      // directives for a function, subroutine, program, or module.2354 2355      if (CurDecl) {2356        auto [Itr, Inserted] = DeclareVarReferences.try_emplace(CurDecl);2357        if (!Inserted) {2358          Diag(VarExpr->getBeginLoc(), diag::err_acc_multiple_references)2359              << Clause.getClauseKind();2360          Diag(Itr->second, diag::note_acc_previous_reference);2361          continue;2362        } else {2363          Itr->second = VarExpr->getBeginLoc();2364        }2365      }2366    }2367    FilteredVarList.push_back(VarExpr);2368  }2369 2370  Clause.setVarListDetails(FilteredVarList, Mods);2371  return false;2372}2373