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