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